示例#1
0
        private void FindSupportPoints(RigidBody body1, RigidBody body2,
                                       Shape shape1, Shape shape2, ref JVector point, ref JVector normal,
                                       out JVector point1, out JVector point2)
        {
            JVector mn; JVector.Negate(ref normal, out mn);

            JVector sA; SupportMapping(body1, shape1, ref mn, out sA);
            JVector sB; SupportMapping(body2, shape2, ref normal, out sB);

            JVector.Subtract(ref sA, ref point, out sA);
            JVector.Subtract(ref sB, ref point, out sB);

            double dot1 = JVector.Dot(ref sA, ref normal);
            double dot2 = JVector.Dot(ref sB, ref normal);

            JVector.Multiply(ref normal, dot1, out sA);
            JVector.Multiply(ref normal, dot2, out sB);

            JVector.Add(ref point, ref sA, out point1);
            JVector.Add(ref point, ref sB, out point2);
        }
示例#2
0
            public bool InSimplex(JVector w)
            {
                //check in case lastW is already removed
                if (w == _lastW)
                {
                    return(true);
                }

                //w is in the current (reduced) simplex
                int numverts = NumVertices;

                for (int i = 0; i < numverts; i++)
                {
                    if (_simplexVectorW[i] == w)
                    {
                        return(true);
                    }
                }

                return(false);
            }
示例#3
0
        /// <summary>
        /// Creates a new instance of the Wheel class.
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="car">The RigidBody on which to apply the wheel forces.</param>
        /// <param name="position">The position of the wheel on the body (in body space).</param>
        /// <param name="radius">The wheel radius.</param>
        public Wheel(RigidBody car, JVector position, float radius)
        {
            this.car      = car;
            this.Position = position;

            raycast = new RaycastCallback(RaycastCallback);

            // set some default values.
            //this.SideFriction = 455f;
            // this.ForwardFriction = 451f;

            this.SideFriction    = 1.5f;
            this.ForwardFriction = 1f;

            this.Radius      = radius;
            this.Inertia     = 1.0f;
            this.WheelTravel = 0.2f;
            //MAX SPEED
            this.MaximumAngularVelocity = 200f;
            this.NumberOfRays           = 10;
        }
        private void AddCardLayer(JVector startPosition, int angledCards)
        {
            Debug.Assert(angledCards % 2 == 0);

            foreach (int i in Enumerable.Range(0, angledCards))
            {
                AddCard(
                    startPosition + new JVector(cardSpacing * i, layerHeight / 2f, 0),
                    (i % 2 == 0) ? angle : oppositeAngle);
            }

            for (float distance = 1.5f; distance < angledCards - 0.5; distance += 4)
            {
                AddCard(startPosition + new JVector(cardSpacing * distance, layerHeight, 0), 0);
            }

            for (float distance = 3.5f; distance < angledCards - 0.5; distance += 4)
            {
                AddCard(startPosition + new JVector(cardSpacing * distance, layerHeight + (float)cardThickness, 0), 0);
            }
        }
示例#5
0
        private void AddShapeToDrawList(Shape shape, JMatrix ori, JVector pos)
        {
            Primitives3D.GeometricPrimitive primitive = null;
            Matrix scaleMatrix = Matrix.Identity;

            if (shape is BoxShape)
            {
                primitive   = primitives[(int)Primitives.box];
                scaleMatrix = Matrix.CreateScale(Conversion.ToXNAVector((shape as BoxShape).Size));
            }
            else if (shape is SphereShape)
            {
                primitive   = primitives[(int)Primitives.sphere];
                scaleMatrix = Matrix.CreateScale((shape as SphereShape).Radius);
            }
            else if (shape is CylinderShape)
            {
                primitive = primitives[(int)Primitives.cylinder];
                CylinderShape cs = shape as CylinderShape;
                scaleMatrix = Matrix.CreateScale(cs.Radius, cs.Height, cs.Radius);
            }
            else if (shape is CapsuleShape)
            {
                primitive = primitives[(int)Primitives.capsule];
                CapsuleShape cs = shape as CapsuleShape;
                scaleMatrix = Matrix.CreateScale(cs.Radius * 2, cs.Length, cs.Radius * 2);
            }
            else if (shape is ConeShape)
            {
                ConeShape cs = shape as ConeShape;
                scaleMatrix = Matrix.CreateScale(cs.Radius, cs.Height, cs.Radius);
                primitive   = primitives[(int)Primitives.cone];
            }

            if (primitive != null)
            {
                primitive.AddWorldMatrix(scaleMatrix * Conversion.ToXNAMatrix(ori) *
                                         Matrix.CreateTranslation(Conversion.ToXNAVector(pos)));
            }
        }
