public MeshData(GLTFMesh gltfMesh, GLTFAccessor.ImportResult[] accessors, GLTFBufferView.ImportResult[] bufferViews) { name = gltfMesh.name; if (gltfMesh.primitives.Count == 0) { Debug.LogWarning("0 primitives in mesh"); } else { for (int i = 0; i < gltfMesh.primitives.Count; i++) { GLTFPrimitive primitive = gltfMesh.primitives[i]; // Load draco mesh if (primitive.extensions != null && primitive.extensions.KHR_draco_mesh_compression != null) { GLTFPrimitive.DracoMeshCompression draco = primitive.extensions.KHR_draco_mesh_compression; GLTFBufferView.ImportResult bufferView = bufferViews[draco.bufferView]; GLTFUtilityDracoLoader loader = new GLTFUtilityDracoLoader(); byte[] buffer = new byte[bufferView.byteLength]; bufferView.stream.Seek(bufferView.byteOffset, System.IO.SeekOrigin.Begin); bufferView.stream.Read(buffer, 0, bufferView.byteLength); GLTFUtilityDracoLoader.MeshAttributes attribs = new GLTFUtilityDracoLoader.MeshAttributes( primitive.extensions.KHR_draco_mesh_compression.attributes.POSITION ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.NORMAL ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.TEXCOORD_0 ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.JOINTS_0 ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.WEIGHTS_0 ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.COLOR_0 ?? -1 ); //Mesh mesh = loader.LoadMesh(buffer, attribs); GLTFUtilityDracoLoader.AsyncMesh asyncMesh = loader.LoadMesh(buffer, attribs); if (asyncMesh == null) { Debug.LogWarning("Draco mesh couldn't be loaded"); } submeshTrisMode.Add(primitive.mode); // Tris int vertCount = verts.Count(); submeshTris.Add(asyncMesh.tris.Reverse().Select(x => x + vertCount).ToList()); verts.AddRange(asyncMesh.verts.Select(x => new Vector3(-x.x, x.y, x.z))); if (asyncMesh.norms != null) { normals.AddRange(asyncMesh.norms.Select(v => { v.x = -v.x; return(v); })); } //tangents.AddRange(asyncMesh.tangents.Select(v => { v.y = -v.y; v.z = -v.z; return v; })); // Weights if (asyncMesh.boneWeights != null) { if (weights == null) { weights = new List <BoneWeight>(); } weights.AddRange(asyncMesh.boneWeights); } // BlendShapes not supported yet /* for (int k = 0; k < mesh.blendShapeCount; k++) { * int frameCount = mesh.GetBlendShapeFrameCount(k); * BlendShape blendShape = new BlendShape(); * blendShape.pos = new Vector3[frameCount]; * blendShape.norm = new Vector3[frameCount]; * blendShape.tan = new Vector3[frameCount]; * for (int o = 0; o < frameCount; o++) { * mesh.GetBlendShapeFrameVertices(k, o, blendShape.pos, blendShape.norm, blendShape.tan); * } * blendShapes.Add(blendShape); * } */ // UVs if (asyncMesh.uv != null) { if (uv1 == null) { uv1 = new List <Vector2>(); } uv1.AddRange(asyncMesh.uv.Select(x => new Vector2(x.x, -x.y))); } } // Load normal mesh else { int vertStartIndex = verts.Count; submeshVertexStart.Add(vertStartIndex); // Verts - (X points left in GLTF) if (primitive.attributes.POSITION.HasValue) { IEnumerable <Vector3> newVerts = accessors[primitive.attributes.POSITION.Value].ReadVec3(true).Select(v => { v.x = -v.x; return(v); }); verts.AddRange(newVerts); } int vertCount = verts.Count; // Tris - (Invert all triangles. Instead of flipping each triangle, just flip the entire array. Much easier) if (primitive.indices.HasValue) { submeshTris.Add(new List <int>(accessors[primitive.indices.Value].ReadInt().Reverse().Select(x => x + vertStartIndex))); submeshTrisMode.Add(primitive.mode); } /// Normals - (X points left in GLTF) if (primitive.attributes.NORMAL.HasValue) { normals.AddRange(accessors[primitive.attributes.NORMAL.Value].ReadVec3(true).Select(v => { v.x = -v.x; return(v); })); } // Tangents - (X points left in GLTF) if (primitive.attributes.TANGENT.HasValue) { tangents.AddRange(accessors[primitive.attributes.TANGENT.Value].ReadVec4(true).Select(v => { v.y = -v.y; v.z = -v.z; return(v); })); } // Vertex colors if (primitive.attributes.COLOR_0.HasValue) { colors.AddRange(accessors[primitive.attributes.COLOR_0.Value].ReadColor()); } // Weights if (primitive.attributes.WEIGHTS_0.HasValue && primitive.attributes.JOINTS_0.HasValue) { Vector4[] weights0 = accessors[primitive.attributes.WEIGHTS_0.Value].ReadVec4(true); Vector4[] joints0 = accessors[primitive.attributes.JOINTS_0.Value].ReadVec4(); if (joints0.Length == weights0.Length) { BoneWeight[] boneWeights = new BoneWeight[weights0.Length]; for (int k = 0; k < boneWeights.Length; k++) { NormalizeWeights(ref weights0[k]); boneWeights[k].weight0 = weights0[k].x; boneWeights[k].weight1 = weights0[k].y; boneWeights[k].weight2 = weights0[k].z; boneWeights[k].weight3 = weights0[k].w; boneWeights[k].boneIndex0 = Mathf.RoundToInt(joints0[k].x); boneWeights[k].boneIndex1 = Mathf.RoundToInt(joints0[k].y); boneWeights[k].boneIndex2 = Mathf.RoundToInt(joints0[k].z); boneWeights[k].boneIndex3 = Mathf.RoundToInt(joints0[k].w); } if (weights == null) { weights = new List <BoneWeight>(new BoneWeight[vertCount - boneWeights.Length]); } weights.AddRange(boneWeights); } else { Debug.LogWarning("WEIGHTS_0 and JOINTS_0 not same length. Skipped"); } } else { if (weights != null) { weights.AddRange(new BoneWeight[vertCount - weights.Count]); } } // UVs ReadUVs(ref uv1, accessors, primitive.attributes.TEXCOORD_0, vertCount); ReadUVs(ref uv2, accessors, primitive.attributes.TEXCOORD_1, vertCount); ReadUVs(ref uv3, accessors, primitive.attributes.TEXCOORD_2, vertCount); ReadUVs(ref uv4, accessors, primitive.attributes.TEXCOORD_3, vertCount); ReadUVs(ref uv5, accessors, primitive.attributes.TEXCOORD_4, vertCount); ReadUVs(ref uv6, accessors, primitive.attributes.TEXCOORD_5, vertCount); ReadUVs(ref uv7, accessors, primitive.attributes.TEXCOORD_6, vertCount); ReadUVs(ref uv8, accessors, primitive.attributes.TEXCOORD_7, vertCount); } } bool hasTargetNames = gltfMesh.extras != null && gltfMesh.extras.targetNames != null; if (hasTargetNames) { if (gltfMesh.primitives.All(x => x.targets.Count != gltfMesh.extras.targetNames.Length)) { Debug.LogWarning("Morph target names found in mesh " + name + " but array length does not match primitive morph target array length"); hasTargetNames = false; } } // Read blend shapes after knowing final vertex count int finalVertCount = verts.Count; for (int i = 0; i < gltfMesh.primitives.Count; i++) { GLTFPrimitive primitive = gltfMesh.primitives[i]; if (primitive.targets != null) { for (int k = 0; k < primitive.targets.Count; k++) { BlendShape blendShape = new BlendShape(); blendShape.pos = GetMorphWeights(primitive.targets[k].POSITION, submeshVertexStart[i], finalVertCount, accessors); blendShape.norm = GetMorphWeights(primitive.targets[k].NORMAL, submeshVertexStart[i], finalVertCount, accessors); blendShape.tan = GetMorphWeights(primitive.targets[k].TANGENT, submeshVertexStart[i], finalVertCount, accessors); if (hasTargetNames) { blendShape.name = gltfMesh.extras.targetNames[k]; } else { blendShape.name = "morph-" + blendShapes.Count; } blendShapes.Add(blendShape); } } } } }