Merge pull request #2208 from ousttrue/fix/avatar_assign_vrm0_normalize

avatar 代入時に姿勢が変わる対策
This commit is contained in:
ousttrue 2024-01-09 13:46:05 +09:00 committed by GitHub
commit 125e42ca8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 31 deletions

View File

@ -199,12 +199,10 @@ namespace VRM
}
}
// 正規化
if (settings.PoseFreeze)
{
// BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用
target = VRMBoneNormalizer.Execute(target, settings.ForceTPose);
destroy.Add(target);
// 正規化
VRMBoneNormalizer.Execute(target, settings.ForceTPose);
}
var fp = target.GetComponent<VRMFirstPerson>();

View File

@ -46,8 +46,7 @@ namespace VRM
{
var go = Selection.activeObject as GameObject;
// BoneNormalizer.Execute はコピーを正規化する。UNDO無用
Selection.activeGameObject = VRMBoneNormalizer.Execute(go, true);
VRMBoneNormalizer.Execute(go, true);
}
}
}

View File

@ -41,17 +41,26 @@ namespace VRM
/// <summary>
/// モデルの正規化を実行する
///
/// v0.115 ヒエラルキーのコピーをしなくまりました(仕様変更)
/// v0.116 Animator.avatar 代入の副作用回避修正
///
/// v0.114以前: 非破壊
/// - return コピーされて正規化されたヒエラルキー
/// v0.115以降: 対象のヒエラルキーが正規化されます。
/// - Transform が変更されます。
/// - Animator.avatar が差し替えられます。
/// - SkinnedMeshRenderer.sharedMesh が差し替えられます。
/// - MeshFilter.sharedMesh が差し替えられます。
/// - return void
/// </summary>
/// <param name="go">対象モデルのルート</param>
/// <param name="forceTPose">強制的にT-Pose化するか</param>
/// <returns>正規化済みのモデル</returns>
public static GameObject Execute(GameObject go, bool forceTPose)
public static void Execute(GameObject go, bool forceTPose)
{
//
// T-Poseにする
//
if (forceTPose)
{
// T-Poseにする
var hips = go.GetComponent<Animator>().GetBoneTransform(HumanBodyBones.Hips);
var hipsPosition = hips.position;
var hipsRotation = hips.rotation;
@ -66,19 +75,30 @@ namespace VRM
}
}
// Meshの焼きこみ
var newMesh = BoneNormalizer.NormalizeHierarchyFreezeMesh(go, true);
// 焼いたMeshで置き換える
BoneNormalizer.Replace(go, newMesh, true, true);
// Transform の回転とスケールを Mesh に適用します。
// - 回転とスケールが反映された新しい Mesh が作成されます
// - Transform の回転とスケールはクリアされます。world position を維持します。
var newMeshMap = BoneNormalizer.NormalizeHierarchyFreezeMesh(go, true);
// 新しいヒエラルキーからAvatarを作る
var newAnimator = go.GetComponent<Animator>();
var newAvatar = UniHumanoid.AvatarDescription.RecreateAvatar(newAnimator);
newAnimator.avatar = newAvatar;
// SkinnedMeshRenderer.sharedMesh と MeshFilter.sharedMesh を新しいMeshで置き換える
BoneNormalizer.Replace(go, newMeshMap, true, true);
// CopyVRMComponents(go, normalized, bMap);
// 回転とスケールが除去された新しいヒエラルキーからAvatarを作る
var animator = go.GetComponent<Animator>();
var newAvatar = UniHumanoid.AvatarDescription.RecreateAvatar(animator);
return go;
// Animator.avatar を代入したときに副作用でTransformが変更されるのを回避するために削除します。
if (Application.isPlaying)
{
GameObject.Destroy(animator);
}
else
{
GameObject.DestroyImmediate(animator);
}
animator = go.AddComponent<Animator>();
animator.avatar = newAvatar;
}
/// <summary>

View File

@ -141,17 +141,9 @@ namespace VRM.RuntimeExporterSample
static byte[] ExportCustom(GameObject exportRoot, bool forceTPose = false)
{
// normalize
var target = VRMBoneNormalizer.Execute(exportRoot, forceTPose);
VRMBoneNormalizer.Execute(exportRoot, forceTPose);
try
{
return ExportSimple(target);
}
finally
{
// cleanup
GameObject.Destroy(target);
}
return ExportSimple(exportRoot);
}
void OnExported(UniGLTF.glTF vrm)