// multiple submMesh is not sharing a VertexBuffer. // each subMesh use a independent VertexBuffer. private static MeshContext _ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { //Debug.LogWarning("_ImportMeshIndependentVertexBuffer"); var targets = gltfMesh.primitives[0].targets; for (int i = 1; i < gltfMesh.primitives.Count; ++i) { if (!gltfMesh.primitives[i].targets.SequenceEqual(targets)) { throw new NotImplementedException(string.Format("different targets: {0} with {1}", gltfMesh.primitives[i], targets)); } } var positions = new List <Vector3>(); var normals = new List <Vector3>(); var tangents = new List <Vector4>(); var uv = new List <Vector2>(); var colors = new List <Color>(); var meshContext = new MeshContext(); foreach (var prim in gltfMesh.primitives) { var indexOffset = positions.Count; var indexBuffer = prim.indices; var positionCount = positions.Count; positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); positionCount = positions.Count - positionCount; // normal if (prim.attributes.NORMAL != -1) { normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } if (prim.attributes.TANGENT != -1) { tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } // uv if (prim.attributes.TEXCOORD_0 != -1) { if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); #pragma warning restore 0612 } else { uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseUV())); } } else { // for inconsistent attributes in primitives uv.AddRange(new Vector2[positionCount]); } // color if (prim.attributes.COLOR_0 != -1) { colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; meshContext.boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = new BlendShape(!string.IsNullOrEmpty(prim.extras.targetNames[i]) ? prim.extras.targetNames[i] : i.ToString()) ; if (primTarget.POSITION != -1) { blendShape.Positions.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { blendShape.Normals.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } meshContext.blendShapes.Add(blendShape); } } var indices = (indexBuffer >= 0) ? ctx.GLTF.GetIndices(indexBuffer) : TriangleUtil.FlipTriangle(Enumerable.Range(0, meshContext.positions.Length)).ToArray() // without index array ; for (int i = 0; i < indices.Length; ++i) { indices[i] += indexOffset; } meshContext.subMeshes.Add(indices); // material meshContext.materialIndices.Add(prim.material); } meshContext.positions = positions.ToArray(); meshContext.normals = normals.ToArray(); meshContext.tangents = tangents.ToArray(); meshContext.uv = uv.ToArray(); return(meshContext); }
/// <summary> /// /// 各primitiveが同じ attribute を共有している場合専用のローダー。 /// /// </summary> /// <param name="ctx"></param> /// <param name="gltfMesh"></param> /// <returns></returns> public void ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { { // 同じVertexBufferを共有しているので先頭のモノを使う var prim = gltfMesh.primitives.First(); m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ())); // normal if (prim.attributes.NORMAL != -1) { m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ())); } #if false // tangent if (prim.attributes.TANGENT != -1) { tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ())); } #endif // uv if (prim.attributes.TEXCOORD_0 != -1) { if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY())); #pragma warning restore 0612 } else { m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV())); } } // uv2 if (prim.attributes.TEXCOORD_1 != -1) { m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV())); } // color if (prim.attributes.COLOR_0 != -1) { if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 3) { var vec3Color = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.COLOR_0); m_colors.AddRange(new Color[vec3Color.Length]); for (int i = 0; i < vec3Color.Length; i++) { Vector3 color = vec3Color[i]; m_colors[i] = new Color(color.x, color.y, color.z); } } else if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 4) { m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } else { throw new NotImplementedException(string.Format("unknown color type {0}", ctx.GLTF.accessors[prim.attributes.COLOR_0].type)); } } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0); for (int i = 0; i < weights0.Length; ++i) { weights0[i] = weights0[i].One(); } for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; m_boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { m_blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape(i.ToString()))); for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = m_blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ()); } if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ()); } } } } foreach (var prim in gltfMesh.primitives) { if (prim.indices == -1) { m_subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray()); } else { var indices = ctx.GLTF.GetIndices(prim.indices); m_subMeshes.Add(indices); } // material m_materialIndices.Add(prim.material); } }
// multiple submesh sharing same VertexBuffer private static MeshContext _ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { var context = new MeshContext(); { var prim = gltfMesh.primitives.First(); context.positions = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ()); // normal if (prim.attributes.NORMAL != -1) { context.normals = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ()); } // tangent if (prim.attributes.TANGENT != -1) { context.tangents = ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ()); } // uv if (prim.attributes.TEXCOORD_0 != -1) { if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { // backward compatibility context.uv = ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()); } else { context.uv = ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()); } } else { // for inconsistent attributes in primitives context.uv = new Vector2[context.positions.Length]; } // color if (prim.attributes.COLOR_0 != -1) { context.colors = ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0); for (int i = 0; i < weights0.Length; ++i) { weights0[i] = weights0[i].One(); } for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; context.boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { context.blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape( i < prim.extras.targetNames.Count && !string.IsNullOrEmpty(prim.extras.targetNames[i]) ? prim.extras.targetNames[i] : i.ToString()))); for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = context.blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ()); } if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ()); } } } } foreach (var prim in gltfMesh.primitives) { if (prim.indices == -1) { context.subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, context.positions.Length)).ToArray()); } else { var indices = ctx.GLTF.GetIndices(prim.indices); context.subMeshes.Add(indices); } // material context.materialIndices.Add(prim.material); } return(context); }
/// <summary> /// 各 primitive の attribute の要素が同じでない。=> uv が有るものと無いものが混在するなど /// glTF 的にはありうる。 /// /// primitive を独立した(Independent) Mesh として扱いこれを連結する。 /// </summary> /// <param name="ctx"></param> /// <param name="gltfMesh"></param> /// <returns></returns> public void ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { foreach (var prim in gltfMesh.primitives) { var indexOffset = m_positions.Count; var indexBuffer = prim.indices; // position は必ずある var positionCount = m_positions.Count; m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); positionCount = m_positions.Count - positionCount; // normal if (prim.attributes.NORMAL != -1) { FillZero(m_normals); m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } #if false if (prim.attributes.TANGENT != -1) { FillZero(tangetns); tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } #endif // uv if (prim.attributes.TEXCOORD_0 != -1) { FillZero(m_uv); if (ctx.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); #pragma warning restore 0612 } else { m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseUV())); } } // uv2 if (prim.attributes.TEXCOORD_1 != -1) { FillZero(m_uv2); m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_1).Select(x => x.ReverseUV())); } // color if (prim.attributes.COLOR_0 != -1) { FillZero(m_colors); m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { FillZero(m_boneWeights); var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; m_boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { for (int i = 0; i < prim.targets.Count; ++i) { var primTarget = prim.targets[i]; var blendShape = new BlendShape(i.ToString()); if (primTarget.POSITION != -1) { FillZero(blendShape.Positions); blendShape.Positions.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { FillZero(blendShape.Normals); blendShape.Normals.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { FillZero(blendShape.Tangents); blendShape.Tangents.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } m_blendShapes.Add(blendShape); } } var indices = (indexBuffer >= 0) ? ctx.GLTF.GetIndices(indexBuffer) : TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray() // without index array ; for (int i = 0; i < indices.Length; ++i) { indices[i] += indexOffset; } m_subMeshes.Add(indices); // material m_materialIndices.Add(prim.material); } }