示例#6
0
        /// <summary>
        /// Returns all triangles which intersect the given axis aligned bounding box.
        /// </summary>
        /// <param name="rayOrigin"></param>
        /// <param name="rayDelta"></param>
        /// <param name="triangles"></param>
        /// <returns></returns>
        #region public int GetTrianglesIntersectingtRay(JVector rayOrigin, JVector rayDelta)
        public int GetTrianglesIntersectingRay(List <int> triangles, JVector rayOrigin, JVector rayDelta)
        {
            if (nodes.Length == 0)
            {
                return(0);
            }
            int curStackIndex = 0;
            int endStackIndex = 1;

            UInt16[] nodeStack = nodeStackPool.GetNew();
            nodeStack[0] = 0;

            int triCount = 0;

            while (curStackIndex < endStackIndex)
            {
                UInt16 nodeIndex = nodeStack[curStackIndex];
                curStackIndex++;
                if (nodes[nodeIndex].box.SegmentIntersect(ref rayOrigin, ref rayDelta))
                {
                    for (int i = 0; i < nodes[nodeIndex].triIndices.Length; ++i)
                    {
                        if (triBoxes[nodes[nodeIndex].triIndices[i]].SegmentIntersect(ref rayOrigin, ref rayDelta))
                        {
                            triangles.Add(nodes[nodeIndex].triIndices[i]);
                            triCount++;
                        }
                    }

                    int numChildren = nodes[nodeIndex].nodeIndices.Length;
                    for (int i = 0; i < numChildren; ++i)
                    {
                        nodeStack[endStackIndex++] = nodes[nodeIndex].nodeIndices[i];
                    }
                }
            }

            nodeStackPool.GiveBack(nodeStack);
            return(triCount);
        }
示例#7
0
        /// <summary>
        /// The points in wolrd space gets recalculated by transforming the
        /// local coordinates. Also new penetration depth is estimated.
        /// </summary>
        public void UpdatePosition()
        {
            if (!body1IsMassPoint)
            {
                JVector.Transform(ref realRelPos1, ref body1.orientation, out p1);
            }

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


            if (!body2IsMassPoint)
            {
                JVector.Transform(ref realRelPos2, ref body2.orientation, out p2);
            }

            JVector.Add(ref p2, ref body2.position, out p2);


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

            penetration = JVector.Dot(ref dist, ref normal);
        }
