public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var info = infoOrig;


            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldSphere = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Sphere;
            var newSphere = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Sphere;

            var oldCapsule = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Capsule;
            var newCapsule = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Capsule;

            var oldSeg = new Segment(oldCapsule.Position, oldCapsule.Length * oldCapsule.Orientation.Backward);
            var newSeg = new Segment(oldCapsule.Position, newCapsule.Length * newCapsule.Orientation.Backward);

            var radSum = newCapsule.Radius + newSphere.Radius;

            var oldDistSq = Distance.PointSegmentDistanceSq(out var oldt, oldSphere.Position, oldSeg);
            var newDistSq = Distance.PointSegmentDistanceSq(out var newt, newSphere.Position, newSeg);

            if (MathHelper.Min(oldDistSq, newDistSq) < (radSum + collTolerance) * (radSum + collTolerance))
            {
                var segPos = oldSeg.GetPoint(oldt);
                var delta  = oldSphere.Position - segPos;

                var dist  = (float)System.Math.Sqrt(oldDistSq);
                var depth = radSum - dist;

                if (dist > JiggleMath.Epsilon)
                {
                    delta /= dist;
                }
                else
                {
                    delta = Vector3.TransformNormal(Vector3.Backward, Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(random.Next(360))));
                }

                var worldPos = segPos + (oldCapsule.Radius - 0.5f * depth) * delta;
                unsafe
                {
                    var collInfo = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, depth);

                    collisionFunctor.CollisionNotify(ref info, ref delta, &collInfo, 1);
                }
            }
        }
Beispiel #2
0
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var info = infoOrig;

            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldSphere = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Sphere;
            var newSphere = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Sphere;

            var oldBox = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Box;
            var newBox = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Box;

            var oldDist = oldBox.GetDistanceToPoint(out var oldBoxPoint, oldSphere.Position);
            var newDist = newBox.GetDistanceToPoint(out var newBoxPoint, newSphere.Position);


            var oldDepth = oldSphere.Radius - oldDist;
            var newDepth = newSphere.Radius - newDist;

            if (System.Math.Max(oldDepth, newDepth) > -collTolerance)
            {
                Vector3 dir;
                if (oldDist < -JiggleMath.Epsilon)
                {
                    dir = oldBoxPoint - oldSphere.Position - oldBoxPoint;
                    JiggleMath.NormalizeSafe(ref dir);
                }
                else if (oldDist > JiggleMath.Epsilon)
                {
                    dir = oldSphere.Position - oldBoxPoint;
                    JiggleMath.NormalizeSafe(ref dir);
                }
                else
                {
                    dir = oldSphere.Position - oldBox.GetCentre();
                    JiggleMath.NormalizeSafe(ref dir);
                }

                unsafe
                {
                    var collInfo = new SmallCollPointInfo(oldBoxPoint - body0Pos, oldBoxPoint - body1Pos, oldDepth);


                    collisionFunctor.CollisionNotify(ref info, ref dir, &collInfo, 1);
                }
            }
        }
Beispiel #3
0
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldSphere = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Sphere;
            var newSphere = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Sphere;

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

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

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


            var oldDist = Distance.PointPlaneDistance(oldSpherePos, oldPlane);
            var newDist = Distance.PointPlaneDistance(newSpherePos, newPlane);

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


            var oldDepth = oldSphere.Radius - oldDist;


            var worldPos = oldSphere.Position - oldSphere.Radius * oldPlane.Normal;

            unsafe
            {
                var collInfo = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, oldDepth);
                collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, &collInfo, 1);
            }
        }
