Exemplo n.º 1
0
        public static glTF Export(GameObject go, string path = null, Action <glTF_VRM> callback = null)
        {
            var gltf = new glTF_VRM();

            gltf.asset.generator = string.Format("UniVRM-{0}.{1}", VRMVersion.MAJOR, VRMVersion.MINOR);
            using (var exporter = new VRMExporter(gltf)
            {
#if VRM_EXPORTER_USE_SPARSE
                // experimental
                UseSparseAccessorForBlendShape = true
#endif
            })
            {
                _Export(gltf, exporter, go);

                if (callback != null)
                {
                    callback(gltf);
                }

                if (!string.IsNullOrEmpty(path))
                {
                    exporter.WriteTo(path);
                }
            }

            return(gltf);
        }
Exemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="settings"></param>
        /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param>
        static void Export(string path, VRMExportSettings settings, List <GameObject> destroy)
        {
            var target = settings.Source;

            // 常にコピーする。シーンを変化させない
            target = GameObject.Instantiate(target);
            destroy.Add(target);

            // 正規化
            if (settings.PoseFreeze)
            {
                // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用
                target = BoneNormalizer.Execute(target, settings.ForceTPose, false);
                destroy.Add(target);
            }

            // 元のBlendShapeClipに変更を加えないように複製
            var proxy = target.GetComponent <VRMBlendShapeProxy>();
            var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip);

            proxy.BlendShapeAvatar = copyBlendShapeAvatar;

            // BlendShape削減
            if (settings.ReduceBlendshape)
            {
                foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>())
                {
                    // 未使用のBlendShapeを間引く
                    ReplaceMesh(target, smr, copyBlendShapeAvatar);
                }
            }

            // 出力
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var vrm = VRMExporter.Export(target, new VRMExporterConfiguration
                {
                    UseSparseAccessorForBlendShape = settings.UseSparseAccessor,
                    ExportOnlyBlendShapePosition   = settings.OnlyBlendshapePosition,
                    RemoveVertexColor = settings.RemoveVertexColor
                });
                vrm.extensions.VRM.meta.title              = settings.Title;
                vrm.extensions.VRM.meta.version            = settings.Version;
                vrm.extensions.VRM.meta.author             = settings.Author;
                vrm.extensions.VRM.meta.contactInformation = settings.ContactInformation;
                vrm.extensions.VRM.meta.reference          = settings.Reference;

                var bytes = vrm.ToGlbBytes(settings.UseExperimentalExporter ? SerializerTypes.Generated : SerializerTypes.UniJSON);
                File.WriteAllBytes(path, bytes);
                Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
            }

            if (path.StartsWithUnityAssetPath())
            {
                // 出力ファイルのインポートを発動
                AssetDatabase.ImportAsset(path.ToUnityRelativePath());
            }
        }
Exemplo n.º 3
0
        public void ImportExportTest()
        {
            var path    = UniGLTF.UnityPath.FromUnityPath("Models/Alicia_vrm-0.40/AliciaSolid_vrm-0.40.vrm");
            var context = new VRMImporterContext(path);

            context.ParseGlb(File.ReadAllBytes(path.FullPath));
            VRMImporter.LoadFromBytes(context);

            using (new ActionDisposer(() => { GameObject.DestroyImmediate(context.Root); }))
            {
                var importJson = JsonParser.Parse(context.Json);
                importJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION);
                importJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION);
                importJson.SetValue("/scene", 0);
                importJson.SetValue("/materials/*/doubleSided", false);
                //importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0);
                //importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 });
                importJson.SetValue("/accessors/*/normalized", false);
                importJson.RemoveValue("/nodes/*/extras");
                importJson.SetValue("/bufferViews/12/byteStride", 4);
                importJson.SetValue("/bufferViews/13/byteStride", 4);
                importJson.SetValue("/bufferViews/14/byteStride", 4);
                importJson.SetValue("/bufferViews/15/byteStride", 4);
                importJson.SetValue("/bufferViews/22/byteStride", 4);
                importJson.SetValue("/bufferViews/29/byteStride", 4);
                importJson.SetValue("/bufferViews/45/byteStride", 4);
                importJson.SetValue("/bufferViews/46/byteStride", 4);
                importJson.SetValue("/bufferViews/47/byteStride", 4);
                importJson.SetValue("/bufferViews/201/byteStride", 4);
                importJson.SetValue("/bufferViews/202/byteStride", 4);
                importJson.SetValue("/bufferViews/203/byteStride", 4);
                importJson.SetValue("/bufferViews/204/byteStride", 4);
                importJson.SetValue("/bufferViews/211/byteStride", 4);
                importJson.SetValue("/bufferViews/212/byteStride", 4);
                importJson.SetValue("/bufferViews/213/byteStride", 4);
                importJson.SetValue("/bufferViews/214/byteStride", 4);
                importJson.SetValue("/bufferViews/215/byteStride", 4);
                importJson.SetValue("/bufferViews/243/byteStride", 4);
                importJson.SetValue("/bufferViews/247/byteStride", 64);
                importJson.SetValue("/bufferViews/248/byteStride", 64);
                importJson.SetValue("/bufferViews/249/byteStride", 64);
                importJson.SetValue("/bufferViews/250/byteStride", 64);
                importJson.SetValue("/bufferViews/251/byteStride", 64);
                importJson.SetValue("/bufferViews/252/byteStride", 64);
                importJson.SetValue("/bufferViews/253/byteStride", 64);

                var vrm        = VRMExporter.Export(context.Root);
                var exportJson = JsonParser.Parse(vrm.ToJson());

                foreach (var kv in importJson.Diff(exportJson))
                {
                    Debug.Log(kv);
                }

                Assert.AreEqual(importJson, exportJson);
            }
        }
