Пример #1
0
        public FastHull(FastHull reference)
        {
            vertices = new List <Vector3>(reference.vertices.Count);
            indices  = new List <int>(reference.indices.Count);

            if (reference.normals != null)
            {
                normals = new List <Vector3>(reference.normals.Count);
            }

            if (reference.colors != null)
            {
                colors = new List <Color32>(reference.colors.Count);
            }

            if (reference.tangents != null)
            {
                tangents = new List <Vector4>(reference.tangents.Count);
            }

            if (reference.uvs != null)
            {
                uvs = new List <Vector2>(reference.uvs.Count);
            }
        }
Пример #2
0
 public FastHull(FastHull reference)
 {
     vertices = new List<Vector3>(reference.vertices.Count);
     indices = new List<int>(reference.indices.Count);
     
     if (reference.normals != null)
     {
         normals = new List<Vector3>(reference.normals.Count);
     }
     
     if (reference.colors != null)
     {
         colors = new List<Color32>(reference.colors.Count);
     }
     
     if (reference.tangents != null)
     {
         tangents = new List<Vector4>(reference.tangents.Count);
     }
     
     if (reference.uvs != null)
     {
         uvs = new List<Vector2>(reference.uvs.Count);
     }
 }
Пример #3
0
        public void Split(Vector3 localPointOnPlane, Vector3 localPlaneNormal, bool fillCut, UvMapper uvMapper, ColorMapper colorMapper, out IHull resultA, out IHull resultB)
        {
            if (localPlaneNormal == Vector3.zero)
            {
                localPlaneNormal = Vector3.up;
            }

            FastHull a = new FastHull(this);
            FastHull b = new FastHull(this);

            bool[] vertexAbovePlane;
            int[]  oldToNewVertexMap;

            AssignVertices(a, b, localPointOnPlane, localPlaneNormal, out vertexAbovePlane, out oldToNewVertexMap);

            IList <Vector3> cutEdges;

            AssignTriangles(a, b, vertexAbovePlane, oldToNewVertexMap, localPointOnPlane, localPlaneNormal, out cutEdges);

            if (fillCut)
            {
                if (colors != null && colorMapper == null)
                {
                    Debug.LogWarning("Fill cut failed: A ColorMapper was not provided even though the mesh has a color channel");
                }
                else if ((tangents != null || uvs != null) && uvMapper == null)
                {
                    Debug.LogWarning("Fill cut failed: A UvMapper was not provided even though the mesh has a tangent/uv channel");
                }
                else
                {
                    FillCutEdges(a, b, cutEdges, localPlaneNormal, uvMapper, colorMapper);
                }
            }

            ValidateOutput(a, b, localPlaneNormal);

            // Set output
            resultA = a;
            resultB = b;
        }
Пример #4
0
        protected void ValidateOutput(FastHull a, FastHull b, Vector3 planeNormal)
        {
            float lengthA = a.LengthAlongAxis(planeNormal);
            float lengthB = b.LengthAlongAxis(planeNormal);

            float sum = lengthA + lengthB;

            if (sum < smallestValidLength)
            {
                a.isValid = false;
                b.isValid = false;
            }
            else if (lengthA / sum < smallestValidRatio)
            {
                a.isValid = false;
            }
            else if (lengthB / sum < smallestValidRatio)
            {
                b.isValid = false;
            }
        }
