예제 #1
0
        /// <summary>
        /// Builds a planar collision skin for the entity.
        /// </summary>
        /// <param name="normal">Normal of the plane.</param>
        /// <param name="distance">
        /// Distance along the normal to the plane. For instance, if the normal is (0,1,0), that
        /// is, the Y axis, the created plane will be y = distance.
        /// </param>
        public void BuildCollisionPlane(Vector3 normal, float distance)
        {
            JigLibX.Geometry.Plane plane = new JigLibX.Geometry.Plane(normal, distance);
            mCollisionSkin.RemoveAllPrimitives();
            mCollisionSkin.AddPrimitive(plane, mMaterialProperties);

            UpdateMaterialPropsOnCollisionSkin();
            UpdateMass();
        }
예제 #2
0
        /// <summary>
        /// CollDetect
        /// </summary>
        /// <param name="info"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == this.Type1)
            {
                CollisionSkin skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                int primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            // todo - proper swept test
            Sphere oldSphere = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Sphere;
            Sphere newSphere = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Sphere;

            JigLibX.Geometry.Plane oldPlane = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as JigLibX.Geometry.Plane;
            JigLibX.Geometry.Plane newPlane = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as JigLibX.Geometry.Plane;

            Matrix newPlaneInvTransform = newPlane.InverseTransformMatrix;
            Matrix oldPlaneInvTransform = oldPlane.InverseTransformMatrix;

            Vector3 oldSpherePos = Vector3.Transform(oldSphere.Position, oldPlaneInvTransform);
            Vector3 newSpherePos = Vector3.Transform(newSphere.Position, newPlaneInvTransform);

            // consider it a contact if either old or new are touching
            float oldDist = Distance.PointPlaneDistance(oldSpherePos, oldPlane);
            float newDist = Distance.PointPlaneDistance(newSpherePos, newPlane);

            if (System.Math.Min(newDist, oldDist) > collTolerance + newSphere.Radius)
            {
                return;
            }

            // collision - record depth using the old values
            float oldDepth = oldSphere.Radius - oldDist;

            // calc the world position based on the old position(s)
            Vector3 worldPos = oldSphere.Position - oldSphere.Radius * oldPlane.Normal;

#if WINDOWS_PHONE
            this.collInfo[0] = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, oldDepth);
            collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, this.collInfo, 1);
#else
            unsafe
            {
                SmallCollPointInfo collInfo = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, oldDepth);
                collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, &collInfo, 1);
            }
#endif
        }
예제 #3
0
        public static bool RayPlaneIntersection(out float t, Ray ray, Plane plane)
        {
            float dot = Vector3.Dot(ray.Dir, plane.Normal);
            if (System.Math.Abs(dot) < JiggleMath.Epsilon)
            {
                t = 0.0f;
                return false;
            }

            float dist = Distance.PointPlaneDistance(ray.Origin, plane);
            t = -dist / dot;
            return (t >= 0.0f);
        }
예제 #4
0
        public static bool LinePlaneIntersection(out float t, Line line, Plane plane)
        {
            float dot = Vector3.Dot(line.Dir, plane.Normal);

            if (System.Math.Abs(dot) < JiggleMath.Epsilon)
            {
                t = 0.0f;
                return false;
            }

            float dist = Distance.PointPlaneDistance(line.Origin,plane);
            t = -dist / dot;
            return true;
        }
예제 #5
0
파일: Plane.cs 프로젝트: bradleat/trafps
 public Plane GetInverse()
 {
     Plane plane = new Plane(this.normal, this.d);
     plane.Invert();
     return plane;
 }
예제 #6
0
파일: Plane.cs 프로젝트: bradleat/trafps
 public override Primitive Clone()
 {
     Plane newPlane = new Plane(this.Normal, this.D);
     newPlane.Transform = Transform;
     return newPlane;
 }
예제 #7
0
 /// <summary>
 /// PointPlaneDistance
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="plane"></param>
 /// <returns>float</returns>
 public static float PointPlaneDistance(ref Vector3 pt, Plane plane)
 {
     float num0;
     Vector3.Dot(ref plane.normal, ref pt, out num0);
     return plane.D + num0;
 }