Beispiel #4
0
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldCapsule0 = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Capsule;
            var newCapsule0 = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Capsule;
            var oldSeg0     = new Segment(oldCapsule0.Position, oldCapsule0.Length * oldCapsule0.Orientation.Backward);
            var newSeg0     = new Segment(newCapsule0.Position, newCapsule0.Length * newCapsule0.Orientation.Backward);

            var oldCapsule1 = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Capsule;
            var newCapsule1 = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Capsule;
            var oldSeg1     = new Segment(oldCapsule1.Position, oldCapsule1.Length * oldCapsule1.Orientation.Backward);
            var newSeg1     = new Segment(newCapsule1.Position, newCapsule1.Length * newCapsule1.Orientation.Backward);

            var radSum = newCapsule0.Radius + newCapsule1.Radius;

            var oldDistSq = Distance.SegmentSegmentDistanceSq(out var oldt0, out var oldt1, oldSeg0, oldSeg1);
            var newDistSq = Distance.SegmentSegmentDistanceSq(out var newt0, out var newt1, newSeg0, newSeg1);

            if (System.Math.Min(oldDistSq, newDistSq) < (radSum + collTolerance) * (radSum + collTolerance))
            {
                var pos0 = oldSeg0.GetPoint(oldt0);
                var pos1 = oldSeg1.GetPoint(oldt1);

                var delta = pos0 - pos1;

                var dist  = (float)System.Math.Sqrt(oldDistSq);
                var depth = radSum - dist;

                if (dist > JiggleMath.Epsilon)
                {
                    delta /= dist;
                }
                else
                {
                    delta = Vector3.TransformNormal(Vector3.Backward, Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(random.Next(360))));
                }

                var worldPos = pos1 + (oldCapsule1.Radius - 0.5f * depth) * delta;

                unsafe
                {
                    var collInfo = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, depth);
                    collisionFunctor.CollisionNotify(ref info, ref delta, &collInfo, 1);
                }
            }
        }
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldSphere0 = (Sphere)info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0);
            var newSphere0 = (Sphere)info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0);
            var oldSphere1 = (Sphere)info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1);
            var newSphere1 = (Sphere)info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1);

            var oldDelta = oldSphere0.Position - oldSphere1.Position;
            var newDelta = newSphere0.Position - oldSphere1.Position;

            var oldDistSq = oldDelta.LengthSquared();
            var newDistSq = newDelta.LengthSquared();

            var radSum = newSphere0.Radius + newSphere1.Radius;

            if (System.Math.Min(oldDistSq, newDistSq) < (radSum + collTolerance) * (radSum + collTolerance))
            {
                var oldDist = (float)System.Math.Sqrt(oldDistSq);
                var depth   = radSum - oldDist;

                if (oldDist > JiggleMath.Epsilon)
                {
                    oldDelta /= oldDist;
                }
                else
                {
                    oldDelta = Vector3.TransformNormal(Vector3.Backward, Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(random.Next(360))));
                }

                var worldPos = oldSphere1.Position + (oldSphere1.Radius - 0.5f * depth) * oldDelta;

                unsafe
                {
                    var collInfo = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, depth);

                    collisionFunctor.CollisionNotify(ref info, ref oldDelta, &collInfo, 1);
                }
            }
        }
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var info = infoOrig;

            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldSphere = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Sphere;
            var newSphere = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Sphere;

            var oldHeightmap = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Heightmap;
            var newHeightmap = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Heightmap;

            newHeightmap.GetHeightAndNormal(out var newDist, out var normal, newSphere.Position);
            if (newDist < collTolerance + newSphere.Radius)
            {
                var oldDist = oldHeightmap.GetHeight(oldSphere.Position);
                var depth   = oldSphere.Radius - oldDist;


                var oldPt = oldSphere.Position - oldSphere.Radius * normal;
                unsafe
                {
                    var ptInfo = new SmallCollPointInfo(oldPt - body0Pos, oldPt - body1Pos, depth);

                    collisionFunctor.CollisionNotify(ref info, ref normal, &ptInfo, 1);
                }
            }
        }
Beispiel #7
0
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var info = infoOrig;

            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


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

            var oldHeightmap = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Heightmap;
            var newHeightmap = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Heightmap;

            oldBox.GetCornerPoints(out var oldPts);
            newBox.GetCornerPoints(out var newPts);

            unsafe
            {
                var collPts = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                {
                    var numCollPts = 0;

                    var collNormal = Vector3.Zero;

                    for (var i = 0; i < 8; ++i)
                    {
                        var newPt = newPts[i];
                        newHeightmap.GetHeightAndNormal(out var newDist, out var normal, newPt);

                        if (newDist < collTolerance)
                        {
                            var oldPt   = oldPts[i];
                            var oldDist = oldHeightmap.GetHeight(oldPt);

                            Vector3.Subtract(ref oldPt, ref body0Pos, out var pt0);
                            Vector3.Subtract(ref oldPt, ref body1Pos, out var pt1);
                            if (numCollPts < MaxLocalStackScpi)
                            {
                                collPts[numCollPts].R0 = pt0;
                                collPts[numCollPts].R1 = pt1;
                                collPts[numCollPts++].InitialPenetration = -oldDist;
                            }

                            Vector3.Add(ref collNormal, ref normal, out collNormal);
                        }
                    }

                    if (numCollPts > 0)
                    {
                        JiggleMath.NormalizeSafe(ref collNormal);
                        collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts);
                    }
                }
            }
        }
Beispiel #8
0
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldCapsule = (Capsule)info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0);
            var newCapsule = (Capsule)info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0);

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

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

            unsafe
            {
                var collPts = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                {
                    var numCollPts = 0;


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

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

                        if (MathHelper.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                        {
                            var oldDepth = oldCapsule.Radius - oldDist;

                            var worldPos = oldCapsule.Position - oldCapsule.Radius * oldPlane.Normal;


                            collPts[numCollPts].R0 = worldPos - body0Pos;
                            collPts[numCollPts].R1 = worldPos - body1Pos;
                            collPts[numCollPts++].InitialPenetration = oldDepth;
                        }
                    }


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

                        if (System.Math.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                        {
                            var oldDepth = oldCapsule.Radius - oldDist;

                            var worldPos = oldCapsule.GetEnd() - oldCapsule.Radius * oldPlane.Normal;


                            collPts[numCollPts].R0 = worldPos - body0Pos;
                            collPts[numCollPts].R1 = worldPos - body1Pos;
                            collPts[numCollPts++].InitialPenetration = oldDepth;
                        }

                        if (numCollPts > 0)
                        {
                            collisionFunctor.CollisionNotify(ref info, ref oldPlane.normal, collPts, numCollPts);
                        }
                    }
                }
            }
        }