Пример #5
0
        protected void FillCutEdges(FastHull a, FastHull b, IList <Vector3> edges, Vector3 planeNormal, UvMapper uvMapper, ColorMapper colorMapper)
        {
            int edgeCount = edges.Count / 2;

            List <Vector3> points  = new List <Vector3>(edgeCount);
            List <int>     outline = new List <int>(edgeCount * 2);

            int start = 0;

            for (int current = 0; current < edgeCount; current++)
            {
                int next = current + 1;

                // Find the next edge
                int   nearest         = start;
                float nearestDistance = (edges[current * 2 + 1] - edges[start * 2 + 0]).sqrMagnitude;

                for (int other = next; other < edgeCount; other++)
                {
                    float distance = (edges[current * 2 + 1] - edges[other * 2 + 0]).sqrMagnitude;

                    if (distance < nearestDistance)
                    {
                        nearest         = other;
                        nearestDistance = distance;
                    }
                }

                // Is the current edge the last edge in this edge loop?
                if (nearest == start && current > start)
                {
                    int pointStart   = points.Count;
                    int pointCounter = pointStart;

                    // Add this edge loop to the triangulation lists
                    for (int edge = start; edge < current; edge++)
                    {
                        points.Add(edges[edge * 2 + 0]);
                        outline.Add(pointCounter++);
                        outline.Add(pointCounter);
                    }

                    points.Add(edges[current * 2 + 0]);
                    outline.Add(pointCounter);
                    outline.Add(pointStart);

                    // Start a new edge loop
                    start = next;
                }
                else if (next < edgeCount)
                {
                    // Move the nearest edge so that it follows the current edge
                    Vector3 n0 = edges[next * 2 + 0];
                    Vector3 n1 = edges[next * 2 + 1];

                    edges[next * 2 + 0] = edges[nearest * 2 + 0];
                    edges[next * 2 + 1] = edges[nearest * 2 + 1];

                    edges[nearest * 2 + 0] = n0;
                    edges[nearest * 2 + 1] = n1;
                }
            }

            if (points.Count > 0)
            {
                // Triangulate the outline
                int[] newEdges, newTriangles, newTriangleEdges;

                ITriangulator triangulator = new Triangulator(points, outline, planeNormal);

                triangulator.Fill(out newEdges, out newTriangles, out newTriangleEdges);

                // Add the new vertices
                int offsetA = a.vertices.Count;
                int offsetB = b.vertices.Count;

                a.vertices.AddRange(points);
                b.vertices.AddRange(points);

                if (normals != null)
                {
                    Vector3 normalA = -planeNormal;
                    Vector3 normalB = planeNormal;

                    for (int i = 0; i < points.Count; i++)
                    {
                        a.normals.Add(normalA);
                        b.normals.Add(normalB);
                    }
                }

                if (colors != null)
                {
                    Color32[] colorsA, colorsB;

                    colorMapper.Map(points, planeNormal, out colorsA, out colorsB);

                    a.colors.AddRange(colorsA);
                    b.colors.AddRange(colorsB);
                }

                if (tangents != null || uvs != null)
                {
                    Vector4[] tangentsA, tangentsB;
                    Vector2[] uvsA, uvsB;

                    uvMapper.Map(points, planeNormal, out tangentsA, out tangentsB, out uvsA, out uvsB);

                    if (tangents != null)
                    {
                        a.tangents.AddRange(tangentsA);
                        b.tangents.AddRange(tangentsB);
                    }

                    if (uvs != null)
                    {
                        a.uvs.AddRange(uvsA);
                        b.uvs.AddRange(uvsB);
                    }
                }

                // Add the new triangles
                int newTriangleCount = newTriangles.Length / 3;

                for (int i = 0; i < newTriangleCount; i++)
                {
                    a.indices.Add(offsetA + newTriangles[i * 3 + 0]);
                    a.indices.Add(offsetA + newTriangles[i * 3 + 2]);
                    a.indices.Add(offsetA + newTriangles[i * 3 + 1]);

                    b.indices.Add(offsetB + newTriangles[i * 3 + 0]);
                    b.indices.Add(offsetB + newTriangles[i * 3 + 1]);
                    b.indices.Add(offsetB + newTriangles[i * 3 + 2]);
                }
            }
        }
