Пример #1
0
        /// <summary>
        /// Copies a Unity Mesh to a KrablMesh.MeshEdges.
        /// </summary>
        /// <param name='unityMesh'>
        /// The Unity Mesh to use as input.
        /// </param>
        /// <param name='meshEdges'>
        /// The KrablMesh.meshEdges to fill with the data from the input mesh. Needs to be empty.
        /// </param>
        /// <param name='tolerance'>
        /// The maximum difference between two values (vertex coordinates, normal coordinates) to treat as begin equal.
        /// Some modelling software outputs float values that are only almost the same when they should be the same.
        /// In this case using a tolerance of about 1e-5f can fix problems.
        /// </param>
        public static void UnityMeshToMeshEdges(UnityEngine.Mesh unityMesh, KrablMesh.MeshEdges meshEdges, float tolerance = 0.0f)
        {
            Vector3[]    verts       = unityMesh.vertices;
            Vector3[]    normals     = unityMesh.normals;
            Color[]      vertColors  = unityMesh.colors;
            BoneWeight[] boneWeights = unityMesh.boneWeights;
            Vector2[]    uv1         = unityMesh.uv;
            Vector2[]    uv2         = unityMesh.uv2;

            meshEdges.Clear();
            meshEdges.numMaterials      = unityMesh.subMeshCount;
            meshEdges.equalityTolerance = tolerance;

            int numVerts = verts.Length;

            meshEdges.hasVertexColors = (vertColors.Length == numVerts);
            meshEdges.bindposes       = unityMesh.bindposes;
            meshEdges.hasBoneWeights  = (meshEdges.bindposes != null && boneWeights.Length == numVerts);
            meshEdges.hasUV1          = (uv1.Length == numVerts);
            meshEdges.hasUV2          = (uv2.Length == numVerts);

            int i;

            for (i = 0; i < numVerts; ++i)
            {
                meshEdges.AddVertex(verts[i]);
            }
            if (meshEdges.hasVertexColors)
            {
                for (i = 0; i < numVerts; ++i)
                {
                    meshEdges.vertices[i].color = vertColors[i];
                }
            }
            if (meshEdges.hasBoneWeights)
            {
                for (i = 0; i < numVerts; ++i)
                {
                    meshEdges.vertices[i].boneWeight = boneWeights[i];
                }
            }

            // Figure out if this is a unity quad mesh.
            // theoretically this could be different per material
            bool quad = true;

            for (int m = 0; m < meshEdges.numMaterials; ++m)
            {
                if (unityMesh.GetTopology(m) != UnityEngine.MeshTopology.Quads)
                {
                    quad = false;
                    break;
                }
            }

            int v0, v1, v2, v3;

            for (int m = 0; m < meshEdges.numMaterials; ++m)
            {
                if (quad)
                {
                    int[] indices = unityMesh.GetIndices(m);
                    int   num     = indices.Length;
                    for (i = 0; i < num;)
                    {
                        v0 = indices[i++]; v1 = indices[i++]; v2 = indices[i++]; v3 = indices[i++];
                        Face f = new Face(v0, v1, v2, v3);
                        meshEdges.AddFace(f);
                        f.vertexNormal[0] = normals[v0]; f.vertexNormal[1] = normals[v1]; f.vertexNormal[2] = normals[v2]; f.vertexNormal[3] = normals[v3];
                        if (meshEdges.hasUV1)
                        {
                            f.uv1[0] = uv1[v0]; f.uv1[1] = uv1[v1]; f.uv1[2] = uv1[v2]; f.uv1[3] = uv1[v3];
                        }
                        if (meshEdges.hasUV2)
                        {
                            f.uv2[0] = uv2[v0]; f.uv2[1] = uv2[v1]; f.uv2[2] = uv2[v2]; f.uv2[3] = uv2[v3];
                        }
                        f.material = m;
                    }
                }
                else
                {
                    int[] tris = unityMesh.GetTriangles(m);
                    int   num  = tris.Length;
                    for (i = 0; i < num;)
                    {
                        v0 = tris[i++]; v1 = tris[i++]; v2 = tris[i++];
                        Face f = new Face(v0, v1, v2);
                        meshEdges.AddFace(f);
                        f.vertexNormal[0] = normals[v0]; f.vertexNormal[1] = normals[v1]; f.vertexNormal[2] = normals[v2];
                        if (meshEdges.hasUV1)
                        {
                            f.uv1[0] = uv1[v0]; f.uv1[1] = uv1[v1]; f.uv1[2] = uv1[v2];
                        }
                        if (meshEdges.hasUV2)
                        {
                            f.uv2[0] = uv2[v0]; f.uv2[1] = uv2[v1]; f.uv2[2] = uv2[v2];
                        }
                        f.material = m;
                    }
                }
            }

            KrablMesh.Ops.RemoveDoubleVertices(meshEdges);
            meshEdges.GenerateEdgeList();
            meshEdges.CalculateEdgeLinkedFaces();
            meshEdges.topology = quad ? MeshTopology.Quads : MeshTopology.Triangles;
            KrablMesh.CreaseDetect.MarkCreasesFromFaceNormals(meshEdges);
        }
