private static bool IsSeparated(ref BurstBoxCollider a, ref BurstBoxCollider b, Vector3 axis) { // Handles the cross product = {0,0,0} case if (axis == Vector3.zero) { return(false); } var aMin = float.MaxValue; var aMax = float.MinValue; var bMin = float.MaxValue; var bMax = float.MinValue; // For each vertex combination >> CalculateMinMax(axis, a.V1, b.V1, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V2, b.V2, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V3, b.V3, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V4, b.V4, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V5, b.V5, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V6, b.V6, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V7, b.V7, ref aMin, ref aMax, ref bMin, ref bMax); CalculateMinMax(axis, a.V8, b.V8, ref aMin, ref aMax, ref bMin, ref bMax); // One-dimensional intersection test between a and b var longSpan = Mathf.Max(aMax, bMax) - Mathf.Min(aMin, bMin); var sumSpan = aMax - aMin + bMax - bMin; return(longSpan >= sumSpan); // > to treat touching as intersection }
private static BurstBoxCollider BurstBoxCollider(Vector3 center, Vector3 size, Quaternion rotation, float4x4 matrix) { var max = size * 0.5f; var min = -max; var box = new BurstBoxCollider { Bounds = new Bounds(center, size), Center = center, Right = rotation * Vector3.right, Up = rotation * Vector3.up, Forward = rotation * Vector3.forward, Max = max, Min = min, ToWorldMatrix = matrix, ToLocalMatrix = math.inverse(matrix), V1 = center + rotation * min, V2 = center + rotation * new Vector3(max.x, min.y, min.z), V3 = center + rotation * new Vector3(min.x, max.y, min.z), V4 = center + rotation * new Vector3(max.x, max.y, min.z), V5 = center + rotation * new Vector3(min.x, min.y, max.z), V6 = center + rotation * new Vector3(max.x, min.y, max.z), V7 = center + rotation * new Vector3(min.x, max.y, max.z), V8 = center + rotation * max, }; box.UpdateBounds(); return(box); }
public static bool BoxSphereIntersects(BurstBoxCollider box, BurstSphereCollider b, out IntersectionInfo info) { info = new IntersectionInfo(); var closest = box.ClosestPosition(b.Center); var distToClosest = Vector3.Distance(b.Center, closest); var gapDistance = distToClosest - b.Radius; var centerToClosest = closest - b.Center; var overlapVector = (b.Radius - distToClosest) * centerToClosest.normalized; info.GapDistance = gapDistance; info.IsIntersecting = gapDistance <= 0 ? 1 : 0; info.PointOnB = closest + overlapVector; info.PointOnA = closest; if (gapDistance <= 0) { info.PenetrationDirection = overlapVector; info.PenetrationDistance = overlapVector.magnitude; return(true); } info.GapDirection = overlapVector; return(false); }
public static bool BoxSphereIntersects(BurstBoxCollider box, BurstSphereCollider sphere) { var closestPosition = box.ClosestPosition(sphere.Center + sphere.Offset); var distance = Vector3.Distance(sphere.Center + sphere.Offset, closestPosition); return(distance - sphere.Radius * sphere.Scale <= 0); }
public static Vector3 ClosestPosition(this BurstBoxCollider box, Vector3 worldPosition, float4x4 toLocal) { var localPosition = math.transform(toLocal, worldPosition); var closest = box.ClosestLocalPosition(localPosition); return(math.transform(math.inverse(box.ToWorldMatrix), closest)); }
public static Vector3 ClosestPosition(this BurstBoxCollider box, Vector3 worldPosition, float4x4 toLocal, float4x4 toWorld) { var localSphereCenter = math.transform(toLocal, worldPosition); var closest = box.ClosestLocalPosition(localSphereCenter); return(math.transform(toWorld, closest)); }
public static bool Contains(this BurstBoxCollider box, Vector3 worldPosition, float4x4 matrix) { var localPosition = math.transform(matrix, worldPosition); return(localPosition.x > box.Min.x && localPosition.x < box.Max.x && localPosition.y > box.Min.y && localPosition.y < box.Max.y && localPosition.z > box.Min.z && localPosition.z < box.Max.z); }
public static bool Contains(this BurstBoxCollider box, Vector3 worldPosition) { var localPosition = box.GetLocalPosition(worldPosition); return(localPosition.x > box.Min.x && localPosition.x < box.Max.x && localPosition.y > box.Min.y && localPosition.y < box.Max.y && localPosition.z > box.Min.z && localPosition.z < box.Max.z); }
private static Vector3 ClosestLocalPosition(this BurstBoxCollider box, float3 localPosition) { var closestX = Mathf.Max(box.Min.x, Mathf.Min(localPosition.x, box.Max.x)); var closestY = Mathf.Max(box.Min.y, Mathf.Min(localPosition.y, box.Max.y)); var closestZ = Mathf.Max(box.Min.z, Mathf.Min(localPosition.z, box.Max.z)); var closest = new Vector3(closestX, closestY, closestZ); return(closest); }
public void Update(Collider collider) { if (collider is SphereCollider sphere) { Sphere = BurstColliderFactory.CreateSphere(sphere); } if (collider is BoxCollider box) { Box = BurstColliderFactory.CreateBox(box); } }
public static void UpdateBounds(this BurstBoxCollider box) { box.Bounds = new Bounds(); box.Bounds.Encapsulate(box.V1); box.Bounds.Encapsulate(box.V2); box.Bounds.Encapsulate(box.V3); box.Bounds.Encapsulate(box.V4); box.Bounds.Encapsulate(box.V5); box.Bounds.Encapsulate(box.V6); box.Bounds.Encapsulate(box.V7); box.Bounds.Encapsulate(box.V8); }
//public class ConvexPolyhedron //{ // public Face[] Faces; // public Vector3[] Vertices; // public Vector3[] Edges; // public class Face // { // public Vector3 Normal; // public Vector3 Vertex; // } // //public class Edge // //{ // //} //} //public static bool Intersects(ConvexPolyhedron C0, ConvexPolyhedron C1) //{ // if (IsFaceSeparation(C0, C1)) // return false; // if (IsFaceSeparation(C1, C0)) // return false; // for (int i = 0; i < C0.Edges.Length; i++) // { // for (int j = 0; j < C1.Edges.Length; j++) // { // var edgePoint0 = C0.Edges[i]; // var edgePoint1 = C1.Edges[j]; // var axis = Vector3.Cross(edgePoint0, edgePoint1); // var side0 = WhichSide(C0.Vertices, axis, edgePoint0); // if (side0 == 0) // { // continue; // } // var side1 = WhichSide(C1.Vertices, axis, edgePoint0); // if (side1 == 0) // { // continue; // } // if (side0 * side1 < 0) // { // return false; // } // } // } //} //private static bool IsFaceSeparation(ConvexPolyhedron C0, ConvexPolyhedron C1) //{ // for (int i = 0; i < C0.Faces.Length; i++) // { // var normal = C0.Faces[i].Normal; // var vertex = C0.Faces[i].Vertex; // if (WhichSide(C1.Vertices, normal, vertex) > 0) // { // return true; // } // } // return false; //} //public static int WhichSide(Vector3[] vertices, Vector3 d, Vector3 p) //{ // var positive = 0; // var negative = 0; // for (int i = 0; i < C.N; i++) // { // var t = Vector3.Dot(d, vertices[i] - p); // if (t > 0) positive++; // else if (t < 0) negative++; // if (positive == 0 && negative == 0) return 0; // } // return positive == 0 ? 0 : positive > 0 ? 1 : -1; //} public static bool BoxBoxIntersects(BurstBoxCollider a, BurstBoxCollider b) { // For each Axis/Normal project and check for separation // Source https://gamedev.stackexchange.com/questions/44500/how-many-and-which-axes-to-use-for-3d-obb-collision-with-sat if (IsSeparated(ref a, ref b, a.Right)) { return(false); } if (IsSeparated(ref a, ref b, a.Up)) { return(false); } if (IsSeparated(ref a, ref b, a.Forward)) { return(false); } if (IsSeparated(ref a, ref b, b.Right)) { return(false); } if (IsSeparated(ref a, ref b, b.Up)) { return(false); } if (IsSeparated(ref a, ref b, b.Forward)) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Right, b.Right))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Right, b.Up))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Right, b.Forward))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Up, b.Right))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Up, b.Up))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Up, b.Forward))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Forward, b.Right))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Forward, b.Up))) { return(false); } if (IsSeparated(ref a, ref b, Vector3.Cross(a.Forward, b.Forward))) { return(false); } return(true); }
public static Vector3 GetWorldPosition(this BurstBoxCollider box, Vector3 localPosition) { return(math.transform(box.ToWorldMatrix, localPosition)); }
public static Vector3 ClosestPosition(this BurstBoxCollider box, Vector3 worldPosition) { return(ClosestPosition(box, worldPosition, box.ToLocalMatrix, box.ToWorldMatrix)); }
public static BurstBaseCollider ToBaseCollider(this BurstBoxCollider box) => new BurstBaseCollider { Type = BurstColliderType.Box, Box = box };