Esempio n. 1
0
        /// <summary>
        /// Copy mesh data from a KrablMesh meshEdges to a Unity Mesh.
        /// </summary>
        /// <param name='meshEdges'>
        /// The input mesh.
        /// </param>
        /// <param name='unityMesh'>
        /// The output Unity Mesh. Any data it contains will be overwritten.
        /// </param>
        public static void MeshEdgesToUnityMesh(KrablMesh.MeshEdges meshEdges, UnityEngine.Mesh unityMesh)
        {
            meshEdges.InvalidateDegenerateFaces();
            //	Ops.TriangulateWithEdges(meshEdges);
            int numFaces = meshEdges.faceCount();

            List <ExportVertex> exVerts = new List <ExportVertex>(numFaces * 3);

            List <Vector3> verts = new List <Vector3>();

            List <int>[] indices     = new List <int> [meshEdges.numMaterials];
            List <int>   vertexTable = new List <int>();

            // Create a list of all vertices based on face corners (= lots of duplicates)
            for (int material = 0; material < meshEdges.numMaterials; ++material)
            {
                indices[material] = new List <int>();
                for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex)
                {
                    Face f = meshEdges.faces[faceIndex];
                    if (f.valid && f.material == material)
                    {
                        int cornerCount = f.cornerCount;
                        for (int cornerIndex = 0; cornerIndex < cornerCount; ++cornerIndex)
                        {
                            ExportVertex ev = new ExportVertex();
                            ev.vertIndex   = f.v[cornerIndex];
                            ev.cornerCount = cornerCount;
                            ev.material    = material;
                            ev.coords      = meshEdges.vertices[f.v[cornerIndex]].coords;
                            ev.normal      = f.vertexNormal[cornerIndex];
                            ev.uv1         = f.uv1[cornerIndex];
                            ev.uv2         = f.uv2[cornerIndex];

                            vertexTable.Add(exVerts.Count);
                            exVerts.Add(ev);
                        }
                    }
                }
            }

            vertexTable.Sort(delegate(int a, int b) {
                return(ExportVertex.CompareEV(exVerts[a], exVerts[b]));
            });

            // Create index list to collapse list to the unique verts added to the final mesh
            // compile unique mesh arrays
            List <Vector3>    normals     = new List <Vector3>();
            List <Vector2>    uv1         = new List <Vector2>();
            List <Vector2>    uv2         = new List <Vector2>();
            List <Color>      vertColors  = new List <Color>();
            List <BoneWeight> boneWeights = new List <BoneWeight>();

            int[] uniqueTable = new int[exVerts.Count];
            int   numUnique   = 0;

            for (int i = 0; i < exVerts.Count; ++i)
            {
                int exIndex = vertexTable[i];
                if (i == 0 || ExportVertex.CompareEV(exVerts[vertexTable[i - 1]], exVerts[exIndex]) != 0)
                {
                    verts.Add(exVerts[exIndex].coords);
                    normals.Add(exVerts[exIndex].normal);
                    uv1.Add(exVerts[exIndex].uv1);
                    uv2.Add(exVerts[exIndex].uv2);

                    Vertex v = meshEdges.vertices[exVerts[exIndex].vertIndex];
                    vertColors.Add(v.color);
                    boneWeights.Add(v.boneWeight);
                    numUnique++;
                }
                uniqueTable[exIndex] = numUnique - 1;
            }
            //	Debug.Log("Num exVerts " + exVerts.Length + " num collapsed " + numUnique + " vertsCount " + verts.Count);
#if false                                                     // Quad topology seams to be broken on windows directx! Disabled it for now.
            if (meshEdges.topology == MeshTopology.Triangles) // quads/tris only
            {
                for (int i = 0; i < exVerts.Count; i += 3)
                {
                    int mat = exVerts[i].material;
                    indices[mat].Add(uniqueTable[i]);
                    indices[mat].Add(uniqueTable[i + 1]);
                    indices[mat].Add(uniqueTable[i + 2]);
                }
            }
            else if (meshEdges.topology == MeshTopology.Quads)
            {
                for (int i = 0; i < exVerts.Count; i += 4)
                {
                    int mat = exVerts[i].material;
                    indices[mat].Add(uniqueTable[i]);
                    indices[mat].Add(uniqueTable[i + 1]);
                    indices[mat].Add(uniqueTable[i + 2]);
                    indices[mat].Add(uniqueTable[i + 3]);
                }
            }
            else
