Skip to content

Commit

Permalink
Merge pull request #2180 from ousttrue/fix/refactor_mesh_integration
Browse files Browse the repository at this point in the history
[vrm1.0] impl refactor mesh integration
  • Loading branch information
ousttrue authored Oct 31, 2023
2 parents 897d6c7 + 9aea31c commit e896c6c
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 86 deletions.
2 changes: 1 addition & 1 deletion Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public static bool Execute(GameObject src, bool onlyBlendShapeRenderers)
// write mesh asset.
foreach (var result in results)
{
var mesh = result.IntegratedRenderer.sharedMesh;
var mesh = result.MeshMap.Integrated;
var assetPath = GetMeshWritePath(mesh);
Debug.LogFormat("CreateAsset: {0}", assetPath);
AssetDatabase.CreateAsset(mesh, assetPath);
Expand Down
29 changes: 29 additions & 0 deletions Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;


Expand Down Expand Up @@ -144,5 +145,33 @@ public static (GameObject, Dictionary<Transform, Transform>) NormalizeHierarchyF

return (normalized, boneMap);
}

public static void WriteBackResult(GameObject go, GameObject normalized, Dictionary<Transform, Transform> boneMap)
{
Func<Transform, Transform> getSrc = dst =>
{
foreach (var (k, v) in boneMap)
{
if (v == dst)
{
return k;
}
}
throw new NotImplementedException();
};
foreach (var (src, dst) in boneMap)
{
src.localPosition = dst.localPosition;
src.localRotation = dst.localRotation;
src.localScale = dst.localScale;
var srcR = src.GetComponent<SkinnedMeshRenderer>();
var dstR = dst.GetComponent<SkinnedMeshRenderer>();
if (srcR != null && dstR != null)
{
srcR.sharedMesh = dstR.sharedMesh;
srcR.bones = dstR.bones.Select(x => getSrc(x)).ToArray();
}
}
}
}
}
15 changes: 15 additions & 0 deletions Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Collections.Generic;
using UnityEngine;

namespace UniGLTF.MeshUtility
{
public class MeshIntegrationGroup
{
/// <summary>
/// FirstPerson flag
/// TODO: enum
/// </summary>
public string Name;
public List<Renderer> Renderers = new List<Renderer>();
}
}
11 changes: 11 additions & 0 deletions Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationGroup.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 21 additions & 2 deletions Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationResult.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace UniGLTF.MeshUtility
Expand All @@ -8,14 +9,32 @@ public class MeshMap
{
public List<Mesh> Sources = new List<Mesh>();
public Mesh Integrated;
public Material[] SharedMaterials;
public Transform[] Bones;
}