Exemplo n.º 4
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;
 }
Exemplo n.º 5
0
        public static glTF Export(MeshExportSettings configuration, GameObject go, Func <Texture, bool> useAsset, GetBytesWithMimeFromTexture2D getTextureBytes)
        {
            var gltf = new glTF();

            using (var exporter = new VRMExporter(gltf))
            {
                exporter.Prepare(go);
                exporter.Export(configuration, useAsset, getTextureBytes);
            }
            return(gltf);
        }
Exemplo n.º 6
0
        public static glTF Export(MeshExportSettings configuration, GameObject go, Func <Texture, bool> useAsset)
        {
            var gltf = new glTF();

            using (var exporter = new VRMExporter(gltf))
            {
                exporter.Prepare(go);
                exporter.Export(configuration, useAsset);
            }
            return(gltf);
        }
Exemplo n.º 7
0
        public static glTF Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer)
        {
            var gltf = new glTF();

            using (var exporter = new VRMExporter(gltf))
            {
                exporter.Prepare(go);
                exporter.Export(configuration, textureSerializer);
            }
            return(gltf);
        }
Exemplo n.º 8
0
        public static glTF Export(MeshExportSettings configuration, GameObject go)
        {
            var gltf = new glTF();

            using (var exporter = new VRMExporter(gltf))
            {
                exporter.Prepare(go);
                exporter.Export(configuration);
            }
            return(gltf);
        }
Exemplo n.º 9
0
        public new static glTF Export(GameObject go)
        {
            var gltf = new glTF();
            using (var exporter = new VRMExporter(gltf)
            {
#if VRM_EXPORTER_USE_SPARSE
                // experimental
                UseSparseAccessorForBlendShape=true
#endif
            })
            {
                _Export(gltf, exporter, go);
            }
            return gltf;
        }
Exemplo n.º 10
0
        public static glTF Export(GameObject go, VRMExporterConfiguration configuration)
        {
            var gltf = new glTF();

            using (var exporter = new VRMExporter(gltf)
            {
                UseSparseAccessorForBlendShape = configuration.UseSparseAccessorForBlendShape,
                ExportOnlyBlendShapePosition = configuration.ExportOnlyBlendShapePosition,
                RemoveVertexColor = configuration.RemoveVertexColor,
            })
            {
                _Export(gltf, exporter, go);
            }

            return(gltf);
        }
Exemplo n.º 11
0
        void OnWizardCreate()
        {
            // save dialog
            Debug.LogFormat("OnWizardCreate: {0}", Dir);
            var path = EditorUtility.SaveFilePanel(
                "Save vrm",
                Dir,
                Target.name + EXTENSION,
                EXTENSION.Substring(1));

            if (string.IsNullOrEmpty(path))
            {
                return;
            }
            Dir = Path.GetDirectoryName(path);

            // export
            var target = Target.gameObject;

            if (PoseFreeze)
            {
                Undo.RecordObjects(Target.transform.Traverse().ToArray(), "before normalize");
                var map = new Dictionary <Transform, Transform>();
                target = VRM.BoneNormalizer.Execute(Target.gameObject, map, ForceTPose);
                VRMHumanoidNorimalizerMenu.CopyVRMComponents(Target.gameObject, target, map);
                Undo.PerformUndo();
            }

            var sw = System.Diagnostics.Stopwatch.StartNew();

            VRMExporter.Export(target, path, gltf => {
                gltf.extensions.VRM.meta.title  = Title;
                gltf.extensions.VRM.meta.author = Author;
            });

            Debug.LogFormat("Export elapsed {0}", sw.Elapsed);

            if (Target.gameObject != target)
            {
                GameObject.DestroyImmediate(target);
            }

            if (path.StartsWithUnityAssetPath())
            {
                AssetDatabase.ImportAsset(path.ToUnityRelativePath());
            }
        }
Exemplo n.º 12
0
        public void ExportDividedMeshTest()
        {
            var path   = AliciaPath;
            var loaded = Load(File.ReadAllBytes(path), path);

            var exported = VRMExporter.Export(new UniGLTF.MeshExportSettings
            {
                DivideVertexBuffer           = true, // test this
                ExportOnlyBlendShapePosition = true,
                ExportTangents = false,
                UseSparseAccessorForMorphTarget = true,
            }, loaded, new EditorTextureSerializer());
            var bytes   = exported.ToGlbBytes();
            var divided = Load(bytes, path);

            var src = GetMeshes(loaded).ToArray();
            var div = GetMeshes(divided).ToArray();

            Assert.AreEqual(src[0].triangles.Length, div[0].triangles.Length);
        }
