RigidBody "LookAt" Rotation

Started by
1 comment, last by Medo Mex 11 years, 4 months ago
Hello everyone,

I'm trying to make a mesh look at another mesh so I will be having two methods:
1. This method will make the mesh look at x, y ,z point instantly when called:
void Mesh::LookAtInstantly(float x, float y, float z);

2. This method will make the mesh move slightly till it look at the point, the method will be called several times to make the mesh look at another mesh, this method should return true when the it's actually looking at another mesh, otherwise it should return false when it's not yet looking at the other mesh (I will use this method to make a tank mesh look at another area, a tank can't just rotate to another area suddenly, it must rotate gradually):
bool Mesh::LookAtGradually(float x, float y, float z);

The following code is getting a valid Quaternion rotation to make the mesh1 look at mesh2, but I'm able to make it look at the other mesh instantly only, I want to be able to make it look at the other mesh gradually as well.

D3DXMATRIX rotation;
// World space position of the 1st, watching mesh.
D3DXVECTOR3 mesh1Pos_World(X, Y, Z);
// World space position of the 2nd, watched mesh.
D3DXVECTOR3 mesh2Pos_World;
if (boolOnYAxis)
mesh2Pos_World = D3DXVECTOR3(x, y, z);
else
mesh2Pos_World = D3DXVECTOR3(x, Y, z);
// mesh2Pos_World.y = 0; // Will NOT rotate on Y axis (UP), should be applied to tank cannon
// Object space direction of the 1st mesh; in other
// words it says where your mesh is looking at prior
// to any transformation. Your mesh is assumed to be
// at the origin.
D3DXVECTOR3 mesh1Dir_Object(0, 0, -1);
// This is the vector that goes from the watching mesh
// to the watched mesh.
D3DXVECTOR3 direction_World = mesh2Pos_World - mesh1Pos_World;
D3DXMATRIX finalCannonRot;
if (direction_World.x != 0 || direction_World.y != 0 || direction_World.z != 0)
{
// Normalize the two directions.
D3DXVec3Normalize(&mesh1Dir_Object, &mesh1Dir_Object);
D3DXVec3Normalize(&direction_World, &direction_World);
// The acos of the dot product between the two directions is
// the rotation angle in world space.
FLOAT angle_World = std::acos(D3DXVec3Dot(&mesh1Dir_Object, &direction_World));
// The normalized cross product between the two directions is
// the rotation axis in world space.
D3DXVECTOR3 axis_World;
D3DXVec3Cross(&axis_World, &mesh1Dir_Object, &direction_World);
D3DXVec3Normalize(&axis_World, &axis_World);
// This is the rotation matrix; this should be set as the
// world matrix for the 1st mesh.
D3DXMatrixRotationAxis(&rotation, &axis_World, angle_World);
// -- Get rotation quaternion
D3DXQUATERNION rotQuaternion;
D3DXQuaternionRotationAxis(&rotQuaternion, &axis_World, angle_World);

btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[ID];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
body->activate(true);
btMatrix3x3 orn = body->getWorldTransform().getBasis();
btQuaternion quat = btQuaternion(rotQuaternion.x, rotQuaternion.y, rotQuaternion.z, rotQuaternion.w);
// *********************************************************************************************
orn.setEulerYPR(???); // I want set this value to rotate the mesh gradually
// *********************************************************************************************
body->getWorldTransform().setBasis(orn);
}
}
Advertisement
Look into slerp for quaternions, it's basically interpolating rotations.
Thanks very much you really helped me! Two things that I'm concerned about:

1. How can I know that the mesh has finished rotating? (I want to know this so the tank mesh should fire after finishing rotation)

2. I can notice that the rotation speed slow down when the mesh is almost done rotating, I want it to be the same speed all the time.

Here is the code that I wrote:

if (?) // Expression to check if the rotation is completed or still in progress
{
// Not completed
btQuaternion currentQuat;
orn.getRotation(currentQuat);
float speed = 0.001f;
currentQuat = currentQuat.slerp(FinalQuat, timeElapsed * speed);
orn = btMatrix3x3(currentQuat);
body->getWorldTransform().setBasis(orn);
// You still need to call this method more to finish the rotation
return false; // RETURN FALSE
} else {
// Rotation completed, you don't need to call this method anymore, the tank mesh should fire now.
return true; // RETURN TRUE
}

This topic is closed to new replies.

Advertisement