summaryrefslogtreecommitdiff
path: root/Assets/ThirdParty/VRM/MeshUtility/Runtime/MeshIntegratorUtility.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/ThirdParty/VRM/MeshUtility/Runtime/MeshIntegratorUtility.cs')
-rw-r--r--Assets/ThirdParty/VRM/MeshUtility/Runtime/MeshIntegratorUtility.cs140
1 files changed, 140 insertions, 0 deletions
diff --git a/Assets/ThirdParty/VRM/MeshUtility/Runtime/MeshIntegratorUtility.cs b/Assets/ThirdParty/VRM/MeshUtility/Runtime/MeshIntegratorUtility.cs
new file mode 100644
index 00000000..cfb1742e
--- /dev/null
+++ b/Assets/ThirdParty/VRM/MeshUtility/Runtime/MeshIntegratorUtility.cs
@@ -0,0 +1,140 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+namespace MeshUtility
+{
+ public static class MeshIntegratorUtility
+ {
+ /// <summary>
+ /// go を root としたヒエラルキーから Renderer を集めて、統合された Mesh 作成する
+ /// </summary>
+ /// <param name="go"></param>
+ /// <param name="onlyBlendShapeRenderers">BlendShapeを保持するSkinnedMeshRendererのみ/BlendShapeを保持しないSkinnedMeshRenderer + MeshRenderer</param>
+ /// <returns></returns>
+ public static MeshIntegrationResult Integrate(GameObject go, bool onlyBlendShapeRenderers)
+ {
+ var result = new MeshIntegrationResult();
+
+ var meshNode = new GameObject();
+ if (onlyBlendShapeRenderers)
+ {
+ meshNode.name = "MeshIntegrator(BlendShape)";
+ }
+ else
+ {
+ meshNode.name = "MeshIntegrator";
+ }
+ meshNode.transform.SetParent(go.transform, false);
+
+ // レンダラから情報を集める
+ var integrator = new MeshUtility.MeshIntegrator();
+
+ if (onlyBlendShapeRenderers)
+ {
+ foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, true))
+ {
+ integrator.Push(x);
+ result.SourceSkinnedMeshRenderers.Add(x);
+ }
+ }
+ else
+ {
+ foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, false))
+ {
+ integrator.Push(x);
+ result.SourceSkinnedMeshRenderers.Add(x);
+ }
+
+ foreach (var x in EnumerateMeshRenderer(go.transform))
+ {
+ integrator.Push(x);
+ result.SourceMeshRenderers.Add(x);
+ }
+ }
+
+ var mesh = new Mesh();
+ mesh.name = "integrated";
+
+ if (integrator.Positions.Count > ushort.MaxValue)
+ {
+ Debug.LogFormat("exceed 65535 vertices: {0}", integrator.Positions.Count);
+ mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
+ }
+
+ mesh.vertices = integrator.Positions.ToArray();
+ mesh.normals = integrator.Normals.ToArray();
+ mesh.uv = integrator.UV.ToArray();
+ mesh.tangents = integrator.Tangents.ToArray();
+ mesh.boneWeights = integrator.BoneWeights.ToArray();
+ mesh.subMeshCount = integrator.SubMeshes.Count;
+ for (var i = 0; i < integrator.SubMeshes.Count; ++i)
+ {
+ mesh.SetIndices(integrator.SubMeshes[i].Indices.ToArray(), MeshTopology.Triangles, i);
+ }
+ mesh.bindposes = integrator.BindPoses.ToArray();
+
+ if (onlyBlendShapeRenderers)
+ {
+ integrator.AddBlendShapesToMesh(mesh);
+ }
+
+ var integrated = meshNode.AddComponent<SkinnedMeshRenderer>();
+ integrated.sharedMesh = mesh;
+ integrated.sharedMaterials = integrator.SubMeshes.Select(x => x.Material).ToArray();
+ integrated.bones = integrator.Bones.ToArray();
+ result.IntegratedRenderer = integrated;
+
+ return result;
+ }
+
+ public static IEnumerable<SkinnedMeshRenderer> EnumerateSkinnedMeshRenderer(Transform root, bool hasBlendShape)
+ {
+ foreach (var x in Traverse(root))
+ {
+ var renderer = x.GetComponent<SkinnedMeshRenderer>();
+ if (renderer != null &&
+ renderer.gameObject.activeInHierarchy &&
+ renderer.sharedMesh != null &&
+ renderer.enabled &&
+ renderer.sharedMesh.blendShapeCount > 0 == hasBlendShape)
+ {
+ yield return renderer;
+ }
+ }
+ }
+
+ public static IEnumerable<MeshRenderer> EnumerateMeshRenderer(Transform root)
+ {
+ foreach (var x in Traverse(root))
+ {
+ var renderer = x.GetComponent<MeshRenderer>();
+ var filter = x.GetComponent<MeshFilter>();
+
+ if (renderer != null &&
+ filter != null &&
+ renderer.gameObject.activeInHierarchy &&
+ filter.sharedMesh != null)
+ {
+ yield return renderer;
+ }
+ }
+ }
+
+ private static IEnumerable<Transform> Traverse(Transform parent)
+ {
+ if (parent.gameObject.activeSelf)
+ {
+ yield return parent;
+
+ foreach (Transform child in parent)
+ {
+ foreach (var x in Traverse(child))
+ {
+ yield return x;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file