Merge pull request #2188 from ousttrue/fix_integration_group

[MeshUtility] 非原点 SkinnedMeshRenderer まわりの修正
This commit is contained in:
ousttrue
2023-12-11 16:11:55 +09:00
committed by GitHub
9 changed files with 136 additions and 28 deletions

View File

@@ -45,8 +45,18 @@ namespace UniGLTF.MeshUtility
};
_groupList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
// Flag / Name
var group = _meshUtil.MeshIntegrationGroups[index];
EditorGUI.TextField(rect, group.Name);
const float LEFT_WIDTH = 92.0f;
var left = rect;
left.width = LEFT_WIDTH;
var right = rect;
right.width -= LEFT_WIDTH;
right.x += LEFT_WIDTH;
group.IntegrationType = (MeshIntegrationGroup.MeshIntegrationTypes)EditorGUI.EnumPopup(left, group.IntegrationType);
group.Name = EditorGUI.TextField(right, group.Name);
};
_groupList.onSelectCallback = rl =>
{
@@ -63,6 +73,12 @@ namespace UniGLTF.MeshUtility
var r = _renderers[index];
EditorGUI.ObjectField(rect, r, typeof(Renderer), true);
};
// +ボタンが押された時のコールバック
_rendererList.onAddCallback = list => Debug.Log("+ clicked.");
// -ボタンが押された時のコールバック
_rendererList.onRemoveCallback = list => Debug.Log("- clicked : " + list.index + ".");
}
public void UpdateMeshIntegrationList(GameObject root)

View File

