public static void DrawDebugHull(NativeHull hull, RigidTransform t, DebugHullFlags options = DebugHullFlags.All, Color BaseColor = default) { if (!hull.IsValid) { throw new ArgumentException("Hull is not valid", nameof(hull)); } if (options == DebugHullFlags.None) { return; } if (BaseColor == default) { BaseColor = Color.yellow; } float faceExplosionDistance = (options & DebugHullFlags.ExplodeFaces) != 0 ? 0.3f : 0; // Iterate each twin pair at the same time. for (int j = 0; j < hull.EdgeCount; j = j + 2) { var edge = hull.GetEdge(j); var twin = hull.GetEdge(j + 1); var edgePlane = edge.Face != -1 ? hull.GetPlane(edge.Face) : new NativePlane(); var twinPlane = twin.Face != -1 ? hull.GetPlane(twin.Face) : new NativePlane(); var rotatedEdgeNormal = math.rotate(t, edgePlane.Normal); var rotatedTwinNormal = math.rotate(t, twinPlane.Normal); var edgeVertex1 = math.transform(t, hull.GetVertex(edge.Origin)); var twinVertex1 = math.transform(t, hull.GetVertex(twin.Origin)); var edgeVertex2 = math.transform(t, hull.GetVertex(edge.Origin)); var twinVertex2 = math.transform(t, hull.GetVertex(twin.Origin)); if ((options & DebugHullFlags.Outline) != 0) { Debug.DrawLine(edgeVertex1 + rotatedEdgeNormal * faceExplosionDistance, twinVertex1 + rotatedEdgeNormal * faceExplosionDistance, BaseColor); Debug.DrawLine(edgeVertex2 + rotatedTwinNormal * faceExplosionDistance, twinVertex2 + rotatedTwinNormal * faceExplosionDistance, BaseColor); } if ((options & DebugHullFlags.EdgeLinks) != 0) { Debug.DrawLine((edgeVertex1 + twinVertex1) / 2 + rotatedEdgeNormal * faceExplosionDistance, (edgeVertex2 + twinVertex2) / 2 + rotatedTwinNormal * faceExplosionDistance, Color.gray); } } if ((options & DebugHullFlags.PlaneNormals) != 0) { for (int i = 0; i < hull.FaceCount; i++) { var centroid = math.transform(t, hull.CalculateFaceCentroid(hull.GetFace(i))); var normal = math.rotate(t, hull.GetPlane(i).Normal); DebugDrawer.DrawArrow(centroid, normal * 0.2f, BaseColor); } } if ((options & DebugHullFlags.Indices) != 0) { var dupeCheck = new HashSet <Vector3>(); for (int i = 0; i < hull.VertexCount; i++) { // Offset the label if multiple verts are on the same position. var v = math.transform(t, hull.GetVertex(i)); var offset = dupeCheck.Contains(v) ? (float3)Vector3.forward * 0.05f : 0; DebugDrawer.DrawLabel(v + offset, i.ToString()); dupeCheck.Add(v); } } if ((options & DebugHullFlags.FaceWinding) != 0) { for (int i = 0; i < hull.FaceCount; i++) { var face = hull.GetFace(i); var plane = hull.GetPlane(i); var tPlane = t * plane; var edge = hull.GetEdge(face.Edge); var startOrigin = edge.Origin; do { var nextEdge = hull.GetEdge(edge.Next); var startVert = math.transform(t, hull.GetVertex(edge.Origin)); var endVert = math.transform(t, hull.GetVertex(nextEdge.Origin)); var center = (endVert + startVert) / 2; var dir = math.normalize(endVert - startVert); var insetDir = math.normalize(math.cross(tPlane.Normal, dir)); if ((options & DebugHullFlags.ExplodeFaces) != 0) { DebugDrawer.DrawArrow(center + tPlane.Normal * faceExplosionDistance, dir * 0.2f, Color.black); } else { DebugDrawer.DrawArrow(center + tPlane.Normal * faceExplosionDistance + insetDir * 0.1f, dir * 0.2f, Color.black); } edge = nextEdge; } while (edge.Origin != startOrigin); } } }
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); } }
private static unsafe void DrawTests(int threadIndex, float3 start, float3 end, NativeString512 text, DrawingMethods methods, NativeArray <float3> polygon) { float3 offset = Vector3.up * 0.05f + Vector3.left * 0.05f; float3 center = (start + (end - start) / 2); if (methods.Sphere) { DebugDrawer.DrawSphere(start, 0.75f, UnityColors.GhostDodgerBlue); } if (methods.RectangleWithOutline) { var size = 0.25f; var points = stackalloc[] { center + offset + new float3(0, 0, 0), center + offset + new float3(0, size, 0), center + offset + new float3(0, size, size), center + offset + new float3(0, 0, size) }; DebugDrawer.DrawSolidRectangleWithOutline(points, UnityColors.LightYellow, UnityColors.Yellow); } if (methods.Polygon) { DebugDrawer.DrawAAConvexPolygon(polygon, center + (float3)Vector3.down * 0.25f, UnityColors.GhostDodgerBlue); } if (methods.Line) { DebugDrawer.DrawLine(start + offset, end + offset); } if (methods.Ray) { DebugDrawer.DrawRay(center, Vector3.up, UnityColors.MediumBlue); } if (methods.Cone) { DebugDrawer.DrawCone(center + (float3)Vector3.up * 0.5f, Vector3.up, UnityColors.DarkKhaki, 22.5f); } if (methods.Circle) { DebugDrawer.DrawCircle(center, Vector3.up, 0.25f, UnityColors.AliceBlue); } if (methods.DottedLine) { DebugDrawer.DrawDottedLine(start, end, Color.yellow); } if (methods.WireCube) { DebugDrawer.DrawWireCube(end, Vector3.one / 2, Color.yellow); } if (methods.DottedWireCube) { DebugDrawer.DrawDottedWireCube(end, Vector3.one, Color.black); } if (methods.Label) { DebugDrawer.DrawLabel(center + (float3)Vector3.down * 0.25f, text); } if (methods.Arrow) { DebugDrawer.DrawArrow(start + (float3)Vector3.up * 0.5f, Vector3.up, Color.blue); } if (methods.Log) { DebugDrawer.Log(threadIndex, text); } if (methods.LogWarning) { DebugDrawer.LogWarning(text); } if (methods.LogError) { DebugDrawer.LogError(text); } if (methods.Point) { DebugDrawer.DrawPoint(center + (float3)Vector3.forward, UnityColors.Lavender, 0.25f); } } }