mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-06-03 06:24:46 -05:00
MeshExportValidator
This commit is contained in:
parent
e21839eaa4
commit
8e8ee5cf65
|
|
@ -0,0 +1,183 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
[Serializable]
|
||||
public class MeshExportValidator : ScriptableObject
|
||||
{
|
||||
public static Mesh GetMesh(Renderer r)
|
||||
{
|
||||
if (r is SkinnedMeshRenderer smr)
|
||||
{
|
||||
return smr.sharedMesh;
|
||||
}
|
||||
if (r is MeshRenderer)
|
||||
{
|
||||
MeshFilter f = r.GetComponent<MeshFilter>();
|
||||
if (f != null)
|
||||
{
|
||||
return f.sharedMesh;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<MeshExportInfo> Meshes = new List<MeshExportInfo>();
|
||||
|
||||
public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize);
|
||||
|
||||
List<Validation> m_validations = new List<Validation>();
|
||||
|
||||
public IEnumerable<Validation> Validations => m_validations;
|
||||
|
||||
public MeshExportSettings Settings;
|
||||
|
||||
public virtual bool UseBlendShape(int index, string relativePath) => true;
|
||||
|
||||
public virtual void CalcMeshSize(ref MeshExportInfo info,
|
||||
string relativePath)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (!info.IsRendererActive)
|
||||
{
|
||||
sb.Append("[NotActive]");
|
||||
}
|
||||
|
||||
info.VertexCount = info.Mesh.vertexCount;
|
||||
info.ExportVertexSize = 0;
|
||||
info.TotalBlendShapeCount = 0;
|
||||
info.ExportBlendShapeCount = 0;
|
||||
|
||||
// float4 x 3
|
||||
// vertices
|
||||
sb.Append($"(Pos");
|
||||
if (info.HasNormal)
|
||||
{
|
||||
sb.Append("+Nom");
|
||||
info.ExportVertexSize += 4 * 3;
|
||||
}
|
||||
if (info.HasUV)
|
||||
{
|
||||
sb.Append("+UV");
|
||||
info.ExportVertexSize += 4 * 2;
|
||||
}
|
||||
if (info.HasVertexColor)
|
||||
{
|
||||
sb.Append("+Col");
|
||||
info.ExportVertexSize += 4 * 4;
|
||||
}
|
||||
if (info.HasSkinning)
|
||||
{
|
||||
// short, float x 4 weights
|
||||
sb.Append("+Skin");
|
||||
info.ExportVertexSize += (2 + 4) * 4;
|
||||
}
|
||||
// indices
|
||||
info.IndexCount = info.Mesh.triangles.Length;
|
||||
|
||||
// postion + normal ?. always tangent is ignored
|
||||
info.TotalBlendShapeCount = info.Mesh.blendShapeCount;
|
||||
info.ExportBlendShapeVertexSize = Settings.ExportOnlyBlendShapePosition ? 4 * 3 : 4 * (3 + 3);
|
||||
for (var i = 0; i < info.Mesh.blendShapeCount; ++i)
|
||||
{
|
||||
if (!UseBlendShape(i, relativePath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
++info.ExportBlendShapeCount;
|
||||
}
|
||||
|
||||
if (info.ExportBlendShapeCount > 0)
|
||||
{
|
||||
sb.Append($"+Morph x {info.ExportBlendShapeCount}");
|
||||
}
|
||||
sb.Append($") x {info.Mesh.vertexCount}");
|
||||
switch (info.VertexColor)
|
||||
{
|
||||
case MeshExportInfo.VertexColorState.ExistsAndIsUsed:
|
||||
case MeshExportInfo.VertexColorState.ExistsAndMixed: // エクスポートする
|
||||
sb.Insert(0, "[use vcolor]");
|
||||
break;
|
||||
case MeshExportInfo.VertexColorState.ExistsButNotUsed:
|
||||
sb.Insert(0, "[remove vcolor]");
|
||||
break;
|
||||
}
|
||||
if (info.ExportBlendShapeCount > 0 && !info.HasSkinning)
|
||||
{
|
||||
sb.Insert(0, "[morph without skin]");
|
||||
}
|
||||
|
||||
// total bytes
|
||||
sb.Insert(0, $"{info.ExportByteSize:#,0} Bytes = ");
|
||||
info.Summary = sb.ToString();
|
||||
}
|
||||
|
||||
bool TryGetMeshInfo(GameObject root, Renderer renderer, out MeshExportInfo info)
|
||||
{
|
||||
info = default;
|
||||
if (root == null)
|
||||
{
|
||||
info.Summary = "";
|
||||
return false;
|
||||
}
|
||||
if (renderer == null)
|
||||
{
|
||||
info.Summary = "no Renderer";
|
||||
return false;
|
||||
}
|
||||
info.Renderer = renderer;
|
||||
|
||||
if (renderer is SkinnedMeshRenderer smr)
|
||||
{
|
||||
info.Skinned = true;
|
||||
info.Mesh = smr.sharedMesh;
|
||||
info.IsRendererActive = smr.EnableForExport();
|
||||
}
|
||||
else if (renderer is MeshRenderer mr)
|
||||
{
|
||||
var filter = mr.GetComponent<MeshFilter>();
|
||||
if (filter != null)
|
||||
{
|
||||
info.Mesh = filter.sharedMesh;
|
||||
}
|
||||
info.IsRendererActive = mr.EnableForExport();
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Summary = "no Mesh";
|
||||
return false;
|
||||
}
|
||||
|
||||
info.VertexColor = MeshExportInfo.DetectVertexColor(info.Mesh, info.Renderer.sharedMaterials);
|
||||
|
||||
var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, root.transform);
|
||||
CalcMeshSize(ref info, relativePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetRoot(GameObject ExportRoot, MeshExportSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
m_validations.Clear();
|
||||
Meshes.Clear();
|
||||
if (ExportRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var renderer in ExportRoot.GetComponentsInChildren<Renderer>(true))
|
||||
{
|
||||
if (TryGetMeshInfo(ExportRoot, renderer, out MeshExportInfo info))
|
||||
{
|
||||
Meshes.Add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 15b6e58b6aafb284783d551ac475ca3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MeshUtility;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
|
|
@ -15,25 +14,8 @@ namespace VRM
|
|||
/// Meshのエクスポートサイズを試算する。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class VRMExportMeshes : ScriptableObject
|
||||
public class VRMExportMeshes : MeshExportValidator
|
||||
{
|
||||
static Mesh GetMesh(Renderer r)
|
||||
{
|
||||
if (r is SkinnedMeshRenderer smr)
|
||||
{
|
||||
return smr.sharedMesh;
|
||||
}
|
||||
if (r is MeshRenderer)
|
||||
{
|
||||
MeshFilter f = r.GetComponent<MeshFilter>();
|
||||
if (f != null)
|
||||
{
|
||||
return f.sharedMesh;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static bool ClipsContainsName(IReadOnlyList<BlendShapeClip> clips, bool onlyPreset, BlendShapeBinding binding)
|
||||
{
|
||||
foreach (var c in clips)
|
||||
|
|
@ -57,172 +39,42 @@ namespace VRM
|
|||
return false;
|
||||
}
|
||||
|
||||
public List<MeshExportInfo> Meshes = new List<MeshExportInfo>();
|
||||
public VRMExportSettings VRMExportSettings;
|
||||
public List<BlendShapeClip> Clips;
|
||||
|
||||
public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize);
|
||||
|
||||
List<Validation> m_validations = new List<Validation>();
|
||||
public IEnumerable<Validation> Validations => m_validations;
|
||||
|
||||
public static void CalcMeshSize(ref MeshExportInfo info,
|
||||
string relativePath, VRMExportSettings settings, IReadOnlyList<BlendShapeClip> clips)
|
||||
public override bool UseBlendShape(int index, string relativePath)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (!info.IsRendererActive)
|
||||
if (VRMExportSettings.ReduceBlendshape)
|
||||
{
|
||||
sb.Append("[NotActive]");
|
||||
}
|
||||
|
||||
info.VertexCount = info.Mesh.vertexCount;
|
||||
info.ExportVertexSize = 0;
|
||||
info.TotalBlendShapeCount = 0;
|
||||
info.ExportBlendShapeCount = 0;
|
||||
|
||||
// float4 x 3
|
||||
// vertices
|
||||
sb.Append($"(Pos");
|
||||
if (info.HasNormal)
|
||||
{
|
||||
sb.Append("+Nom");
|
||||
info.ExportVertexSize += 4 * 3;
|
||||
}
|
||||
if (info.HasUV)
|
||||
{
|
||||
sb.Append("+UV");
|
||||
info.ExportVertexSize += 4 * 2;
|
||||
}
|
||||
if (info.HasVertexColor)
|
||||
{
|
||||
sb.Append("+Col");
|
||||
info.ExportVertexSize += 4 * 4;
|
||||
}
|
||||
if (info.HasSkinning)
|
||||
{
|
||||
// short, float x 4 weights
|
||||
sb.Append("+Skin");
|
||||
info.ExportVertexSize += (2 + 4) * 4;
|
||||
}
|
||||
// indices
|
||||
info.IndexCount = info.Mesh.triangles.Length;
|
||||
|
||||
// postion + normal ?. always tangent is ignored
|
||||
info.TotalBlendShapeCount = info.Mesh.blendShapeCount;
|
||||
info.ExportBlendShapeVertexSize = settings.OnlyBlendshapePosition ? 4 * 3 : 4 * (3 + 3);
|
||||
for (var i = 0; i < info.Mesh.blendShapeCount; ++i)
|
||||
{
|
||||
// var name = Mesh.GetBlendShapeName(i);
|
||||
if (settings.ReduceBlendshape)
|
||||
if (!ClipsContainsName(Clips, VRMExportSettings, new BlendShapeBinding
|
||||
{
|
||||
if (!ClipsContainsName(clips, settings.ReduceBlendshapeClip, new BlendShapeBinding
|
||||
{
|
||||
Index = i,
|
||||
RelativePath = relativePath,
|
||||
}))
|
||||
{
|
||||
// skip
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
++info.ExportBlendShapeCount;
|
||||
}
|
||||
|
||||
if (info.ExportBlendShapeCount > 0)
|
||||
{
|
||||
sb.Append($"+Morph x {info.ExportBlendShapeCount}");
|
||||
}
|
||||
sb.Append($") x {info.Mesh.vertexCount}");
|
||||
switch (info.VertexColor)
|
||||
{
|
||||
case MeshExportInfo.VertexColorState.ExistsAndIsUsed:
|
||||
case MeshExportInfo.VertexColorState.ExistsAndMixed: // エクスポートする
|
||||
sb.Insert(0, "[use vcolor]");
|
||||
break;
|
||||
case MeshExportInfo.VertexColorState.ExistsButNotUsed:
|
||||
sb.Insert(0, "[remove vcolor]");
|
||||
break;
|
||||
}
|
||||
if (info.ExportBlendShapeCount > 0 && !info.HasSkinning)
|
||||
{
|
||||
sb.Insert(0, "[morph without skin]");
|
||||
}
|
||||
|
||||
// total bytes
|
||||
sb.Insert(0, $"{info.ExportByteSize:#,0} Bytes = ");
|
||||
info.Summary = sb.ToString();
|
||||
}
|
||||
|
||||
bool TryGetMeshInfo(GameObject root, Renderer renderer, IReadOnlyList<BlendShapeClip> clips, VRMExportSettings settings, out MeshExportInfo info)
|
||||
{
|
||||
info = default;
|
||||
if (root == null)
|
||||
{
|
||||
info.Summary = "";
|
||||
return false;
|
||||
}
|
||||
if (renderer == null)
|
||||
{
|
||||
info.Summary = "no Renderer";
|
||||
return false;
|
||||
}
|
||||
info.Renderer = renderer;
|
||||
|
||||
if (renderer is SkinnedMeshRenderer smr)
|
||||
{
|
||||
info.Skinned = true;
|
||||
info.Mesh = smr.sharedMesh;
|
||||
info.IsRendererActive = smr.EnableForExport();
|
||||
}
|
||||
else if (renderer is MeshRenderer mr)
|
||||
{
|
||||
var filter = mr.GetComponent<MeshFilter>();
|
||||
if (filter != null)
|
||||
Index = index,
|
||||
RelativePath = relativePath,
|
||||
}))
|
||||
{
|
||||
info.Mesh = filter.sharedMesh;
|
||||
// skip
|
||||
return false;
|
||||
}
|
||||
info.IsRendererActive = mr.EnableForExport();
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Summary = "no Mesh";
|
||||
return false;
|
||||
}
|
||||
|
||||
info.VertexColor = MeshExportInfo.DetectVertexColor(info.Mesh, info.Renderer.sharedMaterials);
|
||||
|
||||
var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, root.transform);
|
||||
CalcMeshSize(ref info, relativePath, settings, clips);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetRoot(GameObject ExportRoot, VRMExportSettings settings)
|
||||
{
|
||||
m_validations.Clear();
|
||||
Meshes.Clear();
|
||||
if (ExportRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var clips = new List<BlendShapeClip>();
|
||||
VRMExportSettings = settings;
|
||||
Clips = new List<BlendShapeClip>();
|
||||
var proxy = ExportRoot.GetComponent<VRMBlendShapeProxy>();
|
||||
if (proxy != null)
|
||||
{
|
||||
// Export サイズ の 計算
|
||||
if (proxy.BlendShapeAvatar != null)
|
||||
{
|
||||
clips.AddRange(proxy.BlendShapeAvatar.Clips);
|
||||
Clips.AddRange(proxy.BlendShapeAvatar.Clips);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var renderer in ExportRoot.GetComponentsInChildren<Renderer>(true))
|
||||
{
|
||||
if (TryGetMeshInfo(ExportRoot, renderer, clips, settings, out MeshExportInfo info))
|
||||
{
|
||||
Meshes.Add(info);
|
||||
}
|
||||
}
|
||||
SetRoot(ExportRoot, settings.MeshExportSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MeshUtility;
|
||||
using UniGLTF;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user