示例#8
0
        // sort cached points so most isolated points come first
        private int SortCachedPoints(ref JVector realRelPos1, float pen)
        {
            //calculate 4 possible cases areas, and take biggest area
            //also need to keep 'deepest'

            int   maxPenetrationIndex = -1;
            float maxPenetration      = pen;

            for (int i = 0; i < 4; i++)
            {
                if (contactList[i].penetration > maxPenetration)
                {
                    maxPenetrationIndex = i;
                    maxPenetration      = contactList[i].penetration;
                }
            }

            float res0 = 0, res1 = 0, res2 = 0, res3 = 0;

            if (maxPenetrationIndex != 0)
            {
                JVector.Subtract(ref realRelPos1, ref contactList[1].relativePos1, out var a0);
示例#9
0
        public void DebugDraw(IDebugDrawer drawer)
        {
            JVector pos1, pos2, pos3;

            for (int i = 0; i < hullPoints.Count; i += 3)
            {
                pos1 = hullPoints[i + 0];
                pos2 = hullPoints[i + 1];
                pos3 = hullPoints[i + 2];

                JVector.Transform(ref pos1, ref orientation, out pos1);
                JVector.Add(ref pos1, ref position, out pos1);

                JVector.Transform(ref pos2, ref orientation, out pos2);
                JVector.Add(ref pos2, ref position, out pos2);

                JVector.Transform(ref pos3, ref orientation, out pos3);
                JVector.Add(ref pos3, ref position, out pos3);

                drawer.DrawTriangle(pos1, pos2, pos3);
            }
        }
示例#10
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)
        {
            // this Sqrt is bad!
            float r = (float)Math.Sqrt(direction.X * direction.X);

            if (Math.Abs(direction.Y) > 0.0f)
            {
                JVector dir; JVector.Normalize(ref direction, out dir);
                JVector.Multiply(ref dir, radius, out result);
                result.Y += Math.Sign(direction.Y) * 0.5f * length;
            }
            else if (r > 0.0f)
            {
                result.X = direction.X / r * radius;
                result.Y = 0.0f;
            }
            else
            {
                result.X = 0.0f;
                result.Y = 0.0f;
            }
        }
示例#11
0
        /// <summary>
        /// Uses the supportMapping to calculate the bounding box. Should be overidden
        /// to make this faster.
        /// </summary>
        /// <param name="orientation">The orientation of the shape.</param>
        /// <param name="box">The resulting axis aligned bounding box.</param>
        public virtual void GetBoundingBox(ref float rotation, out JBBox box)
        {
            JVector vec = JVector.Zero;

            JMatrix orientation = JMatrix.CreateRotationZ(rotation);

            vec.Set(orientation.M11, orientation.M21);
            SupportMapping(ref vec, out vec);
            box.Max.X = orientation.M11 * vec.X + orientation.M21 * vec.Y;

            vec.Set(orientation.M12, orientation.M22);
            SupportMapping(ref vec, out vec);
            box.Max.Y = orientation.M12 * vec.X + orientation.M22 * vec.Y;

            vec.Set(-orientation.M11, -orientation.M21);
            SupportMapping(ref vec, out vec);
            box.Min.X = orientation.M11 * vec.X + orientation.M21 * vec.Y;

            vec.Set(-orientation.M12, -orientation.M22);
            SupportMapping(ref vec, out vec);
            box.Min.Y = orientation.M12 * vec.X + orientation.M22 * vec.Y;
        }
示例#12
0
        public void SweptExpandBoundingBox(float timestep)
        {
            sweptDirection = linearVelocity * timestep;

            if (sweptDirection.X < 0.0f)
            {
                boundingBox.Min.X += sweptDirection.X;
            }
            else
            {
                boundingBox.Max.X += sweptDirection.X;
            }

            if (sweptDirection.Y < 0.0f)
            {
                boundingBox.Min.Y += sweptDirection.Y;
            }
            else
            {
                boundingBox.Max.Y += sweptDirection.Y;
            }
        }
示例#13
0
        /// <summary>
        /// Recalculates the axis aligned bounding box and the inertia
        /// values in world space.
        /// </summary>
        public virtual void Update()
        {
            if (DisableRotation)
            {
                orientation = 0;
            }

            // particles don't rotate
            if (isParticle)
            {
                this.inertia        = 0.0f;
                this.invInertia     = 0.0f;
                this.invOrientation = this.orientation = 0.0f;
                this.boundingBox    = shape.boundingBox;
                JVector.Add(ref boundingBox.Min, ref this.position, out boundingBox.Min);
                JVector.Add(ref boundingBox.Max, ref this.position, out boundingBox.Max);

                angularVelocity = 0.0f;
            }
            else
            {
                // Given: Orientation, Inertia
                // 3d version
                //JMatrix.Transpose(ref orientation, out invOrientation);
                invOrientation = -orientation;
                this.Shape.GetBoundingBox(ref orientation, out boundingBox);
                JVector.Add(ref boundingBox.Min, ref this.position, out boundingBox.Min);
                JVector.Add(ref boundingBox.Max, ref this.position, out boundingBox.Max);

                if (!isStatic)
                {
                    // 3d version
                    //JMatrix.Multiply(ref invOrientation, ref invInertia, out invInertiaWorld);
                    //JMatrix.Multiply(ref invInertiaWorld, ref orientation, out invInertiaWorld);

                    // we don't need a world inverse inertia
                }
            }
        }
示例#14
0
        public static bool IntersectPortal(JVector v0, JVector v1, JVector v2)
        {
            JVector a = JVector.Zero;
            JVector b = v0;
            JVector c = v1;
            JVector d = v2;

            float a1 = (a.X - d.X) * (b.Y - d.Y) - (a.Y - d.Y) * (b.X - d.X);
            float a2 = (a.X - c.X) * (b.Y - c.Y) - (a.Y - c.Y) * (b.X - c.X);

            if (a1 != 0.0f && a2 != 0.0f && a1 * a2 < 0.0f)
            {
                float a3 = (c.X - a.X) * (d.Y - a.Y) - (c.Y - a.Y) * (d.X - a.X);
                float a4 = a3 + a2 - a1;
                if (a3 != 0.0f && a4 != 0.0f && a3 * a4 < 0.0f)
                {
                    return(true);
                }
            }
            // segments not intersecting
            return(false);
        }
示例#15
0
        /// <summary>
        /// Called once before iteration starts.
        /// </summary>
        /// <param name="timestep">The 5simulation timestep</param>
        public override void PrepareForIteration(float timestep)
        {
            effectiveMass = body1.invInertiaWorld;

            softnessOverDt = softness / timestep;

            effectiveMass.M11 += softnessOverDt;
            effectiveMass.M22 += softnessOverDt;
            effectiveMass.M33 += softnessOverDt;

            JMatrix.Inverse(ref effectiveMass, out effectiveMass);

            JMatrix q = JMatrix.Transpose(orientation) * body1.orientation;
            JVector axis;

            float x = q.M32 - q.M23;
            float y = q.M13 - q.M31;
            float z = q.M21 - q.M12;

            float r = JMath.Sqrt(x * x + y * y + z * z);
            float t = q.M11 + q.M22 + q.M33;

            float angle = (float)Math.Atan2(r, t - 1);

            axis = new JVector(x, y, z) * angle;

            if (r != 0.0f)
            {
                axis = axis * (1.0f / r);
            }

            bias = axis * biasFactor * (-1.0f / timestep);

            // Apply previous frame solution as initial guess for satisfying the constraint.
            if (!body1.IsStatic)
            {
                body1.angularVelocity += JVector.Transform(accumulatedImpulse, body1.invInertiaWorld);
            }
        }
示例#16
0
        public override void Update(uint deltaMs)
        {
            var entities = OwnerApp.EntityManager.WithComponent <MovableComponent>().ToArray();

            foreach (var entity in entities)
            {
                var ridgidBodyComponent = OwnerApp.EntityManager.GetComponent <RigidBodyComponent>(entity);
                var movableComponent    = OwnerApp.EntityManager.GetComponent <MovableComponent>(entity);

                var velocity = JVector.Multiply(CalcVelocity(movableComponent.Speed), deltaMs / 16.6f);

                if (velocity != JVector.Zero && !(ridgidBodyComponent.Body is null))
                {
                    ridgidBodyComponent.Body.ApplyImpulse(velocity);
                }

                if (Keyboard.GetState().IsKeyDown(Key.Space)) // TODO && !ridgidBodyComponent.Body.IsActive)
                {
                    ridgidBodyComponent.Body.ApplyImpulse(new JVector(0.0f, movableComponent.JumpSpeed, 0.0f));
                }
            }
        }
示例#17
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);
        }
