public bool IntersectsTriangle(ref Vector3I v0, ref Vector3I v1, ref Vector3I v2) { // This code is based on: Akenine-Moeller, Thomas - "Fast 3D Triangle-Box Overlap Testing" // Test 1) - Separation of triangle and BB by the bounding box's 6 planes Vector3I min, max; Vector3I.Min(ref v0, ref v1, out min); Vector3I.Min(ref min, ref v2, out min); Vector3I.Max(ref v0, ref v1, out max); Vector3I.Max(ref max, ref v2, out max); if (min.X > Max.X) { return(false); } if (max.X < Min.X) { return(false); } if (min.Y > Max.Y) { return(false); } if (max.Y < Min.Y) { return(false); } if (min.Z > Max.Z) { return(false); } if (max.Z < Min.Z) { return(false); } // Test 2) - Separation by the triangle's plane Vector3I f0 = v1 - v0; Vector3I f1 = v2 - v1; Vector3I triN; Vector3I.Cross(ref f0, ref f1, out triN); int d; Vector3I.Dot(ref v0, ref triN, out d); // The triangle's plane. It does not have to be normalized Plane triPlane = new Plane(triN, -d); PlaneIntersectionType intersection; Intersects(ref triPlane, out intersection); if (intersection == PlaneIntersectionType.Back) { return(false); } if (intersection == PlaneIntersectionType.Front) { return(false); } // Test 3) - Separation by planes that are perpendicular to coordinate axes e0, e1, e2 and triangle edges f0, f1, f2 Vector3I center = Center; BoundingBoxI tmpBox = new BoundingBoxI(Min - center, Max - center); Vector3I originHalf = tmpBox.HalfExtents; Vector3I f2 = v0 - v2; Vector3I v0sh = v0 - center; Vector3I v1sh = v1 - center; Vector3I v2sh = v2 - center; float boxR, p0, p1, p2; // Does a plane that has axis e0 x f0 separate the triangle and BB? boxR = originHalf.Y * Math.Abs(f0.Z) + originHalf.Z * Math.Abs(f0.Y); // "Radius" of the BB, if moved to the origin p0 = v0sh.Z * v1sh.Y - v0sh.Y * v1sh.Z; // Projection of v0sh and also v1sh (axis is perpendicular on f0 = v1sh - v0sh) onto the axis p2 = v2sh.Z * f0.Y - v2sh.Y * f0.Z; // Projection of v2sh on the axis if (Math.Min(p0, p2) > boxR || Math.Max(p0, p2) < -boxR) { return(false); // Now we can test projection of the triangle against the projection of the BB (which is (-boxR, +boxR)) } // Now for the remaining 8 combinations...: // e1 x f0 boxR = originHalf.X * Math.Abs(f0.Z) + originHalf.Z * Math.Abs(f0.X); p0 = v0sh.X * v1sh.Z - v0sh.Z * v1sh.X; p2 = v2sh.X * f0.Z - v2sh.Z * f0.X; if (Math.Min(p0, p2) > boxR || Math.Max(p0, p2) < -boxR) { return(false); } // e2 x f0 boxR = originHalf.X * Math.Abs(f0.Y) + originHalf.Y * Math.Abs(f0.X); p0 = v0sh.Y * v1sh.X - v0sh.X * v1sh.Y; p2 = v2sh.Y * f0.X - v2sh.X * f0.Y; if (Math.Min(p0, p2) > boxR || Math.Max(p0, p2) < -boxR) { return(false); } // e0 x f1 boxR = originHalf.Y * Math.Abs(f1.Z) + originHalf.Z * Math.Abs(f1.Y); p1 = v1sh.Z * v2sh.Y - v1sh.Y * v2sh.Z; p0 = v0sh.Z * f1.Y - v0sh.Y * f1.Z; if (Math.Min(p1, p0) > boxR || Math.Max(p1, p0) < -boxR) { return(false); } // e1 x f1 boxR = originHalf.X * Math.Abs(f1.Z) + originHalf.Z * Math.Abs(f1.X); p1 = v1sh.X * v2sh.Z - v1sh.Z * v2sh.X; p0 = v0sh.X * f1.Z - v0sh.Z * f1.X; if (Math.Min(p1, p0) > boxR || Math.Max(p1, p0) < -boxR) { return(false); } // e2 x f1 boxR = originHalf.X * Math.Abs(f1.Y) + originHalf.Y * Math.Abs(f1.X); p1 = v1sh.Y * v2sh.X - v1sh.X * v2sh.Y; p0 = v0sh.Y * f1.X - v0sh.X * f1.Y; if (Math.Min(p1, p0) > boxR || Math.Max(p1, p0) < -boxR) { return(false); } // e0 x f2 boxR = originHalf.Y * Math.Abs(f2.Z) + originHalf.Z * Math.Abs(f2.Y); p2 = v2sh.Z * v0sh.Y - v2sh.Y * v0sh.Z; p1 = v1sh.Z * f2.Y - v1sh.Y * f2.Z; if (Math.Min(p2, p1) > boxR || Math.Max(p2, p1) < -boxR) { return(false); } // e1 x f2 boxR = originHalf.X * Math.Abs(f2.Z) + originHalf.Z * Math.Abs(f2.X); p2 = v2sh.X * v0sh.Z - v2sh.Z * v0sh.X; p1 = v1sh.X * f2.Z - v1sh.Z * f2.X; if (Math.Min(p2, p1) > boxR || Math.Max(p2, p1) < -boxR) { return(false); } // e2 x f2 boxR = originHalf.X * Math.Abs(f2.Y) + originHalf.Y * Math.Abs(f2.X); p2 = v2sh.Y * v0sh.X - v2sh.X * v0sh.Y; p1 = v1sh.Y * f2.X - v1sh.X * f2.Y; if (Math.Min(p2, p1) > boxR || Math.Max(p2, p1) < -boxR) { return(false); } return(true); }
public bool IntersectsTriangle(ref Vector3I v0, ref Vector3I v1, ref Vector3I v2) { Vector3I vectori; Vector3I vectori2; Vector3I vectori5; int num; PlaneIntersectionType type; Vector3I.Min(ref v0, ref v1, out vectori); Vector3I.Min(ref vectori, ref v2, out vectori); Vector3I.Max(ref v0, ref v1, out vectori2); Vector3I.Max(ref vectori2, ref v2, out vectori2); if (vectori.X > this.Max.X) { return(false); } if (vectori2.X < this.Min.X) { return(false); } if (vectori.Y > this.Max.Y) { return(false); } if (vectori2.Y < this.Min.Y) { return(false); } if (vectori.Z > this.Max.Z) { return(false); } if (vectori2.Z < this.Min.Z) { return(false); } Vector3I vectori3 = v1 - v0; Vector3I vectori4 = v2 - v1; Vector3I.Cross(ref vectori3, ref vectori4, out vectori5); Vector3I.Dot(ref v0, ref vectori5, out num); Plane plane = new Plane((Vector3)vectori5, (float)-num); this.Intersects(ref plane, out type); switch (type) { case PlaneIntersectionType.Back: return(false); case PlaneIntersectionType.Front: return(false); } Vector3I center = this.Center; BoundingBoxI xi = new BoundingBoxI(this.Min - center, this.Max - center); Vector3I halfExtents = xi.HalfExtents; Vector3I vectori8 = v0 - v2; Vector3I vectori9 = v0 - center; Vector3I vectori10 = v1 - center; Vector3I vectori11 = v2 - center; float num2 = (halfExtents.Y * Math.Abs(vectori3.Z)) + (halfExtents.Z * Math.Abs(vectori3.Y)); float num3 = (vectori9.Z * vectori10.Y) - (vectori9.Y * vectori10.Z); float num5 = (vectori11.Z * vectori3.Y) - (vectori11.Y * vectori3.Z); if ((Math.Min(num3, num5) > num2) || (Math.Max(num3, num5) < -num2)) { return(false); } num2 = (halfExtents.X * Math.Abs(vectori3.Z)) + (halfExtents.Z * Math.Abs(vectori3.X)); num3 = (vectori9.X * vectori10.Z) - (vectori9.Z * vectori10.X); num5 = (vectori11.X * vectori3.Z) - (vectori11.Z * vectori3.X); if ((Math.Min(num3, num5) > num2) || (Math.Max(num3, num5) < -num2)) { return(false); } num2 = (halfExtents.X * Math.Abs(vectori3.Y)) + (halfExtents.Y * Math.Abs(vectori3.X)); num3 = (vectori9.Y * vectori10.X) - (vectori9.X * vectori10.Y); num5 = (vectori11.Y * vectori3.X) - (vectori11.X * vectori3.Y); if ((Math.Min(num3, num5) > num2) || (Math.Max(num3, num5) < -num2)) { return(false); } num2 = (halfExtents.Y * Math.Abs(vectori4.Z)) + (halfExtents.Z * Math.Abs(vectori4.Y)); float num4 = (vectori10.Z * vectori11.Y) - (vectori10.Y * vectori11.Z); num3 = (vectori9.Z * vectori4.Y) - (vectori9.Y * vectori4.Z); if ((Math.Min(num4, num3) > num2) || (Math.Max(num4, num3) < -num2)) { return(false); } num2 = (halfExtents.X * Math.Abs(vectori4.Z)) + (halfExtents.Z * Math.Abs(vectori4.X)); num4 = (vectori10.X * vectori11.Z) - (vectori10.Z * vectori11.X); num3 = (vectori9.X * vectori4.Z) - (vectori9.Z * vectori4.X); if ((Math.Min(num4, num3) > num2) || (Math.Max(num4, num3) < -num2)) { return(false); } num2 = (halfExtents.X * Math.Abs(vectori4.Y)) + (halfExtents.Y * Math.Abs(vectori4.X)); num4 = (vectori10.Y * vectori11.X) - (vectori10.X * vectori11.Y); num3 = (vectori9.Y * vectori4.X) - (vectori9.X * vectori4.Y); if ((Math.Min(num4, num3) > num2) || (Math.Max(num4, num3) < -num2)) { return(false); } num2 = (halfExtents.Y * Math.Abs(vectori8.Z)) + (halfExtents.Z * Math.Abs(vectori8.Y)); num5 = (vectori11.Z * vectori9.Y) - (vectori11.Y * vectori9.Z); num4 = (vectori10.Z * vectori8.Y) - (vectori10.Y * vectori8.Z); if ((Math.Min(num5, num4) > num2) || (Math.Max(num5, num4) < -num2)) { return(false); } num2 = (halfExtents.X * Math.Abs(vectori8.Z)) + (halfExtents.Z * Math.Abs(vectori8.X)); num5 = (vectori11.X * vectori9.Z) - (vectori11.Z * vectori9.X); num4 = (vectori10.X * vectori8.Z) - (vectori10.Z * vectori8.X); if ((Math.Min(num5, num4) > num2) || (Math.Max(num5, num4) < -num2)) { return(false); } num2 = (halfExtents.X * Math.Abs(vectori8.Y)) + (halfExtents.Y * Math.Abs(vectori8.X)); num5 = (vectori11.Y * vectori9.X) - (vectori11.X * vectori9.Y); num4 = (vectori10.Y * vectori8.X) - (vectori10.X * vectori8.Y); return((Math.Min(num5, num4) <= num2) && (Math.Max(num5, num4) >= -num2)); }