Exemplo n.º 13
0
        public static glTF Export(GameObject go, string path = null, Action <glTF_VRM> callback = null)
        {
            var gltf = new glTF_VRM();

            gltf.asset.generator = string.Format("UniVRM-{0}.{1}", VRMVersion.MAJOR, VRMVersion.MINOR);
            using (var exporter = new VRMExporter(gltf))
            {
                _Export(gltf, exporter, go);

                if (callback != null)
                {
                    callback(gltf);
                }

                if (!string.IsNullOrEmpty(path))
                {
                    exporter.WriteTo(path);
                }
            }
            return(gltf);
        }
Exemplo n.º 14
0
        void Export(string path, List <GameObject> destroy)
        {
            var target = Source;

            if (IsPrefab(target))
            {
                using (new RecordDisposer(Source.transform.Traverse().ToArray(), "before normalize"))
                {
                    target = GameObject.Instantiate(target);
                    destroy.Add(target);
                }
            }
            if (PoseFreeze)
            {
                using (new RecordDisposer(target.transform.Traverse().ToArray(), "before normalize"))
                {
                    var normalized = BoneNormalizer.Execute(target, ForceTPose, false);
                    CopyVRMComponents(target, normalized.Root, normalized.BoneMap);
                    target = normalized.Root;
                    destroy.Add(target);
                }
            }

            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var vrm = VRMExporter.Export(target);
                vrm.extensions.VRM.meta.title  = Title;
                vrm.extensions.VRM.meta.author = Author;

                var bytes = vrm.ToGlbBytes();
                File.WriteAllBytes(path, bytes);
                Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
            }

            if (path.StartsWithUnityAssetPath())
            {
                AssetDatabase.ImportAsset(path.ToUnityRelativePath());
            }
        }
Exemplo n.º 15
0
        public void VrmTestModelsTests()
        {
            var env = System.Environment.GetEnvironmentVariable("VRM_TEST_MODELS");

            if (string.IsNullOrEmpty(env))
            {
                return;
            }
            var root = new DirectoryInfo(env);

            if (!root.Exists)
            {
                return;
            }

            foreach (var gltf in EnumerateGltfFiles(root))
            {
                // import
                var go = Load(gltf, root);
                try
                {
                    // export
                    var vrm = VRMExporter.Export(new UniGLTF.GltfExportSettings(), go, new EditorTextureSerializer());

                    // re import
                    if (vrm != null)
                    {
                        Load(gltf, root, vrm.ToGlbBytes());
                    }
                }
                finally
                {
                    GameObject.DestroyImmediate(go);
                }
            }
        }
Exemplo n.º 16
0
        void Export(string path, List <GameObject> destroy)
        {
            var target = Source;

            if (IsPrefab(target))
            {
                using (new RecordDisposer(Source.transform.Traverse().ToArray(), "before normalize"))
                {
                    target = GameObject.Instantiate(target);
                    destroy.Add(target);
                }
            }

            if (PoseFreeze)
            {
                using (new RecordDisposer(target.transform.Traverse().ToArray(), "before normalize"))
                {
                    var normalized = BoneNormalizer.Execute(target, ForceTPose, false);
                    CopyVRMComponents(target, normalized.Root, normalized.BoneMap);
                    target = normalized.Root;
                    destroy.Add(target);
                }
            }

            // remove unused blendShape
            if (ReduceBlendshapeSize)
            {
                var proxy = target.GetComponent <VRMBlendShapeProxy>();

                // 元のBlendShapeClipに変更を加えないように複製
                var copyBlendShapeAvatar = GameObject.Instantiate(proxy.BlendShapeAvatar);
                var copyBlendShapClips   = new List <BlendShapeClip>();

                foreach (var clip in proxy.BlendShapeAvatar.Clips)
                {
                    copyBlendShapClips.Add(GameObject.Instantiate(clip));
                }

                var skinnedMeshRenderers = target.GetComponentsInChildren <SkinnedMeshRenderer>();

                var names = new Dictionary <int, string>();
                var vs    = new Dictionary <int, Vector3[]>();
                var ns    = new Dictionary <int, Vector3[]>();
                var ts    = new Dictionary <int, Vector3[]>();

                foreach (SkinnedMeshRenderer smr in skinnedMeshRenderers)
                {
                    Mesh mesh = smr.sharedMesh;
                    if (mesh == null)
                    {
                        continue;
                    }
                    if (mesh.blendShapeCount == 0)
                    {
                        continue;
                    }

                    var copyMesh = mesh.Copy(true);
                    var vCount   = copyMesh.vertexCount;
                    names.Clear();

                    vs.Clear();
                    ns.Clear();
                    ts.Clear();

                    var usedBlendshapeIndexArray = copyBlendShapClips
                                                   .SelectMany(clip => clip.Values)
                                                   .Where(val => target.transform.Find(val.RelativePath) == smr.transform)
                                                   .Select(val => val.Index)
                                                   .Distinct()
                                                   .ToArray();

                    foreach (var i in usedBlendshapeIndexArray)
                    {
                        var name     = copyMesh.GetBlendShapeName(i);
                        var vertices = new Vector3[vCount];
                        var normals  = new Vector3[vCount];
                        var tangents = new Vector3[vCount];
                        copyMesh.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents);

                        names.Add(i, name);
                        vs.Add(i, vertices);
                        ns.Add(i, normals);
                        ts.Add(i, tangents);
                    }

                    copyMesh.ClearBlendShapes();

                    foreach (var i in usedBlendshapeIndexArray)
                    {
                        copyMesh.AddBlendShapeFrame(names[i], 100f, vs[i], ns[i], ts[i]);
                    }

                    var indexMapper = usedBlendshapeIndexArray
                                      .Select((x, i) => new { x, i })
                                      .ToDictionary(pair => pair.x, pair => pair.i);

                    foreach (var clip in copyBlendShapClips)
                    {
                        for (var i = 0; i < clip.Values.Length; ++i)
                        {
                            var value = clip.Values[i];
                            if (target.transform.Find(value.RelativePath) != smr.transform)
                            {
                                continue;
                            }
                            value.Index    = indexMapper[value.Index];
                            clip.Values[i] = value;
                        }
                    }

                    copyBlendShapeAvatar.Clips = copyBlendShapClips;

                    proxy.BlendShapeAvatar = copyBlendShapeAvatar;

                    smr.sharedMesh = copyMesh;
                }
            }

            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var vrm = VRMExporter.Export(target, ReduceBlendshapeSize);
                vrm.extensions.VRM.meta.title              = Title;
                vrm.extensions.VRM.meta.version            = Version;
                vrm.extensions.VRM.meta.author             = Author;
                vrm.extensions.VRM.meta.contactInformation = ContactInformation;
                vrm.extensions.VRM.meta.reference          = Reference;


                var bytes = vrm.ToGlbBytes(UseExperimentalExporter?SerializerTypes.Generated:SerializerTypes.UniJSON);
                File.WriteAllBytes(path, bytes);
                Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
            }
            if (IsPrefab(Source))
            {
#if UNITY_2018_3_OR_NEWER
                PrefabUtility.RevertPrefabInstance(Source, InteractionMode.AutomatedAction);
#else
                PrefabUtility.RevertPrefabInstance(target);
#endif
            }

            if (path.StartsWithUnityAssetPath())
            {
                AssetDatabase.ImportAsset(path.ToUnityRelativePath());
            }
        }
