示例#1
0
        /// <summary>
        /// This does a deep clone
        /// </summary>
        public static Triangle[] GetClonedArray(MyVector[] clonedUniquePoints, Triangle[] triangles)
        {
            Triangle[] retVal = new Triangle[triangles.Length];

            for (int cntr = 0; cntr < triangles.Length; cntr++)
            {
                retVal[cntr] = triangles[cntr].Clone(clonedUniquePoints);
            }

            return retVal;
        }
 /// <summary>
 /// This overload returns two different levels of info (coplanar and 3D)
 /// </summary>
 /// <param name="isCoplanar">
 /// Whether the two triangles lie on the same plane or not (if the function returns true, and it's coplanar, you don't
 /// get any intersect points.  Just the knowledge that there is an intersection
 /// </param>
 /// <param name="intersectPoints">This is only populated if the function returns true, and coplanar is false</param>
 /// <returns>
 /// True:  Intersection occurred
 /// False:  No intersection occurred
 /// </returns>
 public static bool IsIntersecting_TriangleTriangle(out bool isCoplanar, out MyVector[] intersectPoints, Triangle triangle1, Triangle triangle2)
 {
     return TriTriIntersectWithIsectline(out isCoplanar, out intersectPoints, triangle1, triangle2, true);
 }
示例#3
0
        /// <summary>
        /// This does a deep clone
        /// </summary>
        public static Triangle[] GetClonedArray(Triangle[] triangles)
        {
            Triangle[] retVal = new Triangle[triangles.Length];

            for (int cntr = 0; cntr < triangles.Length; cntr++)
            {
                retVal[cntr] = triangles[cntr].Clone();
            }

            return retVal;
        }
        public static MyVector IsIntersecting_SphereTriangle(Sphere sphere, Triangle triangle)
        {
            // Find the point on the triangle closest to the sphere's center
            MyVector retVal = triangle.GetClosestPointOnTriangle(sphere.Position);

            // Sphere and triangle intersect if the (squared) distance from sphere
            // center to point is less than the (squared) sphere radius
            MyVector v = retVal - sphere.Position;
            if (MyVector.Dot(v, v) <= sphere.Radius * sphere.Radius)
            {
                return retVal;
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// This overload will always return null if the triangles are coplanar
        /// </summary>
        /// <returns>
        /// Null: no intersection
        /// 2 Points: the two points of intersection (it was always be two points, even if they are at the same position)
        /// </returns>
        public static MyVector[] IsIntersecting_TriangleTriangle(Triangle triangle1, Triangle triangle2)
        {
            MyVector[] retVal;
            bool dummy1;

            TriTriIntersectWithIsectline(out dummy1, out retVal, triangle1, triangle2, false);

            return retVal;
        }
        /// <summary>
        /// If intersecting, this will return the point of intersection.  Otherwise null
        /// </summary>
        /// <param name="lineStartPoint">Starting point of the line</param>
        /// <param name="lineDirection">direction and length of the line</param>
        /// <param name="limitToLineSegment">If false, the line passed in is thought of as infinitely long</param>
        /// <returns>point of intersection or null</returns>
        public static MyVector IsIntersecting_LineTriangle(MyVector lineStartPoint, MyVector lineDirection, Triangle triangle, bool limitToLineSegment)
        {
            // Get triangle edge vectors and plane normal
            MyVector edge21 = triangle.Vertex2 - triangle.Vertex1;
            MyVector edge31 = triangle.Vertex3 - triangle.Vertex1;
            MyVector normal = MyVector.Cross(edge21, edge31);
            if (normal.IsZero)
            {
                // Triangle is degenerate
                return null;
            }

            double a = MyVector.Dot(normal, lineStartPoint - triangle.Vertex1) * -1d;
            double b = MyVector.Dot(normal, lineDirection);
            if (Utility3D.IsNearZero(b))
            {
                // Ray is parallel to the triangle
                return null;
            }

            // Get the intersect point of the ray with the triangle's plane
            double percent = a / b;
            if (limitToLineSegment && (percent < 0d || percent > 1d))
            {
                // The ray intersects the plane, but the intersect point doesn't lie on the line segment
                return null;
            }

            // Calculate the intersect point
            MyVector retVal = lineStartPoint + (percent * lineDirection);

            // Check to see if the intersectPoint inside the triangle
            double uu = MyVector.Dot(edge21, edge21);
            double uv = MyVector.Dot(edge21, edge31);
            double vv = MyVector.Dot(edge31, edge31);
            MyVector w = retVal - triangle.Vertex1;
            double wu = MyVector.Dot(w, edge21);
            double wv = MyVector.Dot(w, edge31);
            double D = (uv * uv) - (uu * vv);

            // get and test parametric coords
            double s = ((uv * wv) - (vv * wu)) / D;
            if (s < 0d || s > 1d)
            {
                if (!(Utility3D.IsNearZero(s) || Utility3D.IsNearValue(s, 1d)))		// I was getting cases where s is VEEEEERY slightly negative, but the line was clearly intersecting
                {
                    // Intersection point is outside the triangle
                    return null;
                }
            }

            double t = ((uv * wu) - (uu * wv)) / D;
            if (t < 0d || (s + t) > 1d)
            {
                if (!(Utility3D.IsNearZero(t) || Utility3D.IsNearValue(s + t, 1d)))		// I was getting cases where s+t is VEEEEERY slightly over 1, but the line was clearly intersecting
                {
                    // Intersection point is outside the triangle
                    return null;
                }
            }

            // Exit Function
            return retVal;		// intersectPoint is in Triangle
        }
        /// <summary>
        /// If intersecting, this will return the point of intersection.  Otherwise null
        /// </summary>
        /// <param name="lineStartPoint">Starting point of the line</param>
        /// <param name="lineDirection">direction and length of the line</param>
        /// <param name="triangle">This represents the plane (3 arbitrary points on the plane)</param>
        /// <param name="limitToLineSegment">If false, the line passed in is thought of as infinitely long</param>
        /// <returns>point of intersection or null</returns>
        public static MyVector IsIntersecting_LinePlane(MyVector lineStartPoint, MyVector lineDirection, Triangle triangle, bool limitToLineSegment)
        {
            MyVector normal = triangle.Normal;

            double denominator = MyVector.Dot(normal, lineDirection);
            if (Utility3D.IsNearZero(denominator))		// parallel to the triangle's plane
            {
                return null;
            }

            double percentAlongLine = (triangle.DistanceFromOriginAlongNormal - MyVector.Dot(normal, lineStartPoint)) / denominator;

            if (limitToLineSegment && (percentAlongLine < 0d || percentAlongLine > 1d))
            {
                // The ray is intersecting, but they want the line segment only
                return null;
            }

            // Calculate the point along the line
            MyVector retVal = lineDirection.Clone();
            double length = retVal.GetMagnitude();
            retVal.Divide(length);
            retVal.Multiply(percentAlongLine * length);
            retVal.Add(lineStartPoint);

            // Exit Function
            return retVal;
        }
        private static bool IsCoplanarTriTri(MyVector N, Triangle triangle1, Triangle triangle2)
        {
            int index1, index2;

            // first project onto an axis-aligned plane, that maximizes the area
            // of the triangles, compute indices: index1, index2.
            MyVector A = new MyVector(Math.Abs(N.X), Math.Abs(N.Y), Math.Abs(N.Z));

            if (A.X > A.Y)
            {
                if (A.X > A.Z)
                {
                    index1 = 1;		// A.X is greatest
                    index2 = 2;
                }
                else
                {
                    index1 = 0;		// A.Z is greatest
                    index2 = 1;
                }
            }
            else		// A.X<=A.Y
            {
                if (A.Z > A.Y)
                {
                    index1 = 0;		// A.Z is greatest
                    index2 = 1;
                }
                else
                {
                    index1 = 0;		// A.Y is greatest
                    index2 = 2;
                }
            }

            // test all edges of triangle 1 against the edges of triangle 2
            if (IsEdgeAgainstTriangleEdges(triangle1.Vertex1, triangle1.Vertex2, triangle2.Vertex1, triangle2.Vertex2, triangle2.Vertex3, index1, index2)) return true;
            if (IsEdgeAgainstTriangleEdges(triangle1.Vertex2, triangle1.Vertex3, triangle2.Vertex1, triangle2.Vertex2, triangle2.Vertex3, index1, index2)) return true;
            if (IsEdgeAgainstTriangleEdges(triangle1.Vertex3, triangle1.Vertex1, triangle2.Vertex1, triangle2.Vertex2, triangle2.Vertex3, index1, index2)) return true;

            // finally, test if tri1 is totally contained in tri2 or vice versa
            if (IsPointInTriangle(triangle1.Vertex1, triangle2.Vertex1, triangle2.Vertex2, triangle2.Vertex3, index1, index2)) return true;
            if (IsPointInTriangle(triangle2.Vertex1, triangle1.Vertex1, triangle1.Vertex2, triangle1.Vertex3, index1, index2)) return true;

            return false;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns>
        /// True: Coplanar
        /// False: Not Coplanar
        /// </returns>
        private static bool ComputeIntervalsIsEctLine(Triangle triangle,
                               double VV0, double VV1, double VV2, double D0, double D1, double D2,
                               double D0D1, double D0D2, out double isect0, out double isect1,
                               out MyVector isectpoint0, out MyVector isectpoint1)
        {
            // Init the return values.  I'm still not sure what these mean
            isect0 = isect1 = 0d;
            isectpoint0 = isectpoint1 = null;

            if (D0D1 > 0d)
            {
                // here we know that D0D2<=0.0
                // that is D0, D1 are on the same side, D2 on the other or on the plane
                Intersect2(triangle.Vertex3, triangle.Vertex1, triangle.Vertex2, VV2, VV0, VV1, D2, D0, D1, out isect0, out isect1, out isectpoint0, out isectpoint1);
            }
            else if (D0D2 > 0d)
            {
                // here we know that d0d1<=0.0
                Intersect2(triangle.Vertex2, triangle.Vertex1, triangle.Vertex3, VV1, VV0, VV2, D1, D0, D2, out isect0, out isect1, out isectpoint0, out isectpoint1);
            }
            else if (D1 * D2 > 0d || D0 != 0d)
            {
                // here we know that d0d1<=0.0 or that D0!=0.0
                Intersect2(triangle.Vertex1, triangle.Vertex2, triangle.Vertex3, VV0, VV1, VV2, D0, D1, D2, out isect0, out isect1, out isectpoint0, out isectpoint1);
            }
            else if (D1 != 0d)
            {
                Intersect2(triangle.Vertex2, triangle.Vertex1, triangle.Vertex3, VV1, VV0, VV2, D1, D0, D2, out isect0, out isect1, out isectpoint0, out isectpoint1);
            }
            else if (D2 != 0d)
            {
                Intersect2(triangle.Vertex3, triangle.Vertex1, triangle.Vertex2, VV2, VV0, VV1, D2, D0, D1, out isect0, out isect1, out isectpoint0, out isectpoint1);
            }
            else
            {
                // triangles are coplanar
                return true;
            }

            return false;
        }
        /// <summary>
        /// This version computes the line of intersection as well (if they are not coplanar):
        /// coplanar returns whether the tris are coplanar
        /// isectpt1, isectpt2 are the endpoints of the line of intersection
        /// </summary>
        /// <remarks>
        /// by Tomas Moller, 1997.
        /// See article "A Fast Triangle-Triangle Intersection Test",
        /// Journal of Graphics Tools, 2(2), 1997
        /// updated: 2001-06-20 (added line of intersection)
        /// </remarks>
        private static bool TriTriIntersectWithIsectline(out bool isCoplanar, out MyVector[] intersectPoints, Triangle triangle1, Triangle triangle2, bool doTestIfCoplanar)
        {
            isCoplanar = false;
            intersectPoints = null;

            #region Part 1a

            // compute plane equation of triangle 1
            MyVector edge1 = triangle1.Vertex2 - triangle1.Vertex1;
            MyVector edge2 = triangle1.Vertex3 - triangle1.Vertex1;
            MyVector normal1 = MyVector.Cross(edge1, edge2);
            double d1 = MyVector.Dot(normal1, triangle1.Vertex1) * -1d;
            // plane equation 1: N1.X+d1=0

            // put triangle 2 into plane equation 1 to compute signed distances to the plane
            double du0 = MyVector.Dot(normal1, triangle2.Vertex1) + d1;
            double du1 = MyVector.Dot(normal1, triangle2.Vertex2) + d1;
            double du2 = MyVector.Dot(normal1, triangle2.Vertex3) + d1;

            // coplanarity robustness check
            if (Utility3D.IsNearZero(du0)) du0 = 0d;
            if (Utility3D.IsNearZero(du1)) du1 = 0d;
            if (Utility3D.IsNearZero(du2)) du2 = 0d;

            double du0du1 = du0 * du1;
            double du0du2 = du0 * du2;

            if (du0du1 > 0d && du0du2 > 0d)		// same sign on all of them + not equal 0 ?
            {
                return false;		// no intersection occurs
            }

            #endregion
            #region Part 1b

            // compute plane of triangle 2
            edge1 = triangle2.Vertex2 - triangle2.Vertex1;
            edge2 = triangle2.Vertex3 - triangle2.Vertex1;
            MyVector normal2 = MyVector.Cross(edge1, edge2);
            double d2 = MyVector.Dot(normal2, triangle2.Vertex1) * -1d;
            // plane equation 2: N2.X+d2=0

            // put V0,V1,V2 into plane equation 2
            double dv0 = MyVector.Dot(normal2, triangle1.Vertex1) + d2;
            double dv1 = MyVector.Dot(normal2, triangle1.Vertex2) + d2;
            double dv2 = MyVector.Dot(normal2, triangle1.Vertex3) + d2;

            // Check for near zero
            if (Utility3D.IsNearZero(dv0)) dv0 = 0d;
            if (Utility3D.IsNearZero(dv1)) dv1 = 0d;
            if (Utility3D.IsNearZero(dv2)) dv2 = 0d;

            double dv0dv1 = dv0 * dv1;
            double dv0dv2 = dv0 * dv2;

            if (dv0dv1 > 0d && dv0dv2 > 0d)		// same sign on all of them + not equal 0 ?
            {
                return false;		// no intersection occurs
            }

            #endregion

            // compute direction of intersection line
            MyVector intersectLineDirection = MyVector.Cross(normal1, normal2);

            #region Part 2

            // compute and index to the largest component of intersectLineDirection
            double max = Math.Abs(intersectLineDirection.X);
            int index = 0;
            double b = Math.Abs(intersectLineDirection.Y);
            double c = Math.Abs(intersectLineDirection.Z);
            if (b > max) { max = b; index = 1; }
            if (c > max) { max = c; index = 2; }

            // this is the simplified projection onto L
            double vp0 = triangle1.Vertex1[index];
            double vp1 = triangle1.Vertex2[index];
            double vp2 = triangle1.Vertex3[index];

            double up0 = triangle2.Vertex1[index];
            double up1 = triangle2.Vertex2[index];
            double up2 = triangle2.Vertex3[index];

            #endregion

            #region Part 3a

            double[] isect1 = new double[2];
            MyVector isectpointA1, isectpointA2;

            // compute interval for triangle 1
            isCoplanar = ComputeIntervalsIsEctLine(triangle1, vp0, vp1, vp2, dv0, dv1, dv2,
                                 dv0dv1, dv0dv2, out isect1[0], out isect1[1], out isectpointA1, out isectpointA2);
            if (isCoplanar)
            {
                if (doTestIfCoplanar)
                {
                    return IsCoplanarTriTri(normal1, triangle1, triangle2);
                }
                else
                {
                    return false;		// They're not going to look at the result anyway
                }
            }

            #endregion
            #region Part 3b

            double[] isect2 = new double[2];
            MyVector isectpointB1, isectpointB2;

            // compute interval for triangle 2
            ComputeIntervalsIsEctLine(triangle2, up0, up1, up2, du0, du1, du2,
                            du0du1, du0du2, out isect2[0], out isect2[1], out isectpointB1, out isectpointB2);


            int smallest1 = Sort(ref isect1[0], ref isect1[1]);
            int smallest2 = Sort(ref isect2[0], ref isect2[1]);

            if (isect1[1] < isect2[0] || isect2[1] < isect1[0])
            {
                return false;
            }

            #endregion

            // at this point, we know that the triangles intersect

            intersectPoints = new MyVector[2];

            #region Part 4 (edge clipping)

            if (isect2[0] < isect1[0])
            {
                if (smallest1 == 0) { intersectPoints[0] = isectpointA1.Clone(); }
                else { intersectPoints[0] = isectpointA2.Clone(); }

                if (isect2[1] < isect1[1])
                {
                    if (smallest2 == 0) { intersectPoints[1] = isectpointB2.Clone(); }
                    else { intersectPoints[1] = isectpointB1.Clone(); }
                }
                else
                {
                    if (smallest1 == 0) { intersectPoints[1] = isectpointA2.Clone(); }
                    else { intersectPoints[1] = isectpointA1.Clone(); }
                }
            }
            else
            {
                if (smallest2 == 0) { intersectPoints[0] = isectpointB1.Clone(); }
                else { intersectPoints[0] = isectpointB2.Clone(); }

                if (isect2[1] > isect1[1])
                {
                    if (smallest1 == 0) { intersectPoints[1] = isectpointA2.Clone(); }
                    else { intersectPoints[1] = isectpointA1.Clone(); }
                }
                else
                {
                    if (smallest2 == 0) { intersectPoints[1] = isectpointB2.Clone(); }
                    else { intersectPoints[1] = isectpointB1.Clone(); }
                }
            }

            #endregion

            return true;
        }
示例#11
0
 public MyPolygon(MyVector[] uniquePoints, Triangle[] triangles)
 {
     _uniquePoints = uniquePoints;
     _triangles = triangles;
 }
示例#12
0
        public MyPolygonSyncedRotation(MyVector[] uniquePoints, Triangle[] triangles, MyQuaternion rotation)
            : base(uniquePoints, triangles)
        {
            MyVector[] clonedPoints = Utility3D.GetClonedArray(uniquePoints);
            _rotatedPoly = new MyPolygon(clonedPoints, Utility3D.GetClonedArray(clonedPoints, triangles));

            SyncRotation(rotation);
        }
示例#13
0
        public static MyPolygon CreateTetrahedron(double size, bool centered)
        {

            // Sketchup and MathWorld are cool

            //double height2D = Math.Sqrt((size * size) - ((size * size) / 4d));
            double height2D = size * (Math.Sqrt(3) / 2d);
            double height3D = Math.Sqrt(6d) * (size / 3d);
            double halfSize = size / 2d;

            MyVector[] uniquePoints = new MyVector[4];

            uniquePoints[0] = new MyVector(0, 0, 0);
            uniquePoints[1] = new MyVector(size, 0, 0);
            uniquePoints[2] = new MyVector(halfSize, height2D, 0);
            uniquePoints[3] = new MyVector(halfSize, Math.Tan(Utility3D.GetDegreesToRadians(30)) * halfSize, height3D);

            if (centered)
            {
                double negHalfHeight3d = height3D * -.5d;
                MyVector offset = new MyVector(negHalfHeight3d, negHalfHeight3d, negHalfHeight3d);

                for (int cntr = 0; cntr < uniquePoints.Length; cntr++)
                {
                    uniquePoints[cntr].Add(offset);
                }
            }

            Triangle[] triangles = new Triangle[4];

            triangles[0] = new Triangle(uniquePoints, 0, 1, 3);
            triangles[1] = new Triangle(uniquePoints, 1, 2, 3);
            triangles[2] = new Triangle(uniquePoints, 0, 3, 2);
            triangles[3] = new Triangle(uniquePoints, 0, 2, 1);

            return new MyPolygon(uniquePoints, triangles);
        }
示例#14
0
        public static MyPolygon CreateCube(double size, bool centered)
        {

            // Sketchup Kicks Ass!!!!!!

            MyVector[] uniquePoints = new MyVector[8];

            uniquePoints[0] = new MyVector(0, 0, 0);
            uniquePoints[1] = new MyVector(size, 0, size);
            uniquePoints[2] = new MyVector(0, 0, size);
            uniquePoints[3] = new MyVector(size, 0, 0);
            uniquePoints[4] = new MyVector(0, size, size);
            uniquePoints[5] = new MyVector(size, size, size);
            uniquePoints[6] = new MyVector(0, size, 0);
            uniquePoints[7] = new MyVector(size, size, 0);

            if (centered)
            {
                double negHalfSize = size * -.5d;
                MyVector offset = new MyVector(negHalfSize, negHalfSize, negHalfSize);

                for (int cntr = 0; cntr < uniquePoints.Length; cntr++)
                {
                    uniquePoints[cntr].Add(offset);
                }
            }

            Triangle[] triangles = new Triangle[12];

            triangles[0] = new Triangle(uniquePoints, 0, 1, 2);
            triangles[1] = new Triangle(uniquePoints, 0, 3, 1);
            triangles[2] = new Triangle(uniquePoints, 2, 1, 4);
            triangles[3] = new Triangle(uniquePoints, 1, 5, 4);
            triangles[4] = new Triangle(uniquePoints, 0, 2, 4);
            triangles[5] = new Triangle(uniquePoints, 0, 4, 6);
            triangles[6] = new Triangle(uniquePoints, 4, 5, 7);
            triangles[7] = new Triangle(uniquePoints, 4, 7, 6);
            triangles[8] = new Triangle(uniquePoints, 1, 3, 7);
            triangles[9] = new Triangle(uniquePoints, 1, 7, 5);
            triangles[10] = new Triangle(uniquePoints, 0, 6, 7);
            triangles[11] = new Triangle(uniquePoints, 0, 7, 3);

            return new MyPolygon(uniquePoints, triangles);
        }