CreateErasedMeshAsync

This commit is contained in:
ousttrue
2023-11-01 20:37:14 +09:00
parent acc47ef119
commit 12c5f9a7d2
4 changed files with 80 additions and 48 deletions

View File

@@ -131,7 +131,7 @@ namespace UniGLTF.MeshUtility
/// <param name="boneWeights"></param>
/// <param name="eraseBoneIndices"></param>
/// <returns></returns>
public static int[] GetExcludedIndices(int[] indices, BoneWeight[] boneWeights, int[] eraseBoneIndices)
static int[] GetExcludedIndices(int[] indices, BoneWeight[] boneWeights, int[] eraseBoneIndices)
{
var count = ExcludeTriangles(indices, boneWeights, eraseBoneIndices);
var dst = new int[count];

View File

@@ -165,6 +165,12 @@ namespace UniGLTF.MeshUtility
public void Push(SkinnedMeshRenderer renderer)
{
if (renderer == null)
{
// Debug.LogWarningFormat("{0} was destroyed", renderer);
return;
}
var mesh = renderer.sharedMesh;
if (mesh == null)
{

View File

@@ -29,7 +29,7 @@ namespace UniVRM10
}
}
public static int[] GetBonesThatHasAncestor(SkinnedMeshRenderer smr, Transform ancestor)
static int[] GetBonesThatHasAncestor(SkinnedMeshRenderer smr, Transform ancestor)
{
var eraseBones = smr.bones
.Where(x => x.Ancestor().Any(y => y == ancestor))
@@ -38,24 +38,46 @@ namespace UniVRM10
return eraseBones;
}
public static async Task<Mesh> CreateErasedMeshAsync(SkinnedMeshRenderer smr,
Transform firstPersonBone,
IAwaitCaller awaitCaller)
{
var eraseBones = GetBonesThatHasAncestor(smr, firstPersonBone);
if (eraseBones.Any())
{
return await BoneMeshEraser.CreateErasedMeshAsync(smr.sharedMesh, eraseBones, awaitCaller);
}
else
{
return null;
}
}
// <summary>
// 頭部を取り除いたモデルを複製する
// </summary>
// <parameter>renderer: 元になるSkinnedMeshRenderer</parameter>
// <parameter>eraseBones: 削除対象になるボーンのindex</parameter>
private async static Task<SkinnedMeshRenderer> CreateHeadlessMeshAsync(SkinnedMeshRenderer renderer, int[] eraseBones, IAwaitCaller awaitCaller)
public async static Task<SkinnedMeshRenderer> CreateHeadlessMeshAsync(SkinnedMeshRenderer renderer,
Transform firstPersonBone, IAwaitCaller awaitCaller)
{
var mesh = await BoneMeshEraser.CreateErasedMeshAsync(renderer.sharedMesh, eraseBones, awaitCaller);
var go = new GameObject("_headless_" + renderer.name);
var erased = go.AddComponent<SkinnedMeshRenderer>();
erased.enabled = false; // hide
erased.sharedMesh = mesh;
erased.sharedMaterials = renderer.sharedMaterials;
erased.bones = renderer.bones;
erased.rootBone = renderer.rootBone;
return erased;
var mesh = await CreateErasedMeshAsync(renderer, firstPersonBone, awaitCaller);
if (mesh != null)
{
var go = new GameObject("_headless_" + renderer.name);
var erased = go.AddComponent<SkinnedMeshRenderer>();
erased.enabled = false; // hide
erased.sharedMesh = mesh;
erased.sharedMaterials = renderer.sharedMaterials;
erased.bones = renderer.bones;
erased.rootBone = renderer.rootBone;
return erased;
}
else
{
// 削除対象が含まれないので何もしない
return null;
}
}
bool m_done;
@@ -70,14 +92,13 @@ namespace UniVRM10
{
if (x.GetRenderer(go.transform) is SkinnedMeshRenderer smr)
{
var eraseBones = GetBonesThatHasAncestor(smr, firstPersonBone);
if (eraseBones.Any())
{
// オリジナルのモデルを3人称用にする
smr.gameObject.layer = layer.ThirdPersonOnly;
// オリジナルのモデルを3人称用にする
smr.gameObject.layer = layer.ThirdPersonOnly;
// 頭を取り除いた複製モデルを作成し、1人称用にする
var headless = await CreateHeadlessMeshAsync(smr, eraseBones, awaitCaller);
// 頭を取り除いた複製モデルを作成し、1人称用にする
var headless = await CreateHeadlessMeshAsync(smr, firstPersonBone, awaitCaller);
if (headless != null)
{
headless.gameObject.layer = layer.FirstPersonOnly;
headless.transform.SetParent(smr.transform, false);
if (runtime != null)
@@ -85,10 +106,6 @@ namespace UniVRM10
runtime.AddRenderer(headless);
}
}
else
{
// 削除対象が含まれないので何もしない
}
}
else if (x.GetRenderer(go.transform) is MeshRenderer mr)
{

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniGLTF.Extensions.VRMC_vrm;
using UniGLTF.MeshUtility;
using UniHumanoid;
using UnityEngine;
@@ -122,6 +120,10 @@ namespace UniVRM10
void RemoveComponent<T>(T c) where T : Component
{
if (c == null)
{
return;
}
var t = c.transform;
if (Application.isPlaying)
{
@@ -225,12 +227,40 @@ namespace UniVRM10
{
// TODO: UNDO
var results = new List<MeshIntegrationResult>();
foreach (var group in copy)
{
var result = MeshIntegrator.Integrate(group, SplitByBlendShape
? MeshIntegrator.BlendShapeOperation.Split
: MeshIntegrator.BlendShapeOperation.None);
results.Add(result);
result.AddIntegratedRendererTo(go);
if (generateFirstPerson && group.Name == "auto")
{
Debug.Log("generateFirstPerson");
var firstPersonBone = vrmInstance.Humanoid.Head;
var task = VRM10ObjectFirstPerson.CreateErasedMeshAsync(
result.IntegratedRenderer,
firstPersonBone,
new ImmediateCaller());
task.Wait();
if (task.Result != null)
{
result.IntegratedRenderer.sharedMesh = task.Result;
result.IntegratedRenderer.name = "auto.headless";
}
else
{
Debug.LogWarning("no result");
}
}
}
foreach (var result in results)
{
foreach (var r in result.SourceMeshRenderers)
{
RemoveComponent(r);
@@ -239,27 +269,6 @@ namespace UniVRM10
{
RemoveComponent(r);
}
result.AddIntegratedRendererTo(go);
if (generateFirstPerson && group.Name == "auto")
{
var firstPersonBone = vrmInstance.Humanoid.Head;
var eraseBones = VRM10ObjectFirstPerson.GetBonesThatHasAncestor(
result.IntegratedRenderer, firstPersonBone);
var task = BoneMeshEraser.CreateErasedMeshAsync(result.MeshMap.Integrated, eraseBones,
new ImmediateCaller());
task.Wait();
if (task.Result.vertexCount > 0)
{
var headless = new GameObject("auto.headless");
var smr = headless.AddComponent<SkinnedMeshRenderer>();
smr.sharedMesh = task.Result;
headless.transform.SetParent(go.transform);
}
}
}
}
}