Пример #6
0
        protected void SplitTriangle(FastHull topHull, FastHull bottomHull, int[] oldToNewVertexMap, Vector3 pointOnPlane, Vector3 planeNormal, int top, int cw, int ccw, out Vector3 cwIntersection, out Vector3 ccwIntersection)
        {
            Vector3 v0 = vertices[top];
            Vector3 v1 = vertices[cw];
            Vector3 v2 = vertices[ccw];

            // Intersect the top-cw edge with the plane
            float cwDenominator = Vector3.Dot(v1 - v0, planeNormal);
            float cwScalar      = Mathf.Clamp01(Vector3.Dot(pointOnPlane - v0, planeNormal) / cwDenominator);

            // Intersect the top-ccw edge with the plane
            float ccwDenominator = Vector3.Dot(v2 - v0, planeNormal);
            float ccwScalar      = Mathf.Clamp01(Vector3.Dot(pointOnPlane - v0, planeNormal) / ccwDenominator);

            // Interpolate vertex positions
            Vector3 cwVertex = new Vector3();

            cwVertex.x = v0.x + (v1.x - v0.x) * cwScalar;
            cwVertex.y = v0.y + (v1.y - v0.y) * cwScalar;
            cwVertex.z = v0.z + (v1.z - v0.z) * cwScalar;

            Vector3 ccwVertex = new Vector3();

            ccwVertex.x = v0.x + (v2.x - v0.x) * ccwScalar;
            ccwVertex.y = v0.y + (v2.y - v0.y) * ccwScalar;
            ccwVertex.z = v0.z + (v2.z - v0.z) * ccwScalar;

            // Create top triangle
            int cwA = topHull.vertices.Count;

            topHull.vertices.Add(cwVertex);

            int ccwA = topHull.vertices.Count;

            topHull.vertices.Add(ccwVertex);

            topHull.indices.Add(oldToNewVertexMap[top]);
            topHull.indices.Add(cwA);
            topHull.indices.Add(ccwA);

            // Create bottom triangles
            int cwB = bottomHull.vertices.Count;

            bottomHull.vertices.Add(cwVertex);

            int ccwB = bottomHull.vertices.Count;

            bottomHull.vertices.Add(ccwVertex);

            bottomHull.indices.Add(oldToNewVertexMap[cw]);
            bottomHull.indices.Add(oldToNewVertexMap[ccw]);
            bottomHull.indices.Add(ccwB);

            bottomHull.indices.Add(oldToNewVertexMap[cw]);
            bottomHull.indices.Add(ccwB);
            bottomHull.indices.Add(cwB);

            // Interpolate normals
            if (normals != null)
            {
                Vector3 n0 = normals[top];
                Vector3 n1 = normals[cw];
                Vector3 n2 = normals[ccw];

                Vector3 cwNormal = new Vector3();

                cwNormal.x = n0.x + (n1.x - n0.x) * cwScalar;
                cwNormal.y = n0.y + (n1.y - n0.y) * cwScalar;
                cwNormal.z = n0.z + (n1.z - n0.z) * cwScalar;

                cwNormal.Normalize();

                Vector3 ccwNormal = new Vector3();

                ccwNormal.x = n0.x + (n2.x - n0.x) * ccwScalar;
                ccwNormal.y = n0.y + (n2.y - n0.y) * ccwScalar;
                ccwNormal.z = n0.z + (n2.z - n0.z) * ccwScalar;

                ccwNormal.Normalize();

                // Add vertex property
                topHull.normals.Add(cwNormal);
                topHull.normals.Add(ccwNormal);

                bottomHull.normals.Add(cwNormal);
                bottomHull.normals.Add(ccwNormal);
            }

            // Interpolate colors
            if (colors != null)
            {
                Color32 c0 = colors[top];
                Color32 c1 = colors[cw];
                Color32 c2 = colors[ccw];

                Color32 cwColor  = Color32.Lerp(c0, c1, cwScalar);
                Color32 ccwColor = Color32.Lerp(c0, c2, ccwScalar);

                // Add vertex property
                topHull.colors.Add(cwColor);
                topHull.colors.Add(ccwColor);

                bottomHull.colors.Add(cwColor);
                bottomHull.colors.Add(ccwColor);
            }

            // Interpolate tangents
            if (tangents != null)
            {
                Vector4 t0 = tangents[top];
                Vector4 t1 = tangents[cw];
                Vector4 t2 = tangents[ccw];

                Vector4 cwTangent = new Vector4();

                cwTangent.x = t0.x + (t1.x - t0.x) * cwScalar;
                cwTangent.y = t0.y + (t1.y - t0.y) * cwScalar;
                cwTangent.z = t0.z + (t1.z - t0.z) * cwScalar;

                cwTangent.Normalize();
                cwTangent.w = t1.w;

                Vector4 ccwTangent = new Vector4();

                ccwTangent.x = t0.x + (t2.x - t0.x) * ccwScalar;
                ccwTangent.y = t0.y + (t2.y - t0.y) * ccwScalar;
                ccwTangent.z = t0.z + (t2.z - t0.z) * ccwScalar;

                ccwTangent.Normalize();
                ccwTangent.w = t2.w;

                // Add vertex property
                topHull.tangents.Add(cwTangent);
                topHull.tangents.Add(ccwTangent);

                bottomHull.tangents.Add(cwTangent);
                bottomHull.tangents.Add(ccwTangent);
            }

            // Interpolate uvs
            if (uvs != null)
            {
                Vector2 u0 = uvs[top];
                Vector2 u1 = uvs[cw];
                Vector2 u2 = uvs[ccw];

                Vector2 cwUv = new Vector2();

                cwUv.x = u0.x + (u1.x - u0.x) * cwScalar;
                cwUv.y = u0.y + (u1.y - u0.y) * cwScalar;

                Vector2 ccwUv = new Vector2();

                ccwUv.x = u0.x + (u2.x - u0.x) * ccwScalar;
                ccwUv.y = u0.y + (u2.y - u0.y) * ccwScalar;

                // Add vertex property
                topHull.uvs.Add(cwUv);
                topHull.uvs.Add(ccwUv);

                bottomHull.uvs.Add(cwUv);
                bottomHull.uvs.Add(ccwUv);
            }

            // Set output
            cwIntersection  = cwVertex;
            ccwIntersection = ccwVertex;
        }