示例#18
0
        /// <summary>
        /// Adds a contact to the arbiter (threadsafe). No more than four contacts
        /// are stored in the contactList. When adding a new contact
        /// to the arbiter the existing are checked and the best are kept.
        /// </summary>
        /// <param name="point1">Point on body1. In world space.</param>
        /// <param name="point2">Point on body2. In world space.</param>
        /// <param name="normal">The normal pointing to body2.</param>
        /// <param name="penetration">The estimated penetration depth.</param>
        public void AddContact(JVector point1, JVector point2, JVector normal, JVector[] triangle,
                               float penetration, ContactSettings contactSettings)
        {
            // Returning false means that the contact doesn't need to be kept (likely because data from the contact
            // was used to manually update controllers).
            if (!World.Events.RaiseContactCreated(body1, body2, point1, point2, normal, triangle, penetration))
            {
                return;
            }

            JVector.Subtract(ref point1, ref body1.position, out var relPos1);

            lock (contactList)
            {
                int index;

                if (contactList.Count == 4)
                {
                    index = SortCachedPoints(ref relPos1, penetration);
                    ReplaceContact(ref point1, ref point2, ref normal, triangle, penetration, index, contactSettings);

                    // TODO: I added this return (to prevent contact count blowing up). Is this correct?
                    return;
                }

                index = GetCacheEntry(ref relPos1, contactSettings.breakThreshold);

                if (index >= 0)
                {
                    ReplaceContact(ref point1, ref point2, ref normal, triangle, penetration, index, contactSettings);
                }

                Contact contact = Contact.Pool.GetNew();
                contact.Initialize(body1, body2, ref point1, ref point2, ref normal, triangle, penetration, true,
                                   contactSettings);
                contactList.Add(contact);
            }
        }
