Exemplo n.º 1
0
    public unsafe static Mesh CreateMesh(IntPtr dracoMesh)
    {
        Profiler.BeginSample("CreateMesh");
        DracoToUnityMesh *tmpMesh = (DracoToUnityMesh *)dracoMesh;

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

        Profiler.BeginSample("CreateMeshAlloc");
        int[]     newTriangles = new int[tmpMesh->numFaces * 3];
        Vector3[] newVertices  = new Vector3[tmpMesh->numVertices];
        Profiler.EndSample();

        Vector2[] newUVs     = null;
        Vector3[] newNormals = null;
        Color[]   newColors  = null;

        Profiler.BeginSample("CreateMeshIndices");
        byte *indicesSrc = (byte *)tmpMesh->indices;
        var   indicesPtr = UnsafeUtility.AddressOf(ref newTriangles[0]);

        UnsafeUtility.MemCpy(indicesPtr, indicesSrc, newTriangles.Length * 4);
        Profiler.EndSample();

        Profiler.BeginSample("CreateMeshPositions");
        byte *posaddr = (byte *)tmpMesh->position;
        /// TODO(atteneder): check if we can avoid mem copies with new Mesh API (2019.3?)
        /// by converting void* to NativeArray via
        /// NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray
        var newVerticesPtr = UnsafeUtility.AddressOf(ref newVertices[0]);

        UnsafeUtility.MemCpy(newVerticesPtr, posaddr, tmpMesh->numVertices * 12);
        Profiler.EndSample();

        if (tmpMesh->hasTexcoord)
        {
            Profiler.BeginSample("CreateMeshUVs");
            Log("Decoded mesh texcoords.");
            newUVs = new Vector2[tmpMesh->numVertices];
            byte *uvaddr    = (byte *)tmpMesh->texcoord;
            var   newUVsPtr = UnsafeUtility.AddressOf(ref newUVs[0]);
            UnsafeUtility.MemCpy(newUVsPtr, uvaddr, tmpMesh->numVertices * 8);
            Profiler.EndSample();
        }
        if (tmpMesh->hasNormal)
        {
            Profiler.BeginSample("CreateMeshNormals");
            Log("Decoded mesh normals.");
            newNormals = new Vector3[tmpMesh->numVertices];
            byte *normaladdr    = (byte *)tmpMesh->normal;
            var   newNormalsPtr = UnsafeUtility.AddressOf(ref newNormals[0]);
            UnsafeUtility.MemCpy(newNormalsPtr, normaladdr, tmpMesh->numVertices * 12);
            Profiler.EndSample();
        }
        if (tmpMesh->hasColor)
        {
            Profiler.BeginSample("CreateMeshColors");
            Log("Decoded mesh colors.");
            newColors = new Color[tmpMesh->numVertices];
            byte *coloraddr    = (byte *)tmpMesh->color;
            var   newColorsPtr = UnsafeUtility.AddressOf(ref newColors[0]);
            UnsafeUtility.MemCpy(newColorsPtr, coloraddr, tmpMesh->numVertices * 16);
            Profiler.EndSample();
        }

        Profiler.BeginSample("CreateMeshRelease");
        ReleaseUnityMesh(&tmpMesh);
        Profiler.EndSample();

        Profiler.BeginSample("CreateMeshFeeding");
        Mesh mesh = new Mesh();

#if UNITY_2017_3_OR_NEWER
        mesh.indexFormat = (newVertices.Length > System.UInt16.MaxValue)
                ? UnityEngine.Rendering.IndexFormat.UInt32
                : UnityEngine.Rendering.IndexFormat.UInt16;
#else
        if (newVertices.Length > System.UInt16.MaxValue)
        {
            throw new System.Exception("Draco meshes with more than 65535 vertices are only supported from Unity 2017.3 onwards.");
        }
#endif

        mesh.vertices = newVertices;
        mesh.SetTriangles(newTriangles, 0, true);
        if (newUVs != null)
        {
            mesh.uv = newUVs;
        }
        if (newNormals != null)
        {
            mesh.normals = newNormals;
        }
        else
        {
            mesh.RecalculateNormals();
            Log("Mesh doesn't have normals, recomputed.");
        }
        if (newColors != null)
        {
            mesh.colors = newColors;
        }

        Profiler.EndSample();
        return(mesh);
    }
