Example #1
0
    // Unity only support maximum 65534 vertices per mesh. So large meshes need
    // to be splitted.
    private void SplitMesh(DecodedMesh mesh, ref List <DecodedMesh> splittedMeshes)
    {
        int[] IndexNew  = new int[maxNumVerticesPerMesh];
        int   BaseIndex = 0;
        int   FaceCount = mesh.faces.Length;

        int[] FaceIndex = new int[FaceCount];
        int[] NewFace   = new int[FaceCount];


        for (int i = 0; i < FaceCount; i++)
        {
            FaceIndex[i] = -1;
        }

        while (BaseIndex < FaceCount)
        {
            int   uniqueCornerId = 0;
            int   UseIndex       = 0;
            int   AddNew         = 0;
            int[] NewCorner      = new int[3];
            for (; BaseIndex + UseIndex < FaceCount;)
            {
                AddNew = 0;
                for (int i = 0; i < 3; i++)
                {
                    if (FaceIndex[mesh.faces[BaseIndex + UseIndex + i]] == -1)
                    {
                        NewCorner[AddNew] = mesh.faces[BaseIndex + UseIndex + i];
                        AddNew++;
                    }
                }

                if (uniqueCornerId + AddNew > maxNumVerticesPerMesh)
                {
                    break;
                }

                for (int i = 0; i < AddNew; i++)
                {
                    FaceIndex[NewCorner[i]]  = uniqueCornerId;
                    IndexNew[uniqueCornerId] = NewCorner[i];
                    uniqueCornerId++;
                }

                for (int i = 0; i < 3; i++)
                {
                    NewFace[UseIndex] = FaceIndex[mesh.faces[BaseIndex + UseIndex]];
                    UseIndex++;
                }
            }

            for (int i = 0; i < uniqueCornerId; i++)
            {
                FaceIndex[IndexNew[i]] = -1;
            }

            DecodedMesh subMesh = new DecodedMesh();
            subMesh.faces = new int[UseIndex];
            Array.Copy(NewFace, subMesh.faces, UseIndex);
            subMesh.vertices = new Vector3[uniqueCornerId];
            for (int i = 0; i < uniqueCornerId; i++)
            {
                subMesh.vertices[i] = mesh.vertices[IndexNew[i]];
            }
            if (mesh.normals != null)
            {
                subMesh.normals = new Vector3[uniqueCornerId];
                for (int i = 0; i < uniqueCornerId; i++)
                {
                    subMesh.normals[i] = mesh.normals[IndexNew[i]];
                }
            }

            if (mesh.colors != null)
            {
                subMesh.colors = new Color[uniqueCornerId];
                for (int i = 0; i < uniqueCornerId; i++)
                {
                    subMesh.colors[i] = mesh.colors[IndexNew[i]];
                }
            }

            if (mesh.uvs != null)
            {
                subMesh.uvs = new Vector2[uniqueCornerId];
                for (int i = 0; i < uniqueCornerId; i++)
                {
                    subMesh.uvs[i] = mesh.uvs[IndexNew[i]];
                }
            }

            splittedMeshes.Add(subMesh);

            BaseIndex += UseIndex;
        }
    }