Beispiel #9
0
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var box0 = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Box;
            var box1 = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Box;

            var oldBox0 = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Box;
            var oldBox1 = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Box;

            var dirs0 = box0.Orientation;
            var dirs1 = box1.Orientation;

            var box0_Right    = dirs0.Right;
            var box0_Up       = dirs0.Up;
            var box0_Backward = dirs0.Backward;

            var box1_Right    = dirs1.Right;
            var box1_Up       = dirs1.Up;
            var box1_Backward = dirs1.Backward;

            if (Disjoint(out var testDepth, ref box0_Right, box0, box1, collTolerance))
            {
                return;
            }

            var depth   = testDepth;
            var N       = box0_Right;
            var minAxis = 0;

            if (Disjoint(out testDepth, ref box0_Up, box0, box1, collTolerance))
            {
                return;
            }

            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = box0_Up;
                minAxis = 1;
            }

            if (Disjoint(out testDepth, ref box0_Backward, box0, box1, collTolerance))
            {
                return;
            }

            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = box0_Backward;
                minAxis = 2;
            }

            if (Disjoint(out testDepth, ref box1_Right, box0, box1, collTolerance))
            {
                return;
            }

            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = box1_Right;
                minAxis = 3;
            }

            if (Disjoint(out testDepth, ref box1_Up, box0, box1, collTolerance))
            {
                return;
            }

            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = box1_Up;
                minAxis = 4;
            }

            if (Disjoint(out testDepth, ref box1_Backward, box0, box1, collTolerance))
            {
                return;
            }

            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = box1_Backward;
                minAxis = 5;
            }

            Vector3.Cross(ref box0_Right, ref box1_Right, out var axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 6;
            }

            Vector3.Cross(ref box0_Right, ref box1_Up, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 7;
            }

            Vector3.Cross(ref box0_Right, ref box1_Backward, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 8;
            }

            Vector3.Cross(ref box0_Up, ref box1_Right, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 9;
            }

            Vector3.Cross(ref box0_Up, ref box1_Up, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 10;
            }

            Vector3.Cross(ref box0_Up, ref box1_Backward, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 11;
            }

            Vector3.Cross(ref box0_Backward, ref box1_Right, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 12;
            }

            Vector3.Cross(ref box0_Backward, ref box1_Up, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 13;
            }

            Vector3.Cross(ref box0_Backward, ref box1_Backward, out axis);
            if (Disjoint(out testDepth, ref axis, box0, box1, collTolerance))
            {
                return;
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth   = testDepth;
                N       = axis;
                minAxis = 14;
            }

            var D = box1.GetCentre() - box0.GetCentre();

            N.Normalize();
            int i;

            /*seperatingAxes[0] = dirs0.Right;
             * seperatingAxes[1] = dirs0.Up;
             * seperatingAxes[2] = dirs0.Backward;
             * seperatingAxes[3] = dirs1.Right;
             * seperatingAxes[4] = dirs1.Up;
             * seperatingAxes[5] = dirs1.Backward;
             * Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[3], out seperatingAxes[6]);
             * Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[4], out seperatingAxes[7]);
             * Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[5], out seperatingAxes[8]);
             * Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[3], out seperatingAxes[9]);
             * Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[4], out seperatingAxes[10]);
             * Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[5], out seperatingAxes[11]);
             * Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[3], out seperatingAxes[12]);
             * Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[4], out seperatingAxes[13]);
             * Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[5], out seperatingAxes[14]);
             *
             *
             *
             *
             * int i;
             * for (i = 0; i < 15; ++i)
             * {
             *
             *  float l2 = seperatingAxes[i].LengthSquared();
             *
             *  if (l2 < JiggleMath.Epsilon) continue;
             *
             *  overlapDepth[i] = float.MaxValue;
             *
             *  if (Disjoint(out overlapDepth[i], ref seperatingAxes[i], box0, box1, collTolerance))
             *      return;
             * }
             *
             *
             * float minDepth = float.MaxValue;
             * int minAxis = -1;
             *
             * for (i = 0; i < 15; ++i)
             * {
             *
             *  float l2 = seperatingAxes[i].LengthSquared();
             *  if (l2 < JiggleMath.Epsilon) continue;
             *
             *
             *  float invl = 1.0f / (float)System.Math.Sqrt(l2);
             *  seperatingAxes[i] *= invl;
             *  overlapDepth[i] *= invl;
             *
             *
             *  if (overlapDepth[i] < minDepth)
             *  {
             *      minDepth = overlapDepth[i];
             *      minAxis = i;
             *  }
             * }
             *
             * if (minAxis == -1)
             *  return;
             *
             *
             *
             * Vector3 D = box1.GetCentre() - box0.GetCentre();
             * Vector3 N = seperatingAxes[minAxis];
             * float depth = overlapDepth[minAxis];*/

            if (Vector3.Dot(D, N) > 0.0f)
            {
                N *= -1.0f;
            }

            var minA = MathHelper.Min(box0.SideLengths.X, MathHelper.Min(box0.SideLengths.Y, box0.SideLengths.Z));
            var minB = MathHelper.Min(box1.SideLengths.X, MathHelper.Min(box1.SideLengths.Y, box1.SideLengths.Z));

            var combinationDist = 0.05f * MathHelper.Min(minA, minB);


            var contactPointsFromOld = true;

            contactPts.Clear();

            if (depth > -JiggleMath.Epsilon)
            {
                GetBoxBoxIntersectionPoints(contactPts, oldBox0, oldBox1, combinationDist, collTolerance);
            }

            var numPts = contactPts.Count;

            if (numPts == 0)
            {
                contactPointsFromOld = false;
                GetBoxBoxIntersectionPoints(contactPts, box0, box1, combinationDist, collTolerance);
            }

            numPts = contactPts.Count;

            var body0OldPos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1OldPos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;
            var body0NewPos = info.Skin0.Owner?.Position ?? Vector3.Zero;
            var body1NewPos = info.Skin1.Owner?.Position ?? Vector3.Zero;

            Vector3.Subtract(ref body0NewPos, ref body0OldPos, out var bodyDelta);
            Vector3.Subtract(ref bodyDelta, ref body1NewPos, out bodyDelta);
            Vector3.Add(ref bodyDelta, ref body1OldPos, out bodyDelta);

            Vector3.Dot(ref bodyDelta, ref N, out var bodyDeltaLen);

            var oldDepth = depth + bodyDeltaLen;

            unsafe
            {
                var collPts = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                {
                    var numCollPts = 0;

                    Vector3 SATPoint;

                    switch (minAxis)
                    {
                    case 0:
                    case 1:
                    case 2:
                    {
                        GetSupportPoint(out SATPoint, box1, -N);
                        break;
                    }

                    case 3:
                    case 4:
                    case 5:
                    {
                        GetSupportPoint(out SATPoint, box0, N);
                        break;
                    }

                    default:
                        /*case 6:
                         * case 7:
                         * case 8:
                         * case 9:
                         * case 10:
                         * case 11:
                         * case 12:
                         * case 13:
                         * case 14:*/
                    {
                        {
                            i = minAxis - 6;
                            var ia = i / 3;
                            var ib = i - ia * 3;

                            GetSupportPoint(out var P0, box0, N);
                            GetSupportPoint(out var P1, box1, -N);


                            JiggleUnsafe.Get(ref box0.transform.Orientation, ia, out var box0Orient);
                            JiggleUnsafe.Get(ref box1.transform.Orientation, ib, out var box1Orient);

                            Vector3.Cross(ref N, ref box1Orient, out var planeNormal);

                            Vector3.Dot(ref planeNormal, ref P1, out var planeD);


                            Vector3.Dot(ref box0Orient, ref planeNormal, out var div);


                            if (System.Math.Abs(div) < JiggleMath.Epsilon)
                            {
                                return;
                            }

                            var t = (planeD - Vector3.Dot(P0, planeNormal)) / div;


                            P0 = Vector3.Add(Vector3.Multiply(box0Orient, t), P0);

                            Vector3.Multiply(ref N, 0.5f * depth, out SATPoint);
                            Vector3.Add(ref SATPoint, ref P0, out SATPoint);
                        }
                        break;
                    }

                        /*default:
                         *  throw new Exception("Impossible switch");*/
                    }


                    if (numPts > 0)
                    {
                        var minDist = float.MaxValue;
                        var maxDist = float.MinValue;
                        for (i = 0; i < numPts; ++i)
                        {
                            var dist = Distance.PointPointDistance(contactPts[i].Pos, SATPoint);
                            if (dist < minDist)
                            {
                                minDist = dist;
                            }
                            if (dist > maxDist)
                            {
                                maxDist = dist;
                            }
                        }

                        if (maxDist < minDist + JiggleMath.Epsilon)
                        {
                            maxDist = minDist + JiggleMath.Epsilon;
                        }


                        for (i = 0; i < numPts; ++i)
                        {
                            var minDepthScale = 0.0f;
                            var dist          = Distance.PointPointDistance(contactPts[i].Pos, SATPoint);

                            var depthDiv   = System.Math.Max(JiggleMath.Epsilon, maxDist - minDist);
                            var depthScale = (dist - minDist) / depthDiv;

                            depth = (1.0f - depthScale) * oldDepth + minDepthScale * depthScale * oldDepth;

                            if (contactPointsFromOld)
                            {
                                if (numCollPts < MaxLocalStackScpi)
                                {
                                    collPts[numCollPts].R0 = contactPts[i].Pos - body0OldPos;
                                    collPts[numCollPts].R1 = contactPts[i].Pos - body1OldPos;
                                    collPts[numCollPts++].InitialPenetration = depth;
                                }
                            }
                            else
                            {
                                if (numCollPts < MaxLocalStackScpi)
                                {
                                    collPts[numCollPts].R0 = contactPts[i].Pos - body0NewPos;
                                    collPts[numCollPts].R1 = contactPts[i].Pos - body1NewPos;
                                    collPts[numCollPts++].InitialPenetration = depth;
                                }
                            }
                        }
                    }
                    else
                    {
                        Vector3.Subtract(ref SATPoint, ref body0NewPos, out var cp0);

                        Vector3.Subtract(ref SATPoint, ref body1NewPos, out var cp1);

                        if (numCollPts < MaxLocalStackScpi)
                        {
                            collPts[numCollPts].R0 = cp0;
                            collPts[numCollPts].R1 = cp1;
                            collPts[numCollPts++].InitialPenetration = oldDepth;
                        }
                    }


                    collisionFunctor.CollisionNotify(ref info, ref N, collPts, numCollPts);
                }
            }
        }
