Example #1
0
            public void Execute(int i)
            {
                MotionData     motionData     = MotionDatas[i];
                MotionVelocity motionVelocity = MotionVelocities[i];

                // Update motion space
                {
                    // center of mass
                    motionData.WorldFromMotion.pos += motionVelocity.LinearVelocity * Timestep;

                    // orientation
                    IntegrateOrientation(ref motionData.WorldFromMotion.rot, motionVelocity.AngularVelocity, Timestep);
                }

                // Update velocities
                {
                    // damping
                    motionVelocity.LinearVelocity  *= math.clamp(1.0f - motionData.LinearDamping * Timestep, 0.0f, 1.0f);
                    motionVelocity.AngularVelocity *= math.clamp(1.0f - motionData.AngularDamping * Timestep, 0.0f, 1.0f);
                }

                // Write back
                MotionDatas[i]      = motionData;
                MotionVelocities[i] = motionVelocity;
            }
Example #2
0
            internal static void ExecuteImpl(int i, NativeArray <MotionData> motionDatas, NativeArray <MotionVelocity> motionVelocities, float timeStep)
            {
                MotionData     motionData     = motionDatas[i];
                MotionVelocity motionVelocity = motionVelocities[i];

                // Update motion space
                {
                    // center of mass
                    motionData.WorldFromMotion.pos += motionVelocity.LinearVelocity * timeStep;

                    // orientation
                    IntegrateOrientation(ref motionData.WorldFromMotion.rot, motionVelocity.AngularVelocity, timeStep);
                }

                // Update velocities
                {
                    // damping
                    motionVelocity.LinearVelocity  *= math.clamp(1.0f - motionData.LinearDamping * timeStep, 0.0f, 1.0f);
                    motionVelocity.AngularVelocity *= math.clamp(1.0f - motionData.AngularDamping * timeStep, 0.0f, 1.0f);
                }

                // Write back
                motionDatas[i]      = motionData;
                motionVelocities[i] = motionVelocity;
            }
        // Build the Jacobian
        public void Build(
            MTransform aFromConstraint, MTransform bFromConstraint,
            MotionVelocity velocityA, MotionVelocity velocityB,
            MotionData motionA, MotionData motionB,
            Constraint constraint, float tau, float damping)
        {
            this = default(AngularLimit2DJacobian);

            // Copy the constraint data
            int freeIndex = constraint.FreeAxis2D;

            AxisAinA = aFromConstraint.Rotation[freeIndex];
            AxisBinB = bFromConstraint.Rotation[freeIndex];
            MinAngle = constraint.Min;
            MaxAngle = constraint.Max;
            Tau      = tau;
            Damping  = damping;
            BFromA   = math.mul(math.inverse(motionB.WorldFromMotion.rot), motionA.WorldFromMotion.rot);

            // Calculate the initial error
            {
                float3 axisAinB = math.mul(BFromA, AxisAinA);
                float  sinAngle = math.length(math.cross(axisAinB, AxisBinB));
                float  cosAngle = math.dot(axisAinB, AxisBinB);
                float  angle    = math.atan2(sinAngle, cosAngle);
                InitialError = JacobianUtilities.CalculateError(angle, MinAngle, MaxAngle);
            }
        }
        // Build the Jacobian
        public void Build(
            MTransform aFromConstraint, MTransform bFromConstraint,
            MotionVelocity velocityA, MotionVelocity velocityB,
            MotionData motionA, MotionData motionB,
            Constraint constraint, float tau, float damping)
        {
            this = default(LinearLimitJacobian);

            WorldFromA = motionA.WorldFromMotion;
            WorldFromB = motionB.WorldFromMotion;

            PivotAinA = aFromConstraint.Translation;
            PivotBinB = bFromConstraint.Translation;

            AxisInB = float3.zero;
            Is1D    = false;

            MinDistance = constraint.Min;
            MaxDistance = constraint.Max;

            Tau     = tau;
            Damping = damping;

            // TODO.ma - this code is not always correct in its choice of pivotB.
            // The constraint model is asymmetrical.  B is the master, and the constraint feature is defined in B-space as a region affixed to body B.
            // For example, we can conceive of a 1D constraint as a plane attached to body B through constraint.PivotB, and constraint.PivotA is constrained to that plane.
            // A 2D constraint is a line attached to body B.  A 3D constraint is a point.
            // So, while we always apply an impulse to body A at pivotA, we apply the impulse to body B somewhere on the constraint region.
            // This code chooses that point by projecting pivotA onto the point, line or plane, which seems pretty reasonable and also analogous to how contact constraints work.
            // However, if the limits are nonzero, then the region is not a point, line or plane.  It is a spherical shell, cylindrical shell, or the space between two parallel planes.
            // In that case, it is not projecting A to a point on the constraint region.  This will not prevent solving the constraint, but the solution may not look correct.
            // For now I am leaving it because it is not important to get the most common constraint situations working.  If you use a ball and socket, or a prismatic constraint with a
            // static master body, or a stiff spring, then there's no problem.  However, I think it should eventually be fixed.  The min and max limits have different projections, so
            // probably the best solution is to make two jacobians whenever min != max.  My assumption is that 99% of these are ball and sockets with min = max = 0, so I would rather have
            // some waste in the min != max case than generalize this code to deal with different pivots and effective masses depending on which limit is hit.

            if (!math.all(constraint.ConstrainedAxes))
            {
                Is1D = constraint.ConstrainedAxes.x ^ constraint.ConstrainedAxes.y ^ constraint.ConstrainedAxes.z;

                // Project pivot A onto the line or plane in B that it is attached to
                RigidTransform bFromA    = math.mul(math.inverse(WorldFromB), WorldFromA);
                float3         pivotAinB = math.transform(bFromA, PivotAinA);
                float3         diff      = pivotAinB - PivotBinB;
                for (int i = 0; i < 3; i++)
                {
                    float3 column = bFromConstraint.Rotation[i];
                    AxisInB = math.select(column, AxisInB, Is1D ^ constraint.ConstrainedAxes[i]);

                    float3 dot = math.select(math.dot(column, diff), 0.0f, constraint.ConstrainedAxes[i]);
                    PivotBinB += column * dot;
                }
            }

            // Calculate the current error
            InitialError = CalculateError(
                new MTransform(WorldFromA.rot, WorldFromA.pos),
                new MTransform(WorldFromB.rot, WorldFromB.pos),
                out float3 directionUnused);
        }
