mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-23 19:15:07 -05:00
Merge pull request #1005 from ousttrue/fix/mesh_export_info
MeshWithRenderer を MeshExportInfo に統合
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public static class ExporterExtensions
|
||||
{
|
||||
public static bool EnableForExport(this Component mono)
|
||||
{
|
||||
if (mono.transform.Ancestors().Any(x => !x.gameObject.activeSelf))
|
||||
{
|
||||
// 自分か祖先に !activeSelf がいる
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace UniGLTF
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings);
|
||||
m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings, new DefualtBlendShapeExportFilter());
|
||||
}
|
||||
|
||||
protected override bool DoGUI(bool isValid)
|
||||
|
||||
@@ -31,148 +31,12 @@ namespace UniGLTF
|
||||
|
||||
public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize);
|
||||
|
||||
public MeshExportSettings Settings;
|
||||
|
||||
public virtual bool UseBlendShape(int index, string relativePath) => true;
|
||||
|
||||
public virtual void CalcMeshSize(ref MeshExportInfo info,
|
||||
string relativePath)
|
||||
public void SetRoot(GameObject ExportRoot, MeshExportSettings settings, IBlendShapeExportFilter blendShapeFilter)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (!info.IsRendererActive)
|
||||
MeshExportInfo.GetInfo(ExportRoot.transform.Traverse().Skip(1), Meshes, settings);
|
||||
foreach(var info in Meshes)
|
||||
{
|
||||
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 VertexColorState.ExistsAndIsUsed:
|
||||
case VertexColorState.ExistsAndMixed: // エクスポートする
|
||||
sb.Insert(0, "[use vcolor]");
|
||||
break;
|
||||
case 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 = VertexColorUtility.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;
|
||||
Meshes.Clear();
|
||||
if (ExportRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var renderer in ExportRoot.GetComponentsInChildren<Renderer>(true))
|
||||
{
|
||||
if (TryGetMeshInfo(ExportRoot, renderer, out MeshExportInfo info))
|
||||
{
|
||||
Meshes.Add(info);
|
||||
}
|
||||
info.CalcMeshSize(ExportRoot, info.Renderers[0].Item1, settings, blendShapeFilter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,28 +68,28 @@ namespace UniGLTF
|
||||
foreach (var info in Meshes)
|
||||
{
|
||||
// invalid materials.len
|
||||
if (info.Renderer.sharedMaterials.Length < info.Mesh.subMeshCount)
|
||||
if (info.Materials.Length < info.Mesh.subMeshCount)
|
||||
{
|
||||
// submesh より material の方が少ない
|
||||
yield return Validation.Error(Messages.MATERIALS_LESS_THAN_SUBMESH_COUNT.Msg());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.Renderer.sharedMaterials.Length > info.Mesh.subMeshCount)
|
||||
if (info.Materials.Length > info.Mesh.subMeshCount)
|
||||
{
|
||||
// submesh より material の方が多い
|
||||
yield return Validation.Warning(Messages.MATERIALS_GREATER_THAN_SUBMESH_COUNT.Msg());
|
||||
}
|
||||
|
||||
if (info.Renderer.sharedMaterials.Take(info.Mesh.subMeshCount).Any(x => x == null))
|
||||
if (info.Materials.Take(info.Mesh.subMeshCount).Any(x => x == null))
|
||||
{
|
||||
// material に null が含まれる(unity で magenta になっているはず)
|
||||
yield return Validation.Error($"{info.Renderer}: {Messages.MATERIALS_CONTAINS_NULL.Msg()}");
|
||||
yield return Validation.Error($"{info.Renderers}: {Messages.MATERIALS_CONTAINS_NULL.Msg()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var m in Meshes.SelectMany(x => x.Renderer.sharedMaterials).Distinct())
|
||||
foreach (var m in Meshes.SelectMany(x => x.Materials).Distinct())
|
||||
{
|
||||
if (m == null)
|
||||
{
|
||||
|
||||
@@ -40,12 +40,15 @@ namespace UniGLTF
|
||||
var (left, right) = LeftRight(r.x, r.y, col0, r.width - col0, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.LabelField(left, $"{i,3}");
|
||||
|
||||
GUI.enabled = false;
|
||||
EditorGUI.ObjectField(right, info.Renderer, info.Renderer.GetType(), true);
|
||||
|
||||
right.y += EditorGUIUtility.singleLineHeight;
|
||||
EditorGUI.ObjectField(right, info.Mesh, info.Renderer.GetType(), true);
|
||||
GUI.enabled = true;
|
||||
using (new EditorGUI.DisabledScope(false))
|
||||
{
|
||||
foreach (var (renderer, _) in info.Renderers)
|
||||
{
|
||||
EditorGUI.ObjectField(right, renderer, info.Renderers.GetType(), true);
|
||||
}
|
||||
right.y += EditorGUIUtility.singleLineHeight;
|
||||
EditorGUI.ObjectField(right, info.Mesh, info.Renderers.GetType(), true);
|
||||
}
|
||||
|
||||
right.y += EditorGUIUtility.singleLineHeight;
|
||||
EditorGUI.LabelField(right, info.Summary);
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace UniGLTF
|
||||
{
|
||||
var current = self;
|
||||
|
||||
var split = path.Split(new [] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
var split = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var childName in split)
|
||||
{
|
||||
@@ -334,5 +334,15 @@ namespace UniGLTF
|
||||
}
|
||||
return go.AddComponent<T>();
|
||||
}
|
||||
|
||||
public static bool EnableForExport(this Component mono)
|
||||
{
|
||||
if (mono.transform.Ancestors().Any(x => !x.gameObject.activeSelf))
|
||||
{
|
||||
// 自分か祖先に !activeSelf がいる
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/BlendShapeFilter.cs
Normal file
18
Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/BlendShapeFilter.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace UniGLTF
|
||||
{
|
||||
public interface IBlendShapeExportFilter
|
||||
{
|
||||
bool UseBlendShape(int blendShapeIndex, string relativePath);
|
||||
}
|
||||
|
||||
public class DefualtBlendShapeExportFilter : IBlendShapeExportFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Export all blendshape
|
||||
/// </summary>
|
||||
/// <param name="blendShapeIndex"></param>
|
||||
/// <param name="relativePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool UseBlendShape(int blendShapeIndex, string relativePath) => true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18a610aab46d5034cb787ab237e3dea2
|
||||
guid: d962c03c08e3d3a4eb5c52f5b4e0c93f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,25 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
[Serializable]
|
||||
public struct MeshExportInfo
|
||||
public class MeshExportInfo
|
||||
{
|
||||
public Renderer Renderer;
|
||||
#region この2つの組が gltf mesh の Unique なキーとなる
|
||||
public Mesh Mesh;
|
||||
public bool IsRendererActive;
|
||||
public bool Skinned;
|
||||
public Material[] Materials;
|
||||
|
||||
public bool IsSameMeshAndMaterials(MeshExportInfo other)
|
||||
{
|
||||
return IsSameMeshAndMaterials(other.Mesh, other.Materials);
|
||||
}
|
||||
|
||||
public bool IsSameMeshAndMaterials(Mesh mesh, Material[] materials)
|
||||
{
|
||||
if (Mesh != mesh) return false;
|
||||
if (Materials.Length != materials.Length) return false;
|
||||
for (var i = 0; i < Materials.Length; i++)
|
||||
{
|
||||
if (Materials[i] != materials[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsSameMeshAndMaterials(Renderer r)
|
||||
{
|
||||
if (r is SkinnedMeshRenderer smr)
|
||||
{
|
||||
return IsSameMeshAndMaterials(smr.sharedMesh, smr.sharedMaterials);
|
||||
}
|
||||
else if (r is MeshRenderer mr)
|
||||
{
|
||||
var filter = r.GetComponent<MeshFilter>();
|
||||
if (filter == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return IsSameMeshAndMaterials(filter.sharedMesh, mr.sharedMaterials);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetSameMeshIndex(List<MeshExportInfo> meshWithRenderers, Mesh mesh, Material[] materials, out int meshIndex)
|
||||
{
|
||||
for (var i = 0; i < meshWithRenderers.Count; i++)
|
||||
{
|
||||
if (meshWithRenderers[i].IsSameMeshAndMaterials(mesh, materials))
|
||||
{
|
||||
meshIndex = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
meshIndex = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanExport
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Mesh == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Mesh.vertexCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Materials == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Materials.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// ひとつの Mesh を複数の Renderer が共有することがありうる
|
||||
/// </summary>
|
||||
List<(Renderer, Transform[] UniqueBones)> _renderers;
|
||||
public IReadOnlyList<(Renderer, Transform[] UniqueBones)> Renderers => _renderers;
|
||||
|
||||
public bool IsRendererActive => Renderers.Any(x => x.Item1.EnableForExport());
|
||||
|
||||
#region SkinnedMeshRenderer
|
||||
public bool Skinned;
|
||||
int[] JointIndexMap;
|
||||
|
||||
/// <summary>
|
||||
/// glTF は skinning の boneList の重複を許可しない
|
||||
/// (unity は ok)
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public int GetJointIndex(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
if (JointIndexMap != null)
|
||||
{
|
||||
return JointIndexMap[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Matrix4x4> GetBindPoses()
|
||||
{
|
||||
var used = new HashSet<int>();
|
||||
for (int i = 0; i < JointIndexMap.Length; ++i)
|
||||
{
|
||||
var index = JointIndexMap[i];
|
||||
if (used.Add(index))
|
||||
{
|
||||
yield return Mesh.bindposes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region VertexAttribute
|
||||
public bool HasNormal => Mesh != null && Mesh.normals != null && Mesh.normals.Length == Mesh.vertexCount;
|
||||
public bool HasUV => Mesh != null && Mesh.uv != null && Mesh.uv.Length == Mesh.vertexCount;
|
||||
|
||||
public bool HasVertexColor => Mesh.colors != null && Mesh.colors.Length == Mesh.vertexCount
|
||||
public bool HasVertexColor => Mesh != null && Mesh.colors != null && Mesh.colors.Length == Mesh.vertexCount
|
||||
&& VertexColor == VertexColorState.ExistsAndIsUsed
|
||||
|| VertexColor == VertexColorState.ExistsAndMixed // Export する
|
||||
;
|
||||
|
||||
public bool HasSkinning => Mesh.boneWeights != null && Mesh.boneWeights.Length == Mesh.vertexCount;
|
||||
public bool HasSkinning => Mesh != null && Mesh.boneWeights != null && Mesh.boneWeights.Length == Mesh.vertexCount;
|
||||
|
||||
public VertexColorState VertexColor;
|
||||
|
||||
@@ -31,20 +160,253 @@ namespace UniGLTF
|
||||
/// [SkinningWeight]
|
||||
/// </summary>
|
||||
public int ExportVertexSize;
|
||||
#endregion
|
||||
|
||||
#region Triangles
|
||||
public int IndexCount;
|
||||
|
||||
// int 決め打ち
|
||||
public int IndicesSize => IndexCount * 4;
|
||||
#endregion
|
||||
|
||||
#region BlendShape
|
||||
public int ExportBlendShapeVertexSize;
|
||||
|
||||
public int TotalBlendShapeCount;
|
||||
|
||||
public int ExportBlendShapeCount;
|
||||
#endregion
|
||||
|
||||
#region Summary
|
||||
public int ExportByteSize => ExportVertexSize * VertexCount + IndicesSize + ExportBlendShapeCount * ExportBlendShapeVertexSize * VertexCount;
|
||||
|
||||
public string Summary;
|
||||
#endregion
|
||||
|
||||
MeshExportInfo(Renderer renderer, MeshExportSettings settings)
|
||||
{
|
||||
if (renderer == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
Materials = renderer.sharedMaterials;
|
||||
_renderers = new List<(Renderer, Transform[])>();
|
||||
if (renderer is SkinnedMeshRenderer smr)
|
||||
{
|
||||
Skinned = true;
|
||||
Mesh = smr.sharedMesh;
|
||||
}
|
||||
else if (renderer is MeshRenderer mr)
|
||||
{
|
||||
var filter = mr.GetComponent<MeshFilter>();
|
||||
if (filter != null)
|
||||
{
|
||||
Mesh = filter.sharedMesh;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
if (Mesh == null)
|
||||
{
|
||||
Summary = "no mesh";
|
||||
}
|
||||
|
||||
VertexColor = VertexColorUtility.DetectVertexColor(Mesh, Materials);
|
||||
|
||||
PushRenderer(renderer);
|
||||
}
|
||||
|
||||
void PushRenderer(Renderer renderer)
|
||||
{
|
||||
if (renderer is SkinnedMeshRenderer smr)
|
||||
{
|
||||
if (smr.bones != null && smr.bones.Length > 0)
|
||||
{
|
||||
var uniqueBones = smr.bones.Distinct().ToArray();
|
||||
var jointIndexMap = new int[smr.bones.Length];
|
||||
var bones = smr.bones;
|
||||
for (int i = 0; i < bones.Length; ++i)
|
||||
{
|
||||
jointIndexMap[i] = Array.IndexOf(uniqueBones, bones[i]);
|
||||
}
|
||||
_renderers.Add((smr, uniqueBones));
|
||||
|
||||
if (JointIndexMap != null)
|
||||
{
|
||||
if (!JointIndexMap.SequenceEqual(jointIndexMap))
|
||||
{
|
||||
// edge case
|
||||
throw new NotImplementedException("different jointIndexMap is not supported");
|
||||
}
|
||||
}
|
||||
JointIndexMap = jointIndexMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
// maybe blendshape only SkinnedMeshRenderer
|
||||
_renderers.Add((smr, null));
|
||||
}
|
||||
}
|
||||
else if (renderer is MeshRenderer mr)
|
||||
{
|
||||
_renderers.Add((mr, null));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static MeshExportInfo Create(GameObject go)
|
||||
{
|
||||
var list = new List<MeshExportInfo>();
|
||||
GetInfo(go.transform.Traverse(), list, MeshExportSettings.Default);
|
||||
return list[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヒエラルキーからエクスポートする Mesh の情報を収集する
|
||||
/// </summary>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="blendShapeFilter"> blendShape の export を filtering する </param>
|
||||
public static void GetInfo(IEnumerable<Transform> nodes, List<MeshExportInfo> list, MeshExportSettings settings)
|
||||
{
|
||||
list.Clear();
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var renderer = node.GetComponent<Renderer>();
|
||||
if (renderer == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var found = list.FirstOrDefault(x => x.IsSameMeshAndMaterials(renderer));
|
||||
if (found != null)
|
||||
{
|
||||
found.PushRenderer(renderer);
|
||||
continue;
|
||||
}
|
||||
|
||||
var info = new MeshExportInfo(renderer, settings);
|
||||
if (info.Mesh != null)
|
||||
{
|
||||
list.Add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryGetMeshInfo()
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void CalcMeshSize(
|
||||
GameObject root,
|
||||
Renderer renderer,
|
||||
MeshExportSettings settings,
|
||||
IBlendShapeExportFilter blendShapeFilter
|
||||
)
|
||||
{
|
||||
var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, root.transform);
|
||||
CalcMeshSize(relativePath, settings, blendShapeFilter);
|
||||
}
|
||||
|
||||
public void CalcMeshSize(
|
||||
string relativePath,
|
||||
MeshExportSettings settings,
|
||||
IBlendShapeExportFilter blendShapeFilter
|
||||
)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (!IsRendererActive)
|
||||
{
|
||||
sb.Append("[NotActive]");
|
||||
}
|
||||
|
||||
if (Mesh == null)
|
||||
{
|
||||
sb.Append("[NoMesh]");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
VertexCount = Mesh.vertexCount;
|
||||
ExportVertexSize = 0;
|
||||
TotalBlendShapeCount = 0;
|
||||
ExportBlendShapeCount = 0;
|
||||
|
||||
// float4 x 3
|
||||
// vertices
|
||||
sb.Append($"(Pos");
|
||||
if (HasNormal)
|
||||
{
|
||||
sb.Append("+Nom");
|
||||
ExportVertexSize += 4 * 3;
|
||||
}
|
||||
if (HasUV)
|
||||
{
|
||||
sb.Append("+UV");
|
||||
ExportVertexSize += 4 * 2;
|
||||
}
|
||||
if (HasVertexColor)
|
||||
{
|
||||
sb.Append("+Col");
|
||||
ExportVertexSize += 4 * 4;
|
||||
}
|
||||
if (HasSkinning)
|
||||
{
|
||||
// short, float x 4 weights
|
||||
sb.Append("+Skin");
|
||||
ExportVertexSize += (2 + 4) * 4;
|
||||
}
|
||||
// indices
|
||||
IndexCount = Mesh.triangles.Length;
|
||||
|
||||
// postion + normal ?. always tangent is ignored
|
||||
TotalBlendShapeCount = Mesh.blendShapeCount;
|
||||
ExportBlendShapeVertexSize = settings.ExportOnlyBlendShapePosition ? 4 * 3 : 4 * (3 + 3);
|
||||
for (var i = 0; i < Mesh.blendShapeCount; ++i)
|
||||
{
|
||||
if (!blendShapeFilter.UseBlendShape(i, relativePath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
++ExportBlendShapeCount;
|
||||
}
|
||||
|
||||
if (ExportBlendShapeCount > 0)
|
||||
{
|
||||
sb.Append($"+Morph x {ExportBlendShapeCount}");
|
||||
}
|
||||
sb.Append($") x {Mesh.vertexCount}");
|
||||
switch (VertexColor)
|
||||
{
|
||||
case VertexColorState.ExistsAndIsUsed:
|
||||
case VertexColorState.ExistsAndMixed: // エクスポートする
|
||||
sb.Insert(0, "[use vcolor]");
|
||||
break;
|
||||
case VertexColorState.ExistsButNotUsed:
|
||||
sb.Insert(0, "[remove vcolor]");
|
||||
break;
|
||||
}
|
||||
if (ExportBlendShapeCount > 0 && !HasSkinning)
|
||||
{
|
||||
sb.Insert(0, "[morph without skin]");
|
||||
}
|
||||
|
||||
// total bytes
|
||||
sb.Insert(0, $"{ExportByteSize:#,0} Bytes = ");
|
||||
}
|
||||
Summary = sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace UniGLTF
|
||||
public static class MeshExporter_DividedVertexBuffer
|
||||
{
|
||||
public static (glTFMesh, Dictionary<int, int>) Export(glTF gltf, int bufferIndex,
|
||||
MeshWithRenderer unityMesh, List<Material> unityMaterials,
|
||||
MeshExportInfo unityMesh, List<Material> unityMaterials,
|
||||
IAxisInverter axisInverter, MeshExportSettings settings)
|
||||
{
|
||||
var mesh = unityMesh.Mesh;
|
||||
@@ -58,7 +58,7 @@ namespace UniGLTF
|
||||
}
|
||||
}
|
||||
|
||||
var material = unityMesh.Renderer.sharedMaterials[i];
|
||||
var material = unityMesh.Materials[i];
|
||||
var materialIndex = -1;
|
||||
if (material != null)
|
||||
{
|
||||
|
||||
@@ -24,11 +24,11 @@ namespace UniGLTF
|
||||
/// <param name="settings"></param>
|
||||
/// <returns></returns>
|
||||
public static (glTFMesh, Dictionary<int, int> blendShapeIndexMap) Export(glTF gltf, int bufferIndex,
|
||||
MeshWithRenderer unityMesh, List<Material> unityMaterials,
|
||||
MeshExportInfo unityMesh, List<Material> unityMaterials,
|
||||
IAxisInverter axisInverter, MeshExportSettings settings)
|
||||
{
|
||||
var mesh = unityMesh.Mesh;
|
||||
var materials = unityMesh.Renderer.sharedMaterials;
|
||||
var materials = unityMesh.Materials;
|
||||
var positions = mesh.vertices.Select(axisInverter.InvertVector3).ToArray();
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER);
|
||||
gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
|
||||
@@ -135,7 +135,7 @@ namespace UniGLTF
|
||||
|
||||
if (j >= materials.Length)
|
||||
{
|
||||
Debug.LogWarningFormat("{0}.materials is not enough", unityMesh.Renderer.name);
|
||||
Debug.LogWarningFormat("{0}.materials is not enough", unityMesh.Mesh.name);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public struct MeshWithRenderer
|
||||
{
|
||||
public readonly Mesh Mesh;
|
||||
public readonly Renderer Renderer;
|
||||
public readonly Transform[] UniqueBones;
|
||||
readonly int[] JointIndexMap;
|
||||
|
||||
public MeshWithRenderer(Transform x)
|
||||
{
|
||||
Mesh = x.GetSharedMesh();
|
||||
Renderer = x.GetComponent<Renderer>();
|
||||
|
||||
if (Renderer is SkinnedMeshRenderer skin && skin.bones != null && skin.bones.Length > 0)
|
||||
{
|
||||
// has joints
|
||||
var uniqueBones = skin.bones.Distinct().ToArray();
|
||||
UniqueBones = uniqueBones;
|
||||
JointIndexMap = new int[skin.bones.Length];
|
||||
|
||||
var bones = skin.bones;
|
||||
for (int i = 0; i < bones.Length; ++i)
|
||||
{
|
||||
JointIndexMap[i] = Array.IndexOf(uniqueBones, bones[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UniqueBones = null;
|
||||
JointIndexMap = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// glTF は skinning の boneList の重複を許可しない
|
||||
/// (unity は ok)
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public int GetJointIndex(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
if (JointIndexMap != null)
|
||||
{
|
||||
return JointIndexMap[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Matrix4x4> GetBindPoses()
|
||||
{
|
||||
var used = new HashSet<int>();
|
||||
for (int i = 0; i < JointIndexMap.Length; ++i)
|
||||
{
|
||||
var index = JointIndexMap[i];
|
||||
if (used.Add(index))
|
||||
{
|
||||
yield return Mesh.bindposes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<MeshWithRenderer> FromNodes(IEnumerable<Transform> nodes)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var x = new MeshWithRenderer(node);
|
||||
if (x.Mesh == null)
|
||||
{
|
||||
continue; ;
|
||||
}
|
||||
if (x.Renderer == null
|
||||
|| x.Renderer.sharedMaterials == null
|
||||
|| x.Renderer.sharedMaterials.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return x;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSameMeshAndMaterials(MeshWithRenderer other)
|
||||
{
|
||||
return IsSameMeshAndMaterials(other.Mesh, other.Renderer.sharedMaterials);
|
||||
}
|
||||
|
||||
public bool IsSameMeshAndMaterials(Mesh mesh, Material[] materials)
|
||||
{
|
||||
if (Mesh != mesh) return false;
|
||||
if (Renderer.sharedMaterials.Length != materials.Length) return false;
|
||||
for (var i = 0; i < Renderer.sharedMaterials.Length; i++)
|
||||
{
|
||||
if (Renderer.sharedMaterials[i] != materials[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed51e6c1221d3b744a914e977e875122
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -138,7 +138,7 @@ namespace UniGLTF
|
||||
}
|
||||
|
||||
#region Export
|
||||
static glTFNode ExportNode(Transform x, List<Transform> nodes, List<MeshWithRenderer> meshWithRenderers, List<SkinnedMeshRenderer> skins)
|
||||
static glTFNode ExportNode(Transform x, List<Transform> nodes, List<MeshExportInfo> meshWithRenderers, List<SkinnedMeshRenderer> skins)
|
||||
{
|
||||
var node = new glTFNode
|
||||
{
|
||||
@@ -160,7 +160,7 @@ namespace UniGLTF
|
||||
{
|
||||
var mesh = meshFilter.sharedMesh;
|
||||
var materials = meshRenderer.sharedMaterials;
|
||||
if (TryGetSameMeshIndex(meshWithRenderers, mesh, materials, out int meshIndex))
|
||||
if (MeshExportInfo.TryGetSameMeshIndex(meshWithRenderers, mesh, materials, out int meshIndex))
|
||||
{
|
||||
node.mesh = meshIndex;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ namespace UniGLTF
|
||||
{
|
||||
var mesh = skinnedMeshRenderer.sharedMesh;
|
||||
var materials = skinnedMeshRenderer.sharedMaterials;
|
||||
if (TryGetSameMeshIndex(meshWithRenderers, mesh, materials, out int meshIndex))
|
||||
if (MeshExportInfo.TryGetSameMeshIndex(meshWithRenderers, mesh, materials, out int meshIndex))
|
||||
{
|
||||
node.mesh = meshIndex;
|
||||
node.skin = skins.IndexOf(skinnedMeshRenderer);
|
||||
@@ -203,21 +203,6 @@ namespace UniGLTF
|
||||
return node;
|
||||
}
|
||||
|
||||
private static bool TryGetSameMeshIndex(List<MeshWithRenderer> meshWithRenderers, Mesh mesh, Material[] materials, out int meshIndex)
|
||||
{
|
||||
for (var i = 0; i < meshWithRenderers.Count; i++)
|
||||
{
|
||||
if (meshWithRenderers[i].IsSameMeshAndMaterials(mesh, materials))
|
||||
{
|
||||
meshIndex = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
meshIndex = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void ExportExtensions(ITextureSerializer textureSerializer)
|
||||
{
|
||||
// do nothing
|
||||
@@ -232,15 +217,11 @@ namespace UniGLTF
|
||||
.Skip(1) // exclude root object for the symmetry with the importer
|
||||
.ToList();
|
||||
|
||||
var unityMeshes = MeshWithRenderer.FromNodes(Nodes).Where(x => x.Mesh.vertices.Any()).ToList();
|
||||
var uniqueUnityMeshes = new List<MeshWithRenderer>();
|
||||
foreach (var um in unityMeshes)
|
||||
{
|
||||
if (!uniqueUnityMeshes.Any(x => x.IsSameMeshAndMaterials(um))) uniqueUnityMeshes.Add(um);
|
||||
}
|
||||
var uniqueUnityMeshes = new List<MeshExportInfo>();
|
||||
MeshExportInfo.GetInfo(Nodes, uniqueUnityMeshes, meshExportSettings);
|
||||
|
||||
#region Materials and Textures
|
||||
Materials = uniqueUnityMeshes.SelectMany(x => x.Renderer.sharedMaterials).Where(x => x != null).Distinct().ToList();
|
||||
Materials = uniqueUnityMeshes.SelectMany(x => x.Materials).Where(x => x != null).Distinct().ToList();
|
||||
|
||||
TextureExporter = new TextureExporter(textureSerializer);
|
||||
|
||||
@@ -267,10 +248,17 @@ namespace UniGLTF
|
||||
#endregion
|
||||
|
||||
#region Nodes and Skins
|
||||
var unitySkins = uniqueUnityMeshes
|
||||
.Where(x => x.UniqueBones != null)
|
||||
.ToList();
|
||||
glTF.nodes = Nodes.Select(x => ExportNode(x, Nodes, uniqueUnityMeshes, unitySkins.Select(y => y.Renderer as SkinnedMeshRenderer).ToList())).ToList();
|
||||
var skins = uniqueUnityMeshes
|
||||
.SelectMany(x => x.Renderers)
|
||||
.Where(x => x.Item1 is SkinnedMeshRenderer && x.UniqueBones != null)
|
||||
.Select(x => x.Item1 as SkinnedMeshRenderer)
|
||||
.ToList()
|
||||
;
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
var gltfNode = ExportNode(node, Nodes, uniqueUnityMeshes, skins);
|
||||
glTF.nodes.Add(gltfNode);
|
||||
}
|
||||
glTF.scenes = new List<gltfScene>
|
||||
{
|
||||
new gltfScene
|
||||
@@ -279,26 +267,30 @@ namespace UniGLTF
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var x in unitySkins)
|
||||
foreach (var x in uniqueUnityMeshes)
|
||||
{
|
||||
var matrices = x.GetBindPoses().Select(m_axisInverter.InvertMat4).ToArray();
|
||||
var accessor = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);
|
||||
|
||||
var renderer = x.Renderer as SkinnedMeshRenderer;
|
||||
var skin = new glTFSkin
|
||||
foreach (var (renderer, uniqueBones) in x.Renderers)
|
||||
{
|
||||
inverseBindMatrices = accessor,
|
||||
joints = x.UniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
|
||||
skeleton = Nodes.IndexOf(renderer.rootBone),
|
||||
};
|
||||
var skinIndex = glTF.skins.Count;
|
||||
glTF.skins.Add(skin);
|
||||
if (uniqueBones != null && renderer is SkinnedMeshRenderer smr)
|
||||
{
|
||||
var matrices = x.GetBindPoses().Select(m_axisInverter.InvertMat4).ToArray();
|
||||
var accessor = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);
|
||||
var skin = new glTFSkin
|
||||
{
|
||||
inverseBindMatrices = accessor,
|
||||
joints = uniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
|
||||
skeleton = Nodes.IndexOf(smr.rootBone),
|
||||
};
|
||||
var skinIndex = glTF.skins.Count;
|
||||
glTF.skins.Add(skin);
|
||||
|
||||
foreach (var z in Nodes.Where(y => y.Has(x.Renderer)))
|
||||
{
|
||||
var nodeIndex = Nodes.IndexOf(z);
|
||||
var node = glTF.nodes[nodeIndex];
|
||||
node.skin = skinIndex;
|
||||
foreach (var z in Nodes.Where(y => y.Has(renderer)))
|
||||
{
|
||||
var nodeIndex = Nodes.IndexOf(z);
|
||||
var node = glTF.nodes[nodeIndex];
|
||||
node.skin = skinIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace UniGLTF
|
||||
|
||||
try
|
||||
{
|
||||
validator.SetRoot(root, MeshExportSettings.Default);
|
||||
validator.SetRoot(root, MeshExportSettings.Default, new DefualtBlendShapeExportFilter());
|
||||
var vs = validator.Validate(root);
|
||||
Assert.False(vs.All(x => x.CanExport));
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace UniGLTF
|
||||
|
||||
try
|
||||
{
|
||||
validator.SetRoot(root, MeshExportSettings.Default);
|
||||
validator.SetRoot(root, MeshExportSettings.Default, new DefualtBlendShapeExportFilter());
|
||||
var vs = validator.Validate(root);
|
||||
Assert.False(vs.All(x => x.CanExport));
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace UniGLTF
|
||||
|
||||
try
|
||||
{
|
||||
validator.SetRoot(root, MeshExportSettings.Default);
|
||||
validator.SetRoot(root, MeshExportSettings.Default, new DefualtBlendShapeExportFilter());
|
||||
var vs = validator.Validate(root);
|
||||
Assert.False(vs.All(x => x.CanExport));
|
||||
}
|
||||
@@ -90,7 +90,7 @@ namespace UniGLTF
|
||||
// remove MeshFilter
|
||||
Component.DestroyImmediate(child.GetComponent<MeshFilter>());
|
||||
|
||||
validator.SetRoot(root, MeshExportSettings.Default);
|
||||
validator.SetRoot(root, MeshExportSettings.Default, new DefualtBlendShapeExportFilter());
|
||||
var vs = validator.Validate(root);
|
||||
Assert.True(vs.All(x => x.CanExport));
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace UniGLTF
|
||||
// set null
|
||||
child.GetComponent<MeshFilter>().sharedMesh = null;
|
||||
|
||||
validator.SetRoot(root, MeshExportSettings.Default);
|
||||
validator.SetRoot(root, MeshExportSettings.Default, new DefualtBlendShapeExportFilter());
|
||||
var vs = validator.Validate(root);
|
||||
Assert.True(vs.All(x => x.CanExport));
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace UniGLTF
|
||||
};
|
||||
var axisInverter = Axes.X.Create();
|
||||
|
||||
var unityMesh = new MeshWithRenderer(go.transform);
|
||||
var unityMesh = MeshExportInfo.Create(go);
|
||||
var (gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer
|
||||
? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, axisInverter, meshExportSettings)
|
||||
: MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials,axisInverter, meshExportSettings)
|
||||
@@ -182,7 +182,7 @@ namespace UniGLTF
|
||||
};
|
||||
var axisInverter = Axes.X.Create();
|
||||
|
||||
var unityMesh = new MeshWithRenderer(go.transform);
|
||||
var unityMesh = MeshExportInfo.Create(go);
|
||||
var (gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer
|
||||
? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, axisInverter, meshExportSettings)
|
||||
: MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials,axisInverter, meshExportSettings)
|
||||
|
||||
@@ -5,14 +5,7 @@ using UnityEngine;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// Export時にMeshを一覧する。
|
||||
///
|
||||
/// Mesh関連の Validation する。
|
||||
/// Meshのエクスポートサイズを試算する。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class VRMMeshExportValidator : MeshExportValidator
|
||||
public class VRMBlendShapeExportFilter : IBlendShapeExportFilter
|
||||
{
|
||||
static bool ClipsContainsName(IReadOnlyList<BlendShapeClip> clips, bool onlyPreset, BlendShapeBinding binding)
|
||||
{
|
||||
@@ -40,7 +33,24 @@ namespace VRM
|
||||
public VRMExportSettings VRMExportSettings;
|
||||
public List<BlendShapeClip> Clips;
|
||||
|
||||
public override bool UseBlendShape(int index, string relativePath)
|
||||
public VRMBlendShapeExportFilter(GameObject exportRoot, VRMExportSettings settings)
|
||||
{
|
||||
VRMExportSettings = settings;
|
||||
Clips = new List<BlendShapeClip>();
|
||||
if (exportRoot != null)
|
||||
{
|
||||
var proxy = exportRoot.GetComponent<VRMBlendShapeProxy>();
|
||||
if (proxy != null)
|
||||
{
|
||||
if (proxy.BlendShapeAvatar != null)
|
||||
{
|
||||
Clips.AddRange(proxy.BlendShapeAvatar.Clips);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseBlendShape(int index, string relativePath)
|
||||
{
|
||||
if (VRMExportSettings.ReduceBlendshape)
|
||||
{
|
||||
@@ -57,24 +67,5 @@ namespace VRM
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetRoot(GameObject ExportRoot, VRMExportSettings settings)
|
||||
{
|
||||
VRMExportSettings = settings;
|
||||
Clips = new List<BlendShapeClip>();
|
||||
if (ExportRoot != null)
|
||||
{
|
||||
var proxy = ExportRoot.GetComponent<VRMBlendShapeProxy>();
|
||||
if (proxy != null)
|
||||
{
|
||||
if (proxy.BlendShapeAvatar != null)
|
||||
{
|
||||
Clips.AddRange(proxy.BlendShapeAvatar.Clips);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetRoot(ExportRoot, settings.MeshExportSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f76ebfda1e249cb48890de41cc221889
|
||||
guid: d634cf68918e2f947b7ea0288d52a720
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -36,7 +36,7 @@ namespace VRM
|
||||
Editor m_settingsInspector;
|
||||
|
||||
|
||||
VRMMeshExportValidator m_meshes;
|
||||
MeshExportValidator m_meshes;
|
||||
Editor m_meshesInspector;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace VRM
|
||||
m_settings = ScriptableObject.CreateInstance<VRMExportSettings>();
|
||||
m_settingsInspector = Editor.CreateEditor(m_settings);
|
||||
|
||||
m_meshes = ScriptableObject.CreateInstance<VRMMeshExportValidator>();
|
||||
m_meshes = ScriptableObject.CreateInstance<MeshExportValidator>();
|
||||
m_meshesInspector = Editor.CreateEditor(m_meshes);
|
||||
|
||||
State.ExportRootChanged += (root) =>
|
||||
@@ -179,7 +179,7 @@ namespace VRM
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
m_meshes.SetRoot(State.ExportRoot, m_settings);
|
||||
m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings, new VRMBlendShapeExportFilter(State.ExportRoot, m_settings));
|
||||
}
|
||||
|
||||
static bool s_foldT = true;
|
||||
@@ -259,7 +259,7 @@ namespace VRM
|
||||
switch (meshInfo.VertexColor)
|
||||
{
|
||||
case UniGLTF.VertexColorState.ExistsAndMixed:
|
||||
Validation.Warning($"{meshInfo.Renderer}: Both vcolor.multiply and not multiply unlit materials exist").DrawGUI();
|
||||
Validation.Warning($"{meshInfo.Renderers}: Both vcolor.multiply and not multiply unlit materials exist").DrawGUI();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
using UniGLTF;
|
||||
using UnityEditor;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
[CustomEditor(typeof(VRMMeshExportValidator))]
|
||||
public class VRMExportMeshesEditor : MeshExportValidatorEditor
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e590565ae8d8e5f45956a20e207d3272
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2,19 +2,17 @@
|
||||
"name": "VRM",
|
||||
"references": [
|
||||
"UniHumanoid",
|
||||
"MeshUtility",
|
||||
"UniGLTF",
|
||||
"VRMShaders.GLTF.IO.Runtime",
|
||||
"VRMShaders.VRM.IO.Runtime",
|
||||
"MToon"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -168,7 +168,7 @@ namespace UniVRM10
|
||||
protected override void OnLayout()
|
||||
{
|
||||
// m_settings, m_meshes.Meshes
|
||||
m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings);
|
||||
m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings, new DefualtBlendShapeExportFilter());
|
||||
}
|
||||
|
||||
protected override bool DoGUI(bool isValid)
|
||||
|
||||
Reference in New Issue
Block a user