예제 #8
0
 /// <summary>
 /// PointPlaneDistance
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="plane"></param>
 /// <returns>float</returns>
 public static float PointPlaneDistance(Vector3 pt, Plane plane)
 {
     return Vector3.Dot(plane.Normal, pt) + plane.D;
 }
예제 #9
0
        /// <summary>
        /// Detect BoxPlane Collisions.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == this.Type1)
            {
                CollisionSkin skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                int primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            Box oldBox = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Box;
            Box newBox = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Box;

            JPlane oldPlane = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as JPlane;
            JPlane newPlane = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as JPlane;

            Matrix  newPlaneInvTransform = newPlane.InverseTransformMatrix;
            Vector3 newBoxCen            = Vector3.Transform(newBox.GetCentre(), newPlaneInvTransform);

            // quick check
            float centreDist = Distance.PointPlaneDistance(newBoxCen, newPlane);

            if (centreDist > collTolerance + newBox.GetBoundingRadiusAroundCentre())
            {
                return;
            }

            Matrix oldPlaneInvTransform = oldPlane.InverseTransformMatrix;

            Vector3[] newPts;
            newBox.GetCornerPoints(out newPts);
            Vector3[] oldPts;
            oldBox.GetCornerPoints(out oldPts);

            unsafe
            {
#if USE_STACKALLOC
                SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI];
#else
                SmallCollPointInfo[] collPtArray = SCPIStackAlloc();
                fixed(SmallCollPointInfo *collPts = collPtArray)
#endif
                {
                    int numCollPts = 0;

                    for (int i = 0; i < 8; ++i)
                    {
                        Vector3.Transform(ref oldPts[i], ref oldPlaneInvTransform, out oldTransPts[i]);
                        Vector3.Transform(ref newPts[i], ref newPlaneInvTransform, out newPts[i]);

                        float oldDepth = -Distance.PointPlaneDistance(ref oldTransPts[i], oldPlane);
                        float newDepth = -Distance.PointPlaneDistance(ref newPts[i], newPlane);

                        if (MathHelper.Max(oldDepth, newDepth) > -collTolerance)
                        {
                            if (numCollPts < MaxLocalStackSCPI)
                            {
                                // BEN-OPTIMISATION: Now reuses instead of reallocating.
                                collPts[numCollPts].R0 = oldPts[i] - body0Pos;
                                collPts[numCollPts].R1 = oldPts[i] - body1Pos;
                                collPts[numCollPts++].InitialPenetration = oldDepth;
                            }
                        }
                    }

                    if (numCollPts > 0)
                    {
                        collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, collPts, numCollPts);
                    }
                }

#if !USE_STACKALLOC
                FreeStackAlloc(collPtArray);
#endif
            }
        }
예제 #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="info"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == this.Type1)
            {
                CollisionSkin skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                int primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            // todo - proper swept test
            Capsule oldCapsule = (Capsule)info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0);
            Capsule newCapsule = (Capsule)info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0);

            JigLibX.Geometry.Plane oldPlane = (JigLibX.Geometry.Plane)info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1);
            JigLibX.Geometry.Plane newPlane = (JigLibX.Geometry.Plane)info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1);

            Matrix newPlaneInvTransform = newPlane.InverseTransformMatrix;
            Matrix oldPlaneInvTransform = oldPlane.InverseTransformMatrix;

            unsafe
            {
#if USE_STACKALLOC
                SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI];
#else
                SmallCollPointInfo[] collPtArray = SCPIStackAlloc();
                fixed(SmallCollPointInfo *collPts = collPtArray)