Exemplo n.º 2
0
    public unsafe static Mesh CreateMesh(IntPtr dracoMesh, out bool hasNormals, out bool hasTexcoords)
    {
        Profiler.BeginSample("CreateMesh");
        DracoToUnityMesh *tmpMesh = (DracoToUnityMesh *)dracoMesh;

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

        Profiler.BeginSample("CreateMeshAlloc");
        int[]     newTriangles = new int[tmpMesh->numFaces * 3];
        Vector3[] newVertices  = new Vector3[tmpMesh->numVertices];
        Profiler.EndSample();

        Vector2[] newUVs     = null;
        Vector3[] newNormals = null;
        Color[]   newColors  = null;
        Vector4[] newWeights = null;
        int[]     newJoints  = null;

        Profiler.BeginSample("CreateMeshIndices");
        byte *indicesSrc = (byte *)tmpMesh->indices;
        var   indicesPtr = UnsafeUtility.AddressOf(ref newTriangles[0]);

        UnsafeUtility.MemCpy(indicesPtr, indicesSrc, newTriangles.Length * 4);
        Profiler.EndSample();

        Profiler.BeginSample("CreateMeshPositions");
        byte *posaddr = (byte *)tmpMesh->position;
        /// TODO(atteneder): check if we can avoid mem copies with new Mesh API (2019.3?)
        /// by converting void* to NativeArray via
        /// NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray
        var newVerticesPtr = UnsafeUtility.AddressOf(ref newVertices[0]);

        UnsafeUtility.MemCpy(newVerticesPtr, posaddr, tmpMesh->numVertices * 12);
        Profiler.EndSample();

        hasTexcoords = tmpMesh->hasTexcoord;
        hasNormals   = tmpMesh->hasNormal;

        if (hasTexcoords)
        {
            Profiler.BeginSample("CreateMeshUVs");
            Log("Decoded mesh texcoords.");
            newUVs = new Vector2[tmpMesh->numVertices];
            byte *uvaddr    = (byte *)tmpMesh->texcoord;
            var   newUVsPtr = UnsafeUtility.AddressOf(ref newUVs[0]);
            UnsafeUtility.MemCpy(newUVsPtr, uvaddr, tmpMesh->numVertices * 8);
            Profiler.EndSample();
        }
        if (hasNormals)
        {
            Profiler.BeginSample("CreateMeshNormals");
            Log("Decoded mesh normals.");
            newNormals = new Vector3[tmpMesh->numVertices];
            byte *normaladdr    = (byte *)tmpMesh->normal;
            var   newNormalsPtr = UnsafeUtility.AddressOf(ref newNormals[0]);
            UnsafeUtility.MemCpy(newNormalsPtr, normaladdr, tmpMesh->numVertices * 12);
            Profiler.EndSample();
        }
        if (tmpMesh->hasColor)
        {
            Profiler.BeginSample("CreateMeshColors");
            Log("Decoded mesh colors.");
            newColors = new Color[tmpMesh->numVertices];
            byte *coloraddr    = (byte *)tmpMesh->color;
            var   newColorsPtr = UnsafeUtility.AddressOf(ref newColors[0]);
            UnsafeUtility.MemCpy(newColorsPtr, coloraddr, tmpMesh->numVertices * 16);
            Profiler.EndSample();
        }
        if (tmpMesh->hasWeights && tmpMesh->hasJoints)
        {
            Profiler.BeginSample("CreateWeights");
            Log("Decoded mesh weights.");
            newWeights = new Vector4[tmpMesh->numVertices];
            byte *weightsAddr   = (byte *)tmpMesh->weights;
            var   newWeightsPtr = UnsafeUtility.AddressOf(ref newWeights[0]);
            UnsafeUtility.MemCpy(newWeightsPtr, weightsAddr, tmpMesh->numVertices * 16);
            Profiler.EndSample();

            Profiler.BeginSample("CreateJoints");
            Log("Decoded mesh joints.");
            newJoints = new int[tmpMesh->numVertices * 4];
            byte *jointsAddr   = (byte *)tmpMesh->joints;
            var   newJointsPtr = UnsafeUtility.AddressOf(ref newJoints[0]);
            UnsafeUtility.MemCpy(newJointsPtr, jointsAddr, tmpMesh->numVertices * 16);
            Profiler.EndSample();
        }

        Profiler.BeginSample("CreateMeshRelease");
        ReleaseUnityMesh(&tmpMesh);
        Profiler.EndSample();

        Profiler.BeginSample("CreateMeshFeeding");
        Mesh mesh = new Mesh();

#if UNITY_2017_3_OR_NEWER
        mesh.indexFormat = (newVertices.Length > System.UInt16.MaxValue)
                ? UnityEngine.Rendering.IndexFormat.UInt32
                : UnityEngine.Rendering.IndexFormat.UInt16;
#else
        if (newVertices.Length > System.UInt16.MaxValue)
        {
            throw new System.Exception("Draco meshes with more than 65535 vertices are only supported from Unity 2017.3 onwards.");
        }
#endif

        mesh.vertices = newVertices;
        mesh.SetTriangles(newTriangles, 0, true);
        if (newNormals != null)
        {
            mesh.normals = newNormals;
        }
        if (newUVs != null)
        {
            mesh.uv = newUVs;
        }
        if (newColors != null)
        {
            mesh.colors = newColors;
        }
        if (newJoints != null && newWeights != null)
        {
            BoneWeight[] weights = new BoneWeight[newWeights.Length];

            for (int i = 0; i < weights.Length; i++)
            {
                Tuple <float, int>[] values = new Tuple <float, int>[] {
                    new Tuple <float, int>(newWeights[i].x, newJoints[i * 4]),
                    new Tuple <float, int>(newWeights[i].y, newJoints[i * 4 + 1]),
                    new Tuple <float, int>(newWeights[i].z, newJoints[i * 4 + 2]),
                    new Tuple <float, int>(newWeights[i].w, newJoints[i * 4 + 3])
                };

                Array.Sort(values, (a, b) => { return(b.Item1.CompareTo(a.Item1)); });

                weights[i].boneIndex0 = values[0].Item2;
                weights[i].boneIndex1 = values[1].Item2;
                weights[i].boneIndex2 = values[2].Item2;
                weights[i].boneIndex3 = values[3].Item2;

                weights[i].weight0 = values[0].Item1;
                weights[i].weight1 = values[1].Item1;
                weights[i].weight2 = values[2].Item1;
                weights[i].weight3 = values[3].Item1;
            }
            mesh.boneWeights = weights;
        }
        Profiler.EndSample();         // CreateMeshFeeding
        Profiler.EndSample();         // CreateMesh
        return(mesh);
    }