/// <summary> /// /// 各primitiveが同じ attribute を共有している場合専用のローダー。 /// /// </summary> /// <param name="ctx"></param> /// <param name="gltfMesh"></param> /// <returns></returns> private void ImportMeshSharingVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) { var isOldVersion = data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16); { // 同じVertexBufferを共有しているので先頭のモノを使う var primitives = gltfMesh.primitives.First(); var positions = primitives.GetPositions(data); var normals = primitives.GetNormals(data, positions.Length); var texCoords0 = primitives.GetTexCoords0(data, positions.Length); var texCoords1 = primitives.GetTexCoords1(data, positions.Length); var colors = primitives.GetColors(data, positions.Length); var skinning = SkinningInfo.Create(data, gltfMesh, primitives); AssignBoneWeight = skinning.ShouldSetRendererNodeAsBone; CheckAttributeUsages(primitives); for (var i = 0; i < positions.Length; ++i) { var position = inverter.InvertVector3(positions[i]); var normal = normals != null?inverter.InvertVector3(normals.Value[i]) : Vector3.zero; var texCoord0 = Vector2.zero; if (texCoords0 != null) { if (isOldVersion) { #pragma warning disable 0612 texCoord0 = texCoords0.Value[i].ReverseY(); #pragma warning restore 0612 } else { texCoord0 = texCoords0.Value[i].ReverseUV(); } } var texCoord1 = texCoords1 != null ? texCoords1.Value[i].ReverseUV() : Vector2.zero; var color = colors != null ? colors.Value[i] : Color.white; AddVertex( new MeshVertex( position, normal, texCoord0, texCoord1, color)); var skin = skinning.GetSkinnedVertex(i); if (skin.HasValue) { AddSkin(skin.Value); } } // blendshape if (primitives.targets != null && primitives.targets.Count > 0) { for (int i = 0; i < primitives.targets.Count; ++i) { var primTarget = primitives.targets[i]; var hasPosition = primTarget.POSITION != -1 && data.GLTF.accessors[primTarget.POSITION].count == positions.Length; var hasNormal = primTarget.NORMAL != -1 && data.GLTF.accessors[primTarget.NORMAL].count == positions.Length; var hasTangent = primTarget.TANGENT != -1 && data.GLTF.accessors[primTarget.TANGENT].count == positions.Length; var blendShape = new BlendShape(i.ToString(), positions.Length, hasPosition, hasNormal, hasTangent); _blendShapes.Add(blendShape); if (hasPosition) { var morphPositions = data.GetArrayFromAccessor <Vector3>(primTarget.POSITION); blendShape.Positions.Capacity = morphPositions.Length; for (var j = 0; j < positions.Length; ++j) { blendShape.Positions.Add(inverter.InvertVector3(morphPositions[j])); } } if (hasNormal) { var morphNormals = data.GetArrayFromAccessor <Vector3>(primTarget.NORMAL); blendShape.Normals.Capacity = morphNormals.Length; for (var j = 0; j < positions.Length; ++j) { blendShape.Normals.Add(inverter.InvertVector3(morphNormals[j])); } } if (hasTangent) { var morphTangents = data.GetArrayFromAccessor <Vector3>(primTarget.TANGENT); blendShape.Tangents.Capacity = morphTangents.Length; for (var j = 0; j < positions.Length; ++j) { blendShape.Tangents.Add(inverter.InvertVector3(morphTangents[j])); } } } } } foreach (var primitive in gltfMesh.primitives) { if (primitive.indices >= 0) { var indexOffset = _currentIndexCount; var indices = data.GetIndicesFromAccessorIndex(primitive.indices); PushIndices(indices, 0); _subMeshes.Add(new SubMeshDescriptor(indexOffset, indices.Count)); } else { var indexOffset = _currentIndexCount; var positions = data.GLTF.accessors[primitive.attributes.POSITION]; for (int i = 0; i < positions.count; i += 3) { // flip triangle AddIndex(i + 2); AddIndex(i + 1); AddIndex(i); } _subMeshes.Add(new SubMeshDescriptor(indexOffset, positions.count)); } // material _materialIndices.Add(primitive.material); } }
/// <summary> /// 各 primitive の attribute の要素が同じでない。=> uv が有るものと無いものが混在するなど /// glTF 的にはありうる。 /// /// primitive を独立した(Independent) Mesh として扱いこれを連結する。 /// </summary> /// <param name="ctx"></param> /// <param name="gltfMesh"></param> /// <returns></returns> private void ImportMeshIndependentVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) { bool isOldVersion = data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16); foreach (var primitives in gltfMesh.primitives) { var vertexOffset = _currentVertexCount; var indexBufferCount = primitives.indices; // position は必ずある var positions = primitives.GetPositions(data); var normals = primitives.GetNormals(data, positions.Length); var texCoords0 = primitives.GetTexCoords0(data, positions.Length); var texCoords1 = primitives.GetTexCoords1(data, positions.Length); var colors = primitives.GetColors(data, positions.Length); var skinning = SkinningInfo.Create(data, gltfMesh, primitives); AssignBoneWeight = skinning.ShouldSetRendererNodeAsBone; CheckAttributeUsages(primitives); for (var i = 0; i < positions.Length; ++i) { var position = inverter.InvertVector3(positions[i]); var normal = normals != null?inverter.InvertVector3(normals.Value[i]) : Vector3.zero; var texCoord0 = Vector2.zero; if (texCoords0 != null) { if (isOldVersion) { #pragma warning disable 0612 // backward compatibility texCoord0 = texCoords0.Value[i].ReverseY(); #pragma warning restore 0612 } else { texCoord0 = texCoords0.Value[i].ReverseUV(); } } var texCoord1 = texCoords1 != null ? texCoords1.Value[i].ReverseUV() : Vector2.zero; var color = colors != null ? colors.Value[i] : Color.white; AddVertex( new MeshVertex( position, normal, texCoord0, texCoord1, color )); var skin = skinning.GetSkinnedVertex(i); if (skin.HasValue) { AddSkin(skin.Value); } } // blendshape if (primitives.targets != null && primitives.targets.Count > 0) { for (var i = 0; i < primitives.targets.Count; ++i) { var primTarget = primitives.targets[i]; var blendShape = GetOrCreateBlendShape(i); if (primTarget.POSITION != -1) { var array = data.GetArrayFromAccessor <Vector3>(primTarget.POSITION); if (array.Length != positions.Length) { throw new Exception("different length"); } blendShape.Positions.AddRange(array.Select(inverter.InvertVector3).ToArray()); } if (primTarget.NORMAL != -1) { var array = data.GetArrayFromAccessor <Vector3>(primTarget.NORMAL); if (array.Length != positions.Length) { throw new Exception("different length"); } blendShape.Normals.AddRange(array.Select(inverter.InvertVector3).ToArray()); } if (primTarget.TANGENT != -1) { var array = data.GetArrayFromAccessor <Vector3>(primTarget.TANGENT); if (array.Length != positions.Length) { throw new Exception("different length"); } blendShape.Tangents.AddRange(array.Select(inverter.InvertVector3).ToArray()); } } } if (indexBufferCount >= 0) { var indexOffset = _currentIndexCount; var dataIndices = data.GetIndicesFromAccessorIndex(indexBufferCount); PushIndices(dataIndices, vertexOffset); _subMeshes.Add(new SubMeshDescriptor(indexOffset, dataIndices.Count)); } else { var indexOffset = _currentIndexCount; for (int i = 0; i < positions.Count(); i += 3) { // flip triangle AddIndex(i + vertexOffset + 2); AddIndex(i + vertexOffset + 1); AddIndex(i + vertexOffset); } _subMeshes.Add(new SubMeshDescriptor(indexOffset, positions.Count())); } // material _materialIndices.Add(primitives.material); } }