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); } } }
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); } } }
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); } }
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); } } }
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); } } } }
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); } } } } }
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); } } }
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); } } } } }
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); } } } }
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); } } } } } }