Skip to content
This repository has been archived by the owner on Apr 27, 2024. It is now read-only.

FitBox math for repositioning holograms is incorrect #44

Open
RickyRoeslerMS opened this issue Jan 5, 2018 · 0 comments
Open

FitBox math for repositioning holograms is incorrect #44

RickyRoeslerMS opened this issue Jan 5, 2018 · 0 comments

Comments

@RickyRoeslerMS
Copy link

Prior to closing the FitBox in FitBox::DismissFitbox() the Hologram Collection object is supposed to get repositioned in front of the user. Unfortunately, there are several mistakes in the math for calculating the new position and rotation of the Hologram Collection.

The first problem is in the calculation of collectionStartingOffsetFromCamera inside Awake(). Here is the code as it currently exists:

// These are the holograms to show when the Fitbox is dismissed
 if (HologramCollection)
{
    collectionStartingOffsetFromCamera = HologramCollection.transform.localPosition;
    HologramCollection.SetActive(false);
 }

The hologram collection is not parented to anything so its localPosition will be the same as its global position. This calculation of the offset is correct if the camera is placed at (0,0,0), which it is for the scenes provided by the Academy. Now it is recommended that user's put the cameras at the origin, but that isn't a strict requirement. A more robust calculation would be:

collectionStartingOffsetFromCamera = Camera.main.transform.InverseTransformPoint(HologramCollection.transform.position);

This calculates the Hologram Collection's position in the local space of the camera and will work regardless of the initial placement of the camera.

Next, take a look at in DismissFitbox() and you will see this code which calculates the new position and rotation of the Hologram Collection:

// Update the Hologram Collection's position so it shows up
// where the Fitbox left off. Start with the camera's localRotation...
Quaternion camQuat = Camera.main.transform.localRotation;

// ... ignore pitch by disabling rotation around the x axis
camQuat.x = 0;

// Rotate the vector and factor y back into the position
Vector3 newPosition = camQuat * collectionStartingOffsetFromCamera;
newPosition.y = collectionStartingOffsetFromCamera.y;

// Position was "Local Position" so add that to where the camera is now
HologramCollection.transform.position = Camera.main.transform.position + newPosition;

// Rotate the Hologram Collection to face the user.
Quaternion toQuat = Camera.main.transform.localRotation * HologramCollection.transform.rotation;
toQuat.x = 0;
toQuat.z = 0;
HologramCollection.transform.rotation = toQuat;

Zeroing out the X coordinate of camQuat does not remove pitch as the comment suggests. camQuat is a quaternion but is being used like Euler angles. The X, Y, Z components of a quaternion tell us the axis around which the object is being rotated not the rotation of the object itself. So setting the X component to 0 means we have a rotation about some new axis in the Y, Z plane but does not mean that the object has zero rotation in the X plane. A more correct implementation would be to convert the quaternion into Euler angles and then remove the unwanted components. This guarantees we have removed the pitch and roll from the object itself.:

// Update the Hologram Collection's position so it shows up where the Fitbox left off. 
// Start with the camera's rotation in euler angles
var euler = Camera.main.transform.eulerAngles;

// Remove pitch and roll by zeroing out rotation around the x and z axes
var camQuat = Quaternion.Euler(0, euler.y, 0);

// Calculate the new offset by rotating the initial offset vector
var newOffset = camQuat * collectionStartingOffsetFromCamera;

// Add the camera's position to the new offset to get the new position of the collection
HologramCollection.transform.position = Camera.main.transform.position + newOffset;

I should note that the original code did not remove roll when calculating the collection's position, but I think that was the desired behavior so that is what I have done here. If you do want to include roll into the calculation you just have to replace the zero in the Z component with euler.z.

Likewise, the new rotation of the Hologram Collection is calculated by setting the X and Z coordinates of the rotation quaternion. Here is the code as it exists:

// Rotate the Hologram Collection to face the user.
Quaternion toQuat = Camera.main.transform.localRotation * HologramCollection.transform.rotation;
toQuat.x = 0;
toQuat.z = 0;
HologramCollection.transform.rotation = toQuat;

I believe the intent is to remove the camera's pitch and roll from the rotation of the Hologram collection. A better way would be to calculate the initial rotational offset in Awake() and then reapply that to the camQuat rotation in DismissFitbox(). This mirrors the calculation we did for position.

Inside Awake() we calculate the delta rotation between the camera's rotation and the collection's.

collectionStartingRotationOffsetFromCamera = Quaternion.Inverse(Camera.main.transform.rotation) * HologramCollection.transform.rotation;

And then inside DismissFitbox() we apply the delta to the camQuat rotation to get the new rotation for the hologram collection:

// Rotate the Hologram Collection to face the user.
Quaternion toQuat = camQuat * collectionStartingRotationOffsetFromCamera;
HologramCollection.transform.rotation = toQuat;

I believe this should achieve the desired placement and rotation of the hologram collection once the fitbox is dismissed. There are a variety of other approaches you could take to achieve the same result. The reason I chose this method was that it stuck closely to the original logic.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant