Пример #1
0
        /// <summary>
        /// Get the position so that the object does not collide with the object anymore.
        /// Important: this is used raycasting checks, as this needs some more corner-cases.
        /// </summary>
        /// <param name="collider">The collider which is the player</param>
        /// <param name="collisionPoint">Point of the collision in the scene</param>
        /// <param name="hitNormal">Collision-normal of the object with which the player collided</param>
        /// <returns>Position which is possible for the collider so there is no collision.</returns>
        private JVector GetPosition(Collider collider, JVector collisionPoint, JVector hitNormal)
        {
            JVector    bbSize     = collider.BoundingBoxSize;
            GameObject gameObject = collider.GameObject;

            // Calculate the size of the forward and right vector based on the bounding-box.
            JVector forward = 0.5f * bbSize.Z * Conversion.ToJitterVector(gameObject.transform.Forward);
            JVector right   = 0.5f * bbSize.X * Conversion.ToJitterVector(gameObject.transform.Right);
            JVector d       = Conversion.ToJitterVector(gameObject.transform.Forward);

            if (hitNormal.IsZero())
            {
                return(bbSize.Z * -0.5f * Conversion.ToJitterVector(gameObject.transform.Forward));
            }

            // Correct directions
            TurnIntoDirectionOf(ref forward, hitNormal);
            TurnIntoDirectionOf(ref right, hitNormal);
            TurnIntoDirectionOf(ref d, hitNormal);

            // Calculate the projected length (half-length) of the player on the hit-normal.
            JVector lengthOnNormal = ProjectOn(forward, hitNormal);
            JVector widthOnNormal  = ProjectOn(right, hitNormal);
            JVector projectedSize  = lengthOnNormal + widthOnNormal;

            JVector margin      = ProjectOn(projectedSize, d);
            JVector endPosition = collisionPoint + margin;

            // Check if it hit a corner and it could actually go closer
            JVector plane = new JVector(-hitNormal.Z, 0, hitNormal.X);

            TurnIntoDirectionOf(ref plane, -1 * forward);
            plane.Normalize();

            // Check if there is an intersection between the front-"plane" of the player and the collided object
            JVector intersection;

            JVector frontMiddle = endPosition + forward;
            JVector frontRight  = endPosition + forward - right;
            JVector planeEnd    = collisionPoint + MathHelper.Max(bbSize.X, bbSize.Z) * plane;

            if (DoIntersect(frontMiddle, frontRight, collisionPoint, planeEnd, out intersection))
            {
                intersection.Y = collider.Position.Y;
                JVector colToIntersection = intersection - collisionPoint;

                JVector margin2 = ProjectOn(colToIntersection, d);

                margin      = margin.LengthSquared() > margin2.LengthSquared() ? margin2 : margin;
                endPosition = collisionPoint + margin;
            }

            //// Todo: Visual debuggin might be removed in the end
            //PhysicsDrawer.Instance.ClearPointsToDraw();
            //PhysicsDrawer.Instance.AddPointToDraw(Conversion.ToXnaVector(collisionPoint));
            //PhysicsDrawer.Instance.AddPointToDraw(Conversion.ToXnaVector(endPosition));

            //return collider.Position;
            return(endPosition);
        }
Пример #2
0
        public JVector CalcVelocity(float speed)
        {
            var state     = Keyboard.GetState(); // Does not implemented in .Net core version of OpenTK
            var direction = new JVector();

            if (state.IsKeyDown(Key.W) || state.IsKeyDown(Key.Up))
            {
                direction.Z -= 1;
            }

            if (state.IsKeyDown(Key.S) || state.IsKeyDown(Key.Down))
            {
                direction.Z += 1;
            }

            if (state.IsKeyDown(Key.A) || state.IsKeyDown(Key.Left))
            {
                direction.X -= 1;
            }

            if (state.IsKeyDown(Key.D) || state.IsKeyDown(Key.Right))
            {
                direction.X += 1;
            }

            if (direction != JVector.Zero)
            {
                return(JVector.Normalize(direction) * speed);
            }
            else
            {
                return(direction);
            }
        }
Пример #3
0
        /// <summary>
        /// SupportMapping. Finds the point in the shape furthest away from the given direction.
        /// Imagine a plane with a normal in the search direction. Now move the plane along the normal
        /// until the plane does not intersect the shape. The last intersection point is the result.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <param name="result">The result.</param>
        public override void SupportMapping(ref JVector direction, out JVector result)
        {
            JVector expandVector;

            JVector.Normalize(ref direction, out expandVector);
            JVector.Multiply(ref expandVector, sphericalExpansion, out expandVector);

            int   minIndex = 0;
            float min      = JVector.Dot(ref points[0], ref direction);
            float dot      = JVector.Dot(ref points[1], ref direction);

            if (dot > min)
            {
                min      = dot;
                minIndex = 1;
            }
            dot = JVector.Dot(ref points[2], ref direction);
            if (dot > min)
            {
                min      = dot;
                minIndex = 2;
            }

            JVector.Add(ref points[minIndex], ref expandVector, out result);
        }
Пример #4
0
        /// <summary>
        /// SupportMapping. Finds the point in the shape furthest away from the given direction.
        /// Imagine a plane with a normal in the search direction. Now move the plane along the normal
        /// until the plane does not intersect the shape. The last intersection point is the result.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <param name="result">The result.</param>
        public override void SupportMapping(ref JVector direction, out JVector result)
        {
            JVector exp;

            JVector.Normalize(ref direction, out exp);
            exp *= sphericalExpansion;

            float min      = JVector.Dot(ref vecs[0], ref direction);
            int   minIndex = 0;
            float dot      = JVector.Dot(ref vecs[1], ref direction);

            if (dot > min)
            {
                min      = dot;
                minIndex = 1;
            }
            dot = JVector.Dot(ref vecs[2], ref direction);
            if (dot > min)
            {
                min      = dot;
                minIndex = 2;
            }

            result = vecs[minIndex] + exp;
        }
Пример #5
0
        /// <summary>
        /// Normalizes the given vector.
        /// </summary>
        /// <param name="value">The vector which should be normalized.</param>
        /// <returns>A normalized vector.</returns>
        #region public static JVector Normalize(JVector value)
        public static JVector Normalize(JVector value)
        {
            JVector result;

            JVector.Normalize(ref value, out result);
            return(result);
        }
Пример #6
0
        /// <summary>
        /// Called once before iteration starts.
        /// </summary>
        /// <param name="timestep">The 5simulation timestep</param>
        public override void PrepareForIteration(float timestep)
        {
            JVector p1, dp;

            JVector.Transform(ref localAnchor1, ref body1.orientation, out r1);
            JVector.Add(ref body1.position, ref r1, out p1);

            JVector.Subtract(ref p1, ref anchor, out dp);
            float deltaLength = dp.Length();

            JVector n = anchor - p1;

            if (n.LengthSquared() != 0.0f)
            {
                n.Normalize();
            }

            jacobian[0] = -1.0f * n;
            jacobian[1] = -1.0f * (r1 % n);

            effectiveMass = body1.inverseMass + JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1];

            softnessOverDt = softness / timestep;
            effectiveMass += softnessOverDt;

            effectiveMass = 1.0f / effectiveMass;

            bias = deltaLength * biasFactor * (1.0f / timestep);

            if (!body1.isStatic)
            {
                body1.linearVelocity  += body1.inverseMass * accumulatedImpulse * jacobian[0];
                body1.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[1], body1.invInertiaWorld);
            }
        }
Пример #7
0
        /// <summary>
        /// SupportMapping. Finds the point in the shape furthest away from the given direction.
        /// Imagine a plane with a normal in the search direction. Now move the plane along the normal
        /// until the plane does not intersect the shape. The last intersection point is the result.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <param name="result">The result.</param>
        public override void SupportMapping(ref JVector direction, out JVector result)
        {
            result = direction;
            result.Normalize();

            JVector.Multiply(ref result, radius, out result);
        }
Пример #8
0
            public void SupportMapping(ref JVector direction, out JVector result)
            {
                float min = JVector.Dot(ref owner.points[indices.I0].position, ref direction);
                float dot = JVector.Dot(ref owner.points[indices.I1].position, ref direction);

                JVector minVertex = owner.points[indices.I0].position;

                if (dot > min)
                {
                    min       = dot;
                    minVertex = owner.points[indices.I1].position;
                }
                dot = JVector.Dot(ref owner.points[indices.I2].position, ref direction);
                if (dot > min)
                {
                    min       = dot;
                    minVertex = owner.points[indices.I2].position;
                }


                JVector exp;

                JVector.Normalize(ref direction, out exp);
                exp   *= owner.triangleExpansion;
                result = minVertex + exp;
            }
Пример #9
0
        public void HandleInput(GameTime gameTime)
        {
            currentTime += (float)gameTime.ElapsedGameTime.Milliseconds;

            KeyboardState keys = Keyboard.GetState();

            if (keys.IsKeyDown(Keys.Up))
            {
                float x = (float)Math.Sin(facing);
                float z = (float)Math.Cos(facing);

                JVector newPath = new JVector(x, 0f, z) * speed;
                newPath = newPath * currentTime;
                newPath.Normalize();

                forward = newPath;

                body.AddForce(newPath * 100f);
                //position = body.Position;
                //position += newPath;

                //body.Position = position;
            }

            if (keys.IsKeyDown(Keys.Left))
            {
                facing -= 0.05f;
            }

            if (keys.IsKeyDown(Keys.Right))
            {
                facing += 0.05f;
            }

            if (keys.IsKeyDown(Keys.Down))
            {
                float x = (float)Math.Sin(facing);
                float z = (float)Math.Cos(facing);

                JVector newPath = new JVector(x, 0f, z) * speed;
                newPath = newPath * currentTime;
                newPath.Normalize();

                body.AddForce(newPath * -100f);
            }

            if (keys.IsKeyDown(Keys.Space))
            {
                body.AddForce(JVector.Up * 100f);
            }

            /*if (keys.IsKeyDown(Keys.A))
             *
             * if (keys.IsKeyDown(Keys.S))
             *
             * if (keys.IsKeyDown(Keys.W))
             */
        }
Пример #10
0
        /// <summary>
        /// Initializes a contact.
        /// </summary>
        /// <param name="body1">The first body.</param>
        /// <param name="body2">The second body.</param>
        /// <param name="point1">The collision point in worldspace</param>
        /// <param name="point2">The collision point in worldspace</param>
        /// <param name="n">The normal pointing to body2.</param>
        /// <param name="penetration">The estimated penetration depth.</param>
        public void Initialize(RigidBody body1, RigidBody body2, ref JVector point1, ref JVector point2, ref JVector n,
                               float penetration, bool newContact, ContactSettings settings)
        {
            this.body1  = body1; this.body2 = body2;
            this.normal = n; normal.Normalize();
            this.p1     = point1; this.p2 = point2;

            this.newContact = newContact;

            JVector.Subtract(ref p1, ref body1.position, out relativePos1);
            JVector.Subtract(ref p2, ref body2.position, out relativePos2);
            JMatrix o1 = JMatrix.CreateRotationZ(body1.invOrientation);
            JMatrix o2 = JMatrix.CreateRotationZ(body2.invOrientation);

            JVector.Transform(ref relativePos1, ref o1, out realRelPos1);
            JVector.Transform(ref relativePos2, ref o2, out realRelPos2);

            this.initialPen  = penetration;
            this.penetration = penetration;

            body1IsMassPoint = body1.isParticle;
            body2IsMassPoint = body2.isParticle;

            // Material Properties
            if (newContact)
            {
                treatBody1AsStatic = body1.isStatic;
                treatBody2AsStatic = body2.isStatic;

                accumulatedNormalImpulse  = 0.0f;
                accumulatedTangentImpulse = 0.0f;

                lostSpeculativeBounce = 0.0f;

                switch (settings.MaterialCoefficientMixing)
                {
                case ContactSettings.MaterialCoefficientMixingType.TakeMaximum:
                    staticFriction  = JMath.Max(body1.material.staticFriction, body2.material.staticFriction);
                    dynamicFriction = JMath.Max(body1.material.kineticFriction, body2.material.kineticFriction);
                    restitution     = JMath.Max(body1.material.restitution, body2.material.restitution);
                    break;

                case ContactSettings.MaterialCoefficientMixingType.TakeMinimum:
                    staticFriction  = JMath.Min(body1.material.staticFriction, body2.material.staticFriction);
                    dynamicFriction = JMath.Min(body1.material.kineticFriction, body2.material.kineticFriction);
                    restitution     = JMath.Min(body1.material.restitution, body2.material.restitution);
                    break;

                case ContactSettings.MaterialCoefficientMixingType.UseAverage:
                    staticFriction  = (body1.material.staticFriction + body2.material.staticFriction) / 2.0f;
                    dynamicFriction = (body1.material.kineticFriction + body2.material.kineticFriction) / 2.0f;
                    restitution     = (body1.material.restitution + body2.material.restitution) / 2.0f;
                    break;
                }
            }
            this.settings = settings;
        }
Пример #11
0
        public Pax4ConstraintBodyVector(Pax4ObjectPhysicsPart p_physicsPart, float p_velocityFactor, Vector3 p_bodyVector)
            : base(p_physicsPart._body, null)
        {
            _velocityFactor = p_velocityFactor;

            _bodyVector = Pax4Tools.ToJVector(p_bodyVector);
            _bodyVector.Normalize();

            SetPhysicsPart(p_physicsPart);
        }
Пример #12
0
        public PointOnLine(RigidBody body1, RigidBody body2, JVector lineStartPointBody1, JVector pointBody2) : base(body1, body2)
        {
            JVector.Subtract(lineStartPointBody1, body1.position, out localAnchor1);
            JVector.Subtract(pointBody2, body2.position, out localAnchor2);

            JVector.Transform(localAnchor1, body1.invOrientation, out localAnchor1);
            JVector.Transform(localAnchor2, body2.invOrientation, out localAnchor2);

            lineNormal = JVector.Normalize(lineStartPointBody1 - pointBody2);
        }
Пример #13
0
        /// <summary>
        /// Called once before iteration starts.
        /// </summary>
        /// <param name="timestep">The simulation timestep</param>
        public override void PrepareForIteration(double timestep)
        {
            JVector.Transform(ref localAnchor1, ref body1.orientation, out r1);
            JVector.Transform(ref localAnchor2, ref body2.orientation, out r2);

            JVector p1, p2, dp;

            JVector.Add(ref body1.position, ref r1, out p1);
            JVector.Add(ref body2.position, ref r2, out p2);

            JVector.Subtract(ref p2, ref p1, out dp);

            JVector l = JVector.Transform(lineNormal, body1.orientation);

            l.Normalize();

            JVector t = (p1 - p2) % l;

            if (t.LengthSquared() != 0.0f)
            {
                t.Normalize();
            }
            t = t % l;

            jacobian[0] = t;                      // linearVel Body1
            jacobian[1] = (r1 + p2 - p1) % t;     // angularVel Body1
            jacobian[2] = -1.0f * t;              // linearVel Body2
            jacobian[3] = -1.0f * r2 % t;         // angularVel Body2

            effectiveMass = body1.inverseMass + body2.inverseMass
                            + JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1]
                            + JVector.Transform(jacobian[3], body2.invInertiaWorld) * jacobian[3];

            softnessOverDt = softness / timestep;
            effectiveMass += softnessOverDt;

            if (effectiveMass != 0)
            {
                effectiveMass = 1.0f / effectiveMass;
            }

            bias = -(l % (p2 - p1)).Length() * biasFactor * (1.0f / timestep);

            if (!body1.isStatic)
            {
                body1.linearVelocity  += body1.inverseMass * accumulatedImpulse * jacobian[0];
                body1.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[1], body1.invInertiaWorld);
            }

            if (!body2.isStatic)
            {
                body2.linearVelocity  += body2.inverseMass * accumulatedImpulse * jacobian[2];
                body2.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[3], body2.invInertiaWorld);
            }
        }
Пример #14
0
        public virtual void Update(GameTime gameTime)
        {
            Cell cellat = area.CellAt(Position);

            if (cellat != null && Position.Y < area.WaterHeight && cellat.isLake)
            {
                JVector d = area.Physics.Gravity * -1;
                d.Normalize();
                RigidBody.AddForce(d * (RigidBody.Mass * Bouyancy * area.Physics.Gravity.Length()));
            }
        }
Пример #15
0
        /// <summary>
        /// Reflect the <paramref name="input"/>-vector on the <paramref name="normal"/>-vector.
        /// </summary>
        /// <param name="input">Input-vector</param>
        /// <param name="normal">Reflector-normal</param>
        /// <returns>Vector which is the reflection of input on normal</returns>
        private JVector ReflectOnNormal(JVector input, JVector normal)
        {
            JVector normalNormalized = normal;

            normalNormalized.Normalize();
            JVector inputNormalized = input;

            inputNormalized.Normalize();

            return(inputNormalized - 2 * JVector.Dot(inputNormalized, normalNormalized) * normalNormalized);
        }
Пример #16
0
        public override void PrepareForIteration(float timestep)
        {
            JVector.Transform(localAnchor1, body1.orientation, out r1);
            JVector.Transform(localAnchor2, body2.orientation, out r2);

            JVector.Add(body1.position, r1, out var p1);
            JVector.Add(body2.position, r2, out var p2);
            JVector.Subtract(p2, p1, out _);

            var l = JVector.Transform(lineNormal, body1.orientation);

            l = JVector.Normalize(l);

            var t = (p1 - p2) % l;

            if (t.LengthSquared() != 0.0f)
            {
                t = JVector.Normalize(t);
            }

            t %= l;

            jacobian[0] = t;
            jacobian[1] = (r1 + p2 - p1) % t;
            jacobian[2] = -1.0f * t;
            jacobian[3] = -1.0f * r2 % t;

            effectiveMass = body1.inverseMass + body2.inverseMass
                            + (JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1])
                            + (JVector.Transform(jacobian[3], body2.invInertiaWorld) * jacobian[3]);

            softnessOverDt = Softness / timestep;
            effectiveMass += softnessOverDt;

            if (effectiveMass != 0)
            {
                effectiveMass = 1.0f / effectiveMass;
            }

            bias = -(l % (p2 - p1)).Length() * BiasFactor * (1.0f / timestep);

            if (!body1.isStatic)
            {
                body1.linearVelocity  += body1.inverseMass * AppliedImpulse * jacobian[0];
                body1.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[1], body1.invInertiaWorld);
            }

            if (!body2.isStatic)
            {
                body2.linearVelocity  += body2.inverseMass * AppliedImpulse * jacobian[2];
                body2.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[3], body2.invInertiaWorld);
            }
        }
Пример #17
0
        public static JVector ComputeNormal(JVector p0, JVector p1, JVector p2, WindingTypes winding,
                                            bool shouldNormalize = true)
        {
            var v0 = JVector.Subtract(p1, p0);
            var v1 = JVector.Subtract(p2, p0);

            // This calculation is the same as the one used in a constructor below, but due to using JVector vs. vec3,
            // it's easier to just duplicate the code.
            var v = JVector.Cross(v0, v1) * (winding == WindingTypes.Clockwise ? 1 : -1);

            return(shouldNormalize ? JVector.Normalize(v) : v);
        }
Пример #18
0
        public PointOnLine(RigidBody body, JVector localAnchor, JVector lineDirection) : base(body, null)
        {
            if (lineDirection.LengthSquared() == 0.0f)
            {
                throw new ArgumentException("Line direction can't be zero", nameof(lineDirection));
            }

            localAnchor1 = localAnchor;
            anchor       = body.position + JVector.Transform(localAnchor, body.orientation);

            lineNormal = lineDirection;
            lineNormal = JVector.Normalize(lineNormal);
        }
Пример #19
0
            /// <summary>
            /// Called once before iteration starts.
            /// </summary>
            /// <param name="timestep">The 5simulation timestep</param>
            public override void PrepareForIteration(float timestep)
            {
                JVector dp;

                JVector.Subtract(ref body2.position, ref body1.position, out dp);

                float deltaLength = dp.Length() - distance;

                if (behavior == DistanceBehavior.LimitMaximumDistance && deltaLength <= 0.0f)
                {
                    skipConstraint = true;
                }
                else if (behavior == DistanceBehavior.LimitMinimumDistance && deltaLength >= 0.0f)
                {
                    skipConstraint = true;
                }
                else
                {
                    skipConstraint = false;

                    JVector n = dp;
                    if (n.LengthSquared() != 0.0f)
                    {
                        n.Normalize();
                    }

                    jacobian[0] = -1.0f * n;
                    //jacobian[1] = -1.0f * (r1 % n);
                    jacobian[1] = 1.0f * n;
                    //jacobian[3] = (r2 % n);

                    effectiveMass = body1.inverseMass + body2.inverseMass;

                    softnessOverDt = softness / timestep;
                    effectiveMass += softnessOverDt;

                    effectiveMass = 1.0f / effectiveMass;

                    bias = deltaLength * biasFactor * (1.0f / timestep);

                    if (!body1.isStatic)
                    {
                        body1.linearVelocity += body1.inverseMass * accumulatedImpulse * jacobian[0];
                    }

                    if (!body2.isStatic)
                    {
                        body2.linearVelocity += body2.inverseMass * accumulatedImpulse * jacobian[1];
                    }
                }
            }
Пример #20
0
        /// <summary>
        /// Called once before iteration starts.
        /// </summary>
        /// <param name="timestep">The 5simulation timestep</param>
        public override void PrepareForIteration(float timestep)
        {
            JVector.Transform(ref localAnchor1, ref body1.orientation, out r1);
            JVector.Transform(ref localAnchor2, ref body2.orientation, out r2);

            JVector p1, p2, dp;

            JVector.Add(ref body1.position, ref r1, out p1);
            JVector.Add(ref body2.position, ref r2, out p2);

            JVector.Subtract(ref p2, ref p1, out dp);

            float deltaLength = dp.Length();

            JVector n = p2 - p1;

            if (n.LengthSquared() != 0.0f)
            {
                n.Normalize();
            }

            jacobian[0] = -1.0f * n;
            jacobian[1] = -1.0f * (r1 % n);
            jacobian[2] = 1.0f * n;
            jacobian[3] = (r2 % n);

            effectiveMass = body1.inverseMass + body2.inverseMass
                            + JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1]
                            + JVector.Transform(jacobian[3], body2.invInertiaWorld) * jacobian[3];

            softnessOverDt = softness / timestep;
            effectiveMass += softnessOverDt;

            effectiveMass = 1.0f / effectiveMass;

            bias = deltaLength * biasFactor * (1.0f / timestep);

            // CUSTOM: Modified to use the IsStatic property (plus the condition below).
            if (!body1.IsStatic)
            {
                body1.linearVelocity  += body1.inverseMass * accumulatedImpulse * jacobian[0];
                body1.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[1], body1.invInertiaWorld);
            }

            if (!body2.IsStatic)
            {
                body2.linearVelocity  += body2.inverseMass * accumulatedImpulse * jacobian[2];
                body2.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[3], body2.invInertiaWorld);
            }
        }
Пример #21
0
        public LimitedHingeJoint(World world, RigidBody body1, RigidBody body2, JVector position, JVector hingeAxis, float hingeFwdAngle, float hingeBckAngle) : base(world)
        {
            worldPointConstraint = new PointOnPoint[2];

            hingeAxis *= 0.5f;

            var pos1 = position;

            JVector.Add(pos1, hingeAxis, out pos1);
            var pos2 = position;

            JVector.Subtract(pos2, hingeAxis, out pos2);

            worldPointConstraint[0] = new PointOnPoint(body1, body2, pos1);
            worldPointConstraint[1] = new PointOnPoint(body1, body2, pos2);

            hingeAxis = JVector.Normalize(hingeAxis);

            var perpDir = JVector.Up;

            if (JVector.Dot(perpDir, hingeAxis) > 0.1f)
            {
                perpDir = JVector.Right;
            }

            var sideAxis = JVector.Cross(hingeAxis, perpDir);

            perpDir = JVector.Cross(sideAxis, hingeAxis);
            perpDir = JVector.Normalize(perpDir);

            float len = 10.0f * 3;

            var hingeRelAnchorPos0 = perpDir * len;

            float angleToMiddle      = 0.5f * (hingeFwdAngle - hingeBckAngle);
            var   hingeRelAnchorPos1 = JVector.Transform(hingeRelAnchorPos0, JMatrix.CreateFromAxisAngle(hingeAxis, -angleToMiddle / 360.0f * 2.0f * JMath.Pi));

            float hingeHalfAngle  = 0.5f * (hingeFwdAngle + hingeBckAngle);
            float allowedDistance = len * 2.0f * (float)System.Math.Sin(hingeHalfAngle * 0.5f / 360.0f * 2.0f * JMath.Pi);

            var hingePos = body1.Position;
            var relPos0c = hingePos + hingeRelAnchorPos0;
            var relPos1c = hingePos + hingeRelAnchorPos1;

            DistanceConstraint = new PointPointDistance(body1, body2, relPos0c, relPos1c)
            {
                Distance = allowedDistance,
                Behavior = PointPointDistance.DistanceBehavior.LimitMaximumDistance
            };
        }
Пример #22
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="rayOrigin"></param>
        /// <param name="rayDelta"></param>
        /// <returns></returns>
        public override int Prepare(ref JVector rayOrigin, ref JVector rayDelta)
        {
            potentialTriangles.Clear();

            #region Expand Spherical
            JVector expDelta;
            JVector.Normalize(ref rayDelta, out expDelta);
            expDelta = rayDelta + expDelta * sphericalExpansion;
            #endregion

            octree.GetTrianglesIntersectingRay(potentialTriangles, rayOrigin, expDelta);

            return(potentialTriangles.Count);
        }
Пример #23
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="rayOrigin"></param>
        /// <param name="rayDelta"></param>
        /// <returns></returns>
        public override int Prepare(ref JVector rayOrigin, ref JVector rayDelta)
        {
            JBBox box = JBBox.SmallBox;

            #region RayEnd + Expand Spherical
            JVector rayEnd;
            JVector.Normalize(ref rayDelta, out rayEnd);
            rayEnd = rayOrigin + rayDelta + rayEnd * sphericalExpansion;
            #endregion

            box.AddPoint(ref rayOrigin);
            box.AddPoint(ref rayEnd);

            return(this.Prepare(ref box));
        }
Пример #24
0
        public override void PrepareForIteration(float timestep)
        {
            JVector.Transform(localAnchor1, body1.orientation, out r1);
            JVector.Transform(localAnchor2, body2.orientation, out r2);

            JVector.Add(body1.position, r1, out var p1);
            JVector.Add(body2.position, r2, out var p2);

            JVector.Subtract(p2, p1, out var dp);

            float deltaLength = dp.Length();

            var n = p2 - p1;

            if (n.LengthSquared() != 0.0f)
            {
                n = JVector.Normalize(n);
            }

            jacobian[0] = -1.0f * n;
            jacobian[1] = -1.0f * (r1 % n);
            jacobian[2] = 1.0f * n;
            jacobian[3] = r2 % n;

            effectiveMass = body1.inverseMass + body2.inverseMass
                            + (JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1])
                            + (JVector.Transform(jacobian[3], body2.invInertiaWorld) * jacobian[3]);

            softnessOverDt = Softness / timestep;
            effectiveMass += softnessOverDt;

            effectiveMass = 1.0f / effectiveMass;

            bias = deltaLength * BiasFactor * (1.0f / timestep);

            if (!body1.isStatic)
            {
                body1.linearVelocity  += body1.inverseMass * AppliedImpulse * jacobian[0];
                body1.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[1], body1.invInertiaWorld);
            }

            if (!body2.isStatic)
            {
                body2.linearVelocity  += body2.inverseMass * AppliedImpulse * jacobian[2];
                body2.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[3], body2.invInertiaWorld);
            }
        }
Пример #25
0
            public override void PrepareForIteration(float timestep)
            {
                JVector.Subtract(body2.position, body1.position, out var dp);

                float deltaLength = dp.Length() - Distance;

                if (Behavior == DistanceBehavior.LimitMaximumDistance && deltaLength <= 0.0f)
                {
                    skipConstraint = true;
                }
                else if (Behavior == DistanceBehavior.LimitMinimumDistance && deltaLength >= 0.0f)
                {
                    skipConstraint = true;
                }
                else
                {
                    skipConstraint = false;

                    var n = dp;
                    if (n.LengthSquared() != 0.0f)
                    {
                        n = JVector.Normalize(n);
                    }

                    jacobian[0] = -1.0f * n;
                    jacobian[1] = 1.0f * n;

                    effectiveMass = body1.inverseMass + body2.inverseMass;

                    softnessOverDt = Softness / timestep;
                    effectiveMass += softnessOverDt;

                    effectiveMass = 1.0f / effectiveMass;

                    bias = deltaLength * BiasFactor * (1.0f / timestep);

                    if (!body1.isStatic)
                    {
                        body1.linearVelocity += body1.inverseMass * AppliedImpulse * jacobian[0];
                    }

                    if (!body2.isStatic)
                    {
                        body2.linearVelocity += body2.inverseMass * AppliedImpulse * jacobian[1];
                    }
                }
            }