示例#19
0
        /// <summary>
        /// Sets the current shape. First <see cref="Prepare"/> has to be called.
        /// After SetCurrentShape the shape immitates another shape.
        /// </summary>
        /// <param name="index"></param>
        public override void SetCurrentShape(int index)
        {
            bool leftTriangle = false;

            if (index >= numX * numZ)
            {
                leftTriangle = true;
                index       -= numX * numZ;
            }

            int quadIndexX = index % numX;
            int quadIndexZ = index / numX;

            // each quad has two triangles, called 'leftTriangle' and !'leftTriangle'
            if (leftTriangle)
            {
                points[0].Set((minX + quadIndexX + 0) * scaleX, heights[minX + quadIndexX + 0, minZ + quadIndexZ + 0], (minZ + quadIndexZ + 0) * scaleZ);
                points[1].Set((minX + quadIndexX + 1) * scaleX, heights[minX + quadIndexX + 1, minZ + quadIndexZ + 0], (minZ + quadIndexZ + 0) * scaleZ);
                points[2].Set((minX + quadIndexX + 0) * scaleX, heights[minX + quadIndexX + 0, minZ + quadIndexZ + 1], (minZ + quadIndexZ + 1) * scaleZ);
            }
            else
            {
                points[0].Set((minX + quadIndexX + 1) * scaleX, heights[minX + quadIndexX + 1, minZ + quadIndexZ + 0], (minZ + quadIndexZ + 0) * scaleZ);
                points[1].Set((minX + quadIndexX + 1) * scaleX, heights[minX + quadIndexX + 1, minZ + quadIndexZ + 1], (minZ + quadIndexZ + 1) * scaleZ);
                points[2].Set((minX + quadIndexX + 0) * scaleX, heights[minX + quadIndexX + 0, minZ + quadIndexZ + 1], (minZ + quadIndexZ + 1) * scaleZ);
            }

            JVector sum = points[0];

            JVector.Add(ref sum, ref points[1], out sum);
            JVector.Add(ref sum, ref points[2], out sum);
            JVector.Multiply(ref sum, 1.0f / 3.0f, out sum);
            geomCen = sum;

            JVector.Subtract(ref points[1], ref points[0], out sum);
            JVector.Subtract(ref points[2], ref points[0], out normal);
            JVector.Cross(ref sum, ref normal, out normal);
        }
示例#20
0
        private void UpdateArbiterContacts(Arbiter arbiter)
        {
            if (arbiter.contactList.Count == 0)
            {
                lock (removedArbiterStack) { removedArbiterStack.Push(arbiter); }
                return;
            }

            for (int i = arbiter.contactList.Count - 1; i >= 0; i--)
            {
                Contact c = arbiter.contactList[i];
                c.UpdatePosition();

                if (c.penetration < -contactSettings.breakThreshold)
                {
                    Contact.Pool.GiveBack(c);
                    arbiter.contactList.RemoveAt(i);
                    continue;
                }
                else
                {
                    JVector diff; JVector.Subtract(ref c.p1, ref c.p2, out diff);
                    double  distance = JVector.Dot(ref diff, ref c.normal);

                    diff     = diff - distance * c.normal;
                    distance = diff.LengthSquared();

                    // hack (multiplication by factor 100) in the
                    // following line.
                    if (distance > contactSettings.breakThreshold * contactSettings.breakThreshold * 100)
                    {
                        Contact.Pool.GiveBack(c);
                        arbiter.contactList.RemoveAt(i);
                        continue;
                    }
                }
            }
        }
        public override void Update(float timestep)
        {
            if (Body.IsStaticOrInactive)
            {
                return;
            }

            var worldBodyAnchor = Body.LocalToWorld(LocalAnchor);

            var difference    = worldBodyAnchor - WorldAnchor;
            var differenceMag = difference.Length();

            if (IsOnlyPull)
            {
                if (differenceMag < Length)
                {
                    return;
                }
            }

            if (JMath.IsNearlyZero(differenceMag))
            {
                return;
            }

            var diffNormal = JVector.Normalize(difference);

            SpringError = differenceMag - Length;

            var springForce = SpringConstant * SpringError;

            var force = diffNormal * -springForce;

            if (!force.IsNearlyZero())
            {
                Body.AddForce(force, worldBodyAnchor);
            }
        }