Exemplo n.º 17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="settings"></param>
        /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param>
        static byte[] Export(GameObject exportRoot, VRMMetaObject meta,
                             VRMExportSettings settings,
                             List <GameObject> destroy)
        {
            var target = exportRoot;

            // 常にコピーする。シーンを変化させない
            target = GameObject.Instantiate(target);
            destroy.Add(target);

            var metaBehaviour = target.GetComponent <VRMMeta>();

            if (metaBehaviour == null)
            {
                metaBehaviour      = target.AddComponent <VRMMeta>();
                metaBehaviour.Meta = meta;
            }
            if (metaBehaviour.Meta == null)
            {
                // 来ないはず
                throw new Exception("meta required");
            }

            {
                // copy元
                var animator         = exportRoot.GetComponent <Animator>();
                var beforeTransforms = exportRoot.GetComponentsInChildren <Transform>();
                // copy先
                var afterTransforms = target.GetComponentsInChildren <Transform>();
                // copy先のhumanoidBoneのリストを得る
                var bones           = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones));
                var humanTransforms = bones
                                      .Where(x => x != HumanBodyBones.LastBone)
                                      .Select(x => animator.GetBoneTransform(x))
                                      .Where(x => x != null)
                                      .Select(x => afterTransforms[Array.IndexOf(beforeTransforms, x)]) // copy 先を得る
                                      .ToArray();

                var nameCount = target.GetComponentsInChildren <Transform>()
                                .GroupBy(x => x.name)
                                .ToDictionary(x => x.Key, x => x.Count());
                foreach (var t in target.GetComponentsInChildren <Transform>())
                {
                    if (humanTransforms.Contains(t))
                    {
                        // keep original name
                        continue;
                    }

                    if (nameCount[t.name] > 1)
                    {
                        // 重複するボーン名をリネームする
                        ForceUniqueName(t, nameCount);
                    }
                }
            }

            // 正規化
            if (settings.PoseFreeze)
            {
                // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用
                target = VRMBoneNormalizer.Execute(target, settings.ForceTPose);
                destroy.Add(target);
            }

            var fp = target.GetComponent <VRMFirstPerson>();

            // 元のBlendShapeClipに変更を加えないように複製
            var proxy = target.GetComponent <VRMBlendShapeProxy>();

            if (proxy != null)
            {
                var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip);
                proxy.BlendShapeAvatar = copyBlendShapeAvatar;

                // BlendShape削減
                if (settings.ReduceBlendshape)
                {
                    foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>())
                    {
                        // 未使用のBlendShapeを間引く
                        ReplaceMesh(target, smr, copyBlendShapeAvatar);
                    }
                }
            }

            // 出力
            var sw   = System.Diagnostics.Stopwatch.StartNew();
            var data = new UniGLTF.ExportingGltfData();
            var gltfExportSettings = settings.GltfExportSettings;

            using (var exporter = new VRMExporter(data, gltfExportSettings,
                                                  settings.KeepAnimation ? new EditorAnimationExporter() : null))
            {
                exporter.Prepare(target);
                exporter.Export(new EditorTextureSerializer());
            }
            var bytes = data.ToGlbBytes();

            Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
            return(bytes);
        }
