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