public class MeshIntegrationResult
{
public List<SkinnedMeshRenderer> SourceSkinnedMeshRenderers = new List<SkinnedMeshRenderer>();
public List<MeshRenderer> SourceMeshRenderers = new List<MeshRenderer>();
public MeshMap MeshMap = new MeshMap();
public SkinnedMeshRenderer IntegratedRenderer;

public MeshMap MeshMap = new MeshMap();
public void AddIntegratedRendererTo(GameObject parent)
{
var go = new GameObject(MeshMap.Integrated.name);
go.transform.SetParent(parent.transform, false);
var smr = go.AddComponent<SkinnedMeshRenderer>();
smr.sharedMesh = MeshMap.Integrated;
smr.sharedMaterials = MeshMap.SharedMaterials;
smr.bones = MeshMap.Bones;

IntegratedRenderer = smr;
}

public void DestroySourceRenderer()
{
throw new NotImplementedException();
}
}
}
81 changes: 28 additions & 53 deletions Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ namespace UniGLTF.MeshUtility
{
public class MeshIntegrator
{
public const string INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME = "Integrated(WithoutBlendShape)";
public const string INTEGRATED_MESH_WITH_BLENDSHAPE_NAME = "Integrated(WithBlendShape)";
public const string INTEGRATED_MESH_ALL_NAME = "Integrated(All)";
private MeshIntegrator()
{

}

struct SubMesh
{
Expand Down Expand Up @@ -81,7 +82,7 @@ static BoneWeight AddBoneIndexOffset(BoneWeight bw, int boneIndexOffset)
return bw;
}

public void Push(MeshRenderer renderer)
void Push(MeshRenderer renderer)
{
var meshFilter = renderer.GetComponent<MeshFilter>();
if (meshFilter == null)
Expand Down Expand Up @@ -232,7 +233,24 @@ public void Push(SkinnedMeshRenderer renderer)
}
}

public MeshIntegrationResult Integrate(MeshEnumerateOption onlyBlendShapeRenderers)
public static MeshIntegrationResult Integrate(MeshIntegrationGroup group, bool useBlendShape)
{
var integrator = new MeshUtility.MeshIntegrator();
foreach (var x in group.Renderers)
{
if (x is SkinnedMeshRenderer smr)
{
integrator.Push(smr);
}
else if (x is MeshRenderer mr)
{
integrator.Push(mr);
}
}
return integrator.Integrate(group.Name, useBlendShape);
}

public MeshIntegrationResult Integrate(string name, bool useBlendShape)
{
var mesh = new Mesh();

Expand All @@ -253,57 +271,14 @@ public MeshIntegrationResult Integrate(MeshEnumerateOption onlyBlendShapeRendere
mesh.SetIndices(SubMeshes[i].Indices.ToArray(), MeshTopology.Triangles, i);
}
mesh.bindposes = BindPoses.ToArray();

// blendshape
switch (onlyBlendShapeRenderers)
{
case MeshEnumerateOption.OnlyWithBlendShape:
{
AddBlendShapesToMesh(mesh);
mesh.name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME;
break;
}

case MeshEnumerateOption.All:
{
AddBlendShapesToMesh(mesh);
mesh.name = INTEGRATED_MESH_ALL_NAME;
break;
}

case MeshEnumerateOption.OnlyWithoutBlendShape:
{
mesh.name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME;
break;
}
}

// meshName
var meshNode = new GameObject();
switch (onlyBlendShapeRenderers)
if (useBlendShape)
{
case MeshEnumerateOption.OnlyWithBlendShape:
{
meshNode.name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME;
break;
}
case MeshEnumerateOption.OnlyWithoutBlendShape:
{
meshNode.name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME;
break;
}
case MeshEnumerateOption.All:
{
meshNode.name = INTEGRATED_MESH_ALL_NAME;
break;
}
AddBlendShapesToMesh(mesh);
}
mesh.name = name;

var integrated = meshNode.AddComponent<SkinnedMeshRenderer>();
integrated.sharedMesh = mesh;
integrated.sharedMaterials = SubMeshes.Select(x => x.Material).ToArray();
integrated.bones = Bones.ToArray();
Result.IntegratedRenderer = integrated;
Result.MeshMap.SharedMaterials = SubMeshes.Select(x => x.Material).ToArray();
Result.MeshMap.Bones = Bones.ToArray();
Result.MeshMap.Integrated = mesh;
return Result;
}
Expand Down
31 changes: 22 additions & 9 deletions Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace UniGLTF.MeshUtility
{
public static class MeshIntegratorUtility
{
public const string INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME = "Integrated(WithoutBlendShape)";
public const string INTEGRATED_MESH_WITH_BLENDSHAPE_NAME = "Integrated(WithBlendShape)";
public const string INTEGRATED_MESH_ALL_NAME = "Integrated(All)";

/// <summary>
/// go を root としたヒエラルキーから Renderer を集めて、統合された Mesh 作成する
/// </summary>
Expand All @@ -22,32 +25,39 @@ public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption
{
var exclude = new MeshExclude(excludes);

var integrator = new MeshUtility.MeshIntegrator();
var group = new MeshIntegrationGroup();
bool useBlendShape = false;

switch (onlyBlendShapeRenderers)
{
case MeshEnumerateOption.OnlyWithBlendShape:
{
group.Name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME;
useBlendShape = true;

foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, onlyBlendShapeRenderers))
{
if (exclude.IsExcluded(x))
{
continue;
}
integrator.Push(x);
group.Renderers.Add(x);
}
break;
}

case MeshEnumerateOption.OnlyWithoutBlendShape:
{
group.Name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME;
useBlendShape = false;

foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, onlyBlendShapeRenderers))
{
if (exclude.IsExcluded(x))
{
continue;
}
integrator.Push(x);
group.Renderers.Add(x);
}

foreach (var x in EnumerateMeshRenderer(go.transform))
Expand All @@ -56,21 +66,24 @@ public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption
{
continue;
}
integrator.Push(x);
group.Renderers.Add(x);
}

break;
}

