public void Box_PointOnFace() { using (var box = CreateBox()) { HullDrawingUtility.DrawBasicHull(box, RigidTransform.identity, Color.black, 100); var rotateEveryAxis45 = Quaternion.Euler((float3)45); // up and rotated position var insideUnitBox = new RigidTransform(rotateEveryAxis45, new float3(0.2f, 1.34f, 0.1f)); var outsideUnitBox = new RigidTransform(rotateEveryAxis45, new float3(0.2f, 1.38f, 0.1f)); Assert.IsTrue(HullCollision.IsColliding(insideUnitBox, box, RigidTransform.identity, box)); Assert.IsFalse(HullCollision.IsColliding(outsideUnitBox, box, RigidTransform.identity, box)); HullDrawingUtility.DrawBasicHull(box, insideUnitBox, Color.blue, 100); HullDrawingUtility.DrawBasicHull(box, outsideUnitBox, Color.black, 100); // down and rotated position insideUnitBox = new RigidTransform(rotateEveryAxis45, new float3(0.2f, -1.34f, 0.1f)); outsideUnitBox = new RigidTransform(rotateEveryAxis45, new float3(0.2f, -1.38f, 0.1f)); Assert.IsTrue(HullCollision.IsColliding(insideUnitBox, box, RigidTransform.identity, box)); Assert.IsFalse(HullCollision.IsColliding(outsideUnitBox, box, RigidTransform.identity, box)); HullDrawingUtility.DrawBasicHull(box, insideUnitBox, Color.blue, 100); HullDrawingUtility.DrawBasicHull(box, outsideUnitBox, Color.black, 100); } }
public void Box_EdgeSeparation() { using (var box = CreateBox()) { // These two boxes are positioned so that both face SAT checks would show no separation, // a working SAT edge test is required to catch the false positive. var boxTransformA = new RigidTransform(Quaternion.Euler(-24.357f, -4.779f, -32.115f), new float3(-0.089f, -0.821f, -2.233f)); var boxTransformB = new RigidTransform(Quaternion.Euler(55.943f, 21.207f, 47.057f), new float3(-0.207f, -0.06f, -1.256f)); Assert.IsFalse(HullCollision.IsColliding(boxTransformA, box, boxTransformB, box)); HullDrawingUtility.DrawBasicHull(box, boxTransformA, Color.blue, 100); HullDrawingUtility.DrawBasicHull(box, boxTransformB, Color.black, 100); } }
public void Box_EdgeOnEdge() { using (var box = CreateBox()) { HullDrawingUtility.DrawBasicHull(box, RigidTransform.identity, Color.black, 100); var rotateEveryAxis45 = Quaternion.Euler((float3)45); var insideUnitBox = new RigidTransform(rotateEveryAxis45, new float3(0.2f, 1.1f, -0.80f)); var outsideUnitBox = new RigidTransform(rotateEveryAxis45, new float3(0.184f, 1.123f, -0.816f)); Assert.IsTrue(HullCollision.IsColliding(insideUnitBox, box, RigidTransform.identity, box)); Assert.IsFalse(HullCollision.IsColliding(outsideUnitBox, box, RigidTransform.identity, box)); HullDrawingUtility.DrawBasicHull(box, insideUnitBox, Color.blue, 100); HullDrawingUtility.DrawBasicHull(box, outsideUnitBox, Color.black, 100); } }
private void HandleHullCollisions() { for (int i = 0; i < Transforms.Count; ++i) { var tA = Transforms[i]; if (tA == null) { continue; } var hullA = Hulls[tA.GetInstanceID()].Hull; var transformA = new RigidTransform(tA.rotation, tA.position); HullDrawingUtility.DrawDebugHull(hullA, transformA, HullDrawingOptions); if (LogClosestPoint) { var sw3 = System.Diagnostics.Stopwatch.StartNew(); var result3 = HullCollision.ClosestPoint(transformA, hullA, 0); sw3.Stop(); var sw4 = System.Diagnostics.Stopwatch.StartNew(); var result4 = HullOperations.ClosestPoint.Invoke(transformA, hullA, 0); sw4.Stop(); if (DrawClosestPoint) { DebugDrawer.DrawSphere(result4, 0.1f, Color.blue); DebugDrawer.DrawLine(result4, Vector3.zero, Color.blue); } Debug.Log($"ClosestPoint between '{tA.name}' and world zero took: {sw3.Elapsed.TotalMilliseconds:N4}ms (Normal), {sw4.Elapsed.TotalMilliseconds:N4}ms (Burst)"); } for (int j = i + 1; j < Transforms.Count; j++) { var tB = Transforms[j]; if (tB == null) { continue; } if (!tA.hasChanged && !tB.hasChanged) { continue; } var hullB = Hulls[tB.GetInstanceID()].Hull; var transformB = new RigidTransform(tB.rotation, tB.position); HullDrawingUtility.DrawDebugHull(hullB, transformB, HullDrawingOptions); DrawHullCollision(tA.gameObject, tB.gameObject, transformA, hullA, transformB, hullB); if (LogCollisions) { var sw1 = System.Diagnostics.Stopwatch.StartNew(); var result1 = HullCollision.IsColliding(transformA, hullA, transformB, hullB); sw1.Stop(); var sw2 = System.Diagnostics.Stopwatch.StartNew(); var result2 = HullOperations.IsColliding.Invoke(transformA, hullA, transformB, hullB); sw2.Stop(); Debug.Assert(result1 == result2); Debug.Log($"Collisions between '{tA.name}'/'{tB.name}' took: {sw1.Elapsed.TotalMilliseconds:N4}ms (Normal), {sw2.Elapsed.TotalMilliseconds:N4}ms (Burst)"); } } } if (LogCollisions) { TestBatchCollision(); } }
public void DrawHullCollision(GameObject a, GameObject b, RigidTransform t1, NativeHull hull1, RigidTransform t2, NativeHull hull2) { var collision = HullCollision.GetDebugCollisionInfo(t1, hull1, t2, hull2); if (collision.IsColliding) { if (DrawIntersection) // Visualize all faces of the intersection { HullIntersection.DrawNativeHullHullIntersection(t1, hull1, t2, hull2); } if (DrawContact || LogContact) // Visualize the minimal contact calcluation for physics { //var manifold = HullOperations.GetContact.Invoke(t1, hull1, t2, hull2); var sw1 = System.Diagnostics.Stopwatch.StartNew(); var tmp = new NativeManifold(Allocator.Persistent); var normalResult = HullIntersection.NativeHullHullContact(ref tmp, t1, hull1, t2, hull2); sw1.Stop(); tmp.Dispose(); var sw2 = System.Diagnostics.Stopwatch.StartNew(); var burstResult = HullOperations.TryGetContact.Invoke(out NativeManifold manifold, t1, hull1, t2, hull2); sw2.Stop(); if (LogContact) { Debug.Log($"GetContact between '{a.name}'/'{b.name}' took: {sw1.Elapsed.TotalMilliseconds:N4}ms (Normal), {sw2.Elapsed.TotalMilliseconds:N4}ms (Burst)"); } if (DrawContact && burstResult) { // Do something with manifold HullDrawingUtility.DebugDrawManifold(manifold); //var points = manifold.Points; for (int i = 0; i < manifold.Length; i++) { var point = manifold[i]; DebugDrawer.DrawSphere(point.Position, 0.02f); DebugDrawer.DrawArrow(point.Position, manifold.Normal * 0.2f); var penentrationPoint = point.Position + manifold.Normal * point.Distance; DebugDrawer.DrawLabel(penentrationPoint, $"{point.Distance:N2}"); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.InEdge1, t1, hull1); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.OutEdge1, t1, hull1); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.InEdge2, t1, hull1); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.OutEdge2, t1, hull1); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.InEdge1, t2, hull2); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.OutEdge1, t2, hull2); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.InEdge2, t2, hull2); HullDrawingUtility.DrawEdge(point.Id.FeaturePair.OutEdge2, t2, hull2); DebugDrawer.DrawDottedLine(point.Position, penentrationPoint); } manifold.Dispose(); } } if (DrawIsCollided) { DebugDrawer.DrawSphere(t1.pos, 0.1f, UnityColors.GhostDodgerBlue); DebugDrawer.DrawSphere(t2.pos, 0.1f, UnityColors.GhostDodgerBlue); } } if (DrawClosestFace) { var color1 = collision.Face1.Distance > 0 ? UnityColors.Red.ToOpacity(0.3f) : UnityColors.Yellow.ToOpacity(0.3f); HullDrawingUtility.DrawFaceWithOutline(collision.Face1.Index, t1, hull1, color1, UnityColors.Black); var color2 = collision.Face2.Distance > 0 ? UnityColors.Red.ToOpacity(0.3f) : UnityColors.Yellow.ToOpacity(0.3f); HullDrawingUtility.DrawFaceWithOutline(collision.Face2.Index, t2, hull2, color2, UnityColors.Black); } }