Exemplo n.º 18
0
        public static void _Export(glTF_VRM gltf, VRMExporter exporter, GameObject go)
        {
            exporter.Prepare(go);
            exporter.Export();

            // avatar
            var animator = go.GetComponent <Animator>();

            if (animator != null)
            {
                var humanoid = go.GetComponent <VRMHumanoidDescription>();
                UniHumanoid.AvatarDescription description = null;
                var nodes = go.transform.Traverse().Skip(1).ToList();
                {
                    var isCreated = false;
                    if (humanoid != null)
                    {
                        description = humanoid.GetDescription(out isCreated);
                    }

                    if (description != null)
                    {
                        // use description
                        gltf.extensions.VRM.humanoid.Apply(description, nodes);
                    }
                    if (isCreated)
                    {
                        GameObject.DestroyImmediate(description);
                    }
                }

                {
                    // set humanoid bone mapping
                    var avatar = animator.avatar;
                    foreach (HumanBodyBones key in Enum.GetValues(typeof(HumanBodyBones)))
                    {
                        if (key == HumanBodyBones.LastBone)
                        {
                            break;
                        }

                        var transform = animator.GetBoneTransform(key);
                        if (transform != null)
                        {
                            gltf.extensions.VRM.humanoid.SetNodeIndex(key, nodes.IndexOf(transform));
                        }
                    }
                }
            }

            // morph
            var master = go.GetComponent <VRMBlendShapeProxy>();

            if (master != null)
            {
                var avatar = master.BlendShapeAvatar;
                if (avatar != null)
                {
                    var meshes = exporter.Meshes;
                    foreach (var x in avatar.Clips)
                    {
                        gltf.extensions.VRM.blendShapeMaster.Add(x, exporter.Copy.transform, meshes);
                    }
                }
            }

            // secondary
            var secondary = exporter.Copy.transform.Find("secondary");

            if (secondary == null)
            {
                secondary = exporter.Copy.transform;
            }

            var colliders = new List <VRMSpringBoneColliderGroup>();

            foreach (var vrmColliderGroup in exporter.Copy.transform.Traverse().Select(x => x.GetComponent <VRMSpringBoneColliderGroup>()).Where(x => x != null))
            {
                colliders.Add(vrmColliderGroup);

                var colliderGroup = new glTF_VRM_SecondaryAnimationColliderGroup
                {
                    node = exporter.Nodes.IndexOf(vrmColliderGroup.transform)
                };

                colliderGroup.colliders = vrmColliderGroup.Colliders.Select(x =>
                {
                    return(new glTF_VRM_SecondaryAnimationCollider
                    {
                        offset = x.Offset,
                        radius = x.Radius,
                    });
                }).ToList();

                gltf.extensions.VRM.secondaryAnimation.colliderGroups.Add(colliderGroup);
            }

            foreach (var spring in secondary.GetComponents <VRMSpringBone>())
            {
                gltf.extensions.VRM.secondaryAnimation.boneGroups.Add(new glTF_VRM_SecondaryAnimationGroup
                {
                    comment        = spring.m_comment,
                    center         = exporter.Nodes.IndexOf(spring.m_center),
                    dragForce      = spring.m_dragForce,
                    gravityDir     = spring.m_gravityDir,
                    gravityPower   = spring.m_gravityPower,
                    stiffiness     = spring.m_stiffnessForce,
                    hitRadius      = spring.m_hitRadius,
                    colliderGroups = spring.ColliderGroups
                                     .Select(x =>
                    {
                        var index = colliders.IndexOf(x);
                        if (index == -1)
                        {
                            throw new IndexOutOfRangeException();
                        }
                        return(index);
                    })
                                     .ToArray(),
                    bones = spring.RootBones.Select(x => exporter.Nodes.IndexOf(x)).ToArray(),
                });
            }

            // meta(obsolete)
            {
                var meta = exporter.Copy.GetComponent <VRMMetaInformation>();
                if (meta != null)
                {
                    gltf.extensions.VRM.meta.author             = meta.Author;
                    gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation;
                    gltf.extensions.VRM.meta.title = meta.Title;
                    if (meta.Thumbnail != null)
                    {
                        gltf.extensions.VRM.meta.texture = gltfExporter.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail);
                    }
                    gltf.extensions.VRM.meta.licenseType     = meta.LicenseType;
                    gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl;
                    gltf.extensions.VRM.meta.reference       = meta.Reference;
                }
            }
            // meta
            {
                var _meta = exporter.Copy.GetComponent <VRMMeta>();
                if (_meta != null && _meta.Meta != null)
                {
                    var meta = _meta.Meta;

                    // info
                    gltf.extensions.VRM.meta.version            = meta.Version;
                    gltf.extensions.VRM.meta.author             = meta.Author;
                    gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation;
                    gltf.extensions.VRM.meta.reference          = meta.Reference;
                    gltf.extensions.VRM.meta.title = meta.Title;
                    if (meta.Thumbnail != null)
                    {
                        gltf.extensions.VRM.meta.texture = gltfExporter.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail);
                    }

                    // ussage pemission
                    gltf.extensions.VRM.meta.allowedUser        = meta.AllowedUser;
                    gltf.extensions.VRM.meta.violentUssage      = meta.ViolentUssage;
                    gltf.extensions.VRM.meta.sexualUssage       = meta.SexualUssage;
                    gltf.extensions.VRM.meta.commercialUssage   = meta.CommercialUssage;
                    gltf.extensions.VRM.meta.otherPermissionUrl = meta.OtherPermissionUrl;

                    // distribution license
                    gltf.extensions.VRM.meta.licenseType = meta.LicenseType;
                    if (meta.LicenseType == LicenseType.Other)
                    {
                        gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl;
                    }
                }
            }

            // firstPerson
            var firstPerson = exporter.Copy.GetComponent <VRMFirstPerson>();

            if (firstPerson != null)
            {
                if (firstPerson.FirstPersonBone != null)
                {
                    gltf.extensions.VRM.firstPerson.firstPersonBone       = exporter.Nodes.IndexOf(firstPerson.FirstPersonBone);
                    gltf.extensions.VRM.firstPerson.firstPersonBoneOffset = firstPerson.FirstPersonOffset;
                    gltf.extensions.VRM.firstPerson.meshAnnotations       = firstPerson.Renderers.Select(x => new glTF_VRM_MeshAnnotation
                    {
                        mesh            = exporter.Meshes.IndexOf(x.SharedMesh),
                        firstPersonFlag = x.FirstPersonFlag.ToString(),
                    }).ToList();
                }

                // lookAt
                {
                    var lookAtHead = exporter.Copy.GetComponent <VRMLookAtHead>();
                    var lookAt     = exporter.Copy.GetComponent <VRMLookAt>();
                    if (lookAtHead != null)
                    {
                        var boneApplyer       = exporter.Copy.GetComponent <VRMLookAtBoneApplyer>();
                        var blendShapeApplyer = exporter.Copy.GetComponent <VRMLookAtBlendShapeApplyer>();
                        if (boneApplyer != null)
                        {
                            gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.Bone;
                            gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(boneApplyer.HorizontalInner);
                            gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(boneApplyer.HorizontalOuter);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(boneApplyer.VerticalDown);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(boneApplyer.VerticalUp);
                        }
                        else if (blendShapeApplyer != null)
                        {
                            gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.BlendShape;
                            gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(blendShapeApplyer.Horizontal);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(blendShapeApplyer.VerticalDown);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(blendShapeApplyer.VerticalUp);
                        }
                    }
                    else if (lookAt != null)
                    {
                        gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(lookAt.HorizontalInner);
                        gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(lookAt.HorizontalOuter);
                        gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(lookAt.VerticalDown);
                        gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(lookAt.VerticalUp);
                    }
                }
            }

            // materials
            foreach (var m in exporter.Materials)
            {
                gltf.extensions.VRM.materialProperties.Add(glTF_VRM_Material.CreateFromMaterial(m, exporter.Textures));
            }
        }