Beispiel #10
0
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var info = infoOrig;

            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldCapsule = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Capsule;
            var newCapsule = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Capsule;

            var oldHeightmap = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Heightmap;
            var newHeightmap = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Heightmap;

            unsafe
            {
                var collPts = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                {
                    var numCollPts    = 0;
                    var averageNormal = Vector3.Zero;


                    {
                        oldHeightmap.GetHeightAndNormal(out var oldDist, out var normal, oldCapsule.Position);
                        newHeightmap.GetHeightAndNormal(out var newDist, out normal, newCapsule.Position);

                        if (MathHelper.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                        {
                            var oldDepth = oldCapsule.Radius - oldDist;

                            var worldPos = oldCapsule.Position - oldCapsule.Radius * normal;
                            if (numCollPts < MaxLocalStackScpi)
                            {
                                collPts[numCollPts].R0 = worldPos - body0Pos;
                                collPts[numCollPts].R1 = worldPos - body1Pos;
                                collPts[numCollPts++].InitialPenetration = oldDepth;
                            }

                            averageNormal += normal;
                        }
                    }

                    {
                        var oldEnd = oldCapsule.GetEnd();
                        var newEnd = newCapsule.GetEnd();
                        oldHeightmap.GetHeightAndNormal(out var oldDist, out var normal, oldEnd);
                        newHeightmap.GetHeightAndNormal(out var newDist, out normal, newEnd);
                        if (MathHelper.Min(newDist, oldDist) < collTolerance + newCapsule.Radius)
                        {
                            var oldDepth = oldCapsule.Radius - oldDist;

                            var worldPos = oldEnd - oldCapsule.Radius * normal;
                            if (numCollPts < MaxLocalStackScpi)
                            {
                                collPts[numCollPts].R0 = worldPos - body0Pos;
                                collPts[numCollPts].R1 = worldPos - body1Pos;
                                collPts[numCollPts++].InitialPenetration = oldDepth;
                            }

                            averageNormal += normal;
                        }
                    }

                    if (numCollPts > 0)
                    {
                        JiggleMath.NormalizeSafe(ref averageNormal);
                        collisionFunctor.CollisionNotify(ref info, ref averageNormal, collPts, numCollPts);
                    }
                }
            }
        }
        private void CollDetectCapsuleStaticMeshOverlap(Capsule oldCapsule, Capsule newCapsule, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;

            var capsuleTolR  = collTolerance + newCapsule.Radius;
            var capsuleTolR2 = capsuleTolR * capsuleTolR;

            var collNormal = Vector3.Zero;

            var bb = BoundingBoxHelper.InitialBox;

            BoundingBoxHelper.AddCapsule(newCapsule, ref bb);

            unsafe
            {
                var collPts            = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                var potentialTriangles = stackalloc int[MaxLocalStackTris];
                {
                    {
                        var numCollPts = 0;

                        var numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb);

                        var capsuleStart     = newCapsule.Position;
                        var capsuleEnd       = newCapsule.GetEnd();
                        var meshInvTransform = mesh.InverseTransformMatrix;

                        var meshSpaceCapsuleStart = Vector3.Transform(capsuleStart, meshInvTransform);
                        var meshSpaceCapsuleEnd   = Vector3.Transform(capsuleEnd, meshInvTransform);

                        for (var iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                        {
                            var meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]);


                            var distToStart = meshTriangle.Plane.DotCoordinate(meshSpaceCapsuleStart);
                            var distToEnd   = meshTriangle.Plane.DotCoordinate(meshSpaceCapsuleEnd);


                            if (distToStart > capsuleTolR && distToEnd > capsuleTolR || distToStart < -capsuleTolR && distToEnd < -capsuleTolR)
                            {
                                continue;
                            }


                            meshTriangle.GetVertexIndices(out var i0, out var i1, out var i2);

                            mesh.GetVertex(i0, out var triVec0);
                            mesh.GetVertex(i1, out var triVec1);
                            mesh.GetVertex(i2, out var triVec2);


                            var transformMatrix = mesh.TransformMatrix;
                            Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0);
                            Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1);
                            Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2);
                            var triangle = new Triangle(ref triVec0, ref triVec1, ref triVec2);

                            var seg = new Segment(capsuleStart, capsuleEnd - capsuleStart);

                            var d2 = Distance.SegmentTriangleDistanceSq(out var tS, out var tT0, out var tT1, seg, triangle);

                            if (d2 < capsuleTolR2)
                            {
                                var oldCapsuleStart = oldCapsule.Position;
                                var oldCapsuleEnd   = oldCapsule.GetEnd();
                                var oldSeg          = new Segment(oldCapsuleStart, oldCapsuleEnd - oldCapsuleStart);
                                d2 = Distance.SegmentTriangleDistanceSq(out tS, out tT0, out tT1, oldSeg, triangle);

                                var dist       = (float)System.Math.Sqrt(d2);
                                var depth      = oldCapsule.Radius - dist;
                                var pt         = triangle.GetPoint(tT0, tT1);
                                var collisionN = d2 > JiggleMath.Epsilon ? JiggleMath.NormalizeSafe(oldSeg.GetPoint(tS) - pt) : meshTriangle.Plane.Normal;
                                if (numCollPts < MaxLocalStackScpi)
                                {
                                    collPts[numCollPts].R0 = pt - body0Pos;
                                    collPts[numCollPts].R1 = pt - body1Pos;
                                    collPts[numCollPts++].InitialPenetration = depth;
                                }

                                collNormal += collisionN;
                            }
                        }

                        if (numCollPts > 0)
                        {
                            JiggleMath.NormalizeSafe(ref collNormal);
                            collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts);
                        }
                    }
                }
            }
        }