#endif
                {
                    int numCollPts = 0;

                    // the start
                    {
                        Vector3 oldCapsuleStartPos = Vector3.Transform(oldCapsule.Position, oldPlaneInvTransform);
                        Vector3 newCapsuleStartPos = Vector3.Transform(newCapsule.Position, newPlaneInvTransform);

                        float oldDist = Distance.PointPlaneDistance(oldCapsuleStartPos, oldPlane);
                        float newDist = Distance.PointPlaneDistance(newCapsuleStartPos, newPlane);

                        if (MathHelper.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                        {
                            float oldDepth = oldCapsule.Radius - oldDist;
                            // calc the world position based on the old position8(s)
                            Vector3 worldPos = oldCapsule.Position - oldCapsule.Radius * oldPlane.Normal;
                            collPts[numCollPts++] = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, oldDepth);
                        }
                    }

                    // the end
                    {
                        Vector3 oldCapsuleEndPos = Vector3.Transform(oldCapsule.GetEnd(), oldPlaneInvTransform);
                        Vector3 newCapsuleEndPos = Vector3.Transform(newCapsule.GetEnd(), newPlaneInvTransform);
                        float   oldDist          = Distance.PointPlaneDistance(oldCapsuleEndPos, oldPlane);
                        float   newDist          = Distance.PointPlaneDistance(newCapsuleEndPos, newPlane);

                        if (System.Math.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                        {
                            float oldDepth = oldCapsule.Radius - oldDist;
                            // calc the world position based on the old position(s)
                            Vector3 worldPos = oldCapsule.GetEnd() - oldCapsule.Radius * oldPlane.Normal;
                            collPts[numCollPts++] = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, oldDepth);
                        }

                        if (numCollPts > 0)
                        {
                            collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, collPts, numCollPts);
                        }
                    }
                }

#if !USE_STACKALLOC
                FreeStackAlloc(collPtArray);
#endif
            }
        }
예제 #11
0
        public void GetHeightAndNormal(out float h, out Vector3 normal,Vector3 point)
        {
            float x = point.X;
            float z = point.Z;

            x = MathHelper.Clamp(x, xMin, xMax);
            z = MathHelper.Clamp(z, zMin, zMax);

            int i0 = (int)((x - xMin) / dx);
            int j0 = (int)((point.Z - zMin) / dz);

            i0 = (int)MathHelper.Clamp((int)i0, 0, mHeights.Nx - 1);
            j0 = (int)MathHelper.Clamp((int)j0, 0, mHeights.Nz - 1);

            int i1 = i0 + 1;
            int j1 = j0 + 1;

            if (i1 >= (int)mHeights.Nx) i1 = mHeights.Nx - 1;
            if (j1 >= (int)mHeights.Nz) j1 = mHeights.Nz - 1;

            float iFrac = (x - (i0 * dx + xMin)) / dx;
            float jFrac = (z - (j0 * dz + zMin)) / dz;

            iFrac = MathHelper.Clamp(iFrac, 0.0f, 1.0f);
            jFrac = MathHelper.Clamp(jFrac, 0.0f, 1.0f);

            float h00 = mHeights[i0, j0];
            float h01 = mHeights[i0, j1];
            float h10 = mHeights[i1, j0];
            float h11 = mHeights[i1, j1];

            // All the triangles are orientated the same way.
            // work out the normal, then z is in the plane of this normal
            if ((i0 == i1) && (j0 == j1))
            {
                normal = Vector3.Up;
            }
            else if (i0 == i1)
            {
                Vector3 right = Vector3.Right;
                normal = Vector3.Cross(new Vector3(0.0f, h01 - h00, dz),right);
                normal.Normalize();
            }

            if (j0 == j1)
            {
                Vector3 backw = Vector3.Backward;
                normal = Vector3.Cross(backw, new Vector3(dx, h10 - h00, 0.0f));
                normal.Normalize();
            }
            else if (iFrac > jFrac)
            {
                normal = Vector3.Cross(new Vector3(dx, h11 - h00, dz), new Vector3(dx, h10 - h00, 0.0f));
                normal.Normalize();
            }
            else
            {
                normal = Vector3.Cross(new Vector3(0.0f, h01 - h00, dz), new Vector3(dx, h11 - h00, dz));
                normal.Normalize();
            }

             // get the plane equation
             // h00 is in all the triangles
             JiggleMath.NormalizeSafe(ref normal);
             Plane plane = new Plane(normal, new Vector3((i0 * dx + xMin), h00, (j0 * dz + zMin)));

             h = Distance.PointPlaneDistance(point,plane);
        }