Exemplo n.º 19
0
        public static void _Export(glTF gltf, VRMExporter exporter, GameObject go)
        {
            exporter.Prepare(go);
            exporter.Export();

            // avatar
            var animator = go.GetComponent <Animator>();

            if (animator != null)
            {
                var humanoid = go.GetComponent <VRMHumanoidDescription>();
                UniHumanoid.AvatarDescription description = null;
                var nodes = go.transform.Traverse().Skip(1).ToList();
                {
                    var isCreated = false;
                    if (humanoid != null)
                    {
                        description = humanoid.GetDescription(out isCreated);
                    }

                    if (description != null)
                    {
                        // use description
                        gltf.extensions.VRM.humanoid.Apply(description, nodes);
                    }
                    if (isCreated)
                    {
                        GameObject.DestroyImmediate(description);
                    }
                }

                {
                    // set humanoid bone mapping
                    var avatar = animator.avatar;
                    foreach (HumanBodyBones key in Enum.GetValues(typeof(HumanBodyBones)))
                    {
                        if (key == HumanBodyBones.LastBone)
                        {
                            break;
                        }

                        var transform = animator.GetBoneTransform(key);
                        if (transform != null)
                        {
                            gltf.extensions.VRM.humanoid.SetNodeIndex(key, nodes.IndexOf(transform));
                        }
                    }
                }
            }

            // morph
            var master = go.GetComponent <VRMBlendShapeProxy>();

            if (master != null)
            {
                var avatar = master.BlendShapeAvatar;
                if (avatar != null)
                {
                    var meshes = exporter.Meshes;
                    foreach (var x in avatar.Clips)
                    {
                        gltf.extensions.VRM.blendShapeMaster.Add(x, exporter.Copy.transform, meshes);
                    }
                }
            }

            // secondary
            VRMSpringUtility.ExportSecondary(exporter.Copy.transform, exporter.Nodes,
                                             x => gltf.extensions.VRM.secondaryAnimation.colliderGroups.Add(x),
                                             x => gltf.extensions.VRM.secondaryAnimation.boneGroups.Add(x)
                                             );

            // meta(obsolete)
            {
                var meta = exporter.Copy.GetComponent <VRMMetaInformation>();
                if (meta != null)
                {
                    gltf.extensions.VRM.meta.author             = meta.Author;
                    gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation;
                    gltf.extensions.VRM.meta.title = meta.Title;
                    if (meta.Thumbnail != null)
                    {
                        gltf.extensions.VRM.meta.texture = TextureIO.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail, false);
                    }
                    gltf.extensions.VRM.meta.licenseType     = meta.LicenseType;
                    gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl;
                    gltf.extensions.VRM.meta.reference       = meta.Reference;
                }
            }
            // meta
            {
                var _meta = exporter.Copy.GetComponent <VRMMeta>();
                if (_meta != null && _meta.Meta != null)
                {
                    var meta = _meta.Meta;

                    // info
                    gltf.extensions.VRM.meta.version            = meta.Version;
                    gltf.extensions.VRM.meta.author             = meta.Author;
                    gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation;
                    gltf.extensions.VRM.meta.reference          = meta.Reference;
                    gltf.extensions.VRM.meta.title = meta.Title;
                    if (meta.Thumbnail != null)
                    {
                        gltf.extensions.VRM.meta.texture = TextureIO.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail, false);
                    }

                    // ussage pemission
                    gltf.extensions.VRM.meta.allowedUser        = meta.AllowedUser;
                    gltf.extensions.VRM.meta.violentUssage      = meta.ViolentUssage;
                    gltf.extensions.VRM.meta.sexualUssage       = meta.SexualUssage;
                    gltf.extensions.VRM.meta.commercialUssage   = meta.CommercialUssage;
                    gltf.extensions.VRM.meta.otherPermissionUrl = meta.OtherPermissionUrl;

                    // distribution license
                    gltf.extensions.VRM.meta.licenseType = meta.LicenseType;
                    if (meta.LicenseType == LicenseType.Other)
                    {
                        gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl;
                    }
                }
            }

            // firstPerson
            var firstPerson = exporter.Copy.GetComponent <VRMFirstPerson>();

            if (firstPerson != null)
            {
                if (firstPerson.FirstPersonBone != null)
                {
                    gltf.extensions.VRM.firstPerson.firstPersonBone       = exporter.Nodes.IndexOf(firstPerson.FirstPersonBone);
                    gltf.extensions.VRM.firstPerson.firstPersonBoneOffset = firstPerson.FirstPersonOffset;
                    gltf.extensions.VRM.firstPerson.meshAnnotations       = firstPerson.Renderers.Select(x => new glTF_VRM_MeshAnnotation
                    {
                        mesh            = exporter.Meshes.IndexOf(x.SharedMesh),
                        firstPersonFlag = x.FirstPersonFlag.ToString(),
                    }).ToList();
                }

                // lookAt
                {
                    var lookAtHead = exporter.Copy.GetComponent <VRMLookAtHead>();
                    var lookAt     = exporter.Copy.GetComponent <VRMLookAt>();
                    if (lookAtHead != null)
                    {
                        var boneApplyer       = exporter.Copy.GetComponent <VRMLookAtBoneApplyer>();
                        var blendShapeApplyer = exporter.Copy.GetComponent <VRMLookAtBlendShapeApplyer>();
                        if (boneApplyer != null)
                        {
                            gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.Bone;
                            gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(boneApplyer.HorizontalInner);
                            gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(boneApplyer.HorizontalOuter);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(boneApplyer.VerticalDown);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(boneApplyer.VerticalUp);
                        }
                        else if (blendShapeApplyer != null)
                        {
                            gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.BlendShape;
                            gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(blendShapeApplyer.Horizontal);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(blendShapeApplyer.VerticalDown);
                            gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(blendShapeApplyer.VerticalUp);
                        }
                    }
                    else if (lookAt != null)
                    {
                        gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(lookAt.HorizontalInner);
                        gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(lookAt.HorizontalOuter);
                        gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(lookAt.VerticalDown);
                        gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(lookAt.VerticalUp);
                    }
                }
            }

            // materials
            foreach (var m in exporter.Materials)
            {
                gltf.extensions.VRM.materialProperties.Add(glTF_VRM_Material.CreateFromMaterial(m, exporter.Textures));
            }
        }
