Background: I am creating an AR treasure hunt app. It is simple, it has a locator that tells you where the treasure is relative to you. I have the camera being the origin and the treasure being an object in AR world.
Question: I would like to rotate my arrow according to where in space the treasure is at. but in 2d. Basically, I would ignore the relative forward plane that is camera.forward.
Example: If the camera rotation is default, the angle can be calculated as atan2(dy,dx). If the camera is looking straight down, the angle is atan2(dz,dx).
What I have tried:
Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
Relative rotation is correct in 3d space but I would like to convert that into 2d ignoring the camera.forward plane. So even if the treasure is in front or behind the camera, it should not change the angle.
Turns out there is a very simple way to get relative X and Y of the target.
Vector2 ExtractRelativeXY(Transform origin, Transform target) {
// Get the absolute look rotation from origin to target.
Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
// Create a relative look rotation with respect to origin's forward.
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
// Obtain Matrix 4x4 from the rotation.
Matrix4x4 m = Matrix4x4.Rotate(relativeRot);
// Get the 3rd column (which is the forward vector of the rotation).
Vector4 mForward = m.GetColumn(2);
// Simply extract the x and y.
return new Vector2(mForward.x, mForward.y);
}
Once obtained x and y, turn it into angle using angle = atan2(y,x)
as suggested by both MBo and Tom.
This works because of the matrix components of the quaternion can be demonstrated in multiple vectors. Better illustration is found here https://stackoverflow.com/a/26724912.