case MeshEnumerateOption.All:
{
group.Name = INTEGRATED_MESH_ALL_NAME;
useBlendShape = true;

foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, onlyBlendShapeRenderers))
{
if (exclude.IsExcluded(x))
{
continue;
}
integrator.Push(x);
group.Renderers.Add(x);
}

foreach (var x in EnumerateMeshRenderer(go.transform))
Expand All @@ -79,14 +92,14 @@ public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption
{
continue;
}
integrator.Push(x);
group.Renderers.Add(x);
}

break;
}
}

return integrator.Integrate(onlyBlendShapeRenderers);
return MeshIntegrator.Integrate(group, useBlendShape);
}

public static IEnumerable<SkinnedMeshRenderer> EnumerateSkinnedMeshRenderer(Transform root, MeshEnumerateOption hasBlendShape)
Expand Down Expand Up @@ -177,7 +190,7 @@ public static void ReplaceMeshWithResults(GameObject copy, List<MeshIntegrationR
// Add integrated
foreach (var result in results)
{
result.IntegratedRenderer.transform.SetParent(copy.transform, false);
result.AddIntegratedRendererTo(copy);
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions Assets/UniGLTF/Runtime/UniHumanoid/AvatarDescription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,5 +306,30 @@ public static Avatar CreateAvatarForCopyHierarchy(
avatar.name = "created";
return avatar;
}

public static Avatar RecreateAvatar(Animator src)
{
if (src == null)
{
throw new ArgumentNullException("src");
}

var srcHumanBones = CachedEnum.GetValues<HumanBodyBones>()
.Where(x => x != HumanBodyBones.LastBone)
.Select(x => new { Key = x, Value = src.GetBoneTransform(x) })
.Where(x => x.Value != null)
;

var map =
srcHumanBones
.ToDictionary(x => x.Key, x => x.Value)
;

var avatarDescription = UniHumanoid.AvatarDescription.Create();
avatarDescription.SetHumanBones(map);
var avatar = avatarDescription.CreateAvatar(src.transform);
avatar.name = "created";
return avatar;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static List<BlendShapeClip> FollowBlendshapeRendererChange(List<MeshInteg
{
return clips;
}
var result = results.FirstOrDefault(x => x.IntegratedRenderer.sharedMesh.blendShapeCount > 0);
var result = results.FirstOrDefault(x => x.MeshMap.Integrated.blendShapeCount > 0);
if (result == null)
{
return clips;
Expand Down
3 changes: 2 additions & 1 deletion Assets/VRM10/Editor/MeshUtility/MeshIntegrationTab.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using UniGLTF.MeshUtility;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
Expand Down Expand Up @@ -38,7 +39,7 @@ public MeshIntegrationTab(EditorWindow editor, Vrm10MeshUtility meshUtility)
_meshUti = meshUtility;
_splitter = new VerticalSplitter(editor, 50, 50);

_groupList = new ReorderableList(_meshUti.MeshIntegrationGroups, typeof(Vrm10MeshUtility.MeshIntegrationGroup));
_groupList = new ReorderableList(_meshUti.MeshIntegrationGroups, typeof(MeshIntegrationGroup));
_groupList.drawHeaderCallback = (Rect rect) =>
{
GUI.Label(rect, "Integration group");
Expand Down
Loading

0 comments on commit e896c6c

Please sign in to comment.