Exemplo n.º 20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="settings"></param>
        /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param>
        static void Export(string path, GameObject exportRoot, VRMMetaObject meta,
                           VRMExportSettings settings, IReadOnlyList <MeshUtility.MeshExportInfo> info,
                           List <GameObject> destroy)
        {
            var target = exportRoot;

            // 常にコピーする。シーンを変化させない
            target = GameObject.Instantiate(target);
            destroy.Add(target);

            var metaBehaviour = target.GetComponent <VRMMeta>();

            if (metaBehaviour == null)
            {
                metaBehaviour      = target.AddComponent <VRMMeta>();
                metaBehaviour.Meta = meta;
            }
            if (metaBehaviour.Meta == null)
            {
                // 来ないはず
                throw new Exception("meta required");
            }

            {
                // copy元
                var animator         = exportRoot.GetComponent <Animator>();
                var beforeTransforms = exportRoot.GetComponentsInChildren <Transform>();
                // copy先
                var afterTransforms = target.GetComponentsInChildren <Transform>();
                // copy先のhumanoidBoneのリストを得る
                var bones           = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones));
                var humanTransforms = bones
                                      .Where(x => x != HumanBodyBones.LastBone)
                                      .Select(x => animator.GetBoneTransform(x))
                                      .Where(x => x != null)
                                      .Select(x => afterTransforms[Array.IndexOf(beforeTransforms, x)]) // copy 先を得る
                                      .ToArray();

                var nameCount = target.GetComponentsInChildren <Transform>()
                                .GroupBy(x => x.name)
                                .ToDictionary(x => x.Key, x => x.Count());
                foreach (var t in target.GetComponentsInChildren <Transform>())
                {
                    if (humanTransforms.Contains(t))
                    {
                        // keep original name
                        continue;
                    }

                    if (nameCount[t.name] > 1)
                    {
                        // 重複するボーン名をリネームする
                        ForceUniqueName(t, nameCount);
                    }
                }
            }

            // 正規化
            if (settings.PoseFreeze)
            {
                // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用
                target = VRMBoneNormalizer.Execute(target, settings.ForceTPose, false);
                destroy.Add(target);
            }

            // 元のBlendShapeClipに変更を加えないように複製
            var proxy = target.GetComponent <VRMBlendShapeProxy>();

            if (proxy != null)
            {
                var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip);
                proxy.BlendShapeAvatar = copyBlendShapeAvatar;

                // BlendShape削減
                if (settings.ReduceBlendshape)
                {
                    foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>())
                    {
                        // 未使用のBlendShapeを間引く
                        ReplaceMesh(target, smr, copyBlendShapeAvatar);
                    }
                }
            }

            // 出力
            var sw   = System.Diagnostics.Stopwatch.StartNew();
            var gltf = new UniGLTF.glTF();

            using (var exporter = new VRMExporter(gltf))
            {
                exporter.Prepare(target);
                exporter.Export(settings.MeshExportSettings);
            }
            var bytes = gltf.ToGlbBytes();

            File.WriteAllBytes(path, bytes);
            Debug.LogFormat("Export elapsed {0}", sw.Elapsed);

            if (path.StartsWithUnityAssetPath())
            {
                // 出力ファイルのインポートを発動
                AssetDatabase.ImportAsset(path.ToUnityRelativePath());
            }
        }
