public override void Dispose() { var tmp = dracoAttribute; ReleaseDracoAttribute(&tmp); dracoAttribute = null; }
// Creates a Unity mesh from the decoded Draco mesh. public unsafe Mesh CreateUnityMesh(DracoMesh *dracoMesh) { float startTime = Time.realtimeSinceStartup; int numFaces = dracoMesh->numFaces; int[] newTriangles = new int[dracoMesh->numFaces * 3]; Vector3[] newVertices = new Vector3[dracoMesh->numVertices]; Vector2[] newUVs = null; Vector3[] newNormals = null; Color[] newColors = null; byte[] newGenerics = null; // Copy face indices. DracoData *indicesData; GetMeshIndices(dracoMesh, &indicesData); int elementSize = DataTypeSize((DracoMeshLoader.DataType)indicesData->dataType); int *indices = (int *)(indicesData->data); var indicesPtr = UnsafeUtility.AddressOf(ref newTriangles[0]); UnsafeUtility.MemCpy(indicesPtr, indices, newTriangles.Length * elementSize); ReleaseDracoData(&indicesData); // Copy positions. DracoAttribute *attr = null; GetAttributeByType(dracoMesh, AttributeType.POSITION, 0, &attr); DracoData *posData = null; GetAttributeData(dracoMesh, attr, &posData); elementSize = DataTypeSize((DracoMeshLoader.DataType)posData->dataType) * attr->numComponents; var newVerticesPtr = UnsafeUtility.AddressOf(ref newVertices[0]); UnsafeUtility.MemCpy(newVerticesPtr, (void *)posData->data, dracoMesh->numVertices * elementSize); ReleaseDracoData(&posData); ReleaseDracoAttribute(&attr); // Copy normals. if (GetAttributeByType(dracoMesh, AttributeType.NORMAL, 0, &attr)) { DracoData *normData = null; if (GetAttributeData(dracoMesh, attr, &normData)) { elementSize = DataTypeSize((DracoMeshLoader.DataType)normData->dataType) * attr->numComponents; newNormals = new Vector3[dracoMesh->numVertices]; var newNormalsPtr = UnsafeUtility.AddressOf(ref newNormals[0]); UnsafeUtility.MemCpy(newNormalsPtr, (void *)normData->data, dracoMesh->numVertices * elementSize); Debug.Log("Decoded mesh normals."); ReleaseDracoData(&normData); ReleaseDracoAttribute(&attr); } } // Copy texture coordinates. if (GetAttributeByType(dracoMesh, AttributeType.TEX_COORD, 0, &attr)) { DracoData *texData = null; if (GetAttributeData(dracoMesh, attr, &texData)) { elementSize = DataTypeSize((DracoMeshLoader.DataType)texData->dataType) * attr->numComponents; newUVs = new Vector2[dracoMesh->numVertices]; var newUVsPtr = UnsafeUtility.AddressOf(ref newUVs[0]); UnsafeUtility.MemCpy(newUVsPtr, (void *)texData->data, dracoMesh->numVertices * elementSize); Debug.Log("Decoded mesh texcoords."); ReleaseDracoData(&texData); ReleaseDracoAttribute(&attr); } } // Copy colors. if (GetAttributeByType(dracoMesh, AttributeType.COLOR, 0, &attr)) { DracoData *colorData = null; if (GetAttributeData(dracoMesh, attr, &colorData)) { elementSize = DataTypeSize((DracoMeshLoader.DataType)colorData->dataType) * attr->numComponents; newColors = new Color[dracoMesh->numVertices]; var newColorsPtr = UnsafeUtility.AddressOf(ref newColors[0]); UnsafeUtility.MemCpy(newColorsPtr, (void *)colorData->data, dracoMesh->numVertices * elementSize); Debug.Log("Decoded mesh colors."); ReleaseDracoData(&colorData); ReleaseDracoAttribute(&attr); } } // Copy generic data. This script does not do anyhting with the generic // data. if (GetAttributeByType(dracoMesh, AttributeType.GENERIC, 0, &attr)) { DracoData *genericData = null; if (GetAttributeData(dracoMesh, attr, &genericData)) { elementSize = DataTypeSize((DracoMeshLoader.DataType)genericData->dataType) * attr->numComponents; newGenerics = new byte[dracoMesh->numVertices * elementSize]; var newGenericPtr = UnsafeUtility.AddressOf(ref newGenerics[0]); UnsafeUtility.MemCpy(newGenericPtr, (void *)genericData->data, dracoMesh->numVertices * elementSize); Debug.Log("Decoded mesh generic data."); ReleaseDracoData(&genericData); ReleaseDracoAttribute(&attr); } } float copyDecodedDataTimeMilli = (Time.realtimeSinceStartup - startTime) * 1000.0f; Debug.Log("copyDecodedDataTimeMilli: " + copyDecodedDataTimeMilli.ToString()); startTime = Time.realtimeSinceStartup; 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(); Debug.Log("Mesh doesn't have normals, recomputed."); } if (newColors != null) { mesh.colors = newColors; } float convertTimeMilli = (Time.realtimeSinceStartup - startTime) * 1000.0f; Debug.Log("convertTimeMilli: " + convertTimeMilli.ToString()); return(mesh); }
// Returns an array of attribute data as well as the type of data in // data_type. On input, data must be null. The returned data must be // released with ReleaseDracoData. [DllImport("dracodec_unity")] private static extern bool GetAttributeData( DracoMesh *mesh, DracoAttribute *attr, DracoData **data);
// 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); }
// Returns an array of attribute data as well as the type of data in // data_type. On input, data must be null. The returned data must be // released with ReleaseDracoData. [DllImport(DRACODEC_UNITY_LIB)] private static extern bool GetAttributeData( DracoMesh *mesh, DracoAttribute *attr, DracoData **data);
// Creates a Unity mesh from the decoded Draco mesh. public unsafe Mesh CreateUnityMesh(DracoMesh *dracoMesh) { int numFaces = dracoMesh->numFaces; int[] newTriangles = new int[dracoMesh->numFaces * 3]; Vector3[] newVertices = new Vector3[dracoMesh->numVertices]; Vector2[] newUVs = null; Vector3[] newNormals = null; Vector4[] newWeights = null; Vector4[] newJoints = null; Color[] newColors = null; // 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 newTriangles[0]); UnsafeUtility.MemCpy(indicesPtr, indices, newTriangles.Length * elementSize); ReleaseDracoData(&indicesData); // Copy positions. DracoAttribute *attr = null; GetAttributeByType(dracoMesh, AttributeType.POSITION, 0, &attr); DracoData *posData = null; GetAttributeData(dracoMesh, attr, &posData); elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)posData->dataType) * attr->numComponents; var newVerticesPtr = UnsafeUtility.AddressOf(ref newVertices[0]); UnsafeUtility.MemCpy(newVerticesPtr, (void * )posData->data, dracoMesh->numVertices * elementSize); ReleaseDracoData(&posData); ReleaseDracoAttribute(&attr); // Copy normals. if (GetAttributeByType(dracoMesh, AttributeType.NORMAL, 0, &attr)) { DracoData *normData = null; if (GetAttributeData(dracoMesh, attr, &normData)) { elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)normData->dataType) * attr->numComponents; newNormals = new Vector3[dracoMesh->numVertices]; var newNormalsPtr = UnsafeUtility.AddressOf(ref newNormals[0]); UnsafeUtility.MemCpy(newNormalsPtr, (void * )normData->data, dracoMesh->numVertices * elementSize); ReleaseDracoData(&normData); ReleaseDracoAttribute(&attr); } } // Copy texture coordinates. if (GetAttributeByType(dracoMesh, AttributeType.TEX_COORD, 0, &attr)) { DracoData *texData = null; if (GetAttributeData(dracoMesh, attr, &texData)) { elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)texData->dataType) * attr->numComponents; newUVs = new Vector2[dracoMesh->numVertices]; var newUVsPtr = UnsafeUtility.AddressOf(ref newUVs[0]); UnsafeUtility.MemCpy(newUVsPtr, (void * )texData->data, dracoMesh->numVertices * elementSize); ReleaseDracoData(&texData); ReleaseDracoAttribute(&attr); } } // Copy colors. if (GetAttributeByType(dracoMesh, AttributeType.COLOR, 0, &attr)) { DracoData *colorData = null; if (GetAttributeData(dracoMesh, attr, &colorData)) { elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)colorData->dataType) * attr->numComponents; newColors = new Color[dracoMesh->numVertices]; var newColorsPtr = UnsafeUtility.AddressOf(ref newColors[0]); UnsafeUtility.MemCpy(newColorsPtr, (void * )colorData->data, dracoMesh->numVertices * elementSize); ReleaseDracoData(&colorData); ReleaseDracoAttribute(&attr); } } // Copy weights. if (GetAttributeByType(dracoMesh, AttributeType.GENERIC, 1, &attr)) { DracoData *weightData = null; if (GetAttributeData(dracoMesh, attr, &weightData)) { elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)weightData->dataType) * attr->numComponents; if (attr->dataType == 9) { newWeights = new Vector4[dracoMesh->numVertices]; var newWeightsPtr = UnsafeUtility.AddressOf(ref newWeights[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); newWeights = newWeightsInt.Select(x => new Vector4(x.x, x.y, x.z, x.w)).ToArray(); } ReleaseDracoData(&weightData); ReleaseDracoAttribute(&attr); } } // Copy joints. if (GetAttributeByType(dracoMesh, AttributeType.GENERIC, 0, &attr)) { DracoData *jointData = null; if (GetAttributeData(dracoMesh, attr, &jointData)) { elementSize = DataTypeSize((GLTFUtilityDracoLoader.DataType)jointData->dataType) * attr->numComponents; if (attr->dataType == 9) { newJoints = new Vector4[dracoMesh->numVertices]; var newJointsPtr = UnsafeUtility.AddressOf(ref newJoints[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); newJoints = newJointsInt.Select(x => new Vector4(x.x, x.y, x.z, x.w)).ToArray(); } ReleaseDracoData(&jointData); ReleaseDracoAttribute(&attr); } } // Dirty fix: // If any value in weights is above 1.5, swap weights and joints. // I honestly have no clue where the correct uniqueIDs are supposed to come from. if (newWeights != null && newJoints != null) { if (newWeights.Any(x => x.x > 1.5f || x.y > 1.5f || x.z > 1.5f || x.w > 1.5f)) { Vector4[] temp = newWeights; newWeights = newJoints; newJoints = temp; } } 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(); Debug.Log("Mesh doesn't have normals, recomputed."); } if (newColors != null) { mesh.colors = newColors; } if (newJoints != null && newWeights != null) { if (newJoints.Length == newWeights.Length) { BoneWeight[] boneWeights = new BoneWeight[newWeights.Length]; for (int k = 0; k < boneWeights.Length; k++) { NormalizeWeights(ref newWeights[k]); boneWeights[k].weight0 = newWeights[k].x; boneWeights[k].weight1 = newWeights[k].y; boneWeights[k].weight2 = newWeights[k].z; boneWeights[k].weight3 = newWeights[k].w; boneWeights[k].boneIndex0 = Mathf.RoundToInt(newJoints[k].x); boneWeights[k].boneIndex1 = Mathf.RoundToInt(newJoints[k].y); boneWeights[k].boneIndex2 = Mathf.RoundToInt(newJoints[k].z); boneWeights[k].boneIndex3 = Mathf.RoundToInt(newJoints[k].w); } mesh.boneWeights = boneWeights; } else { Debug.LogWarning("Draco: joints and weights not same length. Skipped"); } } return(mesh); }
public AttributeMap(DracoAttribute *dracoAttribute, VertexAttribute attribute, VertexAttributeFormat format, bool convertSpace) : base(attribute, format) { this.dracoAttribute = dracoAttribute; this.convertSpace = convertSpace; }
// Returns an array of attribute data as well as the type of data in // data_type. On input, data must be null. The returned data must be // released with ReleaseDracoData. [DllImport(DRACODEC_UNITY_LIB)] unsafe static extern bool GetAttributeData( DracoMesh *mesh, DracoAttribute *attr, DracoData **data, bool flip);
private static extern bool GetAttributeData( DracoMesh *mesh, DracoAttribute *attr, DracoData **data);