Пример #7
0
        protected void AssignTriangles(FastHull a, FastHull b, bool[] vertexAbovePlane, int[] oldToNewVertexMap, Vector3 pointOnPlane, Vector3 planeNormal, out IList <Vector3> cutEdges)
        {
            cutEdges = new List <Vector3>();

            int triangleCount = indices.Count / 3;

            for (int i = 0; i < triangleCount; i++)
            {
                int index0 = indices[i * 3 + 0];
                int index1 = indices[i * 3 + 1];
                int index2 = indices[i * 3 + 2];

                bool above0 = vertexAbovePlane[index0];
                bool above1 = vertexAbovePlane[index1];
                bool above2 = vertexAbovePlane[index2];

                if (above0 && above1 && above2)
                {
                    // Assign triangle to hull A
                    a.indices.Add(oldToNewVertexMap[index0]);
                    a.indices.Add(oldToNewVertexMap[index1]);
                    a.indices.Add(oldToNewVertexMap[index2]);
                }
                else if (!above0 && !above1 && !above2)
                {
                    // Assign triangle to hull B
                    b.indices.Add(oldToNewVertexMap[index0]);
                    b.indices.Add(oldToNewVertexMap[index1]);
                    b.indices.Add(oldToNewVertexMap[index2]);
                }
                else
                {
                    // Split triangle
                    int top, cw, ccw;

                    if (above1 == above2 && above0 != above1)
                    {
                        top = index0;
                        cw  = index1;
                        ccw = index2;
                    }
                    else if (above2 == above0 && above1 != above2)
                    {
                        top = index1;
                        cw  = index2;
                        ccw = index0;
                    }
                    else
                    {
                        top = index2;
                        cw  = index0;
                        ccw = index1;
                    }

                    Vector3 cutVertex0, cutVertex1;

                    if (vertexAbovePlane[top])
                    {
                        SplitTriangle(a, b, oldToNewVertexMap, pointOnPlane, planeNormal, top, cw, ccw, out cutVertex0, out cutVertex1);
                    }
                    else
                    {
                        SplitTriangle(b, a, oldToNewVertexMap, pointOnPlane, planeNormal, top, cw, ccw, out cutVertex1, out cutVertex0);
                    }

                    // Add cut edge
                    if (cutVertex0 != cutVertex1)
                    {
                        cutEdges.Add(cutVertex0);
                        cutEdges.Add(cutVertex1);
                    }
                }
            }
        }
Пример #8
0
        protected void AssignVertices(FastHull a, FastHull b, Vector3 pointOnPlane, Vector3 planeNormal, out bool[] vertexAbovePlane, out int[] oldToNewVertexMap)
        {
            vertexAbovePlane  = new bool[vertices.Count];
            oldToNewVertexMap = new int[vertices.Count];

            for (int i = 0; i < vertices.Count; i++)
            {
                Vector3 vertex = vertices[i];

                bool abovePlane = Vector3.Dot(vertex - pointOnPlane, planeNormal) >= 0.0f;

                vertexAbovePlane[i] = abovePlane;

                if (abovePlane)
                {
                    // Assign vertex to hull A
                    oldToNewVertexMap[i] = a.vertices.Count;

                    a.vertices.Add(vertex);

                    if (normals != null)
                    {
                        a.normals.Add(normals[i]);
                    }

                    if (colors != null)
                    {
                        a.colors.Add(colors[i]);
                    }

                    if (tangents != null)
                    {
                        a.tangents.Add(tangents[i]);
                    }

                    if (uvs != null)
                    {
                        a.uvs.Add(uvs[i]);
                    }
                }
                else
                {
                    // Assign vertex to hull B
                    oldToNewVertexMap[i] = b.vertices.Count;

                    b.vertices.Add(vertex);

                    if (normals != null)
                    {
                        b.normals.Add(normals[i]);
                    }

                    if (colors != null)
                    {
                        b.colors.Add(colors[i]);
                    }

                    if (tangents != null)
                    {
                        b.tangents.Add(tangents[i]);
                    }

                    if (uvs != null)
                    {
                        b.uvs.Add(uvs[i]);
                    }
                }
            }
        }