示例#22
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)
        {
            float sigma = (float)Math.Sqrt((float)(direction.X * direction.X + direction.Z * direction.Z));

            if (direction.Y > direction.Length() * sina)
            {
                result.X = 0.0f;
                result.Y = (2.0f / 3.0f) * height;
                result.Z = 0.0f;
            }
            else if (sigma > 0.0f)
            {
                result.X = radius * direction.X / sigma;
                result.Y = -(1.0f / 3.0f) * height;
                result.Z = radius * direction.Z / sigma;
            }
            else
            {
                result.X = 0.0f;
                result.Y = -(1.0f / 3.0f) * height;
                result.Z = 0.0f;
            }
        }
示例#23
0
        public void DrawTriangle(JVector pos1, JVector pos2, JVector pos3)
        {
            JVector n = JVector.Cross(pos2 - pos1, pos3 - pos1);

            n.Normalize();
            Vector3 xn = new Vector3(n.X, n.Y, n.Z);

            VertexPositionColorNormal[] tri = new VertexPositionColorNormal[3] {
                new VertexPositionColorNormal(new Vector3(pos1.X, pos1.Y, pos1.Z), Color.Green, xn),
                new VertexPositionColorNormal(new Vector3(pos3.X, pos3.Y, pos3.Z), Color.Green, xn),
                new VertexPositionColorNormal(new Vector3(pos2.X, pos2.Y, pos2.Z), Color.Green, xn),
            };

            effect.Parameters["World"].SetValue(Matrix.Identity);
            effect.Parameters["ViewProj"].SetValue(Camera.CurrentCamera.View * Camera.CurrentCamera.Projection);
            effect.CurrentTechnique = effect.Techniques["VBO"];

            foreach (EffectPass p in effect.CurrentTechnique.Passes)
            {
                p.Apply();
                device.DrawUserPrimitives(PrimitiveType.TriangleList, tri, 0, 1);
            }
        }
示例#24
0
        private void AddPressureForces(float timeStep)
        {
            if (pressure == 0.0f || volume == 0.0f)
            {
                return;
            }

            float invVolume = 1.0f / volume;

            foreach (Triangle t in triangles)
            {
                JVector v1 = points[t.indices.I0].position;
                JVector v2 = points[t.indices.I1].position;
                JVector v3 = points[t.indices.I2].position;

                JVector cross  = (v3 - v1) % (v2 - v1);
                JVector center = (v1 + v2 + v3) * (1.0f / 3.0f);

                points[t.indices.I0].AddForce(invVolume * cross * pressure);
                points[t.indices.I1].AddForce(invVolume * cross * pressure);
                points[t.indices.I2].AddForce(invVolume * cross * pressure);
            }
        }
示例#25
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)
        {
            double r = (double)Math.Sqrt(direction.X * direction.X + direction.Z * direction.Z);

            if (Math.Abs(direction.Y) > 0.0f)
            {
                JVector dir; JVector.Normalize(ref direction, out dir);
                JVector.Multiply(ref dir, radius, out result);
                result.Y += Math.Sign(direction.Y) * 0.5f * length;
            }
            else if (r > 0.0f)
            {
                result.X = direction.X / r * radius;
                result.Y = 0.0f;
                result.Z = direction.Z / r * radius;
            }
            else
            {
                result.X = 0.0f;
                result.Y = 0.0f;
                result.Z = 0.0f;
            }
        }
