/// <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; }
/// <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); }