Пример #1
0
        public VRMExporter(ExportingGltfData data, GltfExportSettings exportSettings) : base(data, exportSettings)
        {
            if (exportSettings == null || exportSettings.InverseAxis != Vrm0xSpecificationInverseAxis)
            {
                throw new Exception($"VRM specification requires InverseAxis settings as {Vrm0xSpecificationInverseAxis}");
            }

            _gltf.extensionsUsed.Add(glTF_VRM_extensions.ExtensionName);
        }
Пример #2
0
 public static ExportingGltfData Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer)
 {
     var data = new ExportingGltfData();
     using (var exporter = new VRMExporter(data, configuration))
     {
         exporter.Prepare(go);
         exporter.Export(textureSerializer);
     }
     return data;
 }
Пример #3
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="data"></param>
        /// <param name="gltfMesh"></param>
        /// <param name="option"></param>
        static IEnumerable <glTFPrimitives> ExportMeshDivided(this VrmLib.Mesh mesh, List <object> materials,
                                                              ExportingGltfData writer, ExportArgs option)
        {
            var             usedIndices   = new List <int>();
            var             meshIndices   = 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.GetSubArray(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.PushVertex(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.PushBoneWeight(boneWeight);
                        }
                    }
                }
                var materialIndex = submesh.Material;
                var gltfPrimitive = buffer.ToGltfPrimitive(writer, materialIndex, indices);

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

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

                    gltfPrimitive.targets.Add(blendShape.ToGltf(writer, !option.removeMorphNormal, option.sparse));
                }

                yield return(gltfPrimitive);
            }
        }
Пример #4
0
        /// <summary>
        /// ModelExporter.Export で作られた Model.MeshGroups[*] を GLTF 化する
        /// </summary>
        /// <param name="src"></param>
        /// <param name="materials"></param>
        /// <param name="data"></param>
        /// <param name="option"></param>
        /// <returns></returns>
        public static glTFMesh ExportMeshGroup(this MeshGroup src, List <object> materials, ExportingGltfData writer, ExportArgs option)
        {
            var gltfMesh = new glTFMesh
            {
                name = src.Name
            };

            if (src.Meshes.Count != 1)
            {
                throw new NotImplementedException();
            }

            foreach (var prim in src.Meshes[0].ExportMeshDivided(materials, writer, option))
            {
                gltfMesh.primitives.Add(prim);
            }

            var targetNames = src.Meshes[0].MorphTargets.Select(x => x.Name).ToArray();

            gltf_mesh_extras_targetNames.Serialize(gltfMesh, targetNames);

            return(gltfMesh);
        }
Пример #5
0
        public static IEnumerable <(glTFNode, glTFSkin)> ExportNodes(INativeArrayManager arrayManager, List <Node> nodes, List <MeshGroup> groups, ExportingGltfData data, ExportArgs option)
        {
            foreach (var node in nodes)
            {
                var gltfNode = new glTFNode
                {
                    name = node.Name,
                };
                glTFSkin gltfSkin = default;

                gltfNode.translation = node.LocalTranslation.ToFloat3();
                gltfNode.rotation    = node.LocalRotation.ToFloat4();
                gltfNode.scale       = node.LocalScaling.ToFloat3();

                if (node.MeshGroup != null)
                {
                    gltfNode.mesh = groups.IndexOfThrow(node.MeshGroup);
                    var skin = node.MeshGroup.Skin;
                    if (skin != null)
                    {
                        gltfSkin = new glTFSkin()
                        {
                            joints = skin.Joints.Select(joint => nodes.IndexOfThrow(joint)).ToArray()
                        };
                        if (skin.InverseMatrices == null)
                        {
                            skin.CalcInverseMatrices(arrayManager);
                        }
                        if (skin.InverseMatrices != null)
                        {
                            gltfSkin.inverseBindMatrices = skin.InverseMatrices.AddAccessorTo(data, 0, option.sparse);
                        }
                        if (skin.Root != null)
                        {
                            gltfSkin.skeleton = nodes.IndexOf(skin.Root);
                        }
                    }
                }

                gltfNode.children = node.Children.Select(child => nodes.IndexOfThrow(child)).ToArray();

                yield return(gltfNode, gltfSkin);
            }
        }
Пример #6
0
 public static IEnumerable <glTFMesh> ExportMeshes(List <MeshGroup> groups, List <object> materials, ExportingGltfData data, ExportArgs option)
 {
     foreach (var group in groups)
     {
         yield return(group.ExportMeshGroup(materials, data, option));
     }
 }