Beispiel #12
0
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;

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

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

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


            var centreDist = Distance.PointPlaneDistance(newBoxCen, newPlane);

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

            var oldPlaneInvTransform = oldPlane.InverseTransformMatrix;

            newBox.GetCornerPoints(out var newPts);
            oldBox.GetCornerPoints(out var oldPts);

            unsafe
            {
                var collPts = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                {
                    var numCollPts = 0;

                    for (var 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]);

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

                        if (MathHelper.Max(oldDepth, newDepth) > -collTolerance)
                        {
                            if (numCollPts < MaxLocalStackScpi)
                            {
                                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);
                    }
                }
            }
        }
Beispiel #13
0
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var info = infoOrig;

            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == Type1)
            {
                var skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                var primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;


            var oldCapsule = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Capsule;
            var newCapsule = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Capsule;
            var oldSeg     = new Segment(oldCapsule.Position, oldCapsule.Length * oldCapsule.Orientation.Backward);
            var newSeg     = new Segment(newCapsule.Position, newCapsule.Length * newCapsule.Orientation.Backward);

            var radius = oldCapsule.Radius;

            var oldBox = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Box;
            var newBox = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Box;

            var oldDistSq = Distance.SegmentBoxDistanceSq(out var oldSegT, out var oldBoxT0, out var oldBoxT1, out var oldBoxT2, oldSeg, oldBox);
            var newDistSq = Distance.SegmentBoxDistanceSq(out var newSegT, out var newBoxT0, out var newBoxT1, out var newBoxT2, newSeg, newBox);

            if (MathHelper.Min(oldDistSq, newDistSq) < (radius + collTolerance) * (radius + collTolerance))
            {
                var segPos = oldSeg.GetPoint(oldSegT);
                var boxPos = oldBox.GetCentre() + oldBoxT0 * oldBox.Orientation.Right + oldBoxT1 * oldBox.Orientation.Up + oldBoxT2 * oldBox.Orientation.Backward;

                var dist  = (float)System.Math.Sqrt(oldDistSq);
                var depth = radius - dist;

                Vector3 dir;

                if (dist > JiggleMath.Epsilon)
                {
                    dir = segPos - boxPos;
                    JiggleMath.NormalizeSafe(ref dir);
                }
                else if ((segPos - oldBox.GetCentre()).LengthSquared() > JiggleMath.Epsilon)
                {
                    dir = segPos - oldBox.GetCentre();
                    JiggleMath.NormalizeSafe(ref dir);
                }
                else
                {
                    dir = Vector3.Transform(Vector3.Backward, Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(random.Next(360))));
                }

                unsafe
                {
                    var collInfo = new SmallCollPointInfo(boxPos - body0Pos, boxPos - body1Pos, depth);

                    collisionFunctor.CollisionNotify(ref info, ref dir, &collInfo, 1);
                }
            }
        }
        private static bool DoOverlapBoxTriangleTest(Box oldBox, Box newBox, ref IndexedTriangle triangle, TriangleMesh mesh, ref CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var dirs0 = newBox.Orientation;

            mesh.GetVertex(triangle.GetVertexIndex(0), out var triVec0);
            mesh.GetVertex(triangle.GetVertexIndex(1), out var triVec1);
            mesh.GetVertex(triangle.GetVertexIndex(2), out var triVec2);


            var transformMatrix = mesh.TransformMatrix;

            Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0);
            Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1);
            Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2);

            var tri = new Triangle(ref triVec0, ref triVec1, ref triVec2);


            tri.GetPoint(0, out var pt0);
            tri.GetPoint(1, out var pt1);

            Vector3.Subtract(ref pt1, ref pt0, out var triEdge0);

            tri.GetPoint(2, out var pt2);

            Vector3.Subtract(ref pt2, ref pt1, out var triEdge1);

            Vector3.Subtract(ref pt0, ref pt2, out var triEdge2);

            triEdge0.Normalize();
            triEdge1.Normalize();
            triEdge2.Normalize();

            var triNormal = triangle.Plane.Normal;
            var right     = dirs0.Right;
            var up        = dirs0.Up;
            var backward  = dirs0.Backward;

            if (Disjoint(out var testDepth, ref triNormal, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            var depth = testDepth;
            var N     = triNormal;

            if (Disjoint(out testDepth, ref right, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            if (testDepth < depth)
            {
                depth = testDepth;
                N     = right;
            }

            if (Disjoint(out testDepth, ref up, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            if (testDepth < depth)
            {
                depth = testDepth;
                N     = up;
            }

            if (Disjoint(out testDepth, ref backward, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            if (testDepth < depth)
            {
                depth = testDepth;
                N     = backward;
            }

            Vector3.Cross(ref right, ref triEdge0, out var axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref right, ref triEdge1, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref right, ref triEdge2, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref up, ref triEdge0, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref up, ref triEdge1, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref up, ref triEdge2, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref backward, ref triEdge0, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref backward, ref triEdge1, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            Vector3.Cross(ref backward, ref triEdge2, out axis);
            if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance))
            {
                return(false);
            }

            testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
            if (testDepth < depth)
            {
                depth = testDepth;
                N     = axis;
            }

            var D = newBox.GetCentre() - tri.Centre;

            N.Normalize();
            int i;

            if (Vector3.Dot(D, N) < 0.0f)
            {
                N *= -1;
            }

            var boxOldPos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var boxNewPos = info.Skin0.Owner?.Position ?? Vector3.Zero;
            var meshPos   = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;

            var pts = new List <Vector3>();


            const float combinationDist = 0.05f;

            GetBoxTriangleIntersectionPoints(pts, newBox, tri, depth + combinationDist);


            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out var delta);

            Vector3.Dot(ref delta, ref N, out var oldDepth);
            oldDepth += depth;

            unsafe
            {
                var numPts  = pts.Count;
                var collPts = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                {
                    if (numPts > 0)
                    {
                        if (numPts >= MaxLocalStackScpi)
                        {
                            numPts = MaxLocalStackScpi - 1;
                        }


                        for (i = 0; i < numPts; ++i)
                        {
                            collPts[i].R0.X = pts[i].X - boxNewPos.X;
                            collPts[i].R0.Y = pts[i].Y - boxNewPos.Y;
                            collPts[i].R0.Z = pts[i].Z - boxNewPos.Z;

                            collPts[i].R1.X = pts[i].X - meshPos.X;
                            collPts[i].R1.Y = pts[i].Y - meshPos.Y;
                            collPts[i].R1.Z = pts[i].Z - meshPos.Z;

                            collPts[i].InitialPenetration = oldDepth;
                        }

                        collisionFunctor.CollisionNotify(ref info, ref N, collPts, numPts);
                        return(true);
                    }
                    return(false);
                }
            }
        }
        public static void CollDetectSphereStaticMeshOverlap(BoundingSphere oldSphere, BoundingSphere newSphere, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
            var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;

            var sphereTolR  = collTolerance + newSphere.Radius;
            var sphereTolR2 = sphereTolR * sphereTolR;

            unsafe
            {
                var collPts            = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                var potentialTriangles = stackalloc int[MaxLocalStackTris];
                {
                    {
                        var numCollPts = 0;

                        var collNormal = Vector3.Zero;

                        var bb = BoundingBoxHelper.InitialBox;
                        BoundingBoxHelper.AddSphere(newSphere, ref bb);
                        var numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb);


                        var newSphereCen = Vector3.Transform(newSphere.Center, mesh.InverseTransformMatrix);
                        var oldSphereCen = Vector3.Transform(oldSphere.Center, mesh.InverseTransformMatrix);

                        for (var iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                        {
                            var meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]);
                            var distToCentre = meshTriangle.Plane.DotCoordinate(newSphereCen);


                            if (distToCentre < -sphereTolR || distToCentre > sphereTolR)
                            {
                                continue;
                            }

                            meshTriangle.GetVertexIndices(out var i0, out var i1, out var i2);

                            var triangle = new Triangle(mesh.GetVertex(i0), mesh.GetVertex(i1), mesh.GetVertex(i2));

                            var newD2 = Distance.PointTriangleDistanceSq(out var s, out var t, newSphereCen, triangle);

                            if (newD2 < sphereTolR2)
                            {
                                var oldD2 = Distance.PointTriangleDistanceSq(out s, out t, oldSphereCen, triangle);
                                var dist  = (float)System.Math.Sqrt(oldD2);
                                var depth = oldSphere.Radius - dist;

                                var triPointSTNorm = oldSphereCen - triangle.GetPoint(s, t);
                                JiggleMath.NormalizeSafe(ref triPointSTNorm);

                                var collisionN = dist > float.Epsilon ? triPointSTNorm : triangle.Normal;


                                var pt = oldSphere.Center - oldSphere.Radius * collisionN;

                                if (numCollPts < MaxLocalStackScpi)
                                {
                                    collPts[numCollPts].R0 = pt - body0Pos;
                                    collPts[numCollPts].R1 = pt - body1Pos;
                                    collPts[numCollPts++].InitialPenetration = depth;
                                }

                                collNormal += collisionN;
                            }
                        }

                        if (numCollPts > 0)
                        {
                            JiggleMath.NormalizeSafe(ref collNormal);
                            collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts);
                        }
                    }
                }
            }
        }
        internal static void CollDetectSphereStaticMeshSweep(BoundingSphere oldSphere, BoundingSphere newSphere, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            var delta = newSphere.Center - oldSphere.Center;

            if (delta.LengthSquared() < 0.25f * newSphere.Radius * newSphere.Radius)
            {
                CollDetectSphereStaticMeshOverlap(oldSphere, newSphere, mesh, info, collTolerance, collisionFunctor);
            }
            else
            {
                var body0Pos = info.Skin0.Owner?.OldPosition ?? Vector3.Zero;
                var body1Pos = info.Skin1.Owner?.OldPosition ?? Vector3.Zero;

                var sphereTolR = collTolerance + oldSphere.Radius;
                var sphereToR2 = sphereTolR * sphereTolR;

                var collNormal = Vector3.Zero;

                var bb = BoundingBoxHelper.InitialBox;
                BoundingBoxHelper.AddSphere(oldSphere, ref bb);
                BoundingBoxHelper.AddSphere(newSphere, ref bb);


                var newSphereCen = Vector3.Transform(newSphere.Center, mesh.InverseTransformMatrix);
                var oldSphereCen = Vector3.Transform(oldSphere.Center, mesh.InverseTransformMatrix);

                unsafe
                {
                    var collPts            = stackalloc SmallCollPointInfo[MaxLocalStackScpi];
                    var potentialTriangles = stackalloc int[MaxLocalStackTris];
                    {
                        {
                            var numCollPts = 0;

                            var numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb);

                            for (var iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                            {
                                var meshTriangle    = mesh.GetTriangle(potentialTriangles[iTriangle]);
                                var distToCentreOld = meshTriangle.Plane.DotCoordinate(oldSphereCen);
                                if (distToCentreOld <= 0.0f)
                                {
                                    continue;
                                }


                                var distToCentreNew = meshTriangle.Plane.DotCoordinate(newSphereCen);
                                if (distToCentreNew > sphereTolR)
                                {
                                    continue;
                                }

                                meshTriangle.GetVertexIndices(out var i0, out var i1, out var i2);

                                var triangle = new Triangle(mesh.GetVertex(i0), mesh.GetVertex(i1), mesh.GetVertex(i2));


                                var d2 = Distance.PointTriangleDistanceSq(out var s, out var t, oldSphereCen, triangle);

                                if (d2 < sphereToR2)
                                {
                                    var dist      = (float)System.Math.Sqrt(d2);
                                    var depth     = oldSphere.Radius - dist;
                                    var triangleN = triangle.Normal;
                                    var normSafe  = oldSphereCen - triangle.GetPoint(s, t);

                                    JiggleMath.NormalizeSafe(ref normSafe);

                                    var collisionN = dist > float.Epsilon ? normSafe : triangleN;

                                    var pt = oldSphere.Center - oldSphere.Radius * collisionN;
                                    if (numCollPts < MaxLocalStackScpi)
                                    {
                                        collPts[numCollPts].R0 = pt - body0Pos;
                                        collPts[numCollPts].R1 = pt - body1Pos;
                                        collPts[numCollPts++].InitialPenetration = depth;
                                    }

                                    collNormal += collisionN;
                                }
                                else if (distToCentreNew < distToCentreOld)
                                {
                                    if (Intersection.SweptSphereTriangleIntersection(out var pt, out var N, out var depth, oldSphere, newSphere, triangle, distToCentreOld, distToCentreNew, Intersection.EdgesToTest.EdgeAll, Intersection.CornersToTest.CornerAll))
                                    {
                                        var dist      = (float)System.Math.Sqrt(d2);
                                        var depth2    = oldSphere.Radius - dist;
                                        var triangleN = triangle.Normal;
                                        var normSafe  = oldSphereCen - triangle.GetPoint(s, t);
                                        JiggleMath.NormalizeSafe(ref normSafe);
                                        var collisionN = dist > JiggleMath.Epsilon ? normSafe : triangleN;

                                        var pt2 = oldSphere.Center - oldSphere.Radius * collisionN;
                                        if (numCollPts < MaxLocalStackScpi)
                                        {
                                            collPts[numCollPts].R0 = pt2 - body0Pos;
                                            collPts[numCollPts].R1 = pt2 - body1Pos;
                                            collPts[numCollPts++].InitialPenetration = depth;
                                        }

                                        collNormal += collisionN;
                                    }
                                }
                            }

                            if (numCollPts > 0)
                            {
                                JiggleMath.NormalizeSafe(ref collNormal);
                                collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts);
                            }
                        }
                    }
                }
            }
        }