From ff6864903691b4055154b02f7fed15c04aaa75a9 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 27 Nov 2023 18:58:50 +0900 Subject: [PATCH] MeshAttachInfo --- .../Runtime/MeshUtility/BoneNormalizer.cs | 104 ++++++++++-------- .../Runtime/MeshUtility/GltfMeshUtility.cs | 7 +- .../Runtime/MeshUtility/MeshAttachInfo.cs | 30 +++++ .../MeshUtility/MeshAttachInfo.cs.meta | 11 ++ .../SkinnedMeshUtility/VRMBoneNormalizer.cs | 7 +- 5 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs create mode 100644 Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs.meta diff --git a/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs b/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs index 40981e773..a94a45c7f 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs @@ -71,6 +71,56 @@ namespace UniGLTF.MeshUtility } } + public static MeshAttachInfo CreateMeshInfo(Transform src, Dictionary boneMap, bool freezeBlendShape) + { + Transform dst; + if (!boneMap.TryGetValue(src, out dst)) + { + return default; + } + + // SkinnedMeshRenderer + var smr = src.GetComponent(); + var (mesh, dstBones) = MeshFreezer.NormalizeSkinnedMesh( + smr, + boneMap, + dst.localToWorldMatrix, + freezeBlendShape); + if (mesh != null) + { + var info = new MeshAttachInfo + { + Mesh = mesh, + Materials = smr.sharedMaterials, + }; + if (smr.rootBone != null) + { + if (boneMap.TryGetValue(smr.rootBone, out Transform found)) + { + info.RootBone = found; + } + } + return info; + } + + // MeshRenderer + var mr = src.GetComponent(); + if (mr != null) + { + var dstMesh = MeshFreezer.NormalizeNoneSkinnedMesh(mr); + if (dstMesh != null) + { + return new MeshAttachInfo + { + Mesh = dstMesh, + Materials = mr.sharedMaterials, + }; + } + } + + return default; + } + /// /// 回転とスケールを除去したヒエラルキーのコピーを作成する(MeshをBakeする) @@ -79,7 +129,8 @@ namespace UniGLTF.MeshUtility /// BlendShapeを0クリアするか否か。false の場合 BlendShape の現状を Bake する /// Avatarを作る関数 /// - public static (GameObject, Dictionary) NormalizeHierarchyFreezeMesh(GameObject go, + public static (GameObject, Dictionary, Dictionary) NormalizeHierarchyFreezeMesh( + GameObject go, bool removeScaling = true, bool removeRotation = true, bool freezeBlendShape = true @@ -93,57 +144,16 @@ namespace UniGLTF.MeshUtility // // 各メッシュから回転・スケールを取り除いてBinding行列を再計算する // + var result = new Dictionary(); foreach (var src in go.transform.Traverse()) { - Transform dst; - if (!boneMap.TryGetValue(src, out dst)) + var info = CreateMeshInfo(src, boneMap, freezeBlendShape); + if (info != null) { - continue; - } - - { - // SkinnedMeshRenderer - var srcRenderer = src.GetComponent(); - var (mesh, dstBones) = MeshFreezer.NormalizeSkinnedMesh( - srcRenderer, - boneMap, - dst.localToWorldMatrix, - freezeBlendShape); - if (mesh != null) - { - var dstRenderer = dst.gameObject.AddComponent(); - dstRenderer.sharedMaterials = srcRenderer.sharedMaterials; - if (srcRenderer.rootBone != null) - { - if (boneMap.TryGetValue(srcRenderer.rootBone, out Transform found)) - { - dstRenderer.rootBone = found; - } - } - dstRenderer.bones = dstBones; - dstRenderer.sharedMesh = mesh; - } - } - - { - // MeshRenderer - var srcRenderer = src.GetComponent(); - if (srcRenderer != null) - { - var dstMesh = MeshFreezer.NormalizeNoneSkinnedMesh(srcRenderer); - if (dstMesh != null) - { - var dstFilter = dst.gameObject.AddComponent(); - dstFilter.sharedMesh = dstMesh; - // Materialをコピー - var dstRenderer = dst.gameObject.AddComponent(); - dstRenderer.sharedMaterials = srcRenderer.sharedMaterials; - } - } + result.Add(src, info); } } - - return (normalized, boneMap); + return (normalized, boneMap, result); } public static void WriteBackResult(GameObject go, GameObject normalized, Dictionary boneMap) diff --git a/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs index c7ae49c62..9960b6058 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs @@ -162,11 +162,16 @@ namespace UniGLTF.MeshUtility // 正規化されたヒエラルキーを作る if (FreezeBlendShape || FreezeRotation || FreezeScaling) { - var (normalized, boneMap) = BoneNormalizer.NormalizeHierarchyFreezeMesh(go, + var (normalized, boneMap, newMesh) = BoneNormalizer.NormalizeHierarchyFreezeMesh(go, removeScaling: FreezeScaling, removeRotation: FreezeRotation, freezeBlendShape: FreezeBlendShape); + foreach (var (k, v) in newMesh) + { + v.AttachTo(k.gameObject); + } + // write back normalized transform to boneMap BoneNormalizer.WriteBackResult(go, normalized, boneMap); if (Application.isPlaying) diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs new file mode 100644 index 000000000..0eb16c63f --- /dev/null +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public class MeshAttachInfo + { + public Mesh Mesh; + public Material[] Materials; + public Transform[] Bones; + public Transform RootBone; + public void AttachTo(GameObject dst) + { + if (Bones != null) + { + var dstRenderer = dst.AddComponent(); + dstRenderer.sharedMesh = Mesh; + dstRenderer.sharedMaterials = Materials; + dstRenderer.bones = Bones; + dstRenderer.rootBone = RootBone; + } + else + { + var dstFilter = dst.AddComponent(); + dstFilter.sharedMesh = Mesh; + var dstRenderer = dst.gameObject.AddComponent(); + dstRenderer.sharedMaterials = Materials; + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs.meta b/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs.meta new file mode 100644 index 000000000..0db6210ad --- /dev/null +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6eff3bee96e61849ac190387ec28542 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs index e0901616a..479641975 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs @@ -67,7 +67,12 @@ namespace VRM } // 正規化されたヒエラルキーを作る - var (normalized, bMap) = BoneNormalizer.NormalizeHierarchyFreezeMesh(go); + var (normalized, bMap, newMesh) = BoneNormalizer.NormalizeHierarchyFreezeMesh(go); + + foreach (var (k, v) in newMesh) + { + v.AttachTo(k.gameObject); + } // 新しいヒエラルキーからAvatarを作る var newAvatar = UniHumanoid.AvatarDescription.CreateAvatarForCopyHierarchy(