Example #2
0
    public unsafe int DecodeMesh(byte[] data, ref List <Mesh> meshes)
    {
        DracoToUnityMesh *tmpMesh;

        if (DecodeMeshForUnity(data, data.Length, &tmpMesh) <= 0)
        {
            Debug.Log("Failed: Decoding error.");
            return(-1);
        }

        Debug.Log("Num indices: " + tmpMesh->numFaces.ToString());
        Debug.Log("Num vertices: " + tmpMesh->numVertices.ToString());
        if (tmpMesh->hasNormal)
        {
            Debug.Log("Decoded mesh normals.");
        }
        if (tmpMesh->hasTexcoord)
        {
            Debug.Log("Decoded mesh texcoords.");
        }
        if (tmpMesh->hasColor)
        {
            Debug.Log("Decoded mesh colors.");
        }

        int numFaces = tmpMesh->numFaces;

        int[] newTriangles = new int[tmpMesh->numFaces * 3];
        for (int i = 0; i < tmpMesh->numFaces; ++i)
        {
            byte *addr = (byte *)tmpMesh->indices + i * 3 * 4;
            newTriangles[i * 3]     = *((int *)addr);
            newTriangles[i * 3 + 1] = *((int *)(addr + 4));
            newTriangles[i * 3 + 2] = *((int *)(addr + 8));
        }

        // For floating point numbers, there's no Marshal functions could directly
        // read from the unmanaged data.
        // TODO(zhafang): Find better way to read float numbers.
        Vector3[] newVertices = new Vector3[tmpMesh->numVertices];
        Vector2[] newUVs      = new Vector2[0];
        if (tmpMesh->hasTexcoord)
        {
            newUVs = new Vector2[tmpMesh->numVertices];
        }
        Vector3[] newNormals = new Vector3[0];
        if (tmpMesh->hasNormal)
        {
            newNormals = new Vector3[tmpMesh->numVertices];
        }
        Color[] newColors = new Color[0];
        if (tmpMesh->hasColor)
        {
            newColors = new Color[tmpMesh->numVertices];
        }
        int byteStridePerValue = 4;

        /*
         * TODO(zhafang): Change to:
         * float[] pos = new float[3];
         * for (int i = 0; i < tmpMesh -> numVertices; ++i) {
         *       Marshal.Copy(tmpMesh->position, pos, 3 * i, 3);
         *             for (int j = 0; j < 3; ++j) {
         *                        newVertices[i][j] = pos[j];
         *             }
         * }
         */

        byte *posaddr    = (byte *)tmpMesh->position;
        byte *normaladdr = (byte *)tmpMesh->normal;
        byte *coloraddr  = (byte *)tmpMesh->color;
        byte *uvaddr     = (byte *)tmpMesh->texcoord;

        for (int i = 0; i < tmpMesh->numVertices; ++i)
        {
            int numValuePerVertex = 3;

            for (int j = 0; j < numValuePerVertex; ++j)
            {
                int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
                int OffSet = i * byteStridePerVertex + byteStridePerValue * j;

                newVertices[i][j] = *((float *)(posaddr + OffSet));
                if (tmpMesh->hasNormal)
                {
                    newNormals[i][j] = *((float *)(normaladdr + OffSet));
                }
                if (tmpMesh->hasColor)
                {
                    newColors[i][j] = *((float *)(coloraddr + OffSet));
                }
            }


            if (tmpMesh->hasTexcoord)
            {
                numValuePerVertex = 2;
                for (int j = 0; j < numValuePerVertex; ++j)
                {
                    int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
                    newUVs[i][j] = *((float *)(uvaddr + (i * byteStridePerVertex + byteStridePerValue * j)));
                }
            }
        }

        Marshal.FreeCoTaskMem(tmpMesh->indices);
        Marshal.FreeCoTaskMem(tmpMesh->position);
        if (tmpMesh->hasNormal)
        {
            Marshal.FreeCoTaskMem(tmpMesh->normal);
        }
        if (tmpMesh->hasTexcoord)
        {
            Marshal.FreeCoTaskMem(tmpMesh->texcoord);
        }
        if (tmpMesh->hasColor)
        {
            Marshal.FreeCoTaskMem(tmpMesh->color);
        }
        Marshal.FreeCoTaskMem((IntPtr)tmpMesh);

        if (newVertices.Length > maxNumVerticesPerMesh)
        {
            // Unity only support maximum 65534 vertices per mesh. So large meshes
            // need to be splitted.

            DecodedMesh decodedMesh = new DecodedMesh();
            decodedMesh.vertices = newVertices;
            decodedMesh.faces    = newTriangles;
            if (newUVs.Length != 0)
            {
                decodedMesh.uvs = newUVs;
            }
            if (newNormals.Length != 0)
            {
                decodedMesh.normals = newNormals;
            }
            if (newColors.Length != 0)
            {
                decodedMesh.colors = newColors;
            }
            List <DecodedMesh> splittedMeshes = new List <DecodedMesh> ();

            SplitMesh(decodedMesh, ref splittedMeshes);
            for (int i = 0; i < splittedMeshes.Count; ++i)
            {
                Mesh mesh = new Mesh();
                mesh.vertices  = splittedMeshes [i].vertices;
                mesh.triangles = splittedMeshes [i].faces;
                if (splittedMeshes [i].uvs != null)
                {
                    mesh.uv = splittedMeshes [i].uvs;
                }

                if (splittedMeshes [i].colors != null)
                {
                    mesh.colors = splittedMeshes[i].colors;
                }

                if (splittedMeshes [i].normals != null)
                {
                    mesh.normals = splittedMeshes [i].normals;
                }
                else
                {
                    Debug.Log("Sub mesh doesn't have normals, recomputed.");
                    mesh.RecalculateNormals();
                }
                mesh.RecalculateBounds();
                meshes.Add(mesh);
            }
        }
        else
        {
            Mesh mesh = new Mesh();
            mesh.vertices  = newVertices;
            mesh.triangles = newTriangles;
            if (newUVs.Length != 0)
            {
                mesh.uv = newUVs;
            }
            if (newNormals.Length != 0)
            {
                mesh.normals = newNormals;
            }
            else
            {
                mesh.RecalculateNormals();
                Debug.Log("Mesh doesn't have normals, recomputed.");
            }
            if (newColors.Length != 0)
            {
                mesh.colors = newColors;
            }

            mesh.RecalculateBounds();
            meshes.Add(mesh);
        }
        // TODO(zhafang): Resize mesh to the a proper scale.

        return(numFaces);
    }
