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))); 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().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().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().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(); 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); } } } } }
/// <summary> Set up various components defined in the node. Call after all transforms have been set up </summary> public void SetupComponents() { if (Transform == null) { Debug.LogWarning("Transform is null. Call CreateTransform before calling SetupComponents"); return; } if (this.mesh != -1) { GLTFMesh glTFMesh = glTFObject.meshes[this.mesh]; Mesh mesh = glTFMesh.GetMesh(); Renderer renderer; if (skin != -1) { SkinnedMeshRenderer smr = Transform.gameObject.AddComponent <SkinnedMeshRenderer>(); GLTFSkin glTFSkin = glTFObject.skins[skin]; Transform[] bones = new Transform[glTFSkin.joints.Length]; for (int i = 0; i < bones.Length; i++) { int jointNodeIndex = glTFSkin.joints[i]; GLTFNode jointNode = glTFObject.nodes[jointNodeIndex]; bones[i] = jointNode.Transform; } smr.bones = bones; smr.rootBone = bones[0]; renderer = smr; // Bindposes if (glTFSkin.inverseBindMatrices != -1) { Matrix4x4 m = glTFObject.nodes[0].Transform.localToWorldMatrix; Matrix4x4[] bindPoses = new Matrix4x4[glTFSkin.joints.Length]; for (int i = 0; i < glTFSkin.joints.Length; i++) { bindPoses[i] = glTFObject.nodes[glTFSkin.joints[i]].Transform.worldToLocalMatrix * m; } mesh.bindposes = bindPoses; } smr.sharedMesh = mesh; } else { MeshRenderer mr = Transform.gameObject.AddComponent <MeshRenderer>(); MeshFilter mf = Transform.gameObject.AddComponent <MeshFilter>(); renderer = mr; mf.sharedMesh = mesh; } //Materials Material[] materials = new Material[glTFMesh.primitives.Count]; for (int i = 0; i < glTFMesh.primitives.Count; i++) { GLTFPrimitive primitive = glTFMesh.primitives[i]; // Create material if id is positive or 0 if (primitive.material != -1) { materials[i] = glTFObject.materials[primitive.material].GetMaterial(); } } renderer.materials = materials; } }
public MeshData(GLTFMesh gltfMesh, GLTFAccessor.ImportResult[] accessors) { 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]; int vertStartIndex = verts.Count; submeshVertexStart.Add(vertStartIndex); // Verts - (Z points backwards in GLTF) if (primitive.attributes.POSITION.HasValue) { IEnumerable <Vector3> newVerts = accessors[primitive.attributes.POSITION.Value].ReadVec3().Select(v => { v.z = -v.z; 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))); } /// Normals - (Z points backwards in GLTF) if (primitive.attributes.NORMAL.HasValue) { normals.AddRange(accessors[primitive.attributes.NORMAL.Value].ReadVec3().Select(v => { v.z = -v.z; return(v); })); } // Tangents - (Z points backwards in GLTF) if (primitive.attributes.TANGENT.HasValue) { tangents.AddRange(accessors[primitive.attributes.TANGENT.Value].ReadVec4().Select(v => { v.z = -v.z; v.w = -v.w; 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(); 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); } } } } }
public MeshData(GLTFMesh gltfMesh, GLTFAccessor.ImportResult[] accessors) { 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]; int vertStartIndex = verts.Count; // Verts - (Z points backwards in GLTF) if (primitive.attributes.POSITION.HasValue) { IEnumerable <Vector3> newVerts = accessors[primitive.attributes.POSITION.Value].ReadVec3().Select(v => { v.z = -v.z; 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))); } /// Normals - (Z points backwards in GLTF) if (primitive.attributes.NORMAL.HasValue) { normals.AddRange(accessors[primitive.attributes.NORMAL.Value].ReadVec3().Select(v => { v.z = -v.z; return(v); })); } // Tangents - (Z points backwards in GLTF) if (primitive.attributes.TANGENT.HasValue) { tangents.AddRange(accessors[primitive.attributes.TANGENT.Value].ReadVec4().Select(v => { v.z = -v.z; v.w = -v.w; 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(); 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); } } }