vrm-0.x firstperson

This commit is contained in:
ousttrue
2023-11-28 18:02:56 +09:00
parent 171cdef7d1
commit 32af053a62
5 changed files with 218 additions and 48 deletions

View File

@@ -2,6 +2,7 @@
using UnityEditor;
using UnityEngine;
using UniGLTF.M17N;
using UniGLTF;
namespace VRM
@@ -9,7 +10,6 @@ namespace VRM
public class VrmMeshIntegratorWizard : UniGLTF.MeshUtility.MeshUtilityDialog
{
public new const string MENU_NAME = "VRM 0.x MeshUtility";
public new static void OpenWindow()
{
var window =
@@ -17,29 +17,36 @@ namespace VRM
window.titleContent = new GUIContent(MENU_NAME);
window.Show();
}
protected override void Validate()
{
base.Validate();
if (_exportTarget.GetComponent<VRMMeta>() == null)
{
_validations.Add(Validation.Error("target is not vrm1"));
return;
}
}
// void Integrate()
// {
// // 統合
// var excludes = m_excludes.Where(x => x.Exclude).Select(x => x.Mesh);
// var results = Integrate(copy, excludes, m_separateByBlendShape);
VrmMeshUtility _meshUtil;
VrmMeshUtility VrmMeshUtility
{
get
{
if (_meshUtil == null)
{
_meshUtil = new VrmMeshUtility();
}
return _meshUtil;
}
}
protected override UniGLTF.MeshUtility.GltfMeshUtility MeshUtility => VrmMeshUtility;
// }
// static List<UniGLTF.MeshUtility.MeshIntegrationResult> Integrate(GameObject root, IEnumerable<Mesh> excludes, bool separateByBlendShape)
// {
// var results = new List<UniGLTF.MeshUtility.MeshIntegrationResult>();
// if (separateByBlendShape)
// {
// results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes));
// results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes));
// }
// else
// {
// results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes));
// }
// return results;
// }
protected override bool MeshIntegrateGui()
{
var firstPerson = ToggleIsModified("FirstPerson == AUTO の生成", ref MeshUtility.GenerateMeshForFirstPersonAuto);
var mod = base.MeshIntegrateGui();
return firstPerson || mod;
}
protected override void DialogMessage()
{

View File

@@ -367,6 +367,17 @@ namespace VRM
}
}
/// <summary>
/// for MeshUtility interface
/// </summary>
public Mesh ProcessFirstPerson(Transform firstPersonBone, SkinnedMeshRenderer smr)
{
SetVisibilityFunc dummy = (Renderer renderer, bool firstPerson, bool thirdPerson) =>
{
};
return CreateHeadlessModel(smr, FirstPersonBone, dummy);
}
void OnDestroy()
{
foreach (var mesh in m_headlessMeshes)

View File

@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniHumanoid;
using UnityEngine;
namespace VRM
{
public class VrmMeshUtility : UniGLTF.MeshUtility.GltfMeshUtility
{
bool _generateFirstPerson = false;
protected override List<UniGLTF.MeshUtility.MeshIntegrationGroup> CopyMeshIntegrationGroups()
{
var copy = new List<UniGLTF.MeshUtility.MeshIntegrationGroup>();
_generateFirstPerson = false;
if (GenerateMeshForFirstPersonAuto)
{
foreach (var g in MeshIntegrationGroups)
{
if (g.Name == "auto")
{
_generateFirstPerson = true;
// 元のメッシュを三人称に変更
copy.Add(new UniGLTF.MeshUtility.MeshIntegrationGroup
{
Name = FirstPersonFlag.ThirdPersonOnly.ToString(),
Renderers = g.Renderers.ToList(),
});
}
copy.Add(g);
}
}
else
{
copy.AddRange(MeshIntegrationGroups);
}
return copy;
}
protected override
(UniGLTF.MeshUtility.MeshIntegrationResult, GameObject[]) Integrate(
GameObject empty,
UniGLTF.MeshUtility.MeshIntegrationGroup group)
{
var (result, newList) = base.Integrate(empty, group);
if (_generateFirstPerson && group.Name == nameof(FirstPersonFlag.Auto))
{
// Mesh 統合の後処理
// FirstPerson == "auto" の場合に
// 頭部の無いモデルを追加で作成する
Debug.Log("generateFirstPerson");
if (result.Integrated.Mesh != null)
{
// BlendShape 有り
_ProcessFirstPerson(_vrmInstance.FirstPersonBone, result.Integrated.IntegratedRenderer);
}
if (result.IntegratedNoBlendShape.Mesh != null)
{
// BlendShape 無しの方
_ProcessFirstPerson(_vrmInstance.FirstPersonBone, result.IntegratedNoBlendShape.IntegratedRenderer);
}
}
return (result, newList);
}
private void _ProcessFirstPerson(Transform firstPersonBone, SkinnedMeshRenderer smr)
{
var mesh = _vrmInstance.ProcessFirstPerson(firstPersonBone, smr);
if (mesh != null)
{
smr.sharedMesh = mesh;
smr.name = "auto.headless";
}
else
{
Debug.LogWarning("no result");
}
}
VRMFirstPerson _vrmInstance = null;
/// <summary>
/// glTF に比べて Humanoid や FirstPerson の処理が追加される
/// </summary>
public override (List<UniGLTF.MeshUtility.MeshIntegrationResult>, List<GameObject>) Process(GameObject go)
{
_vrmInstance = go.GetComponent<VRMFirstPerson>();
if (_vrmInstance == null)
{
throw new ArgumentException();
}
if (ForceUniqueName)
{
throw new NotImplementedException();
// 必用?
var animator = go.GetComponent<Animator>();
var newAvatar = AvatarDescription.RecreateAvatar(animator);
animator.avatar = newAvatar;
}
// TODO: update: spring
// TODO: update: constraint
// TODO: update: firstPerson offset
var (list, newList) = base.Process(go);
if (FreezeBlendShape || FreezeRotation || FreezeScaling)
{
var animator = go.GetComponent<Animator>();
var newAvatar = AvatarDescription.RecreateAvatar(animator);
animator.avatar = newAvatar;
}
return (list, newList);
}
public override void UpdateMeshIntegrationGroups(GameObject root)
{
if (root == null)
{
return;
}
var vrm1 = root.GetComponent<VRMFirstPerson>();
if (vrm1 == null)
{
return;
}
foreach (var a in vrm1.Renderers)
{
var g = _GetOrCreateGroup(a.FirstPersonFlag.ToString());
g.Renderers.Add(a.Renderer);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fb346da8b7688c74eb627bebe1b21060
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF.MeshUtility;
using UniHumanoid;
using UnityEngine;
using UnityEngine.Rendering;
namespace UniVRM10
{
@@ -46,27 +45,51 @@ namespace UniVRM10
{
var (result, newList) = base.Integrate(empty, group);
if (_generateFirstPerson && group.Name == "auto")
if (_generateFirstPerson && group.Name == nameof(UniGLTF.Extensions.VRMC_vrm.FirstPersonType.auto))
{
// Mesh 統合の後処理
// FirstPerson == "auto" の場合に
// 頭部の無いモデルを追加で作成する
Debug.Log("generateFirstPerson");
if (result.Integrated.Mesh != null)
{
_ProcessFirstPerson(_vrmInstance, result.Integrated);
// BlendShape 有り
_ProcessFirstPerson(_vrmInstance.Humanoid.Head, result.Integrated.IntegratedRenderer);
}
if (result.IntegratedNoBlendShape.Mesh != null)
{
_ProcessFirstPerson(_vrmInstance, result.IntegratedNoBlendShape);
// BlendShape 無しの方
_ProcessFirstPerson(_vrmInstance.Humanoid.Head, result.IntegratedNoBlendShape.IntegratedRenderer);
}
}
return (result, newList);
}
private void _ProcessFirstPerson(Transform firstPersonBone, SkinnedMeshRenderer smr)
{
var task = VRM10ObjectFirstPerson.CreateErasedMeshAsync(
smr,
firstPersonBone,
new VRMShaders.ImmediateCaller());
task.Wait();
var mesh = task.Result;
if (mesh != null)
{
smr.sharedMesh = mesh;
smr.name = "auto.headless";
}
else
{
Debug.LogWarning("no result");
}
}
Vrm10Instance _vrmInstance = null;
/// <summary>
/// glTF に比べて Humanoid や FirstPerson の処理が追加される
/// </summary>
public override (List<MeshIntegrationResult>, List<GameObject>) Process(GameObject go)
public override (List<UniGLTF.MeshUtility.MeshIntegrationResult>, List<GameObject>) Process(GameObject go)
{
_vrmInstance = go.GetComponent<Vrm10Instance>();
if (_vrmInstance == null)
@@ -99,26 +122,6 @@ namespace UniVRM10
return (list, newList);
}
void _ProcessFirstPerson(Vrm10Instance vrmInstance, UniGLTF.MeshUtility.MeshInfo info)
{
var firstPersonBone = vrmInstance.Humanoid.Head;
var task = VRM10ObjectFirstPerson.CreateErasedMeshAsync(
info.IntegratedRenderer,
firstPersonBone,
new VRMShaders.ImmediateCaller());
task.Wait();
if (task.Result != null)
{
info.IntegratedRenderer.sharedMesh = task.Result;
info.IntegratedRenderer.name = "auto.headless";
}
else
{
Debug.LogWarning("no result");
}
}
public override void UpdateMeshIntegrationGroups(GameObject root)
{
if (root == null)