Search Unity

Angular spring behaviour with dots physics without joint

Discussion in 'Physics for ECS' started by Pronotron, Apr 15, 2021.

  1. Pronotron

    Pronotron

    Joined:
    Aug 27, 2018
    Posts:
    7
    Hello! I'm trying to create spring behaviour with dots physics.

    Code (CSharp):
    1.                
    2.    var impulse = strength * (initialPos - currentPos) + damping *  -linearVel;
    3.    impulse = math.clamp(impulse, new float3(-50.0f), new float3(50.0f));
    4.  
    5.    velocityComponent.ApplyLinearImpulse(pm, impulse);
    6.    SetComponent(entity, velocityComponent);
    7.  
    With the code above, I can do linear springing. But how should I do so that the rotation also springs to the initial rotation?

    And a request to dot physics developers: Please add summaries in mathematics and physics libraries, for those who are not that good at these.
     
  2. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Thanks for the feedback, we'll try to do better method documentation in future.

    It's slightly trickier for angular movement, since you should first decide whether you want to control angular velocity in world space (around world xyz axis) or body space (around body's intertia axis). Then, you can use Get/SetAngularVelocityWorldSpace or ApplyAngularImpulse.

    Please let me know if you need further help on this.
     
  3. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    The code for a linear dashpot is pretty much the same for an angular dashpot. Instead of (initialPos-currentPos) you need to get the axis from a quaternion made from
    math.mul(initialRot, math.inverse(currentRot))
    .

    You might want to add the following to the Unity.Physics.Math static class:
    Code (CSharp):
    1.         public static void ToAxisAngle(this quaternion q, out float3 axis, out float angle)
    2.         {
    3.             if (q.value.w > 1) math.normalize(q);
    4.             var qf = q.value;
    5.             angle = 2 * math.acos(qf.w);
    6.             float s = math.sqrt(1 - qf.w * qf.w);
    7.             axis.x = qf.x;
    8.             axis.y = qf.y;
    9.             axis.z = qf.z;
    10.             if (s > Math.Constants.UnityEpsilon)
    11.             {
    12.                 axis.x = qf.x / s;
    13.                 axis.y = qf.y / s;
    14.                 axis.z = qf.z / s;
    15.             }
    16.         }
    You might also want an ApplyAngularImpulse that takes a worldspace impulse:
    Code (CSharp):
    1.         public static void ApplyAngularImpulse(ref this PhysicsVelocity pv, in PhysicsMass pm, in Rotation r, in float3 impulseWS)
    2.         {
    3.             float3 impulseLS = math.rotate(math.inverse(r.Value), impulseWS);
    4.             pv.ApplyAngularImpulse(pm, impulseLS);
    5.         }
    Alternatively you could just use all the Joints that are part of the SDK rather than having to roll your own (especially with Dashpots that can be very temperamental). You can roll your own Joint with a BallAndSocket and a FixedAngle Constraint, created with custom Spring Frequency and Damping similar to the SoftJointDemo test.