Beispiel #1
0
        /// <summary>
        /// metaObject が null のときは、root から取得する
        /// </summary>
        public VrmLib.Model ToModelFrom10(GameObject root, VRMMetaObject metaObject = null)
        {
            Model = new VrmLib.Model(VrmLib.Coordinates.Unity);

            if (metaObject is null)
            {
                var vrmMeta = root.GetComponent <VRMMeta>();
                if (vrmMeta is null || vrmMeta.Meta is null)
                {
                    throw new NullReferenceException("metaObject is null");
                }
                metaObject = vrmMeta.Meta;
            }

            ToGlbModel(root);

            // meta
            var meta = new VrmLib.Meta();

            meta.Name       = metaObject.Name;
            meta.Version    = metaObject.Version;
            meta.Copyrights = metaObject.Copyrights;
            meta.Authors.AddRange(metaObject.Authors);
            meta.ContactInformation = metaObject.ContactInformation;
            meta.Reference          = metaObject.Reference;
            meta.Thumbnail          = metaObject.Thumbnail.ToPngImage(VrmLib.ImageUsage.None);

            meta.AvatarPermission = new VrmLib.AvatarPermission
            {
                AvatarUsage           = metaObject.AllowedUser,
                IsAllowedViolentUsage = metaObject.ViolentUsage,
                IsAllowedSexualUsage  = metaObject.SexualUsage,
                CommercialUsage       = metaObject.CommercialUsage,
                IsAllowedGameUsage    = metaObject.GameUsage,
                IsAllowedPoliticalOrReligiousUsage = metaObject.PoliticalOrReligiousUsage,
                OtherPermissionUrl = metaObject.OtherPermissionUrl,
            };
            meta.RedistributionLicense = new VrmLib.RedistributionLicense
            {
                CreditNotation        = metaObject.CreditNotation,
                IsAllowRedistribution = metaObject.Redistribution,
                ModificationLicense   = metaObject.ModificationLicense,
                OtherLicenseUrl       = metaObject.OtherLicenseUrl,
            };
            Model.Vrm = new VrmLib.Vrm(meta, UniVRM10.VRMVersion.VERSION, UniVRM10.VRMSpecVersion.Version);

            // humanoid
            {
                var humanoid = root.GetComponent <Humanoid>();
                if (humanoid is null)
                {
                    humanoid = root.AddComponent <Humanoid>();
                    humanoid.AssignBonesFromAnimator();
                }

                foreach (HumanBodyBones humanBoneType in Enum.GetValues(typeof(HumanBodyBones)))
                {
                    var transform = humanoid.GetBoneTransform(humanBoneType);
                    if (transform != null && Nodes.TryGetValue(transform.gameObject, out VrmLib.Node node))
                    {
                        node.HumanoidBone = (VrmLib.HumanoidBones)Enum.Parse(typeof(VrmLib.HumanoidBones), humanBoneType.ToString(), true);
                    }
                }
            }


            // blendShape
            {
                Model.Vrm.BlendShape = new VrmLib.BlendShapeManager();
                var blendShapeProxy = root.GetComponent <UniVRM10.VRMController>();
                if (blendShapeProxy != null)
                {
                    foreach (var clip in blendShapeProxy.BlendShapeAvatar.Clips)
                    {
                        var blendShape = ToVrmLib(clip, root);
                        if (blendShape != null)
                        {
                            Model.Vrm.BlendShape.BlendShapeList.Add(blendShape);
                        }
                    }
                }
            }

            // firstPerson
            {
                var firstPerson          = new VrmLib.FirstPerson();
                var firstPersonComponent = root.GetComponent <UniVRM10.VRMFirstPerson>();
                if (firstPersonComponent != null)
                {
                    foreach (var annotation in firstPersonComponent.Renderers)
                    {
                        firstPerson.Annotations.Add(
                            new VrmLib.FirstPersonMeshAnnotation(Nodes[annotation.Renderer.gameObject],
                                                                 annotation.FirstPersonFlag)
                            );
                    }
                    Model.Vrm.FirstPerson = firstPerson;
                }
            }

            // lookAt
            {
                var blendShapeProxy  = root.GetComponent <UniVRM10.VRMController>();
                var lookAt           = new VrmLib.LookAt();
                var lookAtBlendShape = blendShapeProxy;
                var lookAtBone       = blendShapeProxy;
                if (lookAtBlendShape != null)
                {
                    if (lookAtBlendShape.LookAtType == VRMController.LookAtTypes.BlendShape)
                    {
                        lookAt.HorizontalInner = new VrmLib.LookAtRangeMap();
                        lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBlendShape.HorizontalOuter.CurveXRangeDegree,
                            OutputScaling = lookAtBlendShape.HorizontalOuter.CurveYRangeDegree
                        };
                        lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBlendShape.VerticalUp.CurveXRangeDegree,
                            OutputScaling = lookAtBlendShape.VerticalUp.CurveYRangeDegree,
                        };
                        lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBlendShape.VerticalDown.CurveXRangeDegree,
                            OutputScaling = lookAtBlendShape.VerticalDown.CurveYRangeDegree,
                        };
                    }
                    else if (lookAtBlendShape.LookAtType == VRMController.LookAtTypes.Bone)
                    {
                        lookAt.HorizontalInner = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBone.HorizontalInner.CurveXRangeDegree,
                            OutputScaling = lookAtBone.HorizontalInner.CurveYRangeDegree
                        };
                        lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBone.HorizontalOuter.CurveXRangeDegree,
                            OutputScaling = lookAtBone.HorizontalOuter.CurveYRangeDegree
                        };
                        lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBone.VerticalUp.CurveXRangeDegree,
                            OutputScaling = lookAtBone.VerticalUp.CurveYRangeDegree,
                        };
                        lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
                        {
                            InputMaxValue = lookAtBone.VerticalDown.CurveXRangeDegree,
                            OutputScaling = lookAtBone.VerticalDown.CurveYRangeDegree,
                        };
                    }
                    lookAt.OffsetFromHeadBone = blendShapeProxy.OffsetFromHead.ToNumericsVector3();
                }
                Model.Vrm.LookAt = lookAt;
            }

            // springBone
            {
                var springBoneColliderGroups = root.GetComponentsInChildren <UniVRM10.VRMSpringBoneColliderGroup>();
                if (springBoneColliderGroups != null)
                {
                    Model.Vrm.SpringBone = new VrmLib.SpringBoneManager();
                    var colliders = new Dictionary <UniVRM10.VRMSpringBoneColliderGroup, VrmLib.SpringBoneColliderGroup>();
                    foreach (var colliderGroup in springBoneColliderGroups)
                    {
                        var colliderGroups = colliderGroup.Colliders.Select(x =>
                        {
                            switch (x.ColliderType)
                            {
                            case SpringBoneColliderTypes.Sphere:
                                return(VrmLib.VrmSpringBoneCollider.CreateSphere(x.Offset.ToNumericsVector3(), x.Radius));

                            case SpringBoneColliderTypes.Capsule:
                                return(VrmLib.VrmSpringBoneCollider.CreateCapsule(x.Offset.ToNumericsVector3(), x.Radius, x.Tail.ToNumericsVector3()));

                            default:
                                throw new NotImplementedException();
                            }
                        });
                        var vrmColliderGroup = new VrmLib.SpringBoneColliderGroup(Nodes[colliderGroup.gameObject], colliderGroups);
                        Model.Vrm.SpringBone.Colliders.Add(vrmColliderGroup);

                        colliders.Add(colliderGroup, vrmColliderGroup);
                    }

                    var springBones = root.GetComponentsInChildren <UniVRM10.VRMSpringBone>();
                    foreach (var springBone in springBones)
                    {
                        var vrmSpringBone = new VrmLib.SpringBone()
                        {
                            Comment      = springBone.m_comment,
                            Stiffness    = springBone.m_stiffnessForce,
                            GravityPower = springBone.m_gravityPower,
                            GravityDir   = springBone.m_gravityDir.ToNumericsVector3(),
                            DragForce    = springBone.m_dragForce,
                            Origin       = (springBone.m_center != null) ? Nodes[springBone.m_center.gameObject] : null,
                            HitRadius    = springBone.m_hitRadius,
                        };

                        foreach (var rootBone in springBone.RootBones)
                        {
                            vrmSpringBone.Bones.Add(Nodes[rootBone.gameObject]);
                        }

                        foreach (var collider in springBone.ColliderGroups)
                        {
                            vrmSpringBone.Colliders.Add(colliders[collider]);
                        }

                        Model.Vrm.SpringBone.Springs.Add(vrmSpringBone);
                    }
                }
            }

            return(Model);
        }
        /// <summary>
        /// metaObject が null のときは、root から取得する
        /// </summary>
        public VrmLib.Model ToModelFrom10(GameObject root, VRMMetaObject metaObject = null)
        {
            Model = new VrmLib.Model(VrmLib.Coordinates.Unity);

            if (metaObject is null)
            {
                var vrmMeta = root.GetComponent <VRMMeta>();
                if (vrmMeta is null || vrmMeta.Meta is null)
                {
                    throw new NullReferenceException("metaObject is null");
                }
                metaObject = vrmMeta.Meta;
            }

            var meta = new VrmLib.Meta();

            meta.Name       = metaObject.Name;
            meta.Version    = metaObject.Version;
            meta.Copyrights = metaObject.Copyrights;
            meta.Authors.AddRange(metaObject.Authors);
            meta.ContactInformation = metaObject.ContactInformation;
            meta.Reference          = metaObject.Reference;
            meta.Thumbnail          = metaObject.Thumbnail.ToPngImage(VrmLib.ImageUsage.None);

            meta.AvatarPermission = new VrmLib.AvatarPermission
            {
                AvatarUsage           = metaObject.AllowedUser,
                IsAllowedViolentUsage = metaObject.ViolentUsage,
                IsAllowedSexualUsage  = metaObject.SexualUsage,
                CommercialUsage       = metaObject.CommercialUsage,
                IsAllowedGameUsage    = metaObject.GameUsage,
                IsAllowedPoliticalOrReligiousUsage = metaObject.PoliticalOrReligiousUsage,
                OtherPermissionUrl = metaObject.OtherPermissionUrl,
            };
            meta.RedistributionLicense = new VrmLib.RedistributionLicense
            {
                CreditNotation        = metaObject.CreditNotation,
                IsAllowRedistribution = metaObject.Redistribution,
                ModificationLicense   = metaObject.ModificationLicense,
                OtherLicenseUrl       = metaObject.OtherLicenseUrl,
            };
            Model.Vrm = new VrmLib.Vrm(meta, UniVRM10.VRMVersion.VERSION, UniVRM10.VRMSpecVersion.Version);

            // node
            {
                Model.Root = new VrmLib.Node(root.name);
                CreateNodes(root.transform, Model.Root, Nodes);
                Model.Nodes = Nodes
                              .Where(x => x.Value != Model.Root)
                              .Select(x => x.Value).ToList();
            }

            // humanoid
            {
                var animator = root.GetComponent <Animator>();
                if (animator != null && animator.avatar != null)
                {
                    foreach (HumanBodyBones humanBoneType in Enum.GetValues(typeof(HumanBodyBones)))
                    {
                        if (humanBoneType == HumanBodyBones.LastBone)
                        {
                            continue;
                        }

                        var transform = animator.GetBoneTransform(humanBoneType);
                        if (transform != null && Nodes.TryGetValue(transform.gameObject, out VrmLib.Node node))
                        {
                            node.HumanoidBone = (VrmLib.HumanoidBones)Enum.Parse(typeof(VrmLib.HumanoidBones), humanBoneType.ToString(), true);
                        }
                    }
                }
            }

            // material and textures
            var rendererComponents = root.GetComponentsInChildren <Renderer>();

            {
                foreach (var renderer in rendererComponents)
                {
                    var materials = renderer.sharedMaterials; // avoid copy
                    foreach (var material in materials)
                    {
                        if (Materials.ContainsKey(material))
                        {
                            continue;
                        }

                        var vrmMaterial = Export10(material, GetOrCreateTexture);
                        Model.Materials.Add(vrmMaterial);
                        Materials.Add(material, vrmMaterial);
                    }
                }
            }

            // mesh
            {
                foreach (var renderer in rendererComponents)
                {
                    if (renderer is SkinnedMeshRenderer skinnedMeshRenderer)
                    {
                        if (skinnedMeshRenderer.sharedMesh != null)
                        {
                            var mesh = CreateMesh(skinnedMeshRenderer.sharedMesh, skinnedMeshRenderer, Materials);
                            var skin = CreateSkin(skinnedMeshRenderer, Nodes, root);
                            if (skin != null)
                            {
                                // blendshape only で skinning が無いやつがある
                                mesh.Skin = skin;
                                Model.Skins.Add(mesh.Skin);
                            }
                            Model.MeshGroups.Add(mesh);
                            Nodes[renderer.gameObject].MeshGroup = mesh;
                            Meshes.Add(skinnedMeshRenderer.sharedMesh, mesh);
                        }
                    }
                    else if (renderer is MeshRenderer meshRenderer)
                    {
                        var filter = meshRenderer.gameObject.GetComponent <MeshFilter>();
                        if (filter != null && filter.sharedMesh != null)
                        {
                            var mesh = CreateMesh(filter.sharedMesh, meshRenderer, Materials);
                            Model.MeshGroups.Add(mesh);
                            Nodes[renderer.gameObject].MeshGroup = mesh;
                            Meshes.Add(filter.sharedMesh, mesh);
                        }
                    }
                }
            }

            // blendShape
            {
                Model.Vrm.BlendShape = new VrmLib.BlendShapeManager();
                var blendShapeProxy = root.GetComponent <UniVRM10.VRMBlendShapeProxy>();
                if (blendShapeProxy != null)
                {
                    foreach (var clip in blendShapeProxy.BlendShapeAvatar.Clips)
                    {
                        var blendShape = new VrmLib.BlendShape(clip.Preset, clip.BlendShapeName, clip.IsBinary);
                        blendShape.IgnoreBlink  = clip.IgnoreBlink;
                        blendShape.IgnoreLookAt = clip.IgnoreLookAt;
                        blendShape.IgnoreMouth  = clip.IgnoreMouth;

                        foreach (var value in clip.Values)
                        {
                            var transform = GetTransformFromRelativePath(root.transform, value.RelativePath);
                            if (transform == null)
                            {
                                continue;
                            }
                            var renderer = transform.gameObject.GetComponent <SkinnedMeshRenderer>();
                            if (renderer == null)
                            {
                                continue;
                            }
                            var mesh = renderer.sharedMesh;
                            if (mesh == null)
                            {
                                continue;
                            }

                            var names = new List <string>();
                            for (int i = 0; i < mesh.blendShapeCount; ++i)
                            {
                                names.Add(mesh.GetBlendShapeName(i));
                            }

                            var blendShapeValue = new VrmLib.BlendShapeBindValue(
                                Meshes[mesh],
                                names[value.Index],
                                value.Weight
                                );
                            blendShape.BlendShapeValues.Add(blendShapeValue);
                        }

                        foreach (var value in clip.MaterialValues)
                        {
                            var materialPair = Materials.FirstOrDefault(x => x.Key.name == value.MaterialName);
                            if (materialPair.Equals(default(KeyValuePair <Material, VrmLib.Material>)))
                            {
                                continue;
                            }

                            var bind = new VrmLib.MaterialBindValue(
                                materialPair.Value,
                                value.ValueName,
                                value.TargetValue.ToNumericsVector4()
                                );
                            blendShape.MaterialValues.Add(bind);
                        }

                        Model.Vrm.BlendShape.BlendShapeList.Add(blendShape);
                    }
                }
            }

            // firstPerson
            {
                var firstPerson          = new VrmLib.FirstPerson();
                var firstPersonComponent = root.GetComponent <UniVRM10.VRMFirstPerson>();
                if (firstPersonComponent != null)
                {
                    firstPerson.m_fp = Nodes[firstPersonComponent.FirstPersonBone.gameObject];
                    foreach (var renderer in firstPersonComponent.Renderers)
                    {
                        firstPerson.Annotations.Add(
                            new VrmLib.FirstPersonMeshAnnotation(Meshes[renderer.SharedMesh],
                                                                 renderer.FirstPersonFlag)
                            );
                    }
                    Model.Vrm.FirstPerson = firstPerson;
                }
            }

            // lookAt
            {
                var lookAt           = new VrmLib.LookAt();
                var lookAtBlendShape = root.GetComponent <UniVRM10.VRMLookAtBlendShapeApplier>();
                var lookAtBone       = root.GetComponent <UniVRM10.VRMLookAtBoneApplier>();
                if (lookAtBlendShape != null)
                {
                    lookAt.HorizontalInner = new VrmLib.LookAtRangeMap();
                    lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBlendShape.HorizontalOuter.CurveXRangeDegree,
                        OutputScaling = lookAtBlendShape.HorizontalOuter.CurveYRangeDegree
                    };
                    lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBlendShape.VerticalUp.CurveXRangeDegree,
                        OutputScaling = lookAtBlendShape.VerticalUp.CurveYRangeDegree,
                    };
                    lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBlendShape.VerticalDown.CurveXRangeDegree,
                        OutputScaling = lookAtBlendShape.VerticalDown.CurveYRangeDegree,
                    };
                }
                else if (lookAtBone != null)
                {
                    lookAt.HorizontalInner = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBone.HorizontalInner.CurveXRangeDegree,
                        OutputScaling = lookAtBone.HorizontalInner.CurveYRangeDegree
                    };
                    lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBone.HorizontalOuter.CurveXRangeDegree,
                        OutputScaling = lookAtBone.HorizontalOuter.CurveYRangeDegree
                    };
                    lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBone.VerticalUp.CurveXRangeDegree,
                        OutputScaling = lookAtBone.VerticalUp.CurveYRangeDegree,
                    };
                    lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
                    {
                        InputMaxValue = lookAtBone.VerticalDown.CurveXRangeDegree,
                        OutputScaling = lookAtBone.VerticalDown.CurveYRangeDegree,
                    };
                }

                var firstPersonComponent = root.GetComponent <UniVRM10.VRMFirstPerson>();
                if (firstPersonComponent != null)
                {
                    lookAt.OffsetFromHeadBone = firstPersonComponent.FirstPersonOffset.ToNumericsVector3();
                }
                Model.Vrm.LookAt = lookAt;
            }

            // springBone
            {
                var springBoneColliderGroups = root.GetComponentsInChildren <UniVRM10.VRMSpringBoneColliderGroup>();
                if (springBoneColliderGroups != null)
                {
                    Model.Vrm.SpringBone = new VrmLib.SpringBoneManager();
                    var colliders = new Dictionary <UniVRM10.VRMSpringBoneColliderGroup, VrmLib.SpringBoneColliderGroup>();
                    foreach (var colliderGroup in springBoneColliderGroups)
                    {
                        var colliderGroups = colliderGroup.Colliders.Select(x =>
                                                                            new VrmLib.VrmSpringBoneColliderSphere(x.Offset.ToNumericsVector3(), x.Radius));
                        var vrmColliderGroup = new VrmLib.SpringBoneColliderGroup(Nodes[colliderGroup.gameObject], colliderGroups);
                        Model.Vrm.SpringBone.Colliders.Add(vrmColliderGroup);

                        colliders.Add(colliderGroup, vrmColliderGroup);
                    }

                    var springBones = root.GetComponentsInChildren <UniVRM10.VRMSpringBone>();
                    foreach (var springBone in springBones)
                    {
                        var vrmSpringBone = new VrmLib.SpringBone()
                        {
                            Comment      = springBone.m_comment,
                            Stiffness    = springBone.m_stiffnessForce,
                            GravityPower = springBone.m_gravityPower,
                            GravityDir   = springBone.m_gravityDir.ToNumericsVector3(),
                            DragForce    = springBone.m_dragForce,
                            Origin       = (springBone.m_center != null) ? Nodes[springBone.m_center.gameObject] : null,
                            HitRadius    = springBone.m_hitRadius,
                        };

                        foreach (var rootBone in springBone.RootBones)
                        {
                            vrmSpringBone.Bones.Add(Nodes[rootBone.gameObject]);
                        }

                        foreach (var collider in springBone.ColliderGroups)
                        {
                            vrmSpringBone.Colliders.Add(colliders[collider]);
                        }

                        Model.Vrm.SpringBone.Springs.Add(vrmSpringBone);
                    }
                }
            }

            return(Model);
        }