Ejemplo n.º 1
0
    public void Box_Edges()
    {
        using (var box = CreateBox())
        {
            Assert.IsTrue(box.EdgeCount == 24);

            for (int i = 0; i < box.EdgeCount; i++)
            {
                HullValidation.ValidateEdge(box, i);
            }
        }
    }
Ejemplo n.º 2
0
    public void Box_Faces()
    {
        using (var box = CreateBox())
        {
            Assert.IsTrue(box.FaceCount == 6);

            for (int i = 0; i < box.FaceCount; i++)
            {
                HullValidation.ValidateFace(box, i);
            }
        }
    }
        public static unsafe NativeHull CreateFromMesh(Mesh mesh)
        {
            var faces       = new List <DetailedFaceDef>();
            var verts       = mesh.vertices.Select(RoundVertex).ToArray();
            var uniqueVerts = verts.Distinct().ToList();
            var indices     = mesh.triangles;

            // Create faces from Triangles and collapse multiple vertices with same position into shared vertices.
            for (int i = 0; i < mesh.triangles.Length; i = i + 3)
            {
                var idx1 = i;
                var idx2 = i + 1;
                var idx3 = i + 2;

                Vector3 p1 = verts[indices[idx1]];
                Vector3 p2 = verts[indices[idx2]];
                Vector3 p3 = verts[indices[idx3]];

                var normal = math.normalize(math.cross(p3 - p2, p1 - p2));

                // Round normal so that faces with only slight variances can be grouped properly together.
                var roundedNormal = RoundVertex(normal);

                faces.Add(new DetailedFaceDef
                {
                    Center = ((p1 + p2 + p3) / 3),
                    Normal = roundedNormal,
                    Verts  = new List <float3> {
                        p1, p2, p3
                    },
                    Indices = new List <int>
                    {
                        uniqueVerts.IndexOf(p1),
                        uniqueVerts.IndexOf(p2),
                        uniqueVerts.IndexOf(p3)
                    }
                });
            }

            var faceDefs      = new List <NativeFaceDef>();
            var orphanIndices = new HashSet <int>();

            // Merge all faces with the same normal and shared vertex
            var mergedFaces = GroupBySharedVertex(GroupByNormal(faces));

            foreach (var faceGroup in mergedFaces)
            {
                var indicesFromMergedFaces = faceGroup.SelectMany(face => face.Indices).ToArray();

                // Collapse points inside the new combined face by using only the border vertices.
                var border        = PolygonPerimeter.CalculatePerimeter(indicesFromMergedFaces, ref uniqueVerts);
                var borderIndices = border.Select(b => b.EndIndex).ToArray();

                foreach (var idx in indicesFromMergedFaces.Except(borderIndices))
                {
                    orphanIndices.Add(idx);
                }

                var v   = stackalloc int[borderIndices.Length];
                int max = 0;
                for (int i = 0; i < borderIndices.Length; i++)
                {
                    var idx = borderIndices[i];
                    if (idx > max)
                    {
                        max = idx;
                    }
                    v[i] = idx;
                }

                faceDefs.Add(new NativeFaceDef
                {
                    HighestIndex = max,
                    VertexCount  = borderIndices.Length,
                    Vertices     = v,
                });
            }

            // Remove vertices with no edges connected to them and fix all impacted face vertex references.
            foreach (var orphanIdx in orphanIndices.OrderByDescending(i => i))
            {
                uniqueVerts.RemoveAt(orphanIdx);

                foreach (var face in faceDefs.Where(f => f.HighestIndex >= orphanIdx))
                {
                    for (int i = 0; i < face.VertexCount; i++)
                    {
                        var faceVertIdx = face.Vertices[i];
                        if (faceVertIdx >= orphanIdx)
                        {
                            face.Vertices[i] = --faceVertIdx;
                        }
                    }
                }
            }

            var result = new NativeHull();

            using (var faceNative = new NativeArray <NativeFaceDef>(faceDefs.ToArray(), Allocator.Temp))
                using (var vertsNative = new NativeArray <float3>(uniqueVerts.ToArray(), Allocator.Temp))
                {
                    NativeHullDef hullDef;
                    hullDef.VertexCount    = vertsNative.Length;
                    hullDef.VerticesNative = vertsNative;
                    hullDef.FaceCount      = faceNative.Length;
                    hullDef.FacesNative    = faceNative;
                    SetFromFaces(ref result, hullDef);
                }

            result.IsCreated = true;

            HullValidation.ValidateHull(result);

            return(result);
        }