#endif
            {
                // Mixed tris/quads need to split quads
                int cornerCount, mat;
                int i0, i1, i2, i3;
                for (i0 = 0; i0 < exVerts.Count;)
                {
                    i1          = i0 + 1;
                    i2          = i0 + 2;
                    cornerCount = exVerts[i0].cornerCount;
                    mat         = exVerts[i0].material;
                    if (cornerCount == 3)
                    {
                        indices[mat].Add(uniqueTable[i0]);
                        indices[mat].Add(uniqueTable[i1]);
                        indices[mat].Add(uniqueTable[i2]);
                        i0 += 3;
                    }
                    else                         // Quad!
                    {
                        i3 = i0 + 3;
                        Vector3 diag02 = exVerts[i0].coords - exVerts[i2].coords;
                        Vector3 diag13 = exVerts[i1].coords - exVerts[i3].coords;

                        if (diag02.sqrMagnitude > diag13.sqrMagnitude)
                        {
                            // If 0-2 if shorter than 1-3
                            indices[mat].Add(uniqueTable[i0]);
                            indices[mat].Add(uniqueTable[i1]);
                            indices[mat].Add(uniqueTable[i2]);

                            indices[mat].Add(uniqueTable[i0]);
                            indices[mat].Add(uniqueTable[i2]);
                            indices[mat].Add(uniqueTable[i3]);
                        }
                        else
                        {
                            indices[mat].Add(uniqueTable[i0]);
                            indices[mat].Add(uniqueTable[i1]);
                            indices[mat].Add(uniqueTable[i3]);

                            indices[mat].Add(uniqueTable[i1]);
                            indices[mat].Add(uniqueTable[i2]);
                            indices[mat].Add(uniqueTable[i3]);
                        }
                        i0 += 4;
                    }
                }
            }

            unityMesh.Clear(false);
            unityMesh.name = "KMesh";

            if (verts.Count >= 65536 || exVerts.Count >= 65536 * 3)
            {
                Debug.Log("Cannot create Unity mesh from KrablMesh.MeshEdges. " +
                          "The mesh is too large (>65k). " +
                          "Vertices: " + verts.Count + " Triangles: " + exVerts.Count / 3);
                return;
            }

            unityMesh.subMeshCount = meshEdges.numMaterials;
            unityMesh.vertices     = verts.ToArray();
            unityMesh.normals      = normals.ToArray();
            if (meshEdges.hasVertexColors)
            {
                unityMesh.colors = vertColors.ToArray();
            }
            if (meshEdges.hasUV1)
            {
                unityMesh.uv = uv1.ToArray();
            }
            if (meshEdges.hasUV2)
            {
                unityMesh.uv2 = uv2.ToArray();
            }
            if (meshEdges.hasBoneWeights)
            {
                unityMesh.bindposes   = meshEdges.bindposes;
                unityMesh.boneWeights = boneWeights.ToArray();
            }
#if false
            if (meshEdges.topology == MeshTopology.Quads)
            {
                for (int mat = 0; mat < meshEdges.numMaterials; ++mat)
                {
                    unityMesh.SetIndices(indices[mat].ToArray(), UnityEngine.MeshTopology.Quads, mat);
                }
            }
            else
#endif
            {
                for (int mat = 0; mat < meshEdges.numMaterials; ++mat)
                {
                    unityMesh.SetTriangles(indices[mat].ToArray(), mat);
                }
            }
            if (meshEdges.hasUV1 && meshEdges.calculateTangents)
            {
                _calculateMeshTangents(unityMesh);
            }
        }