예제 #12
0
        /// <summary>
        /// CollDetect
        /// </summary>
        /// <param name="info"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == this.Type1)
            {
                CollisionSkin skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                int primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            // todo - proper swept test
            Capsule oldCapsule = (Capsule)info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0);
            Capsule newCapsule = (Capsule)info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0);

            JigLibX.Geometry.Plane oldPlane = (JigLibX.Geometry.Plane)info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1);
            JigLibX.Geometry.Plane newPlane = (JigLibX.Geometry.Plane)info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1);

            Matrix newPlaneInvTransform = newPlane.InverseTransformMatrix;
            Matrix oldPlaneInvTransform = oldPlane.InverseTransformMatrix;

            SmallCollPointInfo[] collPtArray = SCPIStackAlloc();
            {
                int numCollPts = 0;

                // the start
                {
                    Vector3 oldCapsuleStartPos = Vector3.Transform(oldCapsule.Position, oldPlaneInvTransform);
                    Vector3 newCapsuleStartPos = Vector3.Transform(newCapsule.Position, newPlaneInvTransform);

                    float oldDist = Distance.PointPlaneDistance(oldCapsuleStartPos, oldPlane);
                    float newDist = Distance.PointPlaneDistance(newCapsuleStartPos, newPlane);

                    if (MathHelper.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                    {
                        float oldDepth = oldCapsule.Radius - oldDist;
                        // calc the world position based on the old position8(s)
                        Vector3 worldPos = oldCapsule.Position - oldCapsule.Radius * oldPlane.Normal;

                        // BEN-OPTIMISATION: Now reuses existing collPts instead of reallocating.
                        collPtArray[numCollPts].R0 = worldPos - body0Pos;
                        collPtArray[numCollPts].R1 = worldPos - body1Pos;
                        collPtArray[numCollPts++].InitialPenetration = oldDepth;
                    }
                }

                // the end
                {
                    Vector3 oldCapsuleEndPos = Vector3.Transform(oldCapsule.GetEnd(), oldPlaneInvTransform);
                    Vector3 newCapsuleEndPos = Vector3.Transform(newCapsule.GetEnd(), newPlaneInvTransform);
                    float   oldDist          = Distance.PointPlaneDistance(oldCapsuleEndPos, oldPlane);
                    float   newDist          = Distance.PointPlaneDistance(newCapsuleEndPos, newPlane);

                    if (System.Math.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                    {
                        float oldDepth = oldCapsule.Radius - oldDist;
                        // calc the world position based on the old position(s)
                        Vector3 worldPos = oldCapsule.GetEnd() - oldCapsule.Radius * oldPlane.Normal;

                        // BEN-OPTIMISATION: Now reuses existing collPts instead of reallocating.
                        collPtArray[numCollPts].R0 = worldPos - body0Pos;
                        collPtArray[numCollPts].R1 = worldPos - body1Pos;
                        collPtArray[numCollPts++].InitialPenetration = oldDepth;
                    }

                    if (numCollPts > 0)
                    {
                        collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, collPtArray, numCollPts);
                    }
                }

                FreeStackAlloc(collPtArray);
            }
        }
예제 #13
0
 public static bool SegmentPlaneIntersection(out float tS, Segment seg, Plane plane)
 {
     float denom = Vector3.Dot(plane.Normal, seg.Delta);
     if (System.Math.Abs(denom) > JiggleMath.Epsilon)
     {
         float t = -(Vector3.Dot(plane.Normal, seg.Origin) + plane.D) / denom;
         if (t < 0.0f || t > 1.0f)
         {
             tS = 0.0f;
             return false;
         }
         tS = t;
         return true;
     }
     else
     {
         // parallel - return false even if it's in the plane
         tS = 0.0f;
         return false;
     }
 }
예제 #14
0
        public void CreatePlane(Vector3 normal, float d)
        {
            this.collisionSkin = new CollisionSkin(null);

            JigLibX.Geometry.Plane primitivePlane =
                new JigLibX.Geometry.Plane(normal, d);

            MaterialProperties materialProp = new MaterialProperties(
                elasticity, staticRoughness, dynamicRoughness);

            CollisionSkin.AddPrimitive(primitivePlane, materialProp);

            PhysicsSystem.CurrentPhysicsSystem.CollisionSystem.AddCollisionSkin(this.CollisionSkin);
            Body.CollisionSkin = CollisionSkin;
            CollisionSkin.Owner = Body;
        }