private static CollisionShape ExtractBox_Old(SubMesh subMesh) { if (DoLog) { Log(""); Log(string.Format("Extracting box for submesh {0}", subMesh.Name)); } MeshTriangle[] triangles = ExtractSubmeshTriangles(subMesh); int count = triangles.Length; Plane[] planesUnsorted = new Plane[6]; int planeCount = 0; // Iterate through the triangles. For each triangle, // determine the plane it belongs to, and find the plane // in the array of planes, or if it's not found, add it. for (int i = 0; i < count; i++) { MeshTriangle t = triangles[i]; bool found = false; Plane p = new Plane(t.vertPos[0], t.vertPos[1], t.vertPos[2]); NormalizePlane(ref p); if (DoLog) { Log(string.Format(" {0} => plane {1}", t.ToString(), p.ToString())); } for (int j = 0; j < planeCount; j++) { Plane pj = planesUnsorted[j]; if (SamePlane(pj, p)) { if (DoLog) { Log(string.Format(" plane {0} same as plane {1}", p.ToString(), pj.ToString())); } found = true; break; } } if (!found) { if (planeCount < 6) { if (DoLog) { Log(string.Format(" plane[{0}] = plane {1}", planeCount, p.ToString())); } planesUnsorted[planeCount++] = p; } else { Debug.Assert(false, string.Format("In the definition of box {0}, more than 6 planes were found", subMesh.Name)); } } } Debug.Assert(planeCount == 6, string.Format("In the definition of box {0}, fewer than 6 planes were found", subMesh.Name)); // Now recreate the planes array, making sure that // opposite faces are 3 planes apart Plane[] planes = new Plane[6]; bool[] planeUsed = new bool[6]; for (int i = 0; i < 6; i++) { planeUsed[i] = false; } int planePair = 0; for (int i = 0; i < 6; i++) { if (!planeUsed[i]) { Plane p1 = planesUnsorted[i]; planes[planePair] = p1; planeUsed[i] = true; for (int j = 0; j < 6; j++) { Plane p2 = planesUnsorted[j]; if (!planeUsed[j] && !Orthogonal(p2, p1)) { planes[3 + planePair++] = p2; planeUsed[j] = true; break; } } } } Debug.Assert(planePair == 3, "Didn't find 3 pairs of parallel planes"); // Make sure that the sequence of planes follows the // right-hand rule if (planes[0].Normal.Cross(planes[1].Normal).Dot(planes[3].Normal) < 0) { // Swap the first two plane pairs Plane p = planes[0]; planes[0] = planes[1]; planes[1] = p; p = planes[0 + 3]; planes[0 + 3] = planes[1 + 3]; planes[1 + 3] = p; Debug.Assert(planes[0].Normal.Cross(planes[1].Normal).Dot(planes[3].Normal) > 0, "Even after swapping, planes don't obey the right-hand rule"); } // Now we have our 6 planes, sorted so that opposite // planes are 3 planes apart, and so they obey the // right-hand rule. This guarantees that corners // correspond. Find the 8 intersections that define the // corners. Vector3[] corners = new Vector3[8]; int cornerCount = 0; for (int i = 0; i <= 3; i += 3) { Plane p1 = planes[i]; for (int j = 1; j <= 4; j += 3) { Plane p2 = planes[j]; for (int k = 2; k <= 5; k += 3) { Plane p3 = planes[k]; Vector3 corner = -1 * ((p1.D * (p2.Normal.Cross(p3.Normal)) + p2.D * (p3.Normal.Cross(p1.Normal)) + p3.D * (p1.Normal.Cross(p2.Normal))) / p1.Normal.Dot(p2.Normal.Cross(p3.Normal))); Debug.Assert(cornerCount < 8, string.Format("In the definition of box {0}, more than 8 corners were found", subMesh.Name)); if (DoLog) { Log(string.Format(" corner#{0}: {1}", cornerCount, corner.ToString())); } corners[cornerCount++] = corner; } } } Debug.Assert(cornerCount == 8, string.Format("In the definition of box {0}, fewer than 8 corners were found", subMesh.Name)); // We know that corners correspond. Now find the center Vector3 center = (corners[0] + corners[7]) / 2; Debug.Assert((center - (corners[1] + corners[5]) / 2.0f).Length > geometryEpsilon || (center - (corners[2] + corners[6]) / 2.0f).Length > geometryEpsilon || (center - (corners[3] + corners[7]) / 2.0f).Length > geometryEpsilon, string.Format("In the definition of box {0}, center definition {0} is not consistent", subMesh.Name, center.ToString())); // Find the extents Vector3 extents = new Vector3(Math.Abs((corners[1] - corners[0]).Length / 2.0f), Math.Abs((corners[3] - corners[1]).Length / 2.0f), Math.Abs((corners[4] - corners[0]).Length / 2.0f)); if (DoLog) { Log(string.Format(" extents {0}", extents.ToString())); } // Find the axes Vector3[] axes = new Vector3[3] { (corners[1] - corners[0]).ToNormalized(), (corners[3] - corners[1]).ToNormalized(), (corners[4] - corners[0]).ToNormalized() }; if (DoLog) { for (int i = 0; i < 3; i++) { Log(string.Format(" axis[{0}] {1}", i, axes[i])); } } // Now, is it an obb or an aabb? Figure out if the axes // point in the same direction as the basis vectors, and // if so, the order of the axes int[] mapping = new int[3] { -1, -1, -1 }; int foundMapping = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (axes[i].Cross(Primitives.UnitBasisVectors[j]).Length < geometryEpsilon) { mapping[i] = j; foundMapping++; break; } } } CollisionShape shape; if (foundMapping == 3) { // It's an AABB, so build the min and max vectors, in // the order that matches the unit basis vector order Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; for (int i = 0; i < 3; i++) { float e = extents[i]; int j = mapping[i]; min[j] = center[j] - e; max[j] = center[j] + e; } shape = new CollisionAABB(min, max); } else { Vector3 ruleTest = axes[0].Cross(axes[1]); if (axes[2].Dot(ruleTest) < 0) { axes[2] = -1 * axes[2]; } // Return the OBB shape = new CollisionOBB(center, axes, extents); } if (DoLog) { Log(string.Format("Extraction result: {0}", shape)); } return(shape); }