Пример #2
0
        public void Subdivide(ref MeshEdges mesh)
        {
            int i, j;
            int numVerts = mesh.vertCount();
            int numFaces = mesh.faceCount();
            int numEdges = mesh.edgeCount();

            mesh.CalculateEdgeLinkedFaces();

            _calculateVertexPositions(mesh);

            // TODO:don't generate a new mesh... just add the verts to the old mesh = faster and uses less memory
            MeshEdges newMesh    = new MeshEdges();
            int       faceOffset = numVerts;
            int       edgeOffset = numVerts + numFaces;

            float[] edgeRatio = new float[numEdges];

            // Add vertices to new mesh, precalculate stuff
            for (i = 0; i < numVerts; ++i)
            {
                newMesh.AddVertex(vertPoints[i]);
            }
            for (i = 0; i < numFaces; ++i)
            {
                newMesh.AddVertex(facePoints[i]);
            }
            for (i = 0; i < numEdges; ++i)
            {
                int    vertexIndex = newMesh.AddVertex(edgePoints[i]);
                Vertex nv          = newMesh.vertices[vertexIndex];
                Vertex ov0         = mesh.vertices[mesh.edges[i].v[0]];
                Vertex ov1         = mesh.vertices[mesh.edges[i].v[1]];
                edgeRatio[i] = KrablMesh.UnityUtils.ProjectedRatioOfPointOnVector(nv.coords, ov0.coords, ov1.coords);
            }

            if (mesh.hasBoneWeights)
            {
                for (i = 0; i < numVerts; ++i)
                {
                    newMesh.vertices[i].boneWeight = mesh.vertices[i].boneWeight;
                }
                for (i = 0; i < numEdges; ++i)
                {
                    int[] vi = mesh.edges[i].v;
                    newMesh.vertices[edgeOffset + i].boneWeight = KrablMesh.UnityUtils.BoneWeightLerp(
                        mesh.vertices[vi[0]].boneWeight,
                        mesh.vertices[vi[1]].boneWeight,
                        edgeRatio[i]);
                }
                for (i = 0; i < numFaces; ++i)
                {
                    newMesh.vertices[faceOffset + i].boneWeight = mesh.CalculateFaceCenterBoneWeight(i);
                }
            }

            if (mesh.hasVertexColors)
            {
                for (i = 0; i < numVerts; ++i)
                {
                    newMesh.vertices[i].color = mesh.vertices[i].color;
                }
                for (i = 0; i < numEdges; ++i)
                {
                    int[] vi = mesh.edges[i].v;
                    newMesh.vertices[edgeOffset + i].color = Color.Lerp(
                        mesh.vertices[vi[0]].color,
                        mesh.vertices[vi[1]].color,
                        edgeRatio[i]);
                }
                for (i = 0; i < numFaces; ++i)
                {
                    newMesh.vertices[faceOffset + i].color = mesh.CalculateFaceCenterColor(i);
                }
            }

            // Create the faces
            Face nf, of;
            int  g, h;
            int  a, b, c, d;

            for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex)
            {
                of = mesh.faces[faceIndex];
                if (of.valid)
                {
                    h = of.cornerCount - 1;                     // scan through with indices g, h, i
                    g = of.cornerCount - 2;
                    Vector2 centerUV1          = mesh.CalculateFaceCenterUV1(faceIndex);
                    Vector2 centerUV2          = mesh.CalculateFaceCenterUV2(faceIndex);
                    Vector3 centerVertexNormal = mesh.CalculateFaceCenterVertexNormal(faceIndex);
                    for (i = 0; i < of.cornerCount; ++i)
                    {
                        int edgeIndex0 = mesh.EdgeIndexForVertices(of.v[h], of.v[i]);
                        if (edgeIndex0 < 0)
                        {
                            continue;
                        }
                        float ratio0 = edgeRatio[edgeIndex0];
                        if (mesh.edges[edgeIndex0].v[0] == of.v[h])
                        {
                            a = h; b = i;                             // interpolation indexes. 1- ratio gives inaccurate results (floating point problems)
                        }
                        else
                        {
                            a = i; b = h;
                        }

                        int edgeIndex1 = mesh.EdgeIndexForVertices(of.v[g], of.v[h]);
                        if (edgeIndex1 < 0)
                        {
                            continue;
                        }
                        float ratio1 = edgeRatio[edgeIndex1];
                        if (mesh.edges[edgeIndex1].v[0] == of.v[g])
                        {
                            c = g; d = h;
                        }
                        else
                        {
                            c = h; d = g;
                        }

                        nf = new Face(
                            of.v[h],                             // corner point
                            edgeOffset + edgeIndex0,
                            faceOffset + faceIndex,              // center point
                            edgeOffset + edgeIndex1
                            );
                        nf.uv1[0] = of.uv1[h];
                        nf.uv1[1] = Vector2.Lerp(of.uv1[a], of.uv1[b], ratio0);
                        nf.uv1[2] = centerUV1;
                        nf.uv1[3] = Vector2.Lerp(of.uv1[c], of.uv1[d], ratio1);

                        if (mesh.hasUV2)
                        {
                            nf.uv2[0] = of.uv2[h];
                            nf.uv2[1] = Vector2.Lerp(of.uv2[a], of.uv2[b], ratio0);
                            nf.uv2[2] = centerUV2;
                            nf.uv2[3] = Vector2.Lerp(of.uv2[c], of.uv2[d], ratio1);
                        }

                        if (!recalculateNormals)
                        {
                            nf.vertexNormal[0] = of.vertexNormal[h];
                            nf.vertexNormal[1] = Vector3.Lerp(of.vertexNormal[a], of.vertexNormal[b], ratio0);
                            nf.vertexNormal[2] = centerVertexNormal;
                            nf.vertexNormal[3] = Vector3.Lerp(of.vertexNormal[c], of.vertexNormal[d], ratio1);
                        }

                        nf.material = of.material;

                        newMesh.AddFace(nf);
                        g = h;
                        h = i;
                    }
                }
            }

            newMesh.hasUV1          = mesh.hasUV1;
            newMesh.hasUV2          = mesh.hasUV2;
            newMesh.hasBoneWeights  = mesh.hasBoneWeights;
            newMesh.bindposes       = mesh.bindposes;
            newMesh.numMaterials    = mesh.numMaterials;
            newMesh.hasVertexColors = mesh.hasVertexColors;

            newMesh.topology = MeshTopology.Quads;
            newMesh.GenerateEdgeList();
            newMesh.GenerateEdgeTopology();
            // Need to copy edge information from the original mesh to the new mesh
            // Every edge of the original mesh now has two parts

            int edgePointIndex;

            for (i = 0; i < numEdges; ++i)
            {
                Edge e = mesh.edges[i];
                edgePointIndex = edgeOffset + i;                 // as newmesh was just constructed, we know the correct vertex index of the edge center point!
                for (j = 0; j < 2; ++j)
                {
                    int eindex = newMesh.EdgeIndexForVertices(e.v[j], edgePointIndex);

                    // Copy attributes (just crease for now)
                    newMesh.edges[eindex].crease = e.crease;
                }
            }
            mesh = newMesh;
        }