Ejemplo n.º 1
0
        public static void StartSubdivision(GameObject obj, int iterations)
        {
            MeshFilter mf   = obj.GetComponent <MeshFilter>();
            Mesh       mesh = mf.sharedMesh;
            MeshX      mX   = new MeshX(mesh);

            for (int i = 0; i < iterations; ++i)
            {
                mX = Subdivide(mX);
            }

            mesh          = mX.ConvertToMesh();
            mf.sharedMesh = mesh;
        }
Ejemplo n.º 2
0
        public static MeshX Subdivide(MeshX mesh)
        {
            if (!mesh.helpersInited)
            {
                mesh.InitHelpers();
            }

            MeshX newMesh = new MeshX {
                name    = mesh.name + "/s",
                content = mesh.content,
            };

            newMesh.StartBuilding();

            MeshVertices newVertices = new MeshVertices {
                mesh = newMesh
            };
            Dictionary <System.UInt32, Vertex> edgeMidPositions = new Dictionary <System.UInt32, Vertex>();

            for (int pi = 0; pi < mesh.positions.Count; ++pi)
            {
                newMesh.AddPosition(default(Vertex));
            }

            for (int vi = 0; vi < mesh.vertexCount; ++vi)
            {
                Vertex v = mesh.GetVertex(vi);
                newMesh.AddVertex(v);
            }

            //face points
            foreach (Face f in mesh.IterAllFaces())
            {
                Vertex[]      vs   = mesh.GetVertices(mesh.GetFaceVertexIndices(f));
                Vertex        v    = mesh.Average(vs);
                System.UInt32 keyF = GetFacePointKey(f);
                newVertices.AddVertices(v, Pair(v, keyF));
            }

            //edge points
            foreach (Edge e in mesh.IterAllEdges())
            {
                Edge   n    = mesh.GetNeighbor(e);
                Vertex midE = mesh.Average(
                    mesh.GetVertices(mesh.GetEdgeVertexIndices(e))
                    );

                System.UInt32 keyE = GetEdgePointKey(e);
                edgeMidPositions[keyE] = midE;

                Vertex v = mesh.Average(
                    new[] {
                    midE,
                    newVertices.GetVertex(GetFacePointKey(e.face)),
                    newVertices.GetVertex(GetFacePointKey(n.face)),
                },
                    weights: new[] { 2f, 1f, 1f }
                    );
                newVertices.AddVertices(v, Pair(v, keyE));
            }

            // move control-points
            for (int pi = 0; pi < mesh.positions.Count; ++pi)
            {
                var edges = new List <Edge>();
                var front = new List <Edge>();

                foreach (int vi in mesh.positionVertices[pi])
                {
                    foreach (Edge e in mesh.vertexEdges[vi])
                    {
                        edges.Add(e);

                        foreach (Edge edge in new[] { e, mesh.GetNextInFace(e, -1) })
                        {
                            EdgeType type = mesh.GetEdgeType(edge);
                            if (type != EdgeType.back)
                            {
                                front.Add(edge);
                            }
                        }
                    }
                }

                Vertex   controlPoint;
                Vertex[] ms = new Vertex[front.Count];

                for (int e = 0; e < front.Count; ++e)
                {
                    ms[e] = edgeMidPositions[GetEdgePointKey(front[e])];
                }

                Vertex   edgeMidAverage = mesh.Average(ms, maskPosition);
                Vertex[] fs             = new Vertex[edges.Count];

                for (int e = 0; e < edges.Count; ++e)
                {
                    fs[e] = newVertices.GetVertex(GetFacePointKey(edges[e].face), maskPosition);
                }

                Vertex faceAverage = mesh.Average(fs, maskPosition);
                controlPoint = mesh.Average(
                    new[] {
                    faceAverage,
                    edgeMidAverage,
                    mesh.GetPosition(pi)
                },
                    maskPosition,
                    new[] { 1f, 2f, edges.Count - 3f }
                    );
                newMesh.SetPosition(pi, controlPoint);
            }

            //face creation
            newMesh.submeshes = new Submesh[mesh.submeshes.Length];

            for (int si = 0; si < mesh.submeshes.Length; ++si)
            {
                int[][] faces     = mesh.submeshes[si].faces;
                int     faceCount = 0;

                foreach (int[] face in faces)
                {
                    faceCount += face.Length;
                }

                newMesh.submeshes[si].faces = new int[faceCount][];
                int faceIndex = 0;

                for (int fi = 0; fi < faces.Length; ++fi)
                {
                    int[] fis       = faces[fi];
                    int   edgeCount = fis.Length;
                    Face  f         = new Face {
                        submesh = si, index = fi
                    };
                    int   ci  = newVertices.vertexIndices[GetFacePointKey(f)];
                    int[] eis = new int[edgeCount];

                    for (int i = 0; i < edgeCount; ++i)
                    {
                        Edge e = new Edge {
                            face = f, index = i
                        };
                        eis[i] = newVertices.vertexIndices[GetEdgePointKey(e)];
                    }

                    for (int i = 0; i < edgeCount; ++i)
                    {
                        int[] q = new int[4];
                        int   s = edgeCount == 4 ? i : 0;
                        q[(0 + s) % 4] = fis[i];
                        q[(1 + s) % 4] = eis[i];
                        q[(2 + s) % 4] = ci;
                        q[(3 + s) % 4] = eis[(i - 1 + edgeCount) % edgeCount];
                        newMesh.submeshes[si].faces[faceIndex++] = q;
                    }
                }
            }

            return(newMesh);
        }