Example #3
0
    // Unity only support maximum 65534 vertices per mesh. So large meshes need
    // to be splitted.
    private void SplitMesh(DecodedMesh mesh, ref List <DecodedMesh> splittedMeshes)
    {
        List <int> facesLeft = new List <int>();

        for (int i = 0; i < mesh.faces.Length; ++i)
        {
            facesLeft.Add(mesh.faces[i]);
        }
        int numSubMeshes = 0;

        List <int>            newCorners        = new List <int>();
        Dictionary <int, int> indexToNewIndex   = new Dictionary <int, int>();
        List <int>            tmpLeftFaces      = new List <int>();
        List <int>            facesExtracted    = new List <int>();
        List <Vector3>        verticesExtracted = new List <Vector3>();

        while (facesLeft.Count > 0)
        {
            Debug.Log("Faces left: " + facesLeft.Count.ToString());
            numSubMeshes++;
            tmpLeftFaces.Clear();
            facesExtracted.Clear();
            verticesExtracted.Clear();

            int uniqueCornerId = 0;
            indexToNewIndex.Clear();
            for (int face = 0; face < facesLeft.Count / 3; ++face)
            {
                newCorners.Clear();
                // If all indices has appeared or there's still space for more vertices.
                for (int corner = 0; corner < 3; ++corner)
                {
                    if (!indexToNewIndex.ContainsKey(facesLeft[face * 3 + corner]))
                    {
                        newCorners.Add(facesLeft[face * 3 + corner]);
                    }
                }
                if (newCorners.Count + uniqueCornerId > maxNumVerticesPerMesh)
                {
                    // Save face for the next sub-mesh.
                    for (int corner = 0; corner < 3; ++corner)
                    {
                        tmpLeftFaces.Add(facesLeft[face * 3 + corner]);
                    }
                }
                else
                {
                    // Add new corners.
                    for (int i = 0; i < newCorners.Count; ++i)
                    {
                        indexToNewIndex.Add(newCorners[i], uniqueCornerId);
                        verticesExtracted.Add(mesh.vertices[newCorners[i]]);
                        uniqueCornerId++;
                    }
                    // Add face to this sub-mesh.
                    for (int corner = 0; corner < 3; ++corner)
                    {
                        facesExtracted.Add(
                            indexToNewIndex[facesLeft[face * 3 + corner]]);
                    }
                }
            }

            DecodedMesh subMesh = new DecodedMesh();
            subMesh.faces    = facesExtracted.ToArray();
            subMesh.vertices = verticesExtracted.ToArray();
            splittedMeshes.Add(subMesh);

            facesLeft = tmpLeftFaces;
        }
    }