示例#26
0
        public override void SetCurrentShape(int index)
        {
            bool leftTriangle = false;

            if (index >= numX * numZ)
            {
                leftTriangle = true;
                index       -= numX * numZ;
            }

            int quadIndexX = index % numX;
            int quadIndexZ = index / numX;

            if (leftTriangle)
            {
                points[0] = new JVector((minX + quadIndexX + 0) * scaleX, heights[minX + quadIndexX + 0, minZ + quadIndexZ + 0], (minZ + quadIndexZ + 0) * scaleZ);
                points[1] = new JVector((minX + quadIndexX + 1) * scaleX, heights[minX + quadIndexX + 1, minZ + quadIndexZ + 0], (minZ + quadIndexZ + 0) * scaleZ);
                points[2] = new JVector((minX + quadIndexX + 0) * scaleX, heights[minX + quadIndexX + 0, minZ + quadIndexZ + 1], (minZ + quadIndexZ + 1) * scaleZ);
            }
            else
            {
                points[0] = new JVector((minX + quadIndexX + 1) * scaleX, heights[minX + quadIndexX + 1, minZ + quadIndexZ + 0], (minZ + quadIndexZ + 0) * scaleZ);
                points[1] = new JVector((minX + quadIndexX + 1) * scaleX, heights[minX + quadIndexX + 1, minZ + quadIndexZ + 1], (minZ + quadIndexZ + 1) * scaleZ);
                points[2] = new JVector((minX + quadIndexX + 0) * scaleX, heights[minX + quadIndexX + 0, minZ + quadIndexZ + 1], (minZ + quadIndexZ + 1) * scaleZ);
            }

            var sum = points[0];

            JVector.Add(sum, points[1], out sum);
            JVector.Add(sum, points[2], out sum);
            JVector.Multiply(sum, 1.0f / 3.0f, out sum);
            geomCen = sum;

            JVector.Subtract(points[1], points[0], out sum);
            JVector.Subtract(points[2], points[0], out normal);
            JVector.Cross(sum, normal, out normal);
        }
示例#27
0
        private void CollisionDetected(RigidBody body1, RigidBody body2, JVector point1, JVector point2, JVector normal, float penetration)
        {
            Arbiter arbiter = null;

            lock (arbiterMap)
            {
                arbiterMap.LookUpArbiter(body1, body2, out arbiter);
                if (arbiter == null)
                {
                    arbiter = poolArbiter.GetNew();
                    arbiter.Prepare(poolArbiter, poolContact);
                    arbiter.body1 = body1; arbiter.body2 = body2;
                    arbiterMap.Add(new ArbiterKey(body1, body2), arbiter);

                    addedArbiterQueue.Enqueue(arbiter);

                    events.RaiseBodiesBeginCollide(body1, body2);
                }
            }

            Contact contact = null;

            if (arbiter.body1 == body1)
            {
                JVector.Negate(ref normal, out normal);
                contact = arbiter.AddContact(point1, point2, normal, penetration, contactSettings);
            }
            else
            {
                contact = arbiter.AddContact(point2, point1, normal, penetration, contactSettings);
            }

            if (contact != null)
            {
                events.RaiseContactCreated(contact);
            }
        }
示例#28
0
        public Contact AddContact(
            JVector point1,
            JVector point2,
            JVector normal,
            float penetration,
            ContactSettings contactSettings)
        {
            JVector.Subtract(point1, body1.position, out var relPos1);

            int index;

            lock (contactList)
            {
                if (contactList.Count == 4)
                {
                    index = SortCachedPoints(relPos1, penetration);
                    ReplaceContact(point1, point2, normal, penetration, index, contactSettings);
                    return(null);
                }

                index = GetCacheEntry(relPos1, contactSettings.breakThreshold);

                if (index >= 0)
                {
                    ReplaceContact(point1, point2, normal, penetration, index, contactSettings);
                    return(null);
                }
                else
                {
                    var contact = Contact.Pool.GetNew();
                    contact.Initialize(body1, body2, point1, point2, normal, penetration, true, contactSettings);
                    contactList.Add(contact);
                    return(contact);
                }
            }
        }
