示例#1
0
        public void BlendShapeTest()
        {
            var settings = Google.Protobuf.JsonFormatter.Settings.Default.WithPreserveProtoFieldNames(true);
            var q        = "\"";

            {
                var data = new VrmProtobuf.BlendShapeGroup();
                data.IgnoreBlink = true;

                var json = new Google.Protobuf.JsonFormatter(settings).Format(data);
                Assert.AreEqual($"{{ {q}ignoreBlink{q}: true }}", json);
            }

            {
                var blendShape = new VrmLib.BlendShape(VrmLib.BlendShapePreset.Blink, "blink", true)
                {
                    IgnoreBlink  = true,
                    IgnoreLookAt = true,
                    IgnoreMouth  = true,
                };

                // export
                var gltf = Vrm10.BlendShapeAdapter.ToGltf(blendShape, new List <VrmLib.Node>(), new List <VrmLib.Material>());
                Assert.AreEqual(true, gltf.IgnoreBlink);
                Assert.AreEqual(true, gltf.IgnoreLookAt);
                Assert.AreEqual(true, gltf.IgnoreMouth);

                // import
                var imported = Vrm10.BlendShapeAdapter.FromGltf(gltf, new List <VrmLib.Node>(), new List <VrmLib.Material>());
                Assert.AreEqual(true, imported.IgnoreBlink);
                Assert.AreEqual(true, imported.IgnoreLookAt);
                Assert.AreEqual(true, imported.IgnoreMouth);
            }
        }
示例#2
0
        /// <summary>
        /// VRM-0.X の MaterialBindValue を VRM-1.0 仕様に変換する
        ///
        /// * Property名 => enum MaterialBindType
        /// * 特に _MainTex_ST の場合、MaterialBindType.UvScale + MaterialBindType.UvScale 2つになりうる
        ///
        /// </summary>
        VrmLib.BlendShape ToVrmLib(BlendShapeClip clip, GameObject root)
        {
            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 binding in clip.BlendShapeBindings)
            {
                var transform = GetTransformFromRelativePath(root.transform, binding.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 node            = Nodes[transform.gameObject];
                var blendShapeValue = new VrmLib.BlendShapeBindValue(
                    node,
                    names[binding.Index],
                    binding.Weight
                    );
                blendShape.BlendShapeValues.Add(blendShapeValue);
            }

            foreach (var binding in clip.MaterialColorBindings)
            {
                var materialPair = Materials.FirstOrDefault(x => x.Key.name == binding.MaterialName);
                if (materialPair.Value != null)
                {
                    var bind = new VrmLib.MaterialBindValue(
                        materialPair.Value,
                        binding.BindType,
                        binding.TargetValue.ToNumericsVector4()
                        );
                    blendShape.MaterialValues.Add(bind);
                }
            }

            foreach (var binding in clip.MaterialUVBindings)
            {
                var materialPair = Materials.FirstOrDefault(x => x.Key.name == binding.MaterialName);
                if (materialPair.Value != null)
                {
                    var bind = new VrmLib.UVScaleOffsetValue(
                        materialPair.Value,
                        binding.Scaling.ToNumericsVector2(),
                        binding.Offset.ToNumericsVector2()
                        );
                    blendShape.UVScaleOffsetValues.Add(bind);
                }
            }

            return(blendShape);
        }
示例#3
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;
            }

            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);
        }