Пример #9
0
 protected void ValidateOutput(FastHull a, FastHull b, Vector3 planeNormal)
 {
     float lengthA = a.LengthAlongAxis(planeNormal);
     float lengthB = b.LengthAlongAxis(planeNormal);
     
     float sum = lengthA + lengthB;
     
     if (sum < smallestValidLength)
     {
         a.isValid = false;
         b.isValid = false;
     }
     else if (lengthA / sum < smallestValidRatio)
     {
         a.isValid = false;
     }
     else if (lengthB / sum < smallestValidRatio)
     {
         b.isValid = false;
     }
 }
Пример #10
0
 protected void FillCutEdges(FastHull a, FastHull b, IList<Vector3> edges, Vector3 planeNormal, UvMapper uvMapper, ColorMapper colorMapper)
 {
     int edgeCount = edges.Count / 2;
     
     List<Vector3> points = new List<Vector3>(edgeCount);
     List<int> outline = new List<int>(edgeCount * 2);
     
     int start = 0;
     
     for (int current = 0; current < edgeCount; current++)
     {
         int next = current + 1;
         
         // Find the next edge
         int nearest = start;
         float nearestDistance = (edges[current * 2 + 1] - edges[start * 2 + 0]).sqrMagnitude;
         
         for (int other = next; other < edgeCount; other++)
         {
             float distance = (edges[current * 2 + 1] - edges[other * 2 + 0]).sqrMagnitude;
             
             if (distance < nearestDistance)
             {
                 nearest = other;
                 nearestDistance = distance;
             }
         }
         
         // Is the current edge the last edge in this edge loop?
         if (nearest == start && current > start)
         {
             int pointStart = points.Count;
             int pointCounter = pointStart;
             
             // Add this edge loop to the triangulation lists
             for (int edge = start; edge < current; edge++)
             {
                 points.Add(edges[edge * 2 + 0]);
                 outline.Add(pointCounter++);
                 outline.Add(pointCounter);
             }
             
             points.Add(edges[current * 2 + 0]);
             outline.Add(pointCounter);
             outline.Add(pointStart);
             
             // Start a new edge loop
             start = next;
         }
         else if (next < edgeCount)
         {
             // Move the nearest edge so that it follows the current edge
             Vector3 n0 = edges[next * 2 + 0];
             Vector3 n1 = edges[next * 2 + 1];
             
             edges[next * 2 + 0] = edges[nearest * 2 + 0];
             edges[next * 2 + 1] = edges[nearest * 2 + 1];
             
             edges[nearest * 2 + 0] = n0;
             edges[nearest * 2 + 1] = n1;
         }
     }
     
     if (points.Count > 0)
     {
         // Triangulate the outline
         int[] newEdges, newTriangles, newTriangleEdges;
         
         ITriangulator triangulator = new Triangulator(points, outline, planeNormal);
         
         triangulator.Fill(out newEdges, out newTriangles, out newTriangleEdges);
         
         // Add the new vertices
         int offsetA = a.vertices.Count;
         int offsetB = b.vertices.Count;
         
         a.vertices.AddRange(points);
         b.vertices.AddRange(points);
         
         if (normals != null)
         {
             Vector3 normalA = -planeNormal;
             Vector3 normalB = planeNormal;
             
             for (int i = 0; i < points.Count; i++)
             {
                 a.normals.Add(normalA);
                 b.normals.Add(normalB);
             }
         }
         
         if (colors != null)
         {
             Color32[] colorsA, colorsB;
             
             colorMapper.Map(points, planeNormal, out colorsA, out colorsB);
             
             a.colors.AddRange(colorsA);
             b.colors.AddRange(colorsB);
         }
         
         if (tangents != null || uvs != null)
         {
             Vector4[] tangentsA, tangentsB;
             Vector2[] uvsA, uvsB;
             
             uvMapper.Map(points, planeNormal, out tangentsA, out tangentsB, out uvsA, out uvsB);
             
             if (tangents != null)
             {
                 a.tangents.AddRange(tangentsA);
                 b.tangents.AddRange(tangentsB);
             }
             
             if (uvs != null)
             {
                 a.uvs.AddRange(uvsA);
                 b.uvs.AddRange(uvsB);
             }
         }
         
         // Add the new triangles
         int newTriangleCount = newTriangles.Length / 3;
         
         for (int i = 0; i < newTriangleCount; i++)
         {
             a.indices.Add(offsetA + newTriangles[i * 3 + 0]);
             a.indices.Add(offsetA + newTriangles[i * 3 + 2]);
             a.indices.Add(offsetA + newTriangles[i * 3 + 1]);
             
             b.indices.Add(offsetB + newTriangles[i * 3 + 0]);
             b.indices.Add(offsetB + newTriangles[i * 3 + 1]);
             b.indices.Add(offsetB + newTriangles[i * 3 + 2]);
         }
     }
 }