Example #5
0
            public void Execute(int i)
            {
                MotionData     motionData     = MotionDatas[i];
                MotionVelocity motionVelocity = MotionVelocities[i];

                // Apply gravity
                motionVelocity.LinearVelocity += GravityAcceleration * motionData.GravityFactor;

                // Write back
                MotionVelocities[i] = motionVelocity;

                // Make a copy
                InputVelocities[i] = new Velocity
                {
                    Linear  = motionVelocity.LinearVelocity,
                    Angular = motionVelocity.AngularVelocity
                };
            }
Example #6
0
        // Build the Jacobian
        public void Build(
            MTransform aFromConstraint, MTransform bFromConstraint,
            MotionVelocity velocityA, MotionVelocity velocityB,
            MotionData motionA, MotionData motionB,
            Constraint constraint, float tau, float damping)
        {
            BFromA    = math.mul(math.inverse(motionB.WorldFromMotion.rot), motionA.WorldFromMotion.rot);
            RefBFromA = new quaternion(math.mul(bFromConstraint.Rotation, aFromConstraint.InverseRotation));
            MinAngle  = constraint.Min;
            MaxAngle  = constraint.Max;
            Tau       = tau;
            Damping   = damping;

            quaternion jointOrientation = math.mul(math.inverse(RefBFromA), BFromA);
            float      initialAngle     = math.asin(math.length(jointOrientation.value.xyz)) * 2.0f;

            InitialError = JacobianUtilities.CalculateError(initialAngle, MinAngle, MaxAngle);
        }
Example #7
0
            internal static void ExecuteImpl(int i, float3 gravityAcceleration,
                                             NativeSlice <MotionData> motionDatas, NativeSlice <MotionVelocity> motionVelocities, NativeSlice <Velocity> inputVelocities)
            {
                MotionData     motionData     = motionDatas[i];
                MotionVelocity motionVelocity = motionVelocities[i];

                // Apply gravity
                motionVelocity.LinearVelocity += gravityAcceleration * motionData.GravityFactor;

                // Write back
                motionVelocities[i] = motionVelocity;

                // Make a copy
                inputVelocities[i] = new Velocity
                {
                    Linear  = motionVelocity.LinearVelocity,
                    Angular = motionVelocity.AngularVelocity
                };
            }
Example #8
0
        // Build the Jacobian
        public void Build(
            MTransform aFromConstraint, MTransform bFromConstraint,
            MotionVelocity velocityA, MotionVelocity velocityB,
            MotionData motionA, MotionData motionB,
            Constraint constraint, float tau, float damping)
        {
            // Copy the constraint into the jacobian
            AxisIndex        = constraint.ConstrainedAxis1D;
            AxisInMotionA    = aFromConstraint.Rotation[AxisIndex];
            MinAngle         = constraint.Min;
            MaxAngle         = constraint.Max;
            Tau              = tau;
            Damping          = damping;
            MotionBFromA     = math.mul(math.inverse(motionB.WorldFromMotion.rot), motionA.WorldFromMotion.rot);
            MotionAFromJoint = new quaternion(aFromConstraint.Rotation);
            MotionBFromJoint = new quaternion(bFromConstraint.Rotation);

            // Calculate the current error
            InitialError = CalculateError(MotionBFromA);
        }
Example #9
0
        // Build the Jacobian
        public void Build(
            MTransform aFromConstraint, MTransform bFromConstraint,
            MotionVelocity velocityA, MotionVelocity velocityB,
            MotionData motionA, MotionData motionB,
            Constraint constraint, float tau, float damping)
        {
            this = default(AngularLimit3DJacobian);

            BFromA           = math.mul(math.inverse(motionB.WorldFromMotion.rot), motionA.WorldFromMotion.rot);
            MotionAFromJoint = new quaternion(aFromConstraint.Rotation);
            MotionBFromJoint = new quaternion(bFromConstraint.Rotation);
            MinAngle         = constraint.Min;
            MaxAngle         = constraint.Max;
            Tau     = tau;
            Damping = damping;

            float initialAngle = math.atan2(math.length(BFromA.value.xyz), BFromA.value.w) * 2.0f;

            InitialError = JacobianUtilities.CalculateError(initialAngle, MinAngle, MaxAngle);
        }
Example #10
0
 // Gets a body's motion, even if the body is static
 // TODO - share code with Solver.GetMotions()?
 private static void GetMotion(ref PhysicsWorld world, int bodyIndex, out MotionVelocity velocity, out MotionData motion)
 {
     if (bodyIndex >= world.MotionVelocities.Length)
     {
         // Body is static
         RigidBody body = world.Bodies[bodyIndex];
         velocity = MotionVelocity.Zero;
         motion   = new MotionData
         {
             WorldFromMotion = body.WorldFromBody,
             BodyFromMotion  = RigidTransform.identity
                               // remaining fields all zero
         };
     }
     else
     {
         // Body is dynamic
         velocity = world.MotionVelocities[bodyIndex];
         motion   = world.MotionDatas[bodyIndex];
     }
 }