Hi, I’ve been looking over the internet, but I found no good answer. How does this node works? I would appreciate if someone explain this to me like for dummie
This works by using vectors as directions to point each axis towards. Although I’m unsure the priority order.
The more obvious nodes are “make rotation from xy” Which points the rotations nose (the x axis) into the same direction as x, then twists it around until the right side is as close as it can get to matching the y axis.
I assume that, under the hood, ue4 is putting the vectors together into a normalized quaternion, then converting the quaternion to Euler.
It creates a rotation from 3 given directions → picture it like creating a new coordinate system from 3 different directions.
For example think you could output the default rotation ( roll = 0, pitch = 0, yaw = 0 ) with the following unit vectors:
- Forward (1,0,0)
- Right (0,1,0)
- Up (0,0,1)
You would perhaps expect this to perform orthonormalization, but it doesn’t!
(If you want more on this, google “3d matrix orthonormalization” and you’ll find some good resources.)
The specific implementation of “Make Rotation from Axes” can luckily be found in the C++ source code, which you can check out from GitHub. Check out UKismetMathLibrary::MakeRotationFromAxes()
:
Forward.Normalize();
Right.Normalize();
Up.Normalize();
FMatrix RotMatrix(Forward, Right, Up, FVector::ZeroVector);
return RotMatrix.Rotator();
The constructor for FMatrix
does not orthonormalize the matrix; it just stuffs the vector values into the basis vector elements.
Instead, the Rotator it returns, turns the values of the axes into a rotator using ATan2()
. (This is one reason you might want to avoid FRotator
and use FQuat
where possible, btw.)
const FVector XAxis = GetScaledAxis( EAxis::X );
const FVector YAxis = GetScaledAxis( EAxis::Y );
const FVector ZAxis = GetScaledAxis( EAxis::Z );
FRotator Rotator = FRotator(
FMath::Atan2( XAxis.Z, FMath::Sqrt(FMath::Square(XAxis.X)+FMath::Square(XAxis.Y)) ) * 180.f / PI,
FMath::Atan2( XAxis.Y, XAxis.X ) * 180.f / PI,
0
);
const FVector SYAxis = FRotationMatrix( Rotator ).GetScaledAxis( EAxis::Y );
Rotator.Roll = FMath::Atan2( ZAxis | SYAxis, YAxis | SYAxis ) * 180.f / PI;
GetScaledAxis()
is named like that, so that you remember that the scale is part of the return value, if there’s scale in the matrix. Because the axes are normalized when constructing, they’ll be unit length in this case, but ATan2()
is scale independent anyway, so in this case it’s all just semantic markup that falls away when the code runs.
Why assume, when the code is right there?
Btw, while sharing large parts of the Unreal Engine source code in a public forum is against the GitHub access rules, sharing small snippets that help illustrate and help the engine is totally fine – especially when, what Unreal Engine does, is straight textbook stuff like this, and the only question we really need to answer is “which of the many textbooks, and which page of that book?”
The good thing with standards is that there’s so many to choose from …
Thanks for the answer. I’ve played a little with this function, and I think I get how “forward” vector works. But I have a problem with understanding “right” vector and “up” vector. It seems it depends on “forward” vector values, but I don’t exaclty understand how it works. I’ve noticed that, both “right” and “up” vector are rotating the actor around “forward” vector, but how these 6 floats(3 from “up” vector and 3 from “right”) depend on each other? I’ve also noticed that when I set “right” vector to something else than 0, when “up” vector is set to something else than 0, then when I’m changing “forward” vector the actor starts to rotate around its own axis
This is an honest question, because I don’t understand how to answer better than the code that literally does the math.
What part of the code that calls Atan2()
is unclear? Those are the bits that derive the rotation values.
Is it the axis mapping? Unreal uses left handed conventions, with “Forward == X,” “Right == Y” and “Up == Z.”