Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VrmFirstPersonを修正 #412

Merged
merged 3 commits into from
May 25, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 76 additions & 38 deletions Assets/VRM/UniVRM/Scripts/FirstPerson/VRMFirstPerson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static FirstPersonFlag GetFirstPersonFlag(VRMImporterContext context, Renderer r
return FirstPersonFlag.Auto;
}

foreach(var x in context.GLTF.extensions.VRM.firstPerson.meshAnnotations)
foreach (var x in context.GLTF.extensions.VRM.firstPerson.meshAnnotations)
{
if (x.mesh == index)
{
Expand All @@ -136,14 +136,16 @@ static FirstPersonFlag GetFirstPersonFlag(VRMImporterContext context, Renderer r
return FirstPersonFlag.Auto;
}

void CreateHeadlessModel(Renderer _renderer, Transform EraseRoot)
/// <summary>
/// ヘッドレスモデルを作成した場合に返す
/// </summary>
Mesh CreateHeadlessModel(Renderer _renderer, Transform EraseRoot)
{
{
var renderer = _renderer as SkinnedMeshRenderer;
if (renderer != null)
{
CreateHeadlessModelForSkinnedMeshRenderer(renderer, EraseRoot);
return;
return CreateHeadlessModelForSkinnedMeshRenderer(renderer, EraseRoot);
}
}

Expand All @@ -153,16 +155,18 @@ void CreateHeadlessModel(Renderer _renderer, Transform EraseRoot)
if (renderer != null)
{
CreateHeadlessModelForMeshRenderer(renderer, EraseRoot);
return;
return null;
}
}

// ここには来ない
return null;
}

public static void SetupLayers()
{
if (!TriedSetupLayer) {
if (!TriedSetupLayer)
{
TriedSetupLayer = true;
int layer = LayerMask.NameToLayer("VRMFirstPersonOnly");
FIRSTPERSON_ONLY_LAYER = (layer == -1) ? FIRSTPERSON_ONLY_LAYER : layer;
Expand All @@ -185,54 +189,69 @@ private static void CreateHeadlessModelForMeshRenderer(MeshRenderer renderer, Tr
}
}

private static void CreateHeadlessModelForSkinnedMeshRenderer(SkinnedMeshRenderer renderer, Transform eraseRoot)
/// <summary>
/// ヘッドレスモデルを作成する。
///
/// 以下の場合は作成しない。
///
/// * 削除対象が無い場合
/// * 全部削除対象の場合
///
/// </summary>
private static Mesh CreateHeadlessModelForSkinnedMeshRenderer(SkinnedMeshRenderer renderer, Transform eraseRoot)
{
SetupLayers();
renderer.gameObject.layer = THIRDPERSON_ONLY_LAYER;

var go = new GameObject("_headless_" + renderer.name);
go.layer = FIRSTPERSON_ONLY_LAYER;
go.transform.SetParent(renderer.transform, false);
var bones = renderer.bones;

var m_eraseBones = renderer.bones.Select(x =>
var eraseBones = bones.Select((x, i) =>
{
var eb = new BoneMeshEraser.EraseBone
// 祖先に削除対象が存在するか
bool erase = x.Ancestor().Any(y => y == eraseRoot);
return new
{
Bone = x,
i,
erase,
};

if (eraseRoot != null)
{
// 首の子孫を消去
if (eb.Bone.Ancestor().Any(y => y == eraseRoot))
{
//Debug.LogFormat("erase {0}", x);
eb.Erase = true;
}
}

return eb;
})
.ToArray();
.Where(x => x.erase)
.Select(x => x.i)
.ToArray()
;
if (eraseBones.Length == 0)
{
// 削除対象が存在しない
return null;
}

var bones = renderer.bones;
var eraseBones = m_eraseBones
.Where(x => x.Erase)
.Select(x => bones.IndexOf(x.Bone))
.ToArray();
// 元のメッシュを三人称に変更(自分からは見えない)
renderer.gameObject.layer = THIRDPERSON_ONLY_LAYER;

var mesh = BoneMeshEraser.CreateErasedMesh(renderer.sharedMesh, eraseBones);
// 削除対象のボーンに対するウェイトを保持する三角形を除外して、一人称用のモデルを複製する
var headlessMesh = BoneMeshEraser.CreateErasedMesh(renderer.sharedMesh, eraseBones);
if (headlessMesh.triangles.Length == 0)
{
// 一人称用のmeshには描画すべき部分が無い(全部削除された)
UnityEngine.Object.Destroy(headlessMesh);
return null;
}

// 一人称用のモデルのセットアップ
var go = new GameObject("_headless_" + renderer.name);
go.layer = FIRSTPERSON_ONLY_LAYER;
go.transform.SetParent(renderer.transform, false);
var erased = go.AddComponent<SkinnedMeshRenderer>();
erased.sharedMesh = mesh;
erased.sharedMesh = headlessMesh;
erased.sharedMaterials = renderer.sharedMaterials;
erased.bones = renderer.bones;
erased.bones = bones;
erased.rootBone = renderer.rootBone;
erased.updateWhenOffscreen = true;
return headlessMesh;
}

bool m_done;

List<Mesh> m_headlessMeshes = new List<Mesh>();

/// <summary>
/// 配下のモデルのレイヤー設定など
/// </summary>
Expand All @@ -246,7 +265,13 @@ public void Setup()
switch (x.FirstPersonFlag)
{
case FirstPersonFlag.Auto:
CreateHeadlessModel(x.Renderer, FirstPersonBone);
{
var headlessMesh = CreateHeadlessModel(x.Renderer, FirstPersonBone);
if (headlessMesh != null)
{
m_headlessMeshes.Add(headlessMesh);
}
}
break;

case FirstPersonFlag.FirstPersonOnly:
Expand All @@ -263,5 +288,18 @@ public void Setup()
}
}
}

void OnDestroy()
{
foreach (var mesh in m_headlessMeshes)
{
if (mesh != null)
{
// Debug.LogFormat("[VRMFirstPerson] OnDestroy: {0}", mesh);
UnityEngine.Object.Destroy(mesh);
}
}
m_headlessMeshes.Clear();
}
}
}