Example #4
0
    public unsafe int DecodeMesh(byte[] data, ref List <Mesh> meshes)
    {
        DracoToUnityMesh *tmpMesh;

        if (DecodeMeshForUnity(data, data.Length, &tmpMesh) <= 0)
        {
            Debug.Log("Failed: Decoding error.");
            return(-1);
        }

        Debug.Log("Num indices: " + tmpMesh->numFaces.ToString());
        Debug.Log("Num vertices: " + tmpMesh->numVertices.ToString());

        int numFaces = tmpMesh->numFaces;

        int[] newTriangles = new int[tmpMesh->numFaces * 3];
        for (int i = 0; i < tmpMesh->numFaces; ++i)
        {
            newTriangles[i * 3]     = Marshal.ReadInt32(tmpMesh->indices, i * 3 * 4);
            newTriangles[i * 3 + 1] =
                Marshal.ReadInt32(tmpMesh->indices, i * 3 * 4 + 4);
            newTriangles[i * 3 + 2] =
                Marshal.ReadInt32(tmpMesh->indices, i * 3 * 4 + 8);
        }

        // For floating point numbers, there's no Marshal functions could directly
        // read from the unmanaged data.
        // TODO(zhafang): Find better way to read float numbers.
        Vector3[] newVertices         = new Vector3[tmpMesh->numVertices];
        int       byteStridePerValue  = 4;
        int       numValuePerVertex   = 3;
        int       byteStridePerVertex = byteStridePerValue * numValuePerVertex;

        /*
         * TODO(zhafang): Change to:
         * float[] pos = new float[3];
         * for (int i = 0; i < tmpMesh -> numVertices; ++i) {
         *       Marshal.Copy(tmpMesh->position, pos, 3 * i, 3);
         *             for (int j = 0; j < 3; ++j) {
         *                        newVertices[i][j] = pos[j];
         *             }
         * }
         */
        for (int i = 0; i < tmpMesh->numVertices; ++i)
        {
            for (int j = 0; j < 3; ++j)
            {
                newVertices[i][j] =
                    ReadFloatFromIntPtr(
                        tmpMesh->position,
                        i * byteStridePerVertex + byteStridePerValue * j);
            }
        }
        Marshal.FreeCoTaskMem(tmpMesh->indices);
        Marshal.FreeCoTaskMem(tmpMesh->position);
        Marshal.FreeCoTaskMem((IntPtr)tmpMesh);

        if (newVertices.Length > maxNumVerticesPerMesh)
        {
            // Unity only support maximum 65534 vertices per mesh. So large meshes
            // need to be splitted.
            DecodedMesh decodedMesh = new DecodedMesh();
            decodedMesh.vertices = newVertices;
            decodedMesh.faces    = newTriangles;
            List <DecodedMesh> splittedMeshes = new List <DecodedMesh>();

            SplitMesh(decodedMesh, ref splittedMeshes);
            for (int i = 0; i < splittedMeshes.Count; ++i)
            {
                Mesh mesh = new Mesh();
                mesh.vertices  = splittedMeshes[i].vertices;
                mesh.triangles = splittedMeshes[i].faces;

                mesh.RecalculateBounds();
                mesh.RecalculateNormals();
                meshes.Add(mesh);
            }
        }
        else
        {
            Mesh mesh = new Mesh();
            mesh.vertices  = newVertices;
            mesh.triangles = newTriangles;

            mesh.RecalculateBounds();
            mesh.RecalculateNormals();
            meshes.Add(mesh);
        }
        // TODO(zhafang): Resize mesh to the a proper scale.

        return(numFaces);
    }
    // Unity only support maximum 65534 vertices per mesh. So large meshes need
    // to be splitted.
    private void SplitMesh(DecodedMesh mesh, ref List <DecodedMesh> splittedMeshes)
    {
        // Map between new indices on a splitted mesh and old indices on the
        // original mesh.
        int[] newToOldIndexMap = new int[maxNumVerticesPerMesh];

        // Index of the first unprocessed corner.
        int baseCorner   = 0;
        int indicesCount = mesh.indices.Length;

        // Map between old indices of the original mesh and indices on the currently
        // processed sub-mesh. Inverse of |newToOldIndexMap|.
        int[] oldToNewIndexMap = new int[indicesCount];
        int[] newIndices       = new int[indicesCount];


        // Set mapping between existing vertex indices and new vertex indices to
        // a default value.
        for (int i = 0; i < indicesCount; i++)
        {
            oldToNewIndexMap[i] = -1;
        }

        // Number of added vertices for the currently processed sub-mesh.
        int numAddedVertices = 0;

        // Process all corners (faces) of the original mesh.
        while (baseCorner < indicesCount)
        {
            // Reset the old to new indices map that may have been set by previously
            // processed sub-meshes.
            for (int i = 0; i < numAddedVertices; i++)
            {
                oldToNewIndexMap[newToOldIndexMap[i]] = -1;
            }
            numAddedVertices = 0;

            // Number of processed corners on the current sub-mesh.
            int numProcessedCorners = 0;

            // Local storage for indices added to the new sub-mesh for a currently
            // processed face.
            int[] newlyAddedIndices = new int[3];

            // Sub-mesh processing starts here.
            for (; baseCorner + numProcessedCorners < indicesCount;)
            {
                // Number of vertices that we need to add to the current sub-mesh.
                int verticesAdded = 0;
                for (int i = 0; i < 3; i++)
                {
                    if (oldToNewIndexMap[mesh.indices[baseCorner + numProcessedCorners + i]] == -1)
                    {
                        newlyAddedIndices[verticesAdded] = mesh.indices[baseCorner + numProcessedCorners + i];
                        verticesAdded++;
                    }
                }

                // If the number of new vertices that we need to add is larger than the
                // allowed limit, we need to stop processing the current sub-mesh.
                // The current face will be processed again for the next sub-mesh.
                if (numAddedVertices + verticesAdded > maxNumVerticesPerMesh)
                {
                    break;
                }

                // Update mapping between old an new vertex indices.
                for (int i = 0; i < verticesAdded; i++)
                {
                    oldToNewIndexMap[newlyAddedIndices[i]] = numAddedVertices;
                    newToOldIndexMap[numAddedVertices]     = newlyAddedIndices[i];
                    numAddedVertices++;
                }

                for (int i = 0; i < 3; i++)
                {
                    newIndices[numProcessedCorners] = oldToNewIndexMap[mesh.indices[baseCorner + numProcessedCorners]];
                    numProcessedCorners++;
                }
            }
            // Sub-mesh processing done.
            DecodedMesh subMesh = new DecodedMesh();
            subMesh.indices = new int[numProcessedCorners];
            Array.Copy(newIndices, subMesh.indices, numProcessedCorners);
            subMesh.vertices = new Vector3[numAddedVertices];
            for (int i = 0; i < numAddedVertices; i++)
            {
                subMesh.vertices[i] = mesh.vertices[newToOldIndexMap[i]];
            }
            if (mesh.normals != null)
            {
                subMesh.normals = new Vector3[numAddedVertices];
                for (int i = 0; i < numAddedVertices; i++)
                {
                    subMesh.normals[i] = mesh.normals[newToOldIndexMap[i]];
                }
            }

            if (mesh.colors != null)
            {
                subMesh.colors = new Color[numAddedVertices];
                for (int i = 0; i < numAddedVertices; i++)
                {
                    subMesh.colors[i] = mesh.colors[newToOldIndexMap[i]];
                }
            }

            if (mesh.uvs != null)
            {
                subMesh.uvs = new Vector2[numAddedVertices];
                for (int i = 0; i < numAddedVertices; i++)
                {
                    subMesh.uvs[i] = mesh.uvs[newToOldIndexMap[i]];
                }
            }

            splittedMeshes.Add(subMesh);
            baseCorner += numProcessedCorners;
        }
    }
