static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex, Mesh mesh, int j, bool useSparseAccessorForMorphTarget) { var blendShapeVertices = mesh.vertices; var usePosition = blendShapeVertices != null && blendShapeVertices.Length > 0; var blendShapeNormals = mesh.normals; var useNormal = usePosition && blendShapeNormals != null && blendShapeNormals.Length == blendShapeVertices.Length; var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray(); //var useTangent = usePosition && blendShapeTangents != null && blendShapeTangents.Length == blendShapeVertices.Length; var useTangent = false; var frameCount = mesh.GetBlendShapeFrameCount(j); mesh.GetBlendShapeFrameVertices(j, frameCount - 1, blendShapeVertices, blendShapeNormals, null); var blendShapePositionAccessorIndex = -1; var blendShapeNormalAccessorIndex = -1; var blendShapeTangentAccessorIndex = -1; if (useSparseAccessorForMorphTarget) { var accessorCount = blendShapeVertices.Length; var sparseIndices = Enumerable.Range(0, blendShapeVertices.Length) .Where(x => UseSparse( usePosition, blendShapeVertices[x], useNormal, blendShapeNormals[x], useTangent, blendShapeTangents[x])) .ToArray() ; if (sparseIndices.Length == 0) { usePosition = false; useNormal = false; useTangent = false; } else { Debug.LogFormat("Sparse {0}/{1}", sparseIndices.Length, mesh.vertexCount); } /* * var vertexSize = 12; * if (useNormal) vertexSize += 12; * if (useTangent) vertexSize += 24; * var sparseBytes = (4 + vertexSize) * sparseIndices.Length; * var fullBytes = (vertexSize) * blendShapeVertices.Length; * Debug.LogFormat("Export sparse: {0}/{1}bytes({2}%)", * sparseBytes, fullBytes, (int)((float)sparseBytes / fullBytes) * ); */ var sparseIndicesViewIndex = -1; if (usePosition) { sparseIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(bufferIndex, sparseIndices); blendShapeVertices = sparseIndices.Select(x => blendShapeVertices[x].ReverseZ()).ToArray(); blendShapePositionAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount, blendShapeVertices, sparseIndices, sparseIndicesViewIndex, glBufferTarget.ARRAY_BUFFER); } if (useNormal) { blendShapeNormals = sparseIndices.Select(x => blendShapeNormals[x].ReverseZ()).ToArray(); blendShapeNormalAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount, blendShapeNormals, sparseIndices, sparseIndicesViewIndex, glBufferTarget.ARRAY_BUFFER); } if (useTangent) { blendShapeTangents = sparseIndices.Select(x => blendShapeTangents[x].ReverseZ()).ToArray(); blendShapeTangentAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount, blendShapeTangents, sparseIndices, sparseIndicesViewIndex, glBufferTarget.ARRAY_BUFFER); } } else { for (int i = 0; i < blendShapeVertices.Length; ++i) { blendShapeVertices[i] = blendShapeVertices[i].ReverseZ(); } if (usePosition) { blendShapePositionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, blendShapeVertices, glBufferTarget.ARRAY_BUFFER); } if (useNormal) { for (int i = 0; i < blendShapeNormals.Length; ++i) { blendShapeNormals[i] = blendShapeNormals[i].ReverseZ(); } blendShapeNormalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, blendShapeNormals, glBufferTarget.ARRAY_BUFFER); } if (useTangent) { for (int i = 0; i < blendShapeTangents.Length; ++i) { blendShapeTangents[i] = blendShapeTangents[i].ReverseZ(); } blendShapeTangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, blendShapeTangents, glBufferTarget.ARRAY_BUFFER); } } if (blendShapePositionAccessorIndex != -1) { gltf.accessors[blendShapePositionAccessorIndex].min = blendShapeVertices.Aggregate(blendShapeVertices[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[blendShapePositionAccessorIndex].max = blendShapeVertices.Aggregate(blendShapeVertices[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); } return(new gltfMorphTarget { POSITION = blendShapePositionAccessorIndex, NORMAL = blendShapeNormalAccessorIndex, TANGENT = blendShapeTangentAccessorIndex, }); }
public static gltfMorphTarget Export(glTF gltf, int gltfBuffer, Vector3[] positions, Vector3[] normals, bool useSparse) { var accessorCount = positions.Length; if (normals != null && positions.Length != normals.Length) { throw new Exception(); } int[] sparseIndices = default; if (useSparse) { sparseIndices = Enumerable.Range(0, positions.Length).Where(x => positions[x] != Vector3.zero).ToArray(); if (sparseIndices.Length == 0) { // sparse 対象がすべて [0, 0, 0] の場合 // new glTFSparse // { // count = 0, // } // のようになる。 // たぶん、仕様的にはあり。 // 解釈できない場合あり。 useSparse = false; } } if (useSparse) { if (sparseIndices == null) { throw new Exception(); } // positions var positionAccessorIndex = -1; if (sparseIndices.Length > 0) { var sparseIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(gltfBuffer, sparseIndices); positionAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(gltfBuffer, accessorCount, sparseIndices.Select(x => positions[x]).ToArray(), sparseIndices, sparseIndicesViewIndex, glBufferTarget.NONE); } // normals var normalAccessorIndex = -1; if (normals != null) { var sparseNormalIndices = Enumerable.Range(0, positions.Length).Where(x => normals[x] != Vector3.zero).ToArray(); if (sparseNormalIndices.Length > 0) { var sparseNormalIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(gltfBuffer, sparseNormalIndices); normalAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(gltfBuffer, accessorCount, sparseNormalIndices.Select(x => normals[x]).ToArray(), sparseNormalIndices, sparseNormalIndicesViewIndex, glBufferTarget.NONE); } } return(new gltfMorphTarget { POSITION = positionAccessorIndex, NORMAL = normalAccessorIndex, }); } else { // position var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, positions, glBufferTarget.ARRAY_BUFFER); gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); // normal var normalAccessorIndex = -1; if (normals != null) { normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, normals, glBufferTarget.ARRAY_BUFFER); } return(new gltfMorphTarget { POSITION = positionAccessorIndex, NORMAL = normalAccessorIndex, }); } }