Пример #26
0
        /// <summary>
        /// Discrete Circle vs Circle test. Very fast. Generates contact info.
        /// NOTE: check distance for collisions. If negative then a collision has occurred.
        /// This is done to remove all branches from this test and leave it to the user to decide when to branch.
        /// </summary>
        public static void CircleCircleTest(JVector centerA, float radiusA, JVector centerB, float radiusB, out JVector pointA, out JVector pointB, out JVector normal, out float distance)
        {
            // ||A-B|| - (r1+r2) < 0
            float d = JVector.DistanceSquared(centerA, centerB);
            float r = (radiusA + radiusB);

            r *= r;

            distance = d - r;

            normal = (centerA - centerB) / d;
            normal.Normalize();

            // calculate closest 2 points
            pointA = JVector.Negate(normal) * radiusA + centerA;
            pointB = normal * radiusB + centerB;
        }
Пример #27
0
        // This is primarily used for tracking relative rotation on moving platforms.
        public static float ComputeYaw(this JMatrix matrix)
        {
            // See https://stackoverflow.com/a/4341489/7281613.
            JVector t = JVector.Transform(JVector.Left, matrix);
            JVector f = t - JVector.Dot(t, JVector.Up) * JVector.Up;

            f.Normalize();

            float angle = (float)Math.Acos(JVector.Dot(JVector.Left, f));
            float d     = JVector.Dot(JVector.Up, JVector.Cross(JVector.Left, f));

            if (d < 0)
            {
                angle = Constants.TwoPi - angle;
            }

            return(angle);
        }
Пример #28
0
        /// <summary>
        /// Called once before iteration starts.
        /// </summary>
        /// <param name="timestep">The simulation timestep</param>
        public override void PrepareForIteration(float timestep)
        {
            JVector.Transform(ref localAnchor1, ref body1.orientation, out r1);

            JVector p1, dp;

            JVector.Add(ref body1.position, ref r1, out p1);

            JVector.Subtract(ref p1, ref anchor, out dp);

            JVector l = lineNormal;

            JVector t = (p1 - anchor) % l;

            if (t.LengthSquared() != 0.0f)
            {
                t.Normalize();
            }
            t = t % l;

            jacobian[0] = t;
            jacobian[1] = r1 % t;

            effectiveMass = body1.inverseMass
                            + JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1];

            softnessOverDt = softness / timestep;
            effectiveMass += softnessOverDt;

            if (effectiveMass != 0)
            {
                effectiveMass = 1.0f / effectiveMass;
            }

            bias = -(l % (p1 - anchor)).Length() * biasFactor * (1.0f / timestep);

            // CUSTOM: Modified to use the IsStatic property.
            if (!body1.IsStatic)
            {
                body1.linearVelocity  += body1.inverseMass * accumulatedImpulse * jacobian[0];
                body1.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[1], body1.invInertiaWorld);
            }
        }
Пример #29
0
        public override void PrepareForIteration(float timestep)
        {
            var delta  = Target - Body1.Position;
            var length = delta.Length();

            if (length > 1f * Velocity)
            {
                if (Velocity > targetVelocity.Length())
                {
                    targetVelocity = JVector.Normalize(delta) * (targetVelocity.Length() + Velocity * timestep);
                }
                else
                {
                    targetVelocity = JVector.Normalize(delta) * Velocity;
                }
            }
            else
            {
                targetVelocity = JVector.Normalize(delta) * (float)Math.Sqrt(length);
            }
        }
Пример #30
0
        internal static bool CircleCapsuleTest(JVector centerA, float radiusA, JVector centerB, JVector axis, float length, float radiusB, out JVector pointA, out JVector pointB, out JVector normal, out float distance)
        {
            // get capsule endpoints
            var p0 = centerB - axis * (length * 0.5f);
            var p1 = centerB + axis * (length * 0.5f);

            // get vector from endpoint to circle
            var D = centerA - p0;

            // project vector onto axis and clamp
            var d = JVector.Dot(D, axis);

            d = JMath.Clamp(d, 0, length);

            // get point on axis
            var R = p0 + axis * d;

            // distance
            var b = Math.Abs((centerA - R).Length());

            normal = (centerA - R) / b;

            // calculate closest 2 points
            var RH = JVector.Normalize(centerA - R);

            pointA = JVector.Negate(RH) * radiusA + centerA;
            pointB = RH * radiusB + R;

            normal.Negate();

            distance = b - (radiusA + radiusB);

            //
            if (b < radiusA + radiusB)
            {
                return(true);
            }
            return(false);
        }