UniVRM/Assets/VRM10/Runtime/MeshUtility/Vrm10MeshUtility.cs
2023-10-25 21:50:06 +09:00

142 lines
3.8 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UniGLTF.MeshUtility;
using UniHumanoid;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// - Freeze
/// - Integration
/// - Split
///
/// - Implement runtime logic => Process a hierarchy in scene. Do not process prefab.
/// - Implement undo
///
/// </summary>
public class Vrm10MeshUtility
{
/// <summary>
/// Same as VRM-0 normalization
/// - Mesh
/// - Node
/// - InverseBindMatrices
/// </summary>
public bool FreezeBlendShape = false;
/// <summary>
/// Same as VRM-0 normalization
/// - Mesh
/// - Node
/// - InverseBindMatrices
/// </summary>
public bool FreezeScaling = true;
/// <summary>
/// Same as VRM-0 normalization
/// - Mesh
/// - Node
/// - InverseBindMatrices
/// </summary>
public bool FreezeRotation = false;
public class MeshIntegrationGroup
{
/// <summary>
/// FirstPerson flag
/// TODO: enum
/// </summary>
public string Name;
public List<Renderer> Renderers = new List<Renderer>();
}
public List<MeshIntegrationGroup> MeshIntegrationGroups = new List<MeshIntegrationGroup>();
/// <summary>
/// Create a headless model and solve VRM.FirstPersonFlag.Auto
/// </summary>
public bool GenerateMeshForFirstPersonAuto = false;
/// <summary>
/// Split into having and not having BlendShape
/// </summary>
public bool SplitByBlendShape = false;
public void IntegrateAll(GameObject root)
{
if (root == null)
{
return;
}
MeshIntegrationGroups.Add(new MeshIntegrationGroup
{
Name = "ALL",
Renderers = root.GetComponentsInChildren<Renderer>().ToList(),
});
}
MeshIntegrationGroup GetOrCreateGroup(string name)
{
foreach (var g in MeshIntegrationGroups)
{
if (g.Name == name)
{
return g;
}
}
MeshIntegrationGroups.Add(new MeshIntegrationGroup
{
Name = name,
});
return MeshIntegrationGroups.Last();
}
public void IntegrateFirstPerson(GameObject root)
{
if (root == null)
{
return;
}
var vrm1 = root.GetComponent<Vrm10Instance>();
if (vrm1 == null)
{
return;
}
var vrmObject = vrm1.Vrm;
if (vrmObject == null)
{
return;
}
var fp = vrmObject.FirstPerson;
if (fp == null)
{
return;
}
foreach (var a in fp.Renderers)
{
var g = GetOrCreateGroup(a.FirstPersonFlag.ToString());
g.Renderers.Add(a.GetRenderer(root.transform));
}
}
public void Process(GameObject go)
{
// TODO: UNDO
// 正規化されたヒエラルキーを作る
var (normalized, boneMap) = BoneNormalizer.CreateNormalizedHierarchy(go,
removeScaling: FreezeScaling,
removeRotation: FreezeRotation);
// TODO: update: spring
// TODO: update: constraint
// TODO: update: firstPoint offset
AvatarDescription.AddAnimator(go, normalized, boneMap);
// TODO: write back normalized transform to boneMap
}
}
}