Esempio n. 1
0
        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,
            });
        }
Esempio n. 2
0
        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,
                });
            }
        }