setRotation question
setRotation question
I have a problem rotating an MD2 Mesh, i want it to face the FPS-Camera all the time, but i dont know how to get the angle for setRotation.
Has anyone already tried something like this ?
mfg
erSitzt
Has anyone already tried something like this ?
mfg
erSitzt
I need this too. What I am thinking is to do a little clever maths to figure out the angle. My idea is to get the position of the first node (I'll call it n1 ) that will be looking at another node ( n2 ). Then I plan to figure out the angle from north ( I am saying if n1 was at 0,0 and n2 was at 0,1, with n1 looking at n2 it would be looking north ). To get the way it should be facing I plan on implementing a little hack to have a absolute rotation using this north.
Herein lies a problem. I've never been properly educated in programming ( as some of you may have worked out) and so I don't know how to work things out with vectors ( I don't think math vectors and the vectors Niko uses for storing coordinates are one in the same ). The bigger problem is I haven't done proper math like most of you guys who probably have been forced to do it with your programming course at Uni. Well, if you are good at maths and know a few formula then I can tell you how to do it, just not how to code it
Here is a diagram:
"n1" and "n2" are the example nodes I used in my previous post. The north point isn't that important, it just needs to be a north of the node ( just add on the Y axis ). What you need is a formula to get angle "a" given the positions of "n1" and "n2". That also means a forumla to figure out the length of the sides from the three points of the triangle. I don't have either, while I will make a effort to look through some of the math books I have I am sure someone out there is good enough at maths to be able to either have the formulae on hand or memorised.
Please post back if you do remember the formulae, I'm sure it will help others.
Here is a diagram:
"n1" and "n2" are the example nodes I used in my previous post. The north point isn't that important, it just needs to be a north of the node ( just add on the Y axis ). What you need is a formula to get angle "a" given the positions of "n1" and "n2". That also means a forumla to figure out the length of the sides from the three points of the triangle. I don't have either, while I will make a effort to look through some of the math books I have I am sure someone out there is good enough at maths to be able to either have the formulae on hand or memorised.
Please post back if you do remember the formulae, I'm sure it will help others.
Theres a bigger problem for that with me. I'm 15 years old in 6 days !!!
I have heaps of experience in Visual Basic 6/.NET and C++, but it is pretty much my first time in 3D game programming. So, the maths thing hasn't been a real help for me, since they don't teach us that in Year 9 (and online tutorials can really suck sometimes)
Anyway, I'll keep trying...
Phreak
I have heaps of experience in Visual Basic 6/.NET and C++, but it is pretty much my first time in 3D game programming. So, the maths thing hasn't been a real help for me, since they don't teach us that in Year 9 (and online tutorials can really suck sometimes)
Anyway, I'll keep trying...
Phreak
If you don't succeed, redefine success!
I mocked this bit of code up if you want to try it, I'll test it ( and no doubt debug it a little ) tomorrow probably but feel free to try it yourself. It returns a rotation on the Y axis in the form of a vector, it uses a north which you may want to alter, up to you. Remember that it also works on two dimensions, the X and Y axis, so it will work in 3D but it won't find the rotation of the Z axis. Not that you should need that, if you do then you'll have to extend it a little. Enjoy m8
It is called like this:
It is called like this:
Code: Select all
rotateToFaceNode(
core::position2D<f32>(0,0),
core::position2D<f32>(3,5) )
Code: Select all
#include "irrlicht.h"
#include "math.h"
using namespace irr;
core::vector3df* rotateToFaceNode(
core::position2d<core::f32> node,
core::position2d<core::f32> target)
{
core::position2d<core::f32> northPoint;
core::f32 A;
double cos_a;
double a;
core::f32 B;
core::f32 B1;
core::f32 B2;
core::f32 B3;
core::f32 C;
vector3df* result;
northPoint = node;
northPoint.X = northPoint.X + 6;
B1 = (target.X - node.X)*(target.X - node.X);
B2 = (target.Y - node.Y)*(target.Y - node.Y);
B3 = B1 + B2;
B = sqrt(B3);
C1 = (target.X - northPoint.X)*(target.X - northPoint.X);
C2 = (target.Y - northPoint.Y)*(target.Y - northPoint.Y);
C3 = C1 + C2;
C = sqrt(C3);
cos_a = ( (a*a)+(c*c)-(b*b) ) / 2*(a*c)
a = acos (cos_a) * 180 / 3.14;
result.X = 0;
result.Y = a;
result.Z = 0;
return result;
}
Debugged version
Hey all
I got the debugged version, it works now if anyone needs it. You need the same variables that are defined above.
Edit: Above code has been modified due to me missing out the side A definition.
I got the debugged version, it works now if anyone needs it. You need the same variables that are defined above.
Code: Select all
core::vector3df IBaseClass::rotateToFace( core::position2d<f32> node, core::position2d<f32> target)
{
// This function takes two positions, then works out the angle between node and
// target ( or the needed rotation for node to face target. The output is a
// vector3df
// Create north point ( north from node )
northPoint = node;
northPoint.X = northPoint.X + 6;
// Set side A to 6 ( it's the side between node and northPoint, the one we just added 6 to )
A = 6;
// Find length between target and node using Pythagoras Theorum
B1 = (target.X - node.X)*(target.X - node.X);
B2 = (target.Y - node.Y)*(target.Y - node.Y);
B3 = B1 + B2;
B = sqrt(B3);
// Find length between target and north point using Pythagoras Theorum
C1 = (target.X - northPoint.X)*(target.X - northPoint.X);
C2 = (target.Y - northPoint.Y)*(target.Y - northPoint.Y);
C3 = C1 + C2;
C = sqrt(C3);
// Work out the needed angle from the three lengths using inverse ( arc ) cosine:
// A - Between node and north point
// B - Between target and node
// C - between target and north point
cos_a = ( (A*A)+(C*C)-(B*B) ) / 2*(A*C);
a = (acos (cos_a)) * 180 / 3.14;
// Put results into a vector, then return the value
// Returns as a double from arc cosine
result = core::vector3df(0,0,a);
return result;
}
Last edited by Tyn on Sun May 16, 2004 11:47 am, edited 2 times in total.
How would I get it to face the camera? I can't find a way to use the camera in a position2d argument
I've got this:
The Mesh just lies on its back..
Any help would be great
EDIT:
What does A do? You don't assign it a value, and if I try to assign it anything (even decimals) the model doesn't appear.
Phreak
I've got this:
Code: Select all
node->setRotation(pBot.faceTarget(core::position2d<f32>(node->getPosition().X,node->getPosition().Y),core::position2d<f32>(camera->getPosition().X,camera->getPosition().Y)));
Any help would be great
EDIT:
What does A do? You don't assign it a value, and if I try to assign it anything (even decimals) the model doesn't appear.
Phreak
If you don't succeed, redefine success!
Sorry, it's a little confusing have "a" and "A". It's to do with maths, sides of a triangle are "A","B","C". "A" is the side that connects the North point with the Node. a is the angle. Should have cleared that up a bit, you could change it if it is confusing you.
What you do is you get the X and Y of the node and the target. Include this function ( you'll have to change it slightly because it's tied in with my code ) and call it with the X and Y of both.
Example:
The node is at 0,0,0 and you want it to face a node at 6,2,0. What you do is:
You don't need the Z axis since you aren't turning on the Y axis. It looks at the equation in a 2D way so I thought it easier to think of as 2D coords. It doesn't matter tho, the 2D coords are just numbers. If it is easier to think of you can change them to int's ( e.g. nodeX, nodeY, targX, targY ).
Put this code inside the while(device->run()) loop to have it constantly facing the node and update the coords as the two nodes move. Then you don't even have to worry about the maths going on, just keeping this function loaded with the latest node positions.
Edit: You are right, "A" isn't assigned. D'oh! It's because you don't use Pythagoras there, just a little subtraction. It's been edited and is right now ( thanks for pointing that out )
What you do is you get the X and Y of the node and the target. Include this function ( you'll have to change it slightly because it's tied in with my code ) and call it with the X and Y of both.
Example:
The node is at 0,0,0 and you want it to face a node at 6,2,0. What you do is:
Code: Select all
core::vector3df rotation = rotateToFace( core::position2d<f32>(0,0), core::position2d<f32>(6,2));
node->setRotation(rotation);
Put this code inside the while(device->run()) loop to have it constantly facing the node and update the coords as the two nodes move. Then you don't even have to worry about the maths going on, just keeping this function loaded with the latest node positions.
Edit: You are right, "A" isn't assigned. D'oh! It's because you don't use Pythagoras there, just a little subtraction. It's been edited and is right now ( thanks for pointing that out )
Sorry about this, but I'm still having problems. The code works fine:
With A set to 6 the model doesn't even appear in the 3D scene! No matter what I set it to, it doesn't appear. If I set it to 0, the model appears, but its horizontal, and doesn't move each frame.
Yes I do have this in the game loop.
Any ideas?
Phreak
Code: Select all
core::vector3df CGame::rotateToFace( core::position2d<f32> nodebase, core::position2d<f32> target)
{
// This function takes two positions, then works out the angle between node and
// target ( or the needed rotation for node to face target. The output is a
// vector3df
core::position2d<irr::f32> northPoint;
irr::f32 A;
double cos_a;
double a;
irr::f32 B;
irr::f32 B1;
irr::f32 B2;
irr::f32 B3;
irr::f32 C;
irr::f32 C1;
irr::f32 C2;
irr::f32 C3;
core::vector3df result;
// Create north point ( north from node )
northPoint = nodebase;
northPoint.X = northPoint.X + 6;
// Set side A to 6 ( it's the side between node and northPoint, the one we just added 6 to )
A = 6;
// Find length between target and node using Pythagoras Theorum
B1 = (target.X - nodebase.X)*(target.X - nodebase.X);
B2 = (target.Y - nodebase.Y)*(target.Y - nodebase.Y);
B3 = B1 + B2;
B = sqrt(B3);
// Find length between target and north point using Pythagoras Theorum
C1 = (target.X - northPoint.X)*(target.X - northPoint.X);
C2 = (target.Y - northPoint.Y)*(target.Y - northPoint.Y);
C3 = C1 + C2;
C = sqrt(C3);
// Work out the needed angle from the three lengths using inverse ( arc ) cosine:
// A - Between node and north point
// B - Between target and node
// C - between target and north point
cos_a = ( (A*A)+(C*C)-(B*B) ) / 2*(A*C);
a = (acos (cos_a)) * 180 / 3.14;
// Put results into a vector, then return the value
// Returns as a double from arc cosine
result = core::vector3df(0,0,a);
return result;
}
Yes I do have this in the game loop.
Any ideas?
Phreak
If you don't succeed, redefine success!
Firstly, change a bit of code:
to
This means that when you change A the triangle is being created properly. The number A is of no consequence as long as it is more than 0 because it is just used to create a triangle.
Secondly, I forgot to mention something about setRotation. setRotation is not an absolute rotation but is relative to the current position. So, say the rotation is 10 degrees, in your loop it is just moving the node 10 degrees forward from whatever the current rotation is.
You are going to need some kind of float to tell what the current rotation is, then use the return from rotateToFace to find the difference between them. This is what you should be rotating by.
Try this little experiment. Instead of using rotateToFace to get the rotation, try just calling setRotation to something like
vector3df(0,1,0)
Then load your model and check if the rotation is on the right axis. I have to use
vector3df(0,0,1)
Could you then tell me if the node is rotating the right way? I'm not totally sure why it isn't showing up but if it is rotating on the right axis at least it's a start
To all
Sorry I am doing my debugging on the forums, it's really unprofessional. I gave it a quick test and it seemed to work so I started working on something else I'll try and sort this out on my comp here rather than dealing with debugging peoples apps for them.
Code: Select all
// Create north point ( north from node )
northPoint = nodebase;
northPoint.X = northPoint.X + 6;
// Set side A to 6 ( it's the side between node and northPoint, the one we just added 6 to )
A = 6;
Code: Select all
// Set side A to 6 ( it's the side between node and northPoint, the one we just added 6 to )
A = 6;
// Create north point ( north from node )
northPoint = nodebase;
northPoint.X = northPoint.X + A;
Secondly, I forgot to mention something about setRotation. setRotation is not an absolute rotation but is relative to the current position. So, say the rotation is 10 degrees, in your loop it is just moving the node 10 degrees forward from whatever the current rotation is.
You are going to need some kind of float to tell what the current rotation is, then use the return from rotateToFace to find the difference between them. This is what you should be rotating by.
Try this little experiment. Instead of using rotateToFace to get the rotation, try just calling setRotation to something like
vector3df(0,1,0)
Then load your model and check if the rotation is on the right axis. I have to use
vector3df(0,0,1)
Could you then tell me if the node is rotating the right way? I'm not totally sure why it isn't showing up but if it is rotating on the right axis at least it's a start
To all
Sorry I am doing my debugging on the forums, it's really unprofessional. I gave it a quick test and it seemed to work so I started working on something else I'll try and sort this out on my comp here rather than dealing with debugging peoples apps for them.
A friend of mine helped me solve my problem with this piece of code :
float xNew;
float zNew;
float degree;
xNew = camera->getPosition().X - node->getPosition().X;
zNew = camera->getPosition().Z - node->getPosition().Z;
degree = atan(zNew/xNew) * (180 / 3.141592654);
if(xNew > 0)
{
degree = 90 - degree;
}
else
{
degree = -90 - degree;
}
degree -= 90;
...
node->setRotation(core::vector3df(0,degree,0));
float xNew;
float zNew;
float degree;
xNew = camera->getPosition().X - node->getPosition().X;
zNew = camera->getPosition().Z - node->getPosition().Z;
degree = atan(zNew/xNew) * (180 / 3.141592654);
if(xNew > 0)
{
degree = 90 - degree;
}
else
{
degree = -90 - degree;
}
degree -= 90;
...
node->setRotation(core::vector3df(0,degree,0));