Example #6
0
    public unsafe int DecodeMesh(byte[] data, ref List <Mesh> meshes)
    {
        DracoToUnityMesh *tmpMesh;

        if (DecodeMeshForUnity(data, data.Length, &tmpMesh) <= 0)
        {
            Debug.Log("Failed: Decoding error.");
            return(-1);
        }

        Debug.Log("Num indices: " + tmpMesh->numFaces.ToString());
        Debug.Log("Num vertices: " + tmpMesh->numVertices.ToString());
        if (tmpMesh->hasNormal)
        {
            Debug.Log("Decoded mesh normals.");
        }
        if (tmpMesh->hasTexcoord)
        {
            Debug.Log("Decoded mesh texcoords.");
        }
        if (tmpMesh->hasColor)
        {
            Debug.Log("Decoded mesh colors.");
        }

        int numFaces = tmpMesh->numFaces;

        int[] newTriangles = new int[tmpMesh->numFaces * 3];
        for (int i = 0; i < tmpMesh->numFaces; ++i)
        {
            byte *addr = (byte *)tmpMesh->indices + i * 3 * 4;
            newTriangles[i * 3]     = *((int *)addr);
            newTriangles[i * 3 + 1] = *((int *)(addr + 4));
            newTriangles[i * 3 + 2] = *((int *)(addr + 8));
        }

        // For floating point numbers, there's no Marshal functions could directly
        // read from the unmanaged data.
        // TODO(zhafang): Find better way to read float numbers.
        Vector3[] newVertices = new Vector3[tmpMesh->numVertices];
        Vector2[] newUVs      = new Vector2[0];
        if (tmpMesh->hasTexcoord)
        {
            newUVs = new Vector2[tmpMesh->numVertices];
        }
        Vector3[] newNormals = new Vector3[0];
        if (tmpMesh->hasNormal)
        {
            newNormals = new Vector3[tmpMesh->numVertices];
        }
        Color[] newColors = new Color[0];
        if (tmpMesh->hasColor)
        {
            newColors = new Color[tmpMesh->numVertices];
        }
        int byteStridePerValue = 4;

        byte *posaddr    = (byte *)tmpMesh->position;
        byte *normaladdr = (byte *)tmpMesh->normal;
        byte *coloraddr  = (byte *)tmpMesh->color;
        byte *uvaddr     = (byte *)tmpMesh->texcoord;

        for (int i = 0; i < tmpMesh->numVertices; ++i)
        {
            int numValuePerVertex = 3;
            for (int j = 0; j < numValuePerVertex; ++j)
            {
                int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
                int OffSet = i * byteStridePerVertex + byteStridePerValue * j;

                newVertices[i][j] = *((float *)(posaddr + OffSet));
                if (tmpMesh->hasNormal)
                {
                    newNormals[i][j] = *((float *)(normaladdr + OffSet));
                }
            }

            if (tmpMesh->hasColor)
            {
                numValuePerVertex = 4;
                for (int j = 0; j < numValuePerVertex; ++j)
                {
                    int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
                    newColors[i][j] = *((float *)(coloraddr + (i * byteStridePerVertex + byteStridePerValue * j)));
                }
            }

            if (tmpMesh->hasTexcoord)
            {
                numValuePerVertex = 2;
                for (int j = 0; j < numValuePerVertex; ++j)
                {
                    int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
                    newUVs[i][j] = *((float *)(uvaddr + (i * byteStridePerVertex + byteStridePerValue * j)));
                }
            }
        }

        ReleaseUnityMesh(&tmpMesh);

        if (newVertices.Length > maxNumVerticesPerMesh)
        {
            // Unity only support maximum 65534 vertices per mesh. So large meshes
            // need to be splitted.

            DecodedMesh decodedMesh = new DecodedMesh();
            decodedMesh.vertices = newVertices;
            decodedMesh.indices  = newTriangles;
            if (newUVs.Length != 0)
            {
                decodedMesh.uvs = newUVs;
            }
            if (newNormals.Length != 0)
            {
                decodedMesh.normals = newNormals;
            }
            if (newColors.Length != 0)
            {
                decodedMesh.colors = newColors;
            }
            List <DecodedMesh> splittedMeshes = new List <DecodedMesh> ();

            SplitMesh(decodedMesh, ref splittedMeshes);
            for (int i = 0; i < splittedMeshes.Count; ++i)
            {
                Mesh mesh = new Mesh();
                mesh.vertices  = splittedMeshes [i].vertices;
                mesh.triangles = splittedMeshes [i].indices;
                if (splittedMeshes [i].uvs != null)
                {
                    mesh.uv = splittedMeshes [i].uvs;
                }

                if (splittedMeshes [i].colors != null)
                {
                    mesh.colors = splittedMeshes[i].colors;
                }

                if (splittedMeshes [i].normals != null)
                {
                    mesh.normals = splittedMeshes [i].normals;
                }
                else
                {
                    Debug.Log("Sub mesh doesn't have normals, recomputed.");
                    mesh.RecalculateNormals();
                }
                mesh.RecalculateBounds();
                meshes.Add(mesh);
            }
        }
        else
        {
            Mesh mesh = new Mesh();
            mesh.vertices  = newVertices;
            mesh.triangles = newTriangles;
            if (newUVs.Length != 0)
            {
                mesh.uv = newUVs;
            }
            if (newNormals.Length != 0)
            {
                mesh.normals = newNormals;
            }
            else
            {
                mesh.RecalculateNormals();
                Debug.Log("Mesh doesn't have normals, recomputed.");
            }
            if (newColors.Length != 0)
            {
                mesh.colors = newColors;
            }

            // Scale and translate the decoded mesh so it would be visible to
            // a new camera's default settings.
            float scale = 0.5f / mesh.bounds.extents.x;
            if (0.5f / mesh.bounds.extents.y < scale)
            {
                scale = 0.5f / mesh.bounds.extents.y;
            }
            if (0.5f / mesh.bounds.extents.z < scale)
            {
                scale = 0.5f / mesh.bounds.extents.z;
            }

            Vector3[] vertices = mesh.vertices;
            int       i        = 0;
            while (i < vertices.Length)
            {
                vertices[i] *= scale;
                i++;
            }

            mesh.vertices = vertices;
            mesh.RecalculateBounds();

            Vector3 translate = mesh.bounds.center;
            translate.x = 0 - mesh.bounds.center.x;
            translate.y = 0 - mesh.bounds.center.y;
            translate.z = 2 - mesh.bounds.center.z;

            i = 0;
            while (i < vertices.Length)
            {
                vertices[i] += translate;
                i++;
            }
            mesh.vertices = vertices;
            mesh.RecalculateBounds();
            meshes.Add(mesh);
        }

        return(numFaces);
    }