# 3D rotation in 3 components

I think this ought to be relatively simple but I just cant get my head around it.
I want to control the rotation of my spaceship object by using rigidbody.AddRelativeTorque to accelerate/decelerate the rotation in an attempt to reach a desired facing. The idea being to give different ships different manouverability by specifying 3 maximum torque levels relative to the local axes (i.e. pitch, roll and yaw).
I don’t want to set the rotation directly so that I can have the ship knocked about by collisions using the physics system.

I’m having trouble figuring out the amount of torque to apply at any given frame to keep the ship moving towards the desired rotation. My current thinking is along the lines of;

``````		Vector3 IdealForward;
Vector3 IdealForwardOnYawPlane = (IdealForward - Vector3.Project(IdealForward, transform.up)).normalized;
float AngleA = Mathf.Acos(Vector3.Dot(IdealForward,IdealForwardOnYawPlane);

Vector3 IdealForwardOnPitchPlane = (IdealForward - Vector3.Project(IdealForward, transform.right)).normalized;
float AngleB = Mathf.Acos(Vector3.Dot(IdealForward,IdealForwardOnPitchPlane);
``````

…should give me AngleA and AngleB as the yaw and pitch required to reach the IdealForward.
however I dont have the current angularvelocity in terms of yaw pitch and roll so I cant figure out when to start decelerating so I don’t overshoot. I’m not even convinced I’m approaching the problem from the right way.

Surely this cant be an unusual problem? It seems like it should be pretty fundamental to any 3D game. Can anyone point me at a sample code or a project that handles the same sort of 3D manouvering? Or have I unwittingly hit some classic unsolvable problem that anyone with more experience than me would have never started?

Any help is appreciated. I’m still at a very early stage in getting my project up and running and my brain is too overloaded to cope.

Just came across my own old question and figured I’d post the solution I eventually came up with.
The trick is to realise that the final answer is the sum of three other torque Vectors

Start with the torque required to stop the current rotation instantly. That’s component 1.
Calculate how long it would take your ship to come to rest if we used a MaxTorque value which would be a variable that dictates the ships manouverability.
Calculate what the ships facing and up vectors would be when the ship stopped.
Then calculate the torque required to get from that Facing and Up to the targetfacing and targetup. Those are your components 2 and 3
Limit the overall magnitude to the ships MaxTorque and apply it to the rigidbody.

I’m not sure I’d say it works perfectly, but it does the job. Hope its of use to someone.

``````public Vector3 TargetForward;
public Vector3 TargetUp;
public float MaxTorque = 1;

void FixedUpdate()
{
Vector3 BrakingTorque = -1 * rigidbody.angularVelocity;

float SecondsToComeToRestAtMaxBraking = rigidbody.angularVelocity.magnitude / MaxTorque;
Vector3 RotationWhileBraking = (rigidbody.angularVelocity  / 2) * SecondsToComeToRestAtMaxBraking * Mathf.Rad2Deg;
Vector3 FacingWhenAtRest = Quaternion.Euler(RotationWhileBraking) * transform.forward;
Vector3 UpWhenAtRest = Quaternion.Euler(RotationWhileBraking) * transform.up;

Vector3 OtherTorqueVector = Vector3.Cross(FacingWhenAtRest, TargetForward);
float AngleBetweenRestAndTarget = Vector3.Angle(FacingWhenAtRest, TargetForward);

Vector3 TorqueToTarget = OtherTorqueVector * AngleBetweenRestAndTarget * Mathf.Deg2Rad;

Vector3 OtherTorqueVector2 = Vector3.Cross(UpWhenAtRest, TargetUp);
float AngleBetweenRestAndTarget2 = Vector3.Angle(UpWhenAtRest, TargetUp);

Vector3 TorqueToTarget2 = OtherTorqueVector2 * AngleBetweenRestAndTarget2 * Mathf.Deg2Rad;

//TODO: limit combined torque by axis rather than as overall value
Vector3 CombinedTorque = BrakingTorque + TorqueToTarget + TorqueToTarget2;
if (CombinedTorque.magnitude > MaxTorque) CombinedTorque = CombinedTorque.normalized * MaxTorque;