Exemplo n.º 21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="settings"></param>
        /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param>
        static void Export(string path, GameObject exportRoot, VRMExportSettings settings, List <GameObject> destroy)
        {
            var target = exportRoot;

            // 常にコピーする。シーンを変化させない
            target = GameObject.Instantiate(target);
            destroy.Add(target);

            {
                // copy元
                var animator         = exportRoot.GetComponent <Animator>();
                var beforeTransforms = exportRoot.GetComponentsInChildren <Transform>();
                // copy先
                var afterTransforms = target.GetComponentsInChildren <Transform>();
                // copy先のhumanoidBoneのリストを得る
                var bones           = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones));
                var humanTransforms = bones
                                      .Where(x => x != HumanBodyBones.LastBone)
                                      .Select(x => animator.GetBoneTransform(x))
                                      .Where(x => x != null)
                                      .Select(x => afterTransforms[Array.IndexOf(beforeTransforms, x)]) // copy 先を得る
                                      .ToArray();

                var nameCount = target.GetComponentsInChildren <Transform>()
                                .GroupBy(x => x.name)
                                .ToDictionary(x => x.Key, x => x.Count());
                foreach (var t in target.GetComponentsInChildren <Transform>())
                {
                    if (humanTransforms.Contains(t))
                    {
                        // keep original name
                        continue;
                    }

                    if (nameCount[t.name] > 1)
                    {
                        // 重複するボーン名をリネームする
                        ForceUniqueName(t, nameCount);
                    }
                }
            }

            // 正規化
            if (settings.PoseFreeze)
            {
                // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用
                target = VRMBoneNormalizer.Execute(target, settings.ForceTPose, false);
                destroy.Add(target);
            }

            // 元のBlendShapeClipに変更を加えないように複製
            var proxy = target.GetComponent <VRMBlendShapeProxy>();

            if (proxy != null)
            {
                var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip);
                proxy.BlendShapeAvatar = copyBlendShapeAvatar;

                // BlendShape削減
                if (settings.ReduceBlendshape)
                {
                    foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>())
                    {
                        // 未使用のBlendShapeを間引く
                        ReplaceMesh(target, smr, copyBlendShapeAvatar);
                    }
                }
            }

            // 出力
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var vrm = VRMExporter.Export(target, new VRMExporterConfiguration
                {
                    UseSparseAccessorForBlendShape = settings.UseSparseAccessor,
                    ExportOnlyBlendShapePosition   = settings.OnlyBlendshapePosition,
                    RemoveVertexColor = settings.RemoveVertexColor
                });
                // vrm.extensions.VRM.meta.title = settings.Title;
                // vrm.extensions.VRM.meta.version = settings.Version;
                // vrm.extensions.VRM.meta.author = settings.Author;
                // vrm.extensions.VRM.meta.contactInformation = settings.ContactInformation;
                // vrm.extensions.VRM.meta.reference = settings.Reference;

                var bytes = vrm.ToGlbBytes(settings.UseExperimentalExporter ? SerializerTypes.Generated : SerializerTypes.UniJSON);
                File.WriteAllBytes(path, bytes);
                Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
            }

            if (path.StartsWithUnityAssetPath())
            {
                // 出力ファイルのインポートを発動
                AssetDatabase.ImportAsset(path.ToUnityRelativePath());
            }
        }