Пример #11
0
 protected void SplitTriangle(FastHull topHull, FastHull bottomHull, int[] oldToNewVertexMap, Vector3 pointOnPlane, Vector3 planeNormal, int top, int cw, int ccw, out Vector3 cwIntersection, out Vector3 ccwIntersection)
 {
     Vector3 v0 = vertices[top];
     Vector3 v1 = vertices[cw];
     Vector3 v2 = vertices[ccw];
     
     // Intersect the top-cw edge with the plane
     float cwDenominator = Vector3.Dot(v1 - v0, planeNormal);
     float cwScalar = Mathf.Clamp01(Vector3.Dot(pointOnPlane - v0, planeNormal) / cwDenominator);
     
     // Intersect the top-ccw edge with the plane
     float ccwDenominator = Vector3.Dot(v2 - v0, planeNormal);
     float ccwScalar = Mathf.Clamp01(Vector3.Dot(pointOnPlane - v0, planeNormal) / ccwDenominator);
     
     // Interpolate vertex positions
     Vector3 cwVertex = new Vector3();
     
     cwVertex.x = v0.x + (v1.x - v0.x) * cwScalar;
     cwVertex.y = v0.y + (v1.y - v0.y) * cwScalar;
     cwVertex.z = v0.z + (v1.z - v0.z) * cwScalar;
     
     Vector3 ccwVertex = new Vector3();
     
     ccwVertex.x = v0.x + (v2.x - v0.x) * ccwScalar;
     ccwVertex.y = v0.y + (v2.y - v0.y) * ccwScalar;
     ccwVertex.z = v0.z + (v2.z - v0.z) * ccwScalar;
     
     // Create top triangle
     int cwA = topHull.vertices.Count;
     topHull.vertices.Add(cwVertex);
     
     int ccwA = topHull.vertices.Count;
     topHull.vertices.Add(ccwVertex);
     
     topHull.indices.Add(oldToNewVertexMap[top]);
     topHull.indices.Add(cwA);
     topHull.indices.Add(ccwA);
     
     // Create bottom triangles
     int cwB = bottomHull.vertices.Count;
     bottomHull.vertices.Add(cwVertex);
     
     int ccwB = bottomHull.vertices.Count;
     bottomHull.vertices.Add(ccwVertex);
     
     bottomHull.indices.Add(oldToNewVertexMap[cw]);
     bottomHull.indices.Add(oldToNewVertexMap[ccw]);
     bottomHull.indices.Add(ccwB);
     
     bottomHull.indices.Add(oldToNewVertexMap[cw]);
     bottomHull.indices.Add(ccwB);
     bottomHull.indices.Add(cwB);
     
     // Interpolate normals
     if (normals != null)
     {
         Vector3 n0 = normals[top];
         Vector3 n1 = normals[cw];
         Vector3 n2 = normals[ccw];
         
         Vector3 cwNormal = new Vector3();
         
         cwNormal.x = n0.x + (n1.x - n0.x) * cwScalar;
         cwNormal.y = n0.y + (n1.y - n0.y) * cwScalar;
         cwNormal.z = n0.z + (n1.z - n0.z) * cwScalar;
         
         cwNormal.Normalize();
         
         Vector3 ccwNormal = new Vector3();
         
         ccwNormal.x = n0.x + (n2.x - n0.x) * ccwScalar;
         ccwNormal.y = n0.y + (n2.y - n0.y) * ccwScalar;
         ccwNormal.z = n0.z + (n2.z - n0.z) * ccwScalar;
         
         ccwNormal.Normalize();
         
         // Add vertex property
         topHull.normals.Add(cwNormal);
         topHull.normals.Add(ccwNormal);
         
         bottomHull.normals.Add(cwNormal);
         bottomHull.normals.Add(ccwNormal);
     }
     
     // Interpolate colors
     if (colors != null)
     {
         Color32 c0 = colors[top];
         Color32 c1 = colors[cw];
         Color32 c2 = colors[ccw];
         
         Color32 cwColor = Color32.Lerp(c0, c1, cwScalar);
         Color32 ccwColor = Color32.Lerp(c0, c2, ccwScalar);
         
         // Add vertex property
         topHull.colors.Add(cwColor);
         topHull.colors.Add(ccwColor);
         
         bottomHull.colors.Add(cwColor);
         bottomHull.colors.Add(ccwColor);
     }
     
     // Interpolate tangents
     if (tangents != null)
     {
         Vector4 t0 = tangents[top];
         Vector4 t1 = tangents[cw];
         Vector4 t2 = tangents[ccw];
         
         Vector4 cwTangent = new Vector4();
         
         cwTangent.x = t0.x + (t1.x - t0.x) * cwScalar;
         cwTangent.y = t0.y + (t1.y - t0.y) * cwScalar;
         cwTangent.z = t0.z + (t1.z - t0.z) * cwScalar;
         
         cwTangent.Normalize();
         cwTangent.w = t1.w;
         
         Vector4 ccwTangent = new Vector4();
         
         ccwTangent.x = t0.x + (t2.x - t0.x) * ccwScalar;
         ccwTangent.y = t0.y + (t2.y - t0.y) * ccwScalar;
         ccwTangent.z = t0.z + (t2.z - t0.z) * ccwScalar;
         
         ccwTangent.Normalize();
         ccwTangent.w = t2.w;
         
         // Add vertex property
         topHull.tangents.Add(cwTangent);
         topHull.tangents.Add(ccwTangent);
         
         bottomHull.tangents.Add(cwTangent);
         bottomHull.tangents.Add(ccwTangent);
     }
     
     // Interpolate uvs
     if (uvs != null)
     {
         Vector2 u0 = uvs[top];
         Vector2 u1 = uvs[cw];
         Vector2 u2 = uvs[ccw];
         
         Vector2 cwUv = new Vector2();
         
         cwUv.x = u0.x + (u1.x - u0.x) * cwScalar;
         cwUv.y = u0.y + (u1.y - u0.y) * cwScalar;
         
         Vector2 ccwUv = new Vector2();
         
         ccwUv.x = u0.x + (u2.x - u0.x) * ccwScalar;
         ccwUv.y = u0.y + (u2.y - u0.y) * ccwScalar;
         
         // Add vertex property
         topHull.uvs.Add(cwUv);
         topHull.uvs.Add(ccwUv);
         
         bottomHull.uvs.Add(cwUv);
         bottomHull.uvs.Add(ccwUv);
     }
     
     // Set output
     cwIntersection = cwVertex;
     ccwIntersection = ccwVertex;
 }
