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