Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Something I don't understand about smoothed rotations?

Discussion in 'Physics for ECS' started by PhilSA, Jan 1, 2021.

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I need to calculate the rotation delta of a smoothed/interpolated transform from frame to frame, so that I can make another object rotate by exactly the same amount every frame. I calculate this rotation delta like this in a system that updates after TransformSystemGroup:

    Code (CSharp):
    1. [GenerateAuthoringComponent]
    2. public struct TestRotationCopier : IComponentData
    3. {
    4.     public Entity Target;
    5.     public LocalToWorld PreviousLocalToWorld;
    6. }
    7.  
    8. [UpdateAfter(typeof(TransformSystemGroup))]
    9. public class CopyRotationDeltaFromInterpolationSystem : SystemBase
    10. {
    11.     protected override void OnUpdate()
    12.     {
    13.         Entities.ForEach((Entity entity, ref TestRotationCopier rotationCopier) =>
    14.         {
    15.             // Calculate rotation delta of target
    16.             LocalToWorld targetLocalToWorld = GetComponent<LocalToWorld>(rotationCopier.Target);
    17.             quaternion targetRotationDelta = math.mul(math.inverse(rotationCopier.PreviousLocalToWorld.Rotation), targetLocalToWorld.Rotation);
    18.  
    19.             // Apply rotation delta to self
    20.             LocalToWorld selfLocalToWorld = GetComponent<LocalToWorld>(entity);
    21.             selfLocalToWorld.Value = new float4x4(math.mul(targetRotationDelta, selfLocalToWorld.Rotation), selfLocalToWorld.Position);
    22.             SetComponent(entity, selfLocalToWorld);
    23.  
    24.             // Remember previous LtW
    25.             rotationCopier.PreviousLocalToWorld = targetLocalToWorld;
    26.         }).Schedule();
    27.     }
    28. }
    Now here's the problem: my other object that's supposed to rotate by the same amount as the tracked object rotates slightly faster, and also rotates by a huge rotation every now and then. For example, here the camera tries to track the rotation of the orange platform: https://i.gyazo.com/53cb69c19b435a952ae7fa72a45acbcd.mp4

    What's weird is that if instead of using the LocalToWorld.Rotation, I just use the Rotation (from the actual transform), the issue disappears completely (but there's another issue because now my camera rotation isn't properly interpolated anymore, which means this causes visual jitter of the platform): https://i.gyazo.com/106d9e5a5a56c4aec062d4c747ca9bb5.mp4
     
    Last edited: Jan 1, 2021
  2. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Update:
    I found out that scale has something to do with it. If the object that I'm trying to track the rotation of has a scale of (1,1,1), the problem disappears

    I'm guessing this has nothing to do with physics graphics smoothing, but just with me not knowing the particularities of getting LocalToWorld.Rotation when there are non-unit scales? This thread seems to mention that issue as well

    In the meantime, I've worked around the issue by getting the rotation like this instead:
    Code (CSharp):
    1. quaternion.LookRotationSafe(targetLocalToWorld.Forward, targetLocalToWorld.Up);
     
    Last edited: Jan 1, 2021
  3. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Hi @PhilSA,

    That's correct, you should use quaternion.LookRotationSafe or Unity.Physics.Math.DecomposeRigidBodyOrientation to get actual rotation. We're doing the same thing in CreateRigidBodies job in BuildPhysicsWorld.
    Scale is multiplied with rotation matrix in LocalToWorld, to spare 1 matrix multiplication as you usually need to multiply with rotation and scale.

    Hoping this clarifies things, please let us know if there's anything else to help with.