Merge pull request #1409 from ousttrue/fix10/fix_shared_accessor_convert_twice

同一のバイト列を参照するBufferAccessor が複数回、座標変換(右手・左手変換)されるのを回避する
This commit is contained in:
ousttrue 2021-12-09 19:27:26 +09:00 committed by GitHub
commit 89a346d0fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 19 deletions

View File

@ -106,13 +106,25 @@ namespace UniVRM10
serializedObject.Update();
EditorGUILayout.HelpBox("Experimental", MessageType.Warning);
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(VrmScriptedImporter.RenderPipeline)));
serializedObject.ApplyModifiedProperties();
}
ApplyRevertGUI();
break;
case Vrm10FileType.Vrm0:
EditorGUILayout.HelpBox(m_result.Message, m_model != null ? MessageType.Info : MessageType.Warning);
if (VRMShaders.Symbols.VRM_DEVELOP)
{
if (GUILayout.Button("debug export"))
{
File.WriteAllBytes("tmp.vrm", m_result.MigratedBytes);
}
}
// migration check boxs
base.OnInspectorGUI();
break;

View File

@ -22,6 +22,8 @@ namespace UniVRM10
public readonly Vrm10FileType FileType;
public readonly String Message;
public byte[] MigratedBytes;
public Vrm10Data(GltfData data, VRMC_vrm vrm, Vrm10FileType fileType, string message, Migration.Vrm0Meta oldMeta = null)
{
Data = data;
@ -118,6 +120,13 @@ namespace UniVRM10
throw new NullReferenceException("oldMeta");
}
result = new Vrm10Data(migratedData, vrm, Vrm10FileType.Vrm0, "vrm0: migrated", oldMeta);
if (VRMShaders.Symbols.VRM_DEVELOP)
{
// 右手左手座標変換でバッファが破壊的変更されるので、コピーを作っている
result.MigratedBytes = migrated.Select(x => x).ToArray();
}
return true;
}

View File

@ -151,16 +151,64 @@ namespace UniVRM10
}
}
// update nodes
// update nodes and remove unused skin
var skins = gltf.skins.ToArray();
gltf.skins.Clear();
foreach (var (gltfNode, node) in Enumerable.Zip(gltf.nodes, model.Nodes, (l, r) => (l, r)))
{
gltfNode.translation = node.LocalTranslation.ToFloat3();
gltfNode.rotation = node.LocalRotation.ToFloat4();
gltfNode.scale = node.LocalScaling.ToFloat3();
if (gltfNode.mesh >= 0 && gltfNode.skin >= 0)
if (gltfNode.mesh >= 0)
{
var gltfSkin = gltf.skins[gltfNode.skin];
gltfSkin.inverseBindMatrices = AddAccessor(node.MeshGroup.Skin.InverseMatrices.GetSpan<Matrix4x4>());
if (gltfNode.skin >= 0)
{
//
// mesh with skin
// only this case, skin is enable
// [SkinnedMeshRenderer]
//
var gltfSkin = skins[gltfNode.skin];
// get or create
var skinIndex = gltf.skins.IndexOf(gltfSkin);
if (skinIndex == -1)
{
skinIndex = gltf.skins.Count;
gltfSkin.inverseBindMatrices = AddAccessor(node.MeshGroup.Skin.InverseMatrices.GetSpan<Matrix4x4>());
gltf.skins.Add(gltfSkin);
}
else{
// multi nodes sharing a same skin may be error ?
// edge case.
}
// update
gltfNode.skin = skinIndex;
}
else
{
//
// mesh without skin
// [MeshRenderer]
//
}
}
else
{
if (gltfNode.skin >= 0)
{
//
// no mesh but skin
// fix error
//
gltfNode.skin = -1;
}
else
{
//
// no mesh no skin
//
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using UniGLTF;
@ -153,6 +154,10 @@ namespace VrmLib
/// </summary>
static void ReverseAxisAndFlipTriangle(this Model model, Reverser reverser, bool ignoreVrm)
{
// 複数の gltf.accessor が別の要素間で共有されている場合に、2回処理されることを防ぐ
// edgecase: InverseBindMatrices で遭遇
var unique = new HashSet<ArraySegment<byte>>();
foreach (var g in model.MeshGroups)
{
foreach (var m in g.Meshes)
@ -161,7 +166,10 @@ namespace VrmLib
{
if (k == VertexBuffer.PositionKey || k == VertexBuffer.NormalKey)
{
reverser.ReverseBuffer(v);
if (unique.Add(v.Bytes))
{
reverser.ReverseBuffer(v);
}
}
else if (k == VertexBuffer.TangentKey)
{
@ -169,19 +177,22 @@ namespace VrmLib
}
}
switch (m.IndexBuffer.ComponentType)
if (unique.Add(m.IndexBuffer.Bytes))
{
case AccessorValueType.UNSIGNED_BYTE:
FlipTriangle(SpanLike.Wrap<Byte>(m.IndexBuffer.Bytes));
break;
case AccessorValueType.UNSIGNED_SHORT:
FlipTriangle(SpanLike.Wrap<UInt16>(m.IndexBuffer.Bytes));
break;
case AccessorValueType.UNSIGNED_INT:
FlipTriangle(SpanLike.Wrap<UInt32>(m.IndexBuffer.Bytes));
break;
default:
throw new NotImplementedException();
switch (m.IndexBuffer.ComponentType)
{
case AccessorValueType.UNSIGNED_BYTE:
FlipTriangle(SpanLike.Wrap<Byte>(m.IndexBuffer.Bytes));
break;
case AccessorValueType.UNSIGNED_SHORT:
FlipTriangle(SpanLike.Wrap<UInt16>(m.IndexBuffer.Bytes));
break;
case AccessorValueType.UNSIGNED_INT:
FlipTriangle(SpanLike.Wrap<UInt32>(m.IndexBuffer.Bytes));
break;
default:
throw new NotImplementedException();
}
}
foreach (var mt in m.MorphTargets)
@ -190,7 +201,10 @@ namespace VrmLib
{
if (k == VertexBuffer.PositionKey || k == VertexBuffer.NormalKey)
{
reverser.ReverseBuffer(v);
if (unique.Add(v.Bytes))
{
reverser.ReverseBuffer(v);
}
}
if (k == VertexBuffer.TangentKey)
{
@ -214,7 +228,10 @@ namespace VrmLib
{
if (s.InverseMatrices != null)
{
reverser.ReverseBuffer(s.InverseMatrices);
if (unique.Add(s.InverseMatrices.Bytes))
{
reverser.ReverseBuffer(s.InverseMatrices);
}
}
}

View File

@ -0,0 +1,18 @@
namespace VRMShaders
{
public static class Symbols
{
/// <summary>
/// #if 文を局所化する。
/// VRMShaders が最下層になるため、ここに配置している
/// </summary>
/// <value></value>
public const bool VRM_DEVELOP =
#if VRM_DEVELOP
true
#else
false
#endif
;
}
}

View File

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