@@ -9,7 +9,7 @@ namespace UniGLTF.MeshUtility
{
public static class BoneNormalizer
{
private static MeshAttachInfo CreateMeshInfo(Transform src, bool freezeRotation)
private static MeshAttachInfo CreateMeshInfo(Transform src)
{
// SkinnedMeshRenderer
var smr = src.GetComponent<SkinnedMeshRenderer>();
@@ -29,7 +29,7 @@ namespace UniGLTF.MeshUtility
var mr = src.GetComponent<MeshRenderer>();
if (mr != null)
{
var dstMesh = MeshFreezer.NormalizeNoneSkinnedMesh(mr, freezeRotation);
var dstMesh = MeshFreezer.NormalizeNoneSkinnedMesh(mr, true);
if (dstMesh != null)
{
return new MeshAttachInfo
@@ -51,10 +51,15 @@ namespace UniGLTF.MeshUtility
public static Dictionary<Transform, MeshAttachInfo> NormalizeHierarchyFreezeMesh(
GameObject go, bool freezeRotation)
{
if (!freezeRotation)
{
throw new NotImplementedException("WIP");
}
var result = new Dictionary<Transform, MeshAttachInfo>();
foreach (var src in go.transform.Traverse())
{
var info = CreateMeshInfo(src, freezeRotation);
var info = CreateMeshInfo(src);
if (info != null)
{
result.Add(src, info);
@@ -63,7 +68,7 @@ namespace UniGLTF.MeshUtility
return result;
}
public static void Replace(GameObject go, Dictionary<Transform, MeshAttachInfo> newMesh,
public static void Replace(GameObject go, Dictionary<Transform, MeshAttachInfo> meshMap,
bool FreezeRotation, bool FreezeScaling)
{
var boneMap = go.transform.Traverse().ToDictionary(x => x, x => new EuclideanTransform(x.rotation, x.position));
@@ -96,7 +101,7 @@ namespace UniGLTF.MeshUtility
// second, replace mesh
foreach (var (src, tr) in boneMap)
{
if (newMesh.TryGetValue(src, out var info))
if (meshMap.TryGetValue(src, out var info))
{
info.ReplaceMesh(src.gameObject);
}

View File

@@ -53,7 +53,25 @@ namespace UniGLTF.MeshUtility
/// </summary>
public bool SplitByBlendShape = false;
protected UniGLTF.MeshUtility.MeshIntegrationGroup _GetOrCreateGroup(string name)
static MeshIntegrationGroup.MeshIntegrationTypes TypeFromName(string name)
{
var key = name.ToLower();
if (key.Contains("first"))
{
return MeshIntegrationGroup.MeshIntegrationTypes.FirstPersonOnly;
}
if (key.Contains("third"))
{
return MeshIntegrationGroup.MeshIntegrationTypes.ThirdPersonOnly;
}
if (key.Contains("auto"))
{
return MeshIntegrationGroup.MeshIntegrationTypes.Auto;
}
return MeshIntegrationGroup.MeshIntegrationTypes.Both;
}
protected MeshIntegrationGroup _GetOrCreateGroup(string name)
{
foreach (var g in MeshIntegrationGroups)
{
@@ -62,13 +80,29 @@ namespace UniGLTF.MeshUtility
return g;
}
}
MeshIntegrationGroups.Add(new UniGLTF.MeshUtility.MeshIntegrationGroup
MeshIntegrationGroups.Add(new MeshIntegrationGroup
{
Name = name,
IntegrationType = TypeFromName(name),
});
return MeshIntegrationGroups.Last();
}
protected bool _HasRenderer(Renderer r)
{
foreach (var g in MeshIntegrationGroups)
{
foreach (var x in g.Renderers)
{
if (x == r)
{
return true;
}
}
}
return false;
}
public virtual void UpdateMeshIntegrationGroups(GameObject root)
{
MeshIntegrationGroups.Clear();
@@ -88,7 +122,8 @@ namespace UniGLTF.MeshUtility
}
MeshIntegrationGroups.Add(new MeshIntegrationGroup
{
Name = "ALL",
Name = "All",
IntegrationType = MeshIntegrationGroup.MeshIntegrationTypes.Both,
Renderers = root.GetComponentsInChildren<Renderer>().ToList(),
});
}
@@ -140,12 +175,12 @@ namespace UniGLTF.MeshUtility
if (FreezeBlendShape || FreezeRotation || FreezeScaling)
{
// MeshをBakeする
var newMesh = BoneNormalizer.NormalizeHierarchyFreezeMesh(target, FreezeRotation);
var meshMap = BoneNormalizer.NormalizeHierarchyFreezeMesh(target, FreezeRotation);
// - ヒエラルキーから回転・拡縮を除去する
// - BakeされたMeshで置き換える
// - bindPoses を再計算する
BoneNormalizer.Replace(target, newMesh, FreezeRotation, FreezeScaling);
BoneNormalizer.Replace(target, meshMap, FreezeRotation, FreezeScaling);
}
var newList = new List<GameObject>();

View File

@@ -76,9 +76,19 @@ namespace UniGLTF.MeshUtility
return dst;
}
public static void ApplyRotationAndScale(this Mesh src, Matrix4x4 m)
public static void ApplyRotationAndScale(this Mesh src, Matrix4x4 m, bool removeTranslation = true)
{
m.SetColumn(3, new Vector4(0, 0, 0, 1)); // remove translation
if (removeTranslation)
{
m.SetColumn(3, new Vector4(0, 0, 0, 1)); // remove translation
}
src.ApplyMatrix(m);
}
public static void ApplyTranslation(this Mesh src, Vector3 p)
{
var m = Matrix4x4.identity;
m.SetColumn(3, new Vector4(p.x, p.y, p.z, 1));
src.ApplyMatrix(m);
}

View File

@@ -147,9 +147,10 @@ namespace UniGLTF.MeshUtility
if (!hasBoneWeight)
{
// Before bake, bind no weight bones
//Debug.LogFormat("no weight: {0}", srcMesh.name);
srcMesh = srcMesh.Copy(true);
srcMesh.ApplyRotationAndScale(src.transform.localToWorldMatrix, false);
var bw = new BoneWeight
{
boneIndex0 = 0,
@@ -162,8 +163,9 @@ namespace UniGLTF.MeshUtility
weight3 = 0.0f,
};
srcMesh.boneWeights = Enumerable.Range(0, srcMesh.vertexCount).Select(x => bw).ToArray();
src.rootBone = src.transform;
src.bones = new[] { src.transform };
src.bones = new[] { src.rootBone ?? src.transform };
srcMesh.bindposes = src.bones.Select(x => x.worldToLocalMatrix).ToArray();
src.sharedMesh = srcMesh;
}
@@ -174,21 +176,19 @@ namespace UniGLTF.MeshUtility
mesh.boneWeights = srcMesh.boneWeights;
//var m = src.localToWorldMatrix; // include scaling
var m = default(Matrix4x4);
m.SetTRS(Vector3.zero, src.transform.rotation, Vector3.one); // rotation only
mesh.ApplyMatrix(m);
{
// apply SkinnedMesh.transform rotation
var m = Matrix4x4.TRS(Vector3.zero, src.transform.rotation, Vector3.one);
mesh.ApplyMatrix(m);
}
//
// BlendShapes
//
CopyBlendShapes(src, srcMesh, mesh, m);
if (!hasBoneWeight)
{
// restore bones
src.bones = new Transform[] { };
src.sharedMesh = originalSrcMesh;
var m = src.localToWorldMatrix; // include scaling
m.SetColumn(3, new Vector4(0, 0, 0, 1)); // no translation
CopyBlendShapes(src, srcMesh, mesh, m);
}
return mesh;

View File

@@ -6,6 +6,16 @@ namespace UniGLTF.MeshUtility
public class MeshIntegrationGroup
{
public string Name;
public enum MeshIntegrationTypes
{
Both,
FirstPersonOnly,
ThirdPersonOnly,
Auto,
}
public MeshIntegrationTypes IntegrationType = default;
public List<Renderer> Renderers = new List<Renderer>();
public MeshIntegrationGroup CopyInstantiate(GameObject go, GameObject instance)

View File

@@ -337,8 +337,14 @@ namespace UniGLTF.MeshUtility
mesh.vertices = Positions.ToArray();
mesh.normals = Normals.ToArray();
mesh.uv = UV.ToArray();
mesh.tangents = Tangents.ToArray();
mesh.boneWeights = BoneWeights.ToArray();
if (Tangents != null && Tangents.Count == Positions.Count)
{
mesh.tangents = Tangents.ToArray();
}
if (BoneWeights != null && BoneWeights.Count == Positions.Count)
{
mesh.boneWeights = BoneWeights.ToArray();
}
int subMeshCount = 0;
foreach (var submesh in SubMeshes)

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using UniHumanoid;
using UnityEngine;
using UnityEngine.XR;
namespace VRM
@@ -26,6 +27,7 @@ namespace VRM
yield return new UniGLTF.MeshUtility.MeshIntegrationGroup
{
Name = FirstPersonFlag.ThirdPersonOnly.ToString(),
IntegrationType = UniGLTF.MeshUtility.MeshIntegrationGroup.MeshIntegrationTypes.ThirdPersonOnly,
Renderers = g.Renderers.ToList(),
};
}
@@ -130,6 +132,7 @@ namespace VRM
public override void UpdateMeshIntegrationGroups(GameObject root)
{
MeshIntegrationGroups.Clear();
if (root == null)
{
return;
@@ -144,6 +147,13 @@ namespace VRM
var g = _GetOrCreateGroup(a.FirstPersonFlag.ToString());
g.Renderers.Add(a.Renderer);
}
var orphan = root.GetComponentsInChildren<Renderer>().Where(x => !_HasRenderer(x)).ToArray();
if (orphan.Length > 0)
{
var g = _GetOrCreateGroup("both");
g.Renderers.AddRange(orphan);
}
}
}
}

View File

@@ -9,6 +9,11 @@ namespace UniVRM10
{
public class Vrm10MeshUtility : UniGLTF.MeshUtility.GltfMeshUtility
{
public Vrm10MeshUtility()
{
FreezeRotation = true;
}
bool _generateFirstPerson = false;
public override IEnumerable<UniGLTF.MeshUtility.MeshIntegrationGroup> CopyInstantiate(GameObject go, GameObject instance)
{
@@ -25,6 +30,7 @@ namespace UniVRM10
yield return new UniGLTF.MeshUtility.MeshIntegrationGroup
{
Name = UniGLTF.Extensions.VRMC_vrm.FirstPersonType.thirdPersonOnly.ToString(),
IntegrationType = UniGLTF.MeshUtility.MeshIntegrationGroup.MeshIntegrationTypes.ThirdPersonOnly,
Renderers = g.Renderers.ToList(),
};
}
@@ -113,6 +119,8 @@ namespace UniVRM10
{
var animator = target.GetComponent<Animator>();
var newAvatar = AvatarDescription.RecreateAvatar(animator);
GameObject.DestroyImmediate(animator);
animator = target.AddComponent<Animator>();
animator.avatar = newAvatar;
}
@@ -121,6 +129,7 @@ namespace UniVRM10
public override void UpdateMeshIntegrationGroups(GameObject root)
{
MeshIntegrationGroups.Clear();
if (root == null)
{
return;
@@ -145,6 +154,13 @@ namespace UniVRM10
var g = _GetOrCreateGroup(a.FirstPersonFlag.ToString());
g.Renderers.Add(a.GetRenderer(root.transform));
}
var orphan = root.GetComponentsInChildren<Renderer>().Where(x => !_HasRenderer(x)).ToArray();
if (orphan.Length > 0)
{
var g = _GetOrCreateGroup("both");
g.Renderers.AddRange(orphan);
}
}
}
}