Пример #12
0
 protected void AssignTriangles(FastHull a, FastHull b, bool[] vertexAbovePlane, int[] oldToNewVertexMap, Vector3 pointOnPlane, Vector3 planeNormal, out IList<Vector3> cutEdges)
 {
     cutEdges = new List<Vector3>();
     
     int triangleCount = indices.Count / 3;
     
     for (int i = 0; i < triangleCount; i++)
     {
         int index0 = indices[i * 3 + 0];
         int index1 = indices[i * 3 + 1];
         int index2 = indices[i * 3 + 2];
         
         bool above0 = vertexAbovePlane[index0];
         bool above1 = vertexAbovePlane[index1];
         bool above2 = vertexAbovePlane[index2];
         
         if (above0 && above1 && above2)
         {
             // Assign triangle to hull A
             a.indices.Add(oldToNewVertexMap[index0]);
             a.indices.Add(oldToNewVertexMap[index1]);
             a.indices.Add(oldToNewVertexMap[index2]);
         }
         else if (!above0 && !above1 && !above2)
         {
             // Assign triangle to hull B
             b.indices.Add(oldToNewVertexMap[index0]);
             b.indices.Add(oldToNewVertexMap[index1]);
             b.indices.Add(oldToNewVertexMap[index2]);
         }
         else
         {
             // Split triangle
             int top, cw, ccw;
             
             if (above1 == above2 && above0 != above1)
             {
                 top = index0;
                 cw = index1;
                 ccw = index2;
             }
             else if (above2 == above0 && above1 != above2)
             {
                 top = index1;
                 cw = index2;
                 ccw = index0;
             }
             else
             {
                 top = index2;
                 cw = index0;
                 ccw = index1;
             }
             
             Vector3 cutVertex0, cutVertex1;
             
             if (vertexAbovePlane[top])
             {
                 SplitTriangle(a, b, oldToNewVertexMap, pointOnPlane, planeNormal, top, cw, ccw, out cutVertex0, out cutVertex1);
             }
             else
             {
                 SplitTriangle(b, a, oldToNewVertexMap, pointOnPlane, planeNormal, top, cw, ccw, out cutVertex1, out cutVertex0);
             }
             
             // Add cut edge
             if (cutVertex0 != cutVertex1)
             {
                 cutEdges.Add(cutVertex0);
                 cutEdges.Add(cutVertex1);
             }
         }
     }
 }
