mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-26 21:04:14 -05:00
Merge pull request #2188 from ousttrue/fix_integration_group
[MeshUtility] 非原点 SkinnedMeshRenderer まわりの修正
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user