Page 1 of 1

setRotation question

Posted: Thu May 13, 2004 4:29 pm
by erSitzt
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

Posted: Sat May 15, 2004 8:16 am
by Phreak
There are quite a few posts about this already, although i can't seem to get it to work. I'm also wondering how to have a Mesh face the camera at all times...

You could try searching these forums. You might have better luck than me..

Phreak

Posted: Sat May 15, 2004 8:29 am
by Tyn
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.

Posted: Sat May 15, 2004 8:38 am
by Phreak
Let me know how you go, and paste your code (hopefully with some understandable explanations :P)..

I've been at it for about 7 days now <_<

Phreak

Posted: Sat May 15, 2004 9:08 am
by Tyn
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:

Image

"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.

Posted: Sat May 15, 2004 9:18 am
by Phreak
Theres a bigger problem for that with me. I'm 15 years old in 6 days :P !!!

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

Posted: Sat May 15, 2004 6:09 pm
by Tyn
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:

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

Posted: Sun May 16, 2004 9:30 am
by Tyn
Hey all

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;
}
Edit: Above code has been modified due to me missing out the side A definition.

Posted: Sun May 16, 2004 10:25 am
by Phreak
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:

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)));
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

Posted: Sun May 16, 2004 11:40 am
by Tyn
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:

Code: Select all

core::vector3df rotation = rotateToFace( core::position2d<f32>(0,0), core::position2d<f32>(6,2));
node->setRotation(rotation);
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 :oops: )

Posted: Sun May 16, 2004 12:26 pm
by Phreak
Sorry about this, but I'm still having problems. The code works fine:

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; 
} 
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

Posted: Sun May 16, 2004 12:58 pm
by Tyn
Firstly, change a bit of code:

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;
to

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;
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.

Posted: Sun May 16, 2004 5:54 pm
by erSitzt
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));

Posted: Mon May 17, 2004 11:21 am
by Phreak
Ah! That works!

Many thanks :D

Phreak