How to rotate float3 using Entity Rotation?

Solved by math.mul(quaternionA, vectorA). math.rotate(quaternionA, vectorA) produce similar results.

The important thing I did wrong was using LocalToWorld.Rotation Component, you should get the Entity Rotation quaternion with Rotation.Value Component.

I found this paper incredibly useful finally understanding use of matrix multiplication and quarternion multiplication to rotate vectors and existing rotations. He takes in Appendix C and D some swipes at the gaming/graphics community having some severe misunderstandings about gimbal lock :), but still very good explanations about Euler angels and quaternions.

To rotate vectorA by a quaternionA:math.mul(vectorA, quaternionA)

To rotate quaternionA by quaternionB:

math.mul(quaternionA, quaternionB)

To construct a quaternion from scratch: Tons of functions in math library such as quaternion.AxisAngle , quaternion.Euler etc.

1 Like

While you have math.functions, if you type quaternion, you will find many quaternion.functions on there too. You will need to use (pseudo code) entity.rotation = quaternion.LookRotation(target.position - entity.position, new float3(0,1,0)). Where LookRotation(direction, up vector)

1 Like

Thank you for your replies~

Later I will check the article again, but for now I see that I can use the formula (3.7) and the examples on pages 9, 22.
But that is if I will be unable to use Unity math functions…

I did try math.mul(quaternionA, vectorA), the result in monkey-example:
8578441--1149055--upload_2022-11-11_11-16-40.jpg
The white line indicating the float3 vector (in this example case new float3(0, 0, 1)) direction should point the same direction monkey is facing (monkey is facing z direction initially, like vector). It is true only for the first, not rotated monkey, where quaternion is zero (0,0,0,1).
If I try to change it to math.mul(vectorA, quaternionA), I have an error about converting “Unity.Mathematics.float3” to “float” and “Unity.Mathematics.quaternion” to “float”, so the order should be math.mul(quaternionA, vectorA). I do understand that the order matters, but math.mul does not let you experiment with it (:

I believe you are talking about making one Entity face another. That is an interesting task too, but not my case, I need to rotate existing float3 vector with values on the same amount Entity was rotated.

Maybe I am getting the wrong quaternion or use it not like intended… I am getting localToWorld.Rotation from Entity.

I have compared the quaternion values I get as localToWorld.Rotation, and these are different from the ones found in Entities Hierarchy Inspector Rotation and not the ones I need (I dunno, what are these…).

So the rotation I need is in Entity Rotation Component: Rotation.Value. I guess I will stop using localToWorld.Position too and change it to Translation Component…

Local to world is global rotation and position.
Translation and Rotation components are local to parent.

I haven’t really seen it talked about but 1.0 added a UniformScaleTransform type. This is what the new transform system v2 is built on, but you can still use the type if you’re on transform v1 still. It can be constructed from a LocalToWorld or LocalToParent matrix (or from TRS) and then gives you lots of functions to transform vectors or quaternions relative to the transform space without having to do matrix or quaternion multiplications yourself. Its similar to UnityEngine.Transform in what is provides.

Here is a quick example of getting the world direction that an entity is facing:

LocalToWorld ltw; //...
var ltwTransform = UniformScaleTransform.FromMatrix(ltw.Value);
var entityForward = ltwTransform.TransformDirection(math.forward());

My prefabs/instances have EmptyObject in EntityScene as parent, obviously it has no rotation or whatsoever.
Did not expect it to affect anything… I dunno if localToWorld.Rotation would’ve been more appropriate if the Instances had no parent, or is it just some part of float4x4 matrix I do not understand (:
localToWorld.Position and Translation.Value seem to be the same, unlike localToWorld.Rotation and Rotation.Value.

Anyway, Transform Aspect seems to be doing anything I need for the moment, it is more convenient to deal with it, than with LocalToWorld or LocalToParent…

Is the parent or object scaled by any chance? There is a bug with LocalToWorld.Rotation for scaled entities. Still broken in 1.0 from what I can tell: https://discussions.unity.com/t/788891

Here is a fixed version as an extension method on LocalToWorld:

public static quaternion Rotation(this LocalToWorld ltw) =>
        quaternion.LookRotationSafe(ltw.Forward, ltw.Up);
1 Like

Yes, the Prefab is scaled. Seems like you did pinpoint the issue.