Пример #13
0
 protected void AssignVertices(FastHull a, FastHull b, Vector3 pointOnPlane, Vector3 planeNormal, out bool[] vertexAbovePlane, out int[] oldToNewVertexMap)
 {
     vertexAbovePlane = new bool[vertices.Count];
     oldToNewVertexMap = new int[vertices.Count];
     
     for (int i = 0; i < vertices.Count; i++)
     {
         Vector3 vertex = vertices[i];
         
         bool abovePlane = Vector3.Dot(vertex - pointOnPlane, planeNormal) >= 0.0f;
         
         vertexAbovePlane[i] = abovePlane;
         
         if (abovePlane)
         {
             // Assign vertex to hull A
             oldToNewVertexMap[i] = a.vertices.Count;
             
             a.vertices.Add(vertex);
             
             if (normals != null)
             {
                 a.normals.Add(normals[i]);
             }
             
             if (colors != null)
             {
                 a.colors.Add(colors[i]);
             }
             
             if (tangents != null)
             {
                 a.tangents.Add(tangents[i]);
             }
             
             if (uvs != null)
             {
                 a.uvs.Add(uvs[i]);
             }
         }
         else
         {
             // Assign vertex to hull B
             oldToNewVertexMap[i] = b.vertices.Count;
             
             b.vertices.Add(vertex);
             
             if (normals != null)
             {
                 b.normals.Add(normals[i]);
             }
             
             if (colors != null)
             {
                 b.colors.Add(colors[i]);
             }
             
             if (tangents != null)
             {
                 b.tangents.Add(tangents[i]);
             }
             
             if (uvs != null)
             {
                 b.uvs.Add(uvs[i]);
             }
         }
     }
 }
Пример #14
0
 public void Split(Vector3 localPointOnPlane, Vector3 localPlaneNormal, bool fillCut, UvMapper uvMapper, ColorMapper colorMapper, out IHull resultA, out IHull resultB)
 {
     if (localPlaneNormal == Vector3.zero)
     {
         localPlaneNormal = Vector3.up;
     }
     
     FastHull a = new FastHull(this);
     FastHull b = new FastHull(this);
     
     bool[] vertexAbovePlane;
     int[] oldToNewVertexMap;
     
     AssignVertices(a, b, localPointOnPlane, localPlaneNormal, out vertexAbovePlane, out oldToNewVertexMap);
     
     IList<Vector3> cutEdges;
     
     AssignTriangles(a, b, vertexAbovePlane, oldToNewVertexMap, localPointOnPlane, localPlaneNormal, out cutEdges);
     
     if (fillCut)
     {
         if (colors != null && colorMapper == null)
         {
             Debug.LogWarning("Fill cut failed: A ColorMapper was not provided even though the mesh has a color channel");
         }
         else if ((tangents != null || uvs != null) && uvMapper == null)
         {
             Debug.LogWarning("Fill cut failed: A UvMapper was not provided even though the mesh has a tangent/uv channel");
         }
         else
         {
             FillCutEdges(a, b, cutEdges, localPlaneNormal, uvMapper, colorMapper);
         }
     }
     
     ValidateOutput(a, b, localPlaneNormal);
     
     // Set output
     resultA = a;
     resultB = b;
 }