Getting actor rotation around a specific axis?

I have an actor that is moving in the world while spinning on it’s local Z axis(while starting off tilted on it’s X and Y axis), which cause it’s X and Y values to fluctuate wildly negative and positive. I need to get its X rotation along its direction of travel. I have the actors Physics velocity using:

StaticMeshComponent->GetPhysicsLinearVelocity().ToOrientationQuat();

I need to get the X angle(Preferably Euler or radians) relative to that being the forward vector, but I feel like I’m banging my head against the wall. I have tried using RotateVector and UnrotateVector with the objects rotation, but that doesn’t seem to be getting me anywhere. I’m not sure I’m even looking at this the right way. Anyone point me in the right direction?

Thanks!

Hi. Maybe you can use functionality of RotationComponent? Look at PivotTranslation. Here is similar question Rotating component around custom point. Does this fit?

To be frank, I don’t really understand the question but…

There is a simple way to get the angle between any 2 vectors:

Angle = Acos(DotProduct(V1,V2)/(V1.Size()*V2.Size()))

If both V1 and V2 are normalized ( V1.Size() = V2.Size() = 1.0f ) the angle simplifies to:

Angle = Acos(DotProduct(V1,V2))

Don’t be afraid of angles fluctuating. Angle values always flip their sign at the end of the circle the same way you go from 0 to 180 degrees then flip to -180 and back to 0.

Be careful of what Acos() returns (degrees or radians).

Thank for the response! That was what I needed, with a little modifying. Here is what I used:

FVector v1 = StaticMeshComp->GetPhysicsLinearVelocity().ToOrientationQuat().GetUpVector();
FVector v2 = ActorQuat.GetUpVector();

v2.X = v1.X;
v1.Normalize();
v2.Normalize();
			
float Angle = FMath::Acos(FVector::DotProduct(v1, v2));

I want to ignore one of the angles, the pitch, I want to find the roll angle. So I’m a little confused why this works, ■■■ it looks like i’m setting the roll to be equal to each other. I initially tried

v2.Y = v1.Y;

But that seemed to be equalizing the roll and what I have above works, verified with debug lines.

So that gives me size of the angle, now I need to find whether it is clockwise/counterclockwise from center, on an object that can travel in any direction. Before I start throwing ideas at visual studio, is there any easy way to get that info?

Wait that doesnt work upon further testing. When I look straight along the x axis it works but when i look down the y axis it does not, it is finging the world x axis difference.

Thanks for the reply! It seemed to deleted have my first response, so this has no context. The Acos got me started in the right direction, what I have is:

FVector v1 = StaticMeshComp->GetPhysicsLinearVelocity().ToOrientationQuat().GetUpVector();
FVector v2= myActorQuat.GetUpVector();

v2.X = v1.X;
v1.Normalize();
v2.Normalize();
			
float Angle = FMath::Acos(FVector::DotProduct(v1, v2));

I am equalizing the x values to cancel out the pitch, I initially thought I would need to equalize the Y values but apparently not.

So that seems to get me the difference in roll on the world scale, but I need the local difference in roll, with the X axis pointed down the velocity vector. My first thought is using the Velocity Quat to rotate the actors rotation vector, but that doesn’t seem to be working.

The angle between 2 vectors does not depend on the reference frame and does not depend on the scale or length of the vectors so you are making a mistake when you modify the X components. The fact that it returns a angle close to world YZ plane angle is pure coincidence. To get the local angle (the angle in myActor) you must get the velocity vector in myActor’s coordinate system.

Try this: (I have not tested it but it should work after you fix all punctuation errors)

FVector v1 = StaticMeshComp->GetPhysicsLinearVelocity(); //Get the velocity
FTransform LocalTransform = myActor.GetTransform(); //Get the actor transform
v1 = LocalTransform.TransformVector(v1); //v1 is now in local coordinates
v1.X = 0;	//Project it in YZ plane
FQuat VelocityQuat = FQuat::FindBetweenVectors(v1, FVector::RightVector); //Find the quaternion between the velocity(in local coordinates) and the RightVector = (0.0, 1.0, 0.0)
//From this point on you can get the Angle if you need it with
float Angle = VelocityQuat.GetAngle;

Be careful what transformations you do to the vectors as this will define what angle you get.

1 Like