SFML community forums

Help => General => Topic started by: Groogy on July 11, 2011, 10:36:00 pm

Title: Look At implementation
Post by: Groogy on July 11, 2011, 10:36:00 pm
Alright per request for my engine I am going to implement a LookAt function for the camera. I can do it to a matrix but the problem that arises is that my rotation vector will be wrong, it won't get the new values from the LookAt operation.

Is there anyone here that knows how to do a LookAt with just a rotation vector?

Here's my code so far:
Code: [Select]
void GGE::Interface::Camera::LookAt( const Vector3f aCenter, const Vector3f aUp )
{
Vector3f forward = (aCenter - myPosition).Normalize();
Vector3f side = forward.Cross( aUp.Normalize() );
Vector3f up = side.Cross( forward );
SetRotation( /* This is what I don't know? */ );
}


I can apply those 3 vectors to a matrix but like I said then GetRotation won't return the right rotation. So how do I combine these to one rotation vector? I thought I was close when I multiplied them together, but that always resulted in a zero vector.

I am no math brain, so I am having a really hard time figuring this by myself. Any pointers would be nice.
Title: Look At implementation
Post by: Nexus on July 11, 2011, 11:11:12 pm
Quote from: "Groogy"
Is there anyone here that knows how to do a LookAt with just a rotation vector?
What do you understand by "rotation vector"? You cannot store a general rotation in 3D space in a single vector.

Is it the direction vector of the camera? Then, it can be computed as target position - camera position. Or do you mean the triple (yaw, pitch, roll) in degrees?

Quote from: "Groogy"
I thought I was close when I multiplied them together, but that always resulted in a zero vector.
How did you multiply them? The dot product of perpendicular vectors is zero (scalar value, no zero vector).
Title: Look At implementation
Post by: Laurent on July 11, 2011, 11:19:27 pm
No matter how you build your rotation matrix, you can always extract rotations (in your preferred way) -- if the matrix is still a rotation matrix of course.

You may also have a look at quaternions, they are usually more convenient (and cheaper) for manipulating rotations -- typically for cameras.

For formulas & maths stuff about matrices and quaternions, check the "Matrix and Quaternion FAQ".
Title: Look At implementation
Post by: Groogy on July 12, 2011, 12:17:56 am
This is how the orientation is created for camera in the engine Nexus. As you can see a rotation matrix is created from a single vector. That vector is what you get from the GetRotation() function. It works the same for the camera. So I need to set that vector so the camera faces the point specified in the LookAt function.
Code: [Select]

Matrix33f rotation = Matrix33f::CreateRotateAroundX( myRotation.x );
rotation = Matrix33f::CreateRotateAroundY( myRotation.y ) * rotation;
rotation = Matrix33f::CreateRotateAroundZ( myRotation.z ) * rotation;
myOrientation.SetRotation( rotation );
myOrientation.SetPosition( myPosition );
myOrientation.SetScale( myScale );


Quote from: "Laurent"
No matter how you build your rotation matrix, you can always extract rotations (in your preferred way) -- if the matrix is still a rotation matrix of course.

So how would I do that from:
Code: [Select]
void GGE::Interface::Camera::LookAt( const Vector3f aCenter, const Vector3f aUp )
{
   Vector3f forward = (aCenter - myPosition).Normalize();
   Vector3f side = forward.Cross( aUp.Normalize() );
   Vector3f up = side.Cross( forward );
   Matrix33f rotation;
   // ... Set x rotation to side, y rotation to up and z rotation to -forward ... Already know how to do this
   SetRotation( /* This is what I don't know? */ );
}

UPDATE: Nevermind, I'll post what I think is correct from the FAQ you mentioned and then you can say if it's good or not ^^
Otherwise I don't learn.

Or should I just change it so the engine stores a rotation matrix instead of a vector? I felt that the vector would be simpler to work against. So the creation becomes instead:
Code: [Select]
myOrientation.SetRotation( myRotation );
myOrientation.SetPosition( myPosition );
myOrientation.SetScale( myScale );
Title: Look At implementation
Post by: Groogy on July 12, 2011, 02:06:40 am
Alright seems to be working like it should. Though after following the FAQ it seemed like I got the inversion of the rotation. Might be that I handle camera space wrong or something, or since it is camera space I have to invert it to get it right. Anyway I just inverted the vector before setting it and it worked just fine.

Code: [Select]
void GGE::Graphics::Camera::SetRotationMatrix( const Matrix33f &aRotation )
{
Vector3f angles = Vector3f::Zero;
angles.y = asin( aRotation.myData[ INDEX3( 2, 0 ) ] );
float c = cos( angles.y );
if( fabs( c ) > 0.005f )
{
float tempX = aRotation.myData[ INDEX3( 2, 2 ) ] / c;
float tempY = -aRotation.myData[ INDEX3( 2, 1 ) ] / c;
angles.x = atan2( tempY, tempX );
tempX = aRotation.myData[ INDEX3( 0, 0 ) ] / c;
tempY = -aRotation.myData[ INDEX3( 1, 0 ) ] / c;
angles.z = atan2( tempY, tempX );
}
else
{
angles.x = 0;
float tempX = aRotation.myData[ INDEX3( 1, 1 ) ];
float tempY = aRotation.myData[ INDEX3( 0, 1 ) ];
angles.z = atan2( tempY, tempX );
}
SetRotation( angles * -1 );
}

void GGE::Graphics::Camera::LookAt( const Vector3f aCenter, const Vector3f aUp )
{
Vector3f forward = (aCenter - myPosition).Normalize();
Vector3f side = forward.Cross( aUp.Normalize() );
Vector3f up = side.Cross( forward );
Matrix33f rotation;
rotation.myData[ INDEX3( 0, 0 ) ] = side.x;
rotation.myData[ INDEX3( 1, 0 ) ] = side.y;
rotation.myData[ INDEX3( 2, 0 ) ] = side.z;
rotation.myData[ INDEX3( 0, 1 ) ] = up.x;
rotation.myData[ INDEX3( 1, 1 ) ] = up.y;
rotation.myData[ INDEX3( 2, 1 ) ] = up.z;
rotation.myData[ INDEX3( 0, 2 ) ] = -forward.x;
rotation.myData[ INDEX3( 1, 2 ) ] = -forward.y;
rotation.myData[ INDEX3( 2, 2 ) ] = -forward.z;
SetRotationMatrix( rotation );
}


Do you see anything Laurent you think should be improved? Maybe even know why the vector is inverted. Also if you see anything in my interface/API you feel should be changed then just let me know. My engine is still in alpha stage so I love any comments I can get.