Пример #1
0
        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);
        }
Пример #2
0
        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));
        }