- Home /
Amplifying HMD rotation in VR
I am trying to amplify the rotation of the Camera in VR. Essentially, if you look 15 degrees to the left, the camera actually turns 30 degrees.
To rotate the camera, I am using a parent object and manipulating the parent transform.
My current solution uses Euler angles, which is causing a lot of problems due to the flip from 0 to 360 degrees. I have tried to mitigate this in my code, but when the HMD is pointed straight up or straight down, the camera ends up tilted somehow.
I figure quaternions will help fix this, but I am finding it difficult to implement a solution as I don't know how to scale a quaternion. I also can't find a similar function to RotateAround using quaternions. [I think] I need this function as the parent transform I am rotating isn't in the same position as the camera.
My current solution simply takes the change in euler angles between frames, and scales it by a factor. See below:
[ICODE]
void ApplyRedirection(Vector3 newOrientation, Vector3 curOrientation)
{
float changeInPitch = newOrientation.x - curOrientation.x;
if (changeInPitch > 200)
{
changeInPitch -= 360;
}
if(changeInPitch < -200)
{
changeInPitch += 360;
}
PitchChange = changeInPitch;
camOffset.transform.RotateAround(currentHeadPosition, new Vector3(0, currentHeadOrientation.y, 0), changeInPitch * redirectionIntensityP * Time.fixedDeltaTime);
float changeInYaw = newOrientation.y - curOrientation.y;
if (changeInYaw > 200)
{
changeInYaw -= 360;
}
if (changeInYaw < -200)
{
changeInYaw += 360;
}
YawChange = changeInYaw;
camOffset.transform.RotateAround(currentHeadPosition, new Vector3(0, currentHeadOrientation.y, 0), changeInYaw * redirectionIntensityY * Time.fixedDeltaTime); //Do yaw reditection (horizontal)
currentHeadOrientation = newOrientation;
}
[/ICODE]
EDIT: I have a solution working with quaternions, but it has a similar issue to the euler solution.
Essentially, when you look to the floor and turn to the right, you're essentially looking to the right, but with a roll of +90 degrees. When you then try to look straight ahead from this position, the pitch angle is about 15 degrees lower than it should be, despite your physical head being at 0,0,0.
This problem seems to be related to the roll angle, which is why I didn't include this in the euler solution. However, I'm not sure how you might remove this angle from the quaternion calculations.
I thought to limit the rotation of the cam tracker on the z axis, but this just leads to the headset flipping back and forth from flat/z-rotated views.
(Cam Tracker is a game object with a script that follows the position and rotation of the Camera object)
void ApplyRedirection(Vector3 newOrientation, Vector3 curOrientation)
{
Quaternion newQuat = camTracker.transform.rotation;
Quaternion curQuat = initRotation;
Vector3 rotAxis = new Vector3(0, 0, 0);
float rotAngle = 0f;
Quaternion changeInRot = newQuat * Quaternion.Inverse(curQuat);
changeInRot.ToAngleAxis(out rotAngle, out rotAxis);
rotAngle *= redirectionIntensity;
Quaternion newRotation = Quaternion.AngleAxis(rotAngle, rotAxis);
camParent.transform.RotateAround(rig.cameraGameObject.transform.position, rotAxis, rotAngle * Time.deltaTime);
camTracker.transform.RotateAround(rig.cameraGameObject.transform.position, rotAxis, rotAngle * Time.deltaTime);
initRotation = camTracker.transform.rotation;
Hello, i have the same issue.. have you finally found the proper way of doing this?
Answer by XpctD · Mar 31, 2021 at 05:27 PM
Hi there @Trqncescqpe . No, I ended up using an acceleration instead of a direct amplification of the movement. Essentially, I measured the distance over several frames and integrated to get a speed. Then I used this variable to scale the rotation. This stops the skew or at least makes it possible to fix by making fast rotations. Here is the acceleration version:
void ApplyRedirection(Vector3 newOrientation, Vector3 curOrientation)
{
float changeInPitch = newOrientation.x - curOrientation.x;
if (changeInPitch > 200)
{
changeInPitch -= 360;
}
if (changeInPitch < -200)
{
changeInPitch += 360;
}
PitchChange = changeInPitch;
accelerationP = Mathf.Clamp(Mathf.Abs((angleChange[1, 0] + angleChange[1, 1] + angleChange[1, 2] + angleChange[1, 3] + angleChange[1, 4]) / 25 * redirectionIntensityP), 0, redirectionIntensityP);
camOffset.transform.RotateAround(currentHeadPosition, new Vector3(0, currentHeadOrientation.y, 0), changeInPitch * accelerationP * Time.fixedDeltaTime);
float changeInYaw = newOrientation.y - curOrientation.y;
if (changeInYaw > 200)
{
changeInYaw -= 360;
}
if (changeInYaw < -200)
{
changeInYaw += 360;
}
YawChange = changeInYaw;
accelerationY = Mathf.Clamp(Mathf.Abs((angleChange[0, 0] + angleChange[0, 1] + angleChange[0, 2] + angleChange[0, 3] + angleChange[0, 4]) / 25 * redirectionIntensityY), 0 , redirectionIntensityY);
camOffset.transform.RotateAround(currentHeadPosition, new Vector3(0, currentHeadOrientation.y, 0), changeInYaw * accelerationY * Time.fixedDeltaTime); //Do yaw reditection (horizontal)
updateAngles(changeInYaw, changeInPitch);
currentHeadOrientation = newOrientation;
}
Answer by Trqncescqpe · Mar 31, 2021 at 05:34 PM
Thanks for the code.. that I absolutely not understand haha. I spoke with some folks and increasing the rotation could increase the motion sickness so what I will do is controlling the rotation with the controller axis instead. Thanks for the help
Your answer
Follow this Question
Related Questions
How to write a script to disable position and rotation tracking for VR 0 Answers
Object snapping to floor and other objects in VR 1 Answer
Getting the rotation around the vector3.up. 1 Answer
Rotate object based on rotation of SteamVR Controller? 2 Answers
Set a rotation relative to position between two objects. 0 Answers