/// <summary>
 /// Maps an asyncmesh into a renderable mesh.
 /// </summary>
 public static void Apply(AsyncMesh source, Mesh destination)
 {
     destination.vertices  = source.Vertices;
     destination.normals   = source.Normals;
     destination.triangles = source.Triangles;
     destination.uv        = source.UVs;
 }
Example #2
0
    /// <summary>
    /// Performs a mesh subdivision.
    /// </summary>
    /// <param name="mesh">The mesh to subdivide.</param>
    public void Subdivide(AsyncMesh mesh)
    {
        _newVectices = new Dictionary <uint, int>();

        _vertices = new List <Vector3>(mesh.Vertices);
        _normals  = new List <Vector3>(mesh.Normals);
        _uvs      = new List <Vector2>(mesh.UVs);
        _indices  = new List <int>();

        int[] triangles = mesh.Triangles;
        for (int i = 0; i < triangles.Length; i += 3)
        {
            int i1 = triangles[i + 0];
            int i2 = triangles[i + 1];
            int i3 = triangles[i + 2];

            int a = GetNewVertex(i1, i2);
            int b = GetNewVertex(i2, i3);
            int c = GetNewVertex(i3, i1);

            _indices.Add(i1); _indices.Add(a); _indices.Add(c);
            _indices.Add(i2); _indices.Add(b); _indices.Add(a);
            _indices.Add(i3); _indices.Add(c); _indices.Add(b);
            _indices.Add(a);  _indices.Add(b); _indices.Add(c);             // center triangle
        }

        mesh.Vertices  = _vertices.ToArray();
        mesh.Normals   = _normals.ToArray();
        mesh.Triangles = _indices.ToArray();
        mesh.UVs       = _uvs.ToArray();
    }
    // Decodes a Draco mesh, creates a Unity mesh from the decoded data and
    // adds the Unity mesh to meshes. encodedData is the compressed Draco mesh.
    public unsafe AsyncMesh LoadMesh(byte[] encodedData, MeshAttributes attributes)
    {
        DracoMesh *mesh = null;

        if (DecodeDracoMesh(encodedData, encodedData.Length, &mesh) <= 0)
        {
            Debug.Log("Failed: Decoding error.");
            return(null);
        }

        AsyncMesh unityMesh = CreateAsyncMesh(mesh, attributes);

        int numFaces = mesh->numFaces;

        ReleaseDracoMesh(&mesh);
        if (numFaces > 0)
        {
            return(unityMesh);
        }
        else
        {
            return(null);
        }
    }
    // Creates a Unity mesh from the decoded Draco mesh.
    public unsafe AsyncMesh CreateAsyncMesh(DracoMesh *dracoMesh, MeshAttributes attributes)
    {
        int numFaces = dracoMesh->numFaces;

        AsyncMesh mesh = new AsyncMesh();

        mesh.tris  = new int[dracoMesh->numFaces * 3];
        mesh.verts = new Vector3[dracoMesh->numVertices];

        // Copy face indices.
        DracoData *indicesData;

        GetMeshIndices(dracoMesh, &indicesData);
        int elementSize =
            DataTypeSize((GLTFUtilityDracoLoader.DataType)indicesData->dataType);
        int *indices    = (int * )(indicesData->data);
        var  indicesPtr = UnsafeUtility.AddressOf(ref mesh.tris[0]);

        UnsafeUtility.MemCpy(indicesPtr, indices,
                             mesh.tris.Length * elementSize);
        ReleaseDracoData(&indicesData);

        DracoAttribute *attr = null;

        // Copy positions.
        if (GetAttributeByUniqueId(dracoMesh, attributes.pos, &attr))
        {
            DracoData *posData = null;
            GetAttributeData(dracoMesh, attr, &posData);
            elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)posData->dataType) *
                          attr->numComponents;
            var newVerticesPtr = UnsafeUtility.AddressOf(ref mesh.verts[0]);
            UnsafeUtility.MemCpy(newVerticesPtr, (void * )posData->data,
                                 dracoMesh->numVertices * elementSize);
            ReleaseDracoData(&posData);
            ReleaseDracoAttribute(&attr);
        }

        // Copy normals.
        if (GetAttributeByUniqueId(dracoMesh, attributes.norms, &attr))
        {
            DracoData *normData = null;
            if (GetAttributeData(dracoMesh, attr, &normData))
            {
                elementSize =
                    DataTypeSize((GLTFUtilityDracoLoader.DataType)normData->dataType) *
                    attr->numComponents;
                mesh.norms = new Vector3[dracoMesh->numVertices];
                var newNormalsPtr = UnsafeUtility.AddressOf(ref mesh.norms[0]);
                UnsafeUtility.MemCpy(newNormalsPtr, (void * )normData->data,
                                     dracoMesh->numVertices * elementSize);
                ReleaseDracoData(&normData);
                ReleaseDracoAttribute(&attr);
            }
        }

        // Copy texture coordinates.
        if (GetAttributeByUniqueId(dracoMesh, attributes.uv, &attr))
        {
            DracoData *texData = null;
            if (GetAttributeData(dracoMesh, attr, &texData))
            {
                elementSize =
                    DataTypeSize((GLTFUtilityDracoLoader.DataType)texData->dataType) *
                    attr->numComponents;
                mesh.uv = new Vector2[dracoMesh->numVertices];
                var newUVsPtr = UnsafeUtility.AddressOf(ref mesh.uv[0]);
                UnsafeUtility.MemCpy(newUVsPtr, (void * )texData->data,
                                     dracoMesh->numVertices * elementSize);
                ReleaseDracoData(&texData);
                ReleaseDracoAttribute(&attr);
            }
        }

        // Copy colors.
        if (GetAttributeByUniqueId(dracoMesh, attributes.col, &attr))
        {
            DracoData *colorData = null;
            if (GetAttributeData(dracoMesh, attr, &colorData))
            {
                elementSize =
                    DataTypeSize((GLTFUtilityDracoLoader.DataType)colorData->dataType) *
                    attr->numComponents;
                mesh.colors = new Color[dracoMesh->numVertices];
                var newColorsPtr = UnsafeUtility.AddressOf(ref mesh.colors[0]);
                UnsafeUtility.MemCpy(newColorsPtr, (void * )colorData->data,
                                     dracoMesh->numVertices * elementSize);
                ReleaseDracoData(&colorData);
                ReleaseDracoAttribute(&attr);
            }
        }

        // Copy weights.
        Vector4[] weights = null;
        if (GetAttributeByUniqueId(dracoMesh, attributes.weights, &attr))
        {
            DracoData *weightData = null;
            if (GetAttributeData(dracoMesh, attr, &weightData))
            {
                elementSize =
                    DataTypeSize((GLTFUtilityDracoLoader.DataType)weightData->dataType) *
                    attr->numComponents;
                if (attr->dataType == 9)
                {
                    weights = new Vector4[dracoMesh->numVertices];
                    var newWeightsPtr = UnsafeUtility.AddressOf(ref weights[0]);
                    UnsafeUtility.MemCpy(newWeightsPtr, (void * )weightData->data,
                                         dracoMesh->numVertices * elementSize);
                }
                else if (attr->dataType == 4)
                {
                    var newWeightsInt = new Vector4 <UInt16> [dracoMesh->numVertices];
                    var newWeightsPtr = UnsafeUtility.AddressOf(ref newWeightsInt[0]);
                    UnsafeUtility.MemCpy(newWeightsPtr, (void * )weightData->data,
                                         dracoMesh->numVertices * elementSize);
                    weights = newWeightsInt.Select(x => new Vector4(x.x, x.y, x.z, x.w)).ToArray();
                }

                ReleaseDracoData(&weightData);
                ReleaseDracoAttribute(&attr);
            }
        }

        // Copy joints.
        Vector4[] joints = null;
        if (GetAttributeByUniqueId(dracoMesh, attributes.joints, &attr))
        {
            DracoData *jointData = null;
            if (GetAttributeData(dracoMesh, attr, &jointData))
            {
                elementSize =
                    DataTypeSize((GLTFUtilityDracoLoader.DataType)jointData->dataType) *
                    attr->numComponents;
                if (attr->dataType == 9)
                {
                    joints = new Vector4[dracoMesh->numVertices];
                    var newJointsPtr = UnsafeUtility.AddressOf(ref joints[0]);
                    UnsafeUtility.MemCpy(newJointsPtr, (void * )jointData->data,
                                         dracoMesh->numVertices * elementSize);
                }
                else if (attr->dataType == 4)
                {
                    var newJointsInt = new Vector4 <UInt16> [dracoMesh->numVertices];
                    var newJointsPtr = UnsafeUtility.AddressOf(ref newJointsInt[0]);
                    UnsafeUtility.MemCpy(newJointsPtr, (void * )jointData->data,
                                         dracoMesh->numVertices * elementSize);
                    joints = newJointsInt.Select(x => new Vector4(x.x, x.y, x.z, x.w)).ToArray();
                }

                ReleaseDracoData(&jointData);
                ReleaseDracoAttribute(&attr);
            }
        }

/* #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 */

        if (joints != null && weights != null)
        {
            if (joints.Length == weights.Length)
            {
                BoneWeight[] boneWeights = new BoneWeight[weights.Length];
                for (int k = 0; k < boneWeights.Length; k++)
                {
                    NormalizeWeights(ref weights[k]);
                    boneWeights[k].weight0    = weights[k].x;
                    boneWeights[k].weight1    = weights[k].y;
                    boneWeights[k].weight2    = weights[k].z;
                    boneWeights[k].weight3    = weights[k].w;
                    boneWeights[k].boneIndex0 = Mathf.RoundToInt(joints[k].x);
                    boneWeights[k].boneIndex1 = Mathf.RoundToInt(joints[k].y);
                    boneWeights[k].boneIndex2 = Mathf.RoundToInt(joints[k].z);
                    boneWeights[k].boneIndex3 = Mathf.RoundToInt(joints[k].w);
                }
                mesh.boneWeights = boneWeights;
            }
            else
            {
                Debug.LogWarning("Draco: joints and weights not same length. Skipped");
            }
        }
        return(mesh);
    }