Ejemplo n.º 1
0
        /// <summary>
        /// Pass in a cloud of points and an array of triangle indices shall be returned.
        /// </summary>
        /// <param name="points">Points to create hull from.</param>
        /// <returns>Triangle index array of hull.</returns>
        public static int[] ComputeHull(Vector3[] points)
        {
            if (points.Length < 3) return null;

            //local copy of the point set
            Face.points = points;

            //calculates the first convex tetrahedron

            //creates a face with the first 3 vertices
            Face faceA = new Face(0, 1, 2);

            //this is the center of the tetrahedron, all face should point outwards:
            //they should not be visible to the centroid
            Vector3 v = Centroid(points, 3, faceA);

            if (faceA.IsVisible(v))
            {
                faceA.Flip();
            }

            Face face0 = new Face(3, faceA.i0, faceA.i1);
            if (face0.IsVisible(v))
            {
                face0.Flip();
            }

            Face face1 = new Face(3, faceA.i1, faceA.i2);
            if (face1.IsVisible(v))
            {
                face1.Flip();
            }

            Face face2 = new Face(3, faceA.i2, faceA.i0);
            if (face2.IsVisible(v))
            {
                face2.Flip();
            }

            //store the tetrahedron faces in the valid faces list
            validFaces = new List<Face> { faceA, face0, face1, face2 };

            visibleFaces = new List<Face>(points.Length);
            tmpFaces = new List<Face>(points.Length);

            //so as we have a convex tetrahedron, we can skip the first 4 points
            for (int i = 4; i < points.Length; i++)
            {
                //for each avaiable vertices
                v = points[i];

                //checks the point's visibility from all faces
                visibleFaces.Clear();
                for (int j = 0; j < validFaces.Count; j++)
                {
                    if (validFaces[j].IsVisible(v))
                    {
                        visibleFaces.Add(validFaces[j]);
                    }
                }

                //the vertex is not visible : it is inside the convex hull, keep on
                if (visibleFaces.Count == 0) continue;

                //the vertex is outside the convex hull
                //delete all visible faces from the valid List
                for (int index = 0; index < visibleFaces.Count; index++)
                {
                    validFaces.Remove(visibleFaces[index]);
                }

                //special case : only one face is visible
                //it's ok to create 3 faces directly for they won't enclose any other point
                if (visibleFaces.Count == 1)
                {
                    faceA = visibleFaces[0];
                    validFaces.Add(new Face(i, faceA.i0, faceA.i1));
                    validFaces.Add(new Face(i, faceA.i1, faceA.i2));
                    validFaces.Add(new Face(i, faceA.i2, faceA.i0));
                    continue;
                }

                if (visibleFaces.Count > 2000)
                {
                    Debug.LogWarning("Visible faces is too big, " + visibleFaces.Count + " cancelling operation.");
                    return new int[0];
                }

                //creates all possible new faces from the visibleFaces
                tmpFaces.Clear();
                for (int k = 0; k < visibleFaces.Count; k++)
                {
                    tmpFaces.Add(new Face(i, visibleFaces[k].i0, visibleFaces[k].i1));
                    tmpFaces.Add(new Face(i, visibleFaces[k].i1, visibleFaces[k].i2));
                    tmpFaces.Add(new Face(i, visibleFaces[k].i2, visibleFaces[k].i0));
                }

                if (tmpFaces.Count > 8000)
                {
                    Debug.LogWarning("Temp faces is too big, " + tmpFaces.Count + " cancelling operation.");
                    return new int[0];
                }

                //Face other;
                for (int l = 0; l < tmpFaces.Count; l++)
                {
                    Face face = tmpFaces[l];
                    //search if there is a point in front of the face :
                    //this means the face doesn't belong to the convex hull

                    for (int index1 = 0; index1 < tmpFaces.Count; index1++)
                    {
                        if (face != tmpFaces[index1])
                        {
                            if (face.IsVisible(tmpFaces[index1].Centroid))
                            {
                                face = null;
                                break;
                            }
                        }
                    }

                    //the face has no point in front of it
                    if (face != null)
                    {
                        validFaces.Add(face);
                    }
                }
            }

            var result = new int[validFaces.Count * 3];
            int vertIndex = 0;

            for (int i = 0; i < validFaces.Count; i++)
            {
                result[vertIndex++] = validFaces[i].i0;
                result[vertIndex++] = validFaces[i].i1;
                result[vertIndex++] = validFaces[i].i2;
            }

            return result;
        }
Ejemplo n.º 2
0
 private static Vector3 Centroid(Vector3[] points, int index, Face face)
 {
     Vector3 p = points[index];
     p += points[face.i0];
     p += points[face.i1];
     p += points[face.i2];
     return p / 4;
 }