示例#29
0
        /// <summary>
        /// Detect a possible collision between the object and a planned end-position.
        /// </summary>
        /// <param name="rigidBody">Rigid-body to test for</param>
        /// <param name="start">Start of the test-ray</param>
        /// <param name="end">End of the test-ray</param>
        /// <returns>Position on the ray which is still possible to place the rigid-body without collision</returns>
        public JVector DetectCollision(RigidBody rigidBody, JVector start, JVector end)
        {
            JVector p  = rigidBody.Position;
            JVector d  = end - start;
            JVector d5 = 5 * d;

            Collider collider = rigidBody as Collider;

            RigidBody resBody;
            JVector   hitNormal;
            float     fraction;

            bool result = World.CollisionSystem.Raycast(p, d5, RaycastCallback,
                                                        out resBody, out hitNormal, out fraction);

            if (result && resBody != rigidBody)
            {
                float   maxLength   = d.LengthSquared();
                JVector collisionAt = p + fraction * d5;
                JVector position    = GetPosition(collider, collisionAt, hitNormal);

                float ncLength = (position - p).LengthSquared();

                //resBody.Tag = BodyTag.DrawMe;
                //Debug.Log(fraction);
                //Debug.Log((resBody as Collider).GameObject.name);
                //World.AddBody(new RigidBody(new CylinderShape(1.0f, .25f)) { Position = p, IsStatic = true, PureCollider = true });
                //World.AddBody(new RigidBody(new CylinderShape(2.5f, 0.5f)) { Position = end, IsStatic = true, PureCollider = true });
                ////World.AddBody(new RigidBody(new CylinderShape(1.0f, 1.0f)) { Position = p + d5, IsStatic = true, PureCollider = true });
                //World.AddBody(new RigidBody(new CylinderShape(1.0f, 1.0f)) { Position = collisionAt, IsStatic = true, PureCollider = true });

                return(maxLength < ncLength ? end : position);
            }

            return(end);
        }
        /// <summary>
        /// Sets the current shape. First <see cref="Prepare"/> has to be called.
        /// After SetCurrentShape the shape immitates another shape.
        /// </summary>
        /// <param name="index"></param>
        public override void SetCurrentShape(int index)
        {
            vecs[0] = octree.GetVertex(octree.tris[potentialTriangles[index]].I0);
            vecs[1] = octree.GetVertex(octree.tris[potentialTriangles[index]].I1);
            vecs[2] = octree.GetVertex(octree.tris[potentialTriangles[index]].I2);

            JVector sum = vecs[0];

            JVector.Add(ref sum, ref vecs[1], out sum);
            JVector.Add(ref sum, ref vecs[2], out sum);
            JVector.Multiply(ref sum, 1.0f / 3.0f, out sum);


            geomCen = sum;

            JVector.Subtract(ref vecs[1], ref vecs[0], out sum);
            JVector.Subtract(ref vecs[2], ref vecs[0], out normal);
            JVector.Cross(ref sum, ref normal, out normal);

            if (flipNormal)
            {
                normal.Negate();
            }
        }
示例#31
0
 protected virtual void Update()
 {
     position = cacheTransform.position.ConvertToJVector();
     orientation = cacheTransform.rotation.ConvertToJMatrix();
 }
示例#32
0
        //object locker = new object();
        private void CollisionDetected(RigidBody body1, RigidBody body2, JVector point1, JVector point2, JVector normal,
                                       float penetration)
        {
            Arbiter arbiter;

            arbiterMap.LookUpArbiter(body1, body2, out arbiter);
            if (arbiter == null)
            {
                arbiter = Arbiter.Pool.GetNew();
                arbiter.body1 = body1;
                arbiter.body2 = body2;

                arbiterMap.Add(new ArbiterKey(body1, body2), arbiter);

                addedArbiterQueue.Enqueue(arbiter);

                events.RaiseBodiesBeginCollide(body1, body2);
            }

            Contact contact;

            if (arbiter.body1 == body1)
            {
                JVector.Negate(ref normal, out normal);
                contact = arbiter.AddContact(point1, point2, normal, penetration, contactSettings);
            }
            else
            {
                contact = arbiter.AddContact(point2, point1, normal, penetration, contactSettings);
            }

            if (contact != null) events.RaiseContactCreated(contact);
        }