Unity は BoneWeight の無い BlendShape を SkinnedMeshRenderer で扱う。 GLTF が理解できるように正規化で BoneWeight を付与する

This commit is contained in:
ousttrue 2020-10-06 15:20:58 +09:00
parent 82e2031573
commit 81e95d5364
5 changed files with 51 additions and 20 deletions

View File

@ -22,6 +22,16 @@ namespace UniGLTF
public bool IsRendererActive;
public bool Skinned;
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
&& VertexColor == VertexColorState.ExistsAndIsUsed
|| VertexColor == VertexColorState.ExistsAndMixed // Export する
;
public bool HasSkinning => Mesh.boneWeights != null && Mesh.boneWeights.Length == Mesh.vertexCount;
/// <summary>
/// Mesh に頂点カラーが含まれているか。
/// 含まれている場合にマテリアルは Unlit.VColorMultiply になっているか?

View File

@ -79,25 +79,22 @@ namespace VRM
// float4 x 3
// vertices
sb.Append($"(Pos");
if (info.Mesh.normals != null && info.Mesh.normals.Length == info.Mesh.vertexCount)
if (info.HasNormal)
{
sb.Append("+Nom");
info.ExportVertexSize += 4 * 3;
}
if (info.Mesh.uv != null && info.Mesh.uv.Length == info.Mesh.vertexCount)
if (info.HasUV)
{
sb.Append("+UV");
info.ExportVertexSize += 4 * 2;
}
if (info.Mesh.colors != null && info.Mesh.colors.Length == info.Mesh.vertexCount
&& info.VertexColor == UniGLTF.MeshExportInfo.VertexColorState.ExistsAndIsUsed
|| info.VertexColor == UniGLTF.MeshExportInfo.VertexColorState.ExistsAndMixed // Export する
)
if (info.HasVertexColor)
{
sb.Append("+Col");
info.ExportVertexSize += 4 * 4;
}
if (info.Mesh.boneWeights != null && info.Mesh.boneWeights.Length == info.Mesh.vertexCount)
if (info.HasSkinning)
{
// short, float x 4 weights
sb.Append("+Skin");
@ -143,6 +140,12 @@ namespace VRM
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();
}

View File

@ -84,7 +84,7 @@ namespace VRM
/// <param name="ExportRoot"></param>
/// <param name="m_settings"></param>
/// <returns></returns>
public bool RootAndHumanoidCheck(GameObject ExportRoot, VRMExportSettings m_settings)
public bool RootAndHumanoidCheck(GameObject ExportRoot, VRMExportSettings m_settings, IReadOnlyList<UniGLTF.MeshExportInfo> info)
{
//
// root
@ -107,25 +107,31 @@ namespace VRM
return false;
}
if (HasRotationOrScale(ExportRoot))
if (HasRotationOrScale(ExportRoot) || info.Any(x => x.ExportBlendShapeCount > 0 && !x.HasSkinning))
{
// 正規化必用
if (m_settings.PoseFreeze)
{
EditorGUILayout.HelpBox("Root OK", MessageType.Info);
// する
EditorGUILayout.HelpBox("PoseFreeze checked. OK", MessageType.Info);
}
else
{
// しない
Validation.Warning(Msg(VRMExporterWizardMessages.ROTATION_OR_SCALEING_INCLUDED_IN_NODE)).DrawGUI();
}
}
else
{
// 不要
if (m_settings.PoseFreeze)
{
// する
Validation.Warning(Msg(VRMExporterWizardMessages.IS_POSE_FREEZE_DONE)).DrawGUI();
}
else
{
// しない
EditorGUILayout.HelpBox("Root OK", MessageType.Info);
}
}

View File

@ -78,8 +78,14 @@ namespace VRM
}
else
{
// do validation
Validate();
// default setting
m_settings.PoseFreeze = VRMExporterValidator.HasRotationOrScale(ExportRoot);
m_settings.PoseFreeze =
VRMExporterValidator.HasRotationOrScale(ExportRoot)
|| m_meshes.Meshes.Any(x => x.ExportBlendShapeCount > 0 && !x.HasSkinning)
;
var meta = ExportRoot.GetComponent<VRMMeta>();
if (meta != null)
@ -93,6 +99,17 @@ namespace VRM
}
}
void Validate()
{
if (!m_requireValidation)
{
return;
}
m_validator.Validate(ExportRoot, m_settings, Meta != null ? Meta : m_tmpMeta);
m_requireValidation = false;
m_meshes.SetRoot(ExportRoot, m_settings);
}
VRMMetaObject m_tmpMeta;
Editor m_metaEditor;
@ -202,18 +219,13 @@ namespace VRM
// EventType.Layout と EventType.Repaint 間で内容が変わらないようしている。
if (Event.current.type == EventType.Layout)
{
if (m_requireValidation)
{
m_validator.Validate(ExportRoot, m_settings, Meta != null ? Meta : m_tmpMeta);
m_requireValidation = false;
m_meshes.SetRoot(ExportRoot, m_settings);
}
Validate();
}
//
// Humanoid として適正か? ここで失敗する場合は Export UI を表示しない
//
if (!m_validator.RootAndHumanoidCheck(ExportRoot, m_settings))
if (!m_validator.RootAndHumanoidCheck(ExportRoot, m_settings, m_meshes.Meshes))
{
return;
}

View File

@ -21,8 +21,8 @@ namespace VRM
[LangMsg(Languages.en, "Prefab Asset cannot be exported. Prefab Asset has different behaviour with Scene GameObject. Please put the prefab into the scene")]
PREFAB_CANNOT_EXPORT,
[LangMsg(Languages.ja, "回転・拡大縮小を持つノードが含まれています。正規化が必用です。Setting の PoseFreeze を有効にしてください")]
[LangMsg(Languages.en, " Normalization is required. There are nodes (child GameObject) where rotation and scaling are not default. Please enable PoseFreeze")]
[LangMsg(Languages.ja, "回転・拡大縮小もしくはWeightの無いBlendShapeが含まれています。正規化が必用です。Setting の PoseFreeze を有効にしてください")]
[LangMsg(Languages.en, " Normalization is required. There are nodes (child GameObject) where rotation and scaling or blendshape without bone weight are not default. Please enable PoseFreeze")]
ROTATION_OR_SCALEING_INCLUDED_IN_NODE,
[LangMsg(Languages.ja, "正規化済みです。Setting の PoseFreeze は不要です")]