Ejemplo n.º 1
0
        private static VrmLib.BufferAccessor ToBufferAccessor <T>(T[] value, VrmLib.AccessorValueType valueType, VrmLib.AccessorVectorType vectorType) where T : struct
        {
            var span = SpanLike.CopyFrom(value);

            return(new VrmLib.BufferAccessor(
                       span.Bytes,
                       valueType,
                       vectorType,
                       value.Length
                       ));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// https://github.com/vrm-c/UniVRM/issues/800
        ///
        /// SubMesh 単位に分割する。
        /// SubMesh を Gltf の Primitive に対応させる。
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="materials"></param>
        /// <param name="storage"></param>
        /// <param name="gltfMesh"></param>
        /// <param name="option"></param>
        static IEnumerable <glTFPrimitives> ExportMeshDivided(this VrmLib.Mesh mesh, List <object> materials, Vrm10Storage storage, ExportArgs option)
        {
            var             bufferIndex   = 0;
            var             usedIndices   = new List <int>();
            var             meshIndices   = SpanLike.CopyFrom(mesh.IndexBuffer.GetAsIntArray());
            var             positions     = mesh.VertexBuffer.Positions.GetSpan <UnityEngine.Vector3>().ToArray();
            var             normals       = mesh.VertexBuffer.Normals.GetSpan <UnityEngine.Vector3>().ToArray();
            var             uv            = mesh.VertexBuffer.TexCoords.GetSpan <UnityEngine.Vector2>().ToArray();
            var             hasSkin       = mesh.VertexBuffer.Weights != null;
            var             weights       = mesh.VertexBuffer.Weights?.GetSpan <UnityEngine.Vector4>().ToArray();
            var             joints        = mesh.VertexBuffer.Joints?.GetSpan <SkinJoints>().ToArray();
            Func <int, int> getJointIndex = default;

            if (hasSkin)
            {
                getJointIndex = i =>
                {
                    return(i);
                };
            }

            foreach (var submesh in mesh.Submeshes)
            {
                var indices = meshIndices.Slice(submesh.Offset, submesh.DrawCount).ToArray();
                var hash    = new HashSet <int>(indices);

                // mesh
                // index の順に attributes を蓄える
                var buffer = new MeshExportUtil.VertexBuffer(indices.Length, getJointIndex);
                usedIndices.Clear();
                for (int k = 0; k < positions.Length; ++k)
                {
                    if (hash.Contains(k))
                    {
                        // indices から参照される頂点だけを蓄える
                        usedIndices.Add(k);
                        buffer.Push(k, positions[k], normals[k], uv[k]);
                        if (getJointIndex != null)
                        {
                            var j          = joints[k];
                            var w          = weights[k];
                            var boneWeight = new UnityEngine.BoneWeight
                            {
                                boneIndex0 = j.Joint0,
                                boneIndex1 = j.Joint1,
                                boneIndex2 = j.Joint2,
                                boneIndex3 = j.Joint3,
                                weight0    = w.x,
                                weight1    = w.y,
                                weight2    = w.z,
                                weight3    = w.w,
                            };
                            buffer.Push(boneWeight);
                        }
                    }
                }
                var materialIndex = submesh.Material;
                var gltfPrimitive = buffer.ToGltfPrimitive(storage.Gltf, bufferIndex, materialIndex, indices);

                // blendShape
                for (int j = 0; j < mesh.MorphTargets.Count; ++j)
                {
                    var blendShape = new MeshExportUtil.BlendShapeBuffer(indices.Length);

                    // index の順に attributes を蓄える
                    var morph = mesh.MorphTargets[j];
                    var blendShapePositions = morph.VertexBuffer.Positions.GetSpan <UnityEngine.Vector3>();
                    SpanLike <UnityEngine.Vector3>?blendShapeNormals = default;
                    if (morph.VertexBuffer.Normals != null)
                    {
                        blendShapeNormals = morph.VertexBuffer.Normals.GetSpan <UnityEngine.Vector3>();
                    }
                    foreach (var k in usedIndices)
                    {
                        blendShape.Push(
                            blendShapePositions[k],
                            blendShapeNormals.HasValue ? blendShapeNormals.Value[k] : UnityEngine.Vector3.zero
                            );
                    }

                    gltfPrimitive.targets.Add(blendShape.ToGltf(storage.Gltf, bufferIndex, !option.removeMorphNormal));
                }

                yield return(gltfPrimitive);
            }
        }