Rotating plane to face object while rotating around z axis. C++

I want to create a plane 2d sprite plane that looks at a 3d object and then rotates by its z axis. So I have created a LookAt Function in my game which will make the object look automatically at the sphere, but it is executed every frame, I believe this is because it makes the rotations every frame, now if I want to rotate it again by its local axis, the LookAt() overwrites this because its matrix is being set the same each time and so cannot rotate.

I believe I will have to rotate manually, now I know this problem is easy on one axis of rotation.

My maths is rusty. So I don't think I could just do this for a 3D rotation but I'm not sure. If so do I require quaternions?

Step by step desired action

1. Rotation on the z axis to make the plane face on the right x angle of sphere ignoring its y position.
2. Rotate on its x ais to make the plane face the y angle between sphere and 2d plane.
3. Rotate around the z axis each second, while remaining faced at the object.

@Jay

Here is the code related to the first answer which makes my model dissapear.

selec->SetPosition(a->unit_x, a->unit_y, a->unit_z);
selec->GetMatrix(&rotmatrix);
CMatrix4x4 crotmatrix{ &rotmatrix };
crotmatrix.RotateLocalZ(0.025);

selec->GetMatrix(&lookatm);
CMatrix4x4 clookat{ &lookatm };
clookat.FaceTarget(CVector3{ 0,0,0 });

clookat.MultiplyAffine(crotmatrix);
convertmatrix(clookat);

selec->SetMatrix(&lookatm);

This does multiply the matrices, but it keeps multiplying and creating a crazy motion, then causes a crash, maybe from gimbal lock?

• crotmatrix should only hold the z-rotation for that time. Is that correct?
– Jay
Nov 29 '17 at 15:09

Im going to quickly describe this, as I have to do similar for billboarding of my particles.

Simply, you have your desired target vector (target - viewer), and you have your viewer direction vector. You want your target vector to have no "Z" component effectively (as you are rotating around the Z axis). I eliminate the Z component and normalise the vector. You then cross the 2 vectors to get your rotation axis, Dot the vectors to be able to determine angle of rotation (Acos if i recall). Create a matrix with the axis and the angle.

vecb here would be your previous direction vector.

void CalculateBillboardMatrix(Vector3 a_targetDirection, ref Matrix a_billboardMatrix)
{
Vector3 veca = a_targetDirection;
Vector3 vecb = new Vector3(1, 0, 0); // this is always the direction the particle is initially created in.
veca.Normalize();
Vector3 axis = Vector3.Cross(veca, vecb);
axis.Normalize();
float angle = VectorExt.AngleBetweenVectors(vecb, veca, axis);

a_billboardMatrix = Matrix.RotationAxis(axis, angle);
}

This piece works out which direction to rotate the angle.

static public float AngleBetweenVectors(Vector3 a_direction1, Vector3 a_direction2, Vector3 a_planeNormal)
{
Debug.Assert(a_direction1.IsNormalized);
Debug.Assert(a_direction2.IsNormalized);

float angle = Vector3.Dot(a_direction1, a_direction2);

angle = (float)Math.Acos(angle);
Vector3 cross = Vector3.Cross(a_direction1, a_direction2);
cross.Normalize();
if (Vector3.Dot(a_planeNormal, cross) < 0)
{ // Or > 0
angle = -angle;
}

return angle;
}

The trick with the second item is to work out the winding, to this, you need to cross prod the axis with the vectors axis. The ordering changes the axis vector, you then Dot this to find out if its positive or negative which tells you the direction you need to rotate.

• I think this what i am looking for. Nov 30 '17 at 22:55

You don't need quaternions, you can do this with rotation matrices.

To get the final rotation you need to multiply successive rotations together. Order matters and in this case you'd use the rotations in the order you described.

Final rotation should be lookAt4x4 * local4x4.

• I don't know how to get the matrix of the 4x4 lookat, unless I perform the lookat(function) then store that into a CMatrix4x4 Nov 29 '17 at 13:03
• please view updated question , I have added a more indepth reply. Nov 29 '17 at 13:47