diff --git a/Assets/UniGLTF/Runtime/AssemblyInfo.cs b/Assets/UniGLTF/Runtime/AssemblyInfo.cs new file mode 100644 index 000000000..67e2c8115 --- /dev/null +++ b/Assets/UniGLTF/Runtime/AssemblyInfo.cs @@ -0,0 +1,5 @@ +#if UNITY_EDITOR +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("UniGLTF.Tests")] +#endif \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/AssemblyInfo.cs.meta b/Assets/UniGLTF/Runtime/AssemblyInfo.cs.meta new file mode 100644 index 000000000..97a459ad4 --- /dev/null +++ b/Assets/UniGLTF/Runtime/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7aed15fa830416246b0c408322cd4099 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs index f73c6de45..55097373c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs @@ -13,6 +13,7 @@ namespace UniGLTF private NativeArray _vertices; public NativeArray Vertices => _vertices.GetSubArray(0, _currentVertexCount); int _currentVertexCount = 0; + private NativeArray _skinnedMeshVertices; public NativeArray SkinnedMeshVertices => _skinnedMeshVertices.GetSubArray(0, _currentSkinCount); int _currentSkinCount = 0; @@ -23,14 +24,16 @@ namespace UniGLTF private readonly List _subMeshes = new List(); public IReadOnlyList SubMeshes => _subMeshes; + private readonly List _materialIndices = new List(); public IReadOnlyList MaterialIndices => _materialIndices; + private readonly List _blendShapes = new List(); public IReadOnlyList BlendShapes => _blendShapes; - public bool HasNormal { get; private set; } = true; + public bool HasNormal { get; private set; } public string Name { get; private set; } - public bool AssignBoneWeight { get; private set; } + public bool ShouldSetRendererNodeAsBone { get; private set; } public MeshData(int vertexCapacity, int indexCapacity) { @@ -56,19 +59,20 @@ namespace UniGLTF _blendShapes.Clear(); Name = null; HasNormal = false; - AssignBoneWeight = false; + ShouldSetRendererNodeAsBone = false; } /// /// バッファ共有方式(vrm-0.x)の判定。 /// import の後方互換性のためで、vrm-1.0 export では使いません。 /// - /// * バッファ共用方式は VertexBuffer が同じでSubMeshの index buffer がスライドしていく方式 + /// バッファ共用方式は連結済みの VertexBuffer を共有して、SubMeshの index buffer による参照がスライドしていく方式 + /// /// * バッファがひとつのとき /// * すべての primitive の attribute が 同一の accessor を使用している時 /// /// - private static bool HasSharedVertexBuffer(glTFMesh gltfMesh) + public static bool HasSharedVertexBuffer(glTFMesh gltfMesh) { glTFAttributes lastAttributes = null; foreach (var prim in gltfMesh.primitives) @@ -196,15 +200,6 @@ namespace UniGLTF return (vertexCount, indexCount); } - /// - /// 各種頂点属性が使われているかどうかをチェックし、使われていなかったらフラグを切る - /// MEMO: O(1)で検知する手段がありそう - /// - private void CheckAttributeUsages(glTFPrimitives primitives) - { - if (!primitives.HasNormal()) HasNormal = false; - } - private BlendShape GetOrCreateBlendShape(int i) { if (i < _blendShapes.Count && _blendShapes[i] != null) @@ -317,16 +312,18 @@ namespace UniGLTF var vertexOffset = _currentVertexCount; var indexBufferCount = primitives.indices; - // position は必ずある + // position は必ず存在する。normal, texCoords, colors, skinning は無いかもしれない var positions = primitives.GetPositions(data); var normals = primitives.GetNormals(data, positions.Length); + if (normals.HasValue) + { + HasNormal = true; + } var texCoords0 = primitives.GetTexCoords0(data, positions.Length); var texCoords1 = primitives.GetTexCoords1(data, positions.Length); var colors = primitives.GetColors(data, positions.Length); var skinning = SkinningInfo.Create(data, gltfMesh, primitives); - AssignBoneWeight = skinning.ShouldSetRendererNodeAsBone ; - - CheckAttributeUsages(primitives); + ShouldSetRendererNodeAsBone = skinning.ShouldSetRendererNodeAsBone; for (var i = 0; i < positions.Length; ++i) { @@ -447,18 +444,20 @@ namespace UniGLTF var isOldVersion = data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16); { - // 同じVertexBufferを共有しているので先頭のモノを使う + // すべての primitives で連結済みの VertexBuffer を共有している。代表して先頭を使う var primitives = gltfMesh.primitives.First(); var positions = primitives.GetPositions(data); var normals = primitives.GetNormals(data, positions.Length); + if (normals.HasValue) + { + HasNormal = true; + } var texCoords0 = primitives.GetTexCoords0(data, positions.Length); var texCoords1 = primitives.GetTexCoords1(data, positions.Length); var colors = primitives.GetColors(data, positions.Length); var skinning = SkinningInfo.Create(data, gltfMesh, primitives); - AssignBoneWeight = skinning.ShouldSetRendererNodeAsBone ; - - CheckAttributeUsages(primitives); + ShouldSetRendererNodeAsBone = skinning.ShouldSetRendererNodeAsBone; for (var i = 0; i < positions.Length; ++i) { diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs index 6190804c5..7185b724e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs @@ -138,7 +138,7 @@ namespace UniGLTF { Mesh = mesh, Materials = data.MaterialIndices.Select(materialFromIndex).ToArray(), - ShouldSetRendererNodeAsBone = data.AssignBoneWeight, + ShouldSetRendererNodeAsBone = data.ShouldSetRendererNodeAsBone, }; await awaitCaller.NextFrame(); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs b/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs index f32e2a0e6..5164008b7 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs @@ -5,7 +5,7 @@ namespace UniGLTF { public const int MAJOR = 2; public const int MINOR = 37; - public const int PATCH = 0; - public const string VERSION = "2.37.0"; + public const int PATCH = 1; + public const string VERSION = "2.37.1"; } } diff --git a/Assets/UniGLTF/Tests/UniGLTF/MeshDataTests.cs b/Assets/UniGLTF/Tests/UniGLTF/MeshDataTests.cs new file mode 100644 index 000000000..fa255e424 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/MeshDataTests.cs @@ -0,0 +1,210 @@ +using System; +using NUnit.Framework; +using UnityEngine; + +namespace UniGLTF +{ + public class MeshDataTests + { + /// + /// shared + /// 3 2 + /// +-+ + /// |/| + /// +-+ + /// 0 1 + /// + /// divided + /// 2 + /// + + /// /| + /// +-+ + /// 0 1 + /// 4 3 + /// +-+ + /// |/ + /// + + /// 5 + /// + static byte[] CreateTestData(bool shared, bool hasNormal) + { + var data = new ExportingGltfData(); + data.Gltf.asset.version = "2.0"; + var mesh = new glTFMesh(); + data.Gltf.meshes.Add(mesh); + + if (shared) + { + var positions = new Vector3[] + { + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + }; + var normals = new Vector3[] + { + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + }; + + var position = data.ExtendBufferAndGetAccessorIndex(positions); + var normal = data.ExtendBufferAndGetAccessorIndex(normals); + { + var prim = new glTFPrimitives + { + attributes = new glTFAttributes + { + POSITION = position, + }, + indices = data.ExtendBufferAndGetAccessorIndex(new uint[] { 0, 1, 2 }), + }; + mesh.primitives.Add(prim); + if (hasNormal) + { + prim.attributes.NORMAL = normal; + } + } + { + var prim = new glTFPrimitives + { + attributes = new glTFAttributes + { + POSITION = position, + }, + indices = data.ExtendBufferAndGetAccessorIndex(new uint[] { 2, 3, 0 }), + }; + mesh.primitives.Add(prim); + if (hasNormal) + { + prim.attributes.NORMAL = normal; + } + } + } + else + { + { + var positions = new Vector3[] + { + new Vector3(), + new Vector3(), + new Vector3(), + }; + var position = data.ExtendBufferAndGetAccessorIndex(positions); + var prim = new glTFPrimitives + { + attributes = new glTFAttributes + { + POSITION = position, + }, + indices = data.ExtendBufferAndGetAccessorIndex(new uint[] { 0, 1, 2 }), + }; + if (hasNormal) + { + var normals = new Vector3[] + { + new Vector3(), + new Vector3(), + new Vector3(), + }; + var normal = data.ExtendBufferAndGetAccessorIndex(normals); + prim.attributes.NORMAL = normal; + } + mesh.primitives.Add(prim); + } + { + var positions = new Vector3[] + { + new Vector3(), + new Vector3(), + new Vector3(), + }; + var position = data.ExtendBufferAndGetAccessorIndex(positions); + var prim = new glTFPrimitives + { + attributes = new glTFAttributes + { + POSITION = position, + }, + indices = data.ExtendBufferAndGetAccessorIndex(new uint[] { 0, 1, 2 }), + }; + if (hasNormal) + { + var normals = new Vector3[] + { + new Vector3(), + new Vector3(), + new Vector3(), + }; + var normal = data.ExtendBufferAndGetAccessorIndex(normals); + prim.attributes.NORMAL = normal; + } + mesh.primitives.Add(prim); + } + } + return data.ToGlbBytes(); + } + + [Test] + public void SharedHasNormalTest() + { + var glb = CreateTestData(true, true); + using (var parsed = new GlbBinaryParser(glb, "test").Parse()) + { + Assert.True(MeshData.HasSharedVertexBuffer(parsed.GLTF.meshes[0])); + using (var data = new MeshData(6, 6)) + { + data.LoadFromGltf(parsed, 0, new ReverseZ()); + Assert.True(data.HasNormal); + } + } + } + + [Test] + public void SharedNotHasNormalTest() + { + var glb = CreateTestData(true, false); + using (var parsed = new GlbBinaryParser(glb, "test").Parse()) + { + Assert.True(MeshData.HasSharedVertexBuffer(parsed.GLTF.meshes[0])); + using (var data = new MeshData(6, 6)) + { + data.LoadFromGltf(parsed, 0, new ReverseZ()); + Assert.False(data.HasNormal); + } + } + } + + [Test] + public void DividedHasNormalTest() + { + var glb = CreateTestData(false, true); + using (var parsed = new GlbBinaryParser(glb, "test").Parse()) + { + Assert.False(MeshData.HasSharedVertexBuffer(parsed.GLTF.meshes[0])); + using (var data = new MeshData(6, 6)) + { + data.LoadFromGltf(parsed, 0, new ReverseZ()); + Assert.True(data.HasNormal); + } + } + } + + [Test] + public void DividedNotHasNormalTest() + { + var glb = CreateTestData(false, false); + using (var parsed = new GlbBinaryParser(glb, "test").Parse()) + { + Assert.False(MeshData.HasSharedVertexBuffer(parsed.GLTF.meshes[0])); + using (var data = new MeshData(6, 6)) + { + data.LoadFromGltf(parsed, 0, new ReverseZ()); + Assert.False(data.HasNormal); + } + } + } + } +} diff --git a/Assets/UniGLTF/Tests/UniGLTF/MeshDataTests.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/MeshDataTests.cs.meta new file mode 100644 index 000000000..abeec9770 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/MeshDataTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e1e46a1dd2717854194c1b10ec096bef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/package.json b/Assets/UniGLTF/package.json index 95a002e5e..c2cd7b8c3 100644 --- a/Assets/UniGLTF/package.json +++ b/Assets/UniGLTF/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.gltf", - "version": "0.101.0", + "version": "0.101.1", "displayName": "UniGLTF", "description": "GLTF importer and exporter", "unity": "2019.4", @@ -11,6 +11,6 @@ "name": "VRM Consortium" }, "dependencies": { - "com.vrmc.vrmshaders": "0.101.0" + "com.vrmc.vrmshaders": "0.101.1" } } \ No newline at end of file diff --git a/Assets/VRM/Runtime/Format/VRMVersion.cs b/Assets/VRM/Runtime/Format/VRMVersion.cs index a99d41d78..4c61305d0 100644 --- a/Assets/VRM/Runtime/Format/VRMVersion.cs +++ b/Assets/VRM/Runtime/Format/VRMVersion.cs @@ -5,7 +5,7 @@ namespace VRM { public const int MAJOR = 0; public const int MINOR = 101; - public const int PATCH = 0; - public const string VERSION = "0.101.0"; + public const int PATCH = 1; + public const string VERSION = "0.101.1"; } } diff --git a/Assets/VRM/package.json b/Assets/VRM/package.json index 52dcd6d3c..89e44c0b1 100644 --- a/Assets/VRM/package.json +++ b/Assets/VRM/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.univrm", - "version": "0.101.0", + "version": "0.101.1", "displayName": "VRM", "description": "VRM importer", "unity": "2019.4", @@ -14,8 +14,8 @@ "name": "VRM Consortium" }, "dependencies": { - "com.vrmc.vrmshaders": "0.101.0", - "com.vrmc.gltf": "0.101.0" + "com.vrmc.vrmshaders": "0.101.1", + "com.vrmc.gltf": "0.101.1" }, "samples": [ { diff --git a/Assets/VRM10/package.json b/Assets/VRM10/package.json index 4454537d2..a7e8bc24e 100644 --- a/Assets/VRM10/package.json +++ b/Assets/VRM10/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.vrm", - "version": "0.101.0", + "version": "0.101.1", "displayName": "VRM-1.0β", "description": "VRM-1.0β importer", "unity": "2019.4", @@ -14,8 +14,8 @@ "name": "VRM Consortium" }, "dependencies": { - "com.vrmc.vrmshaders": "0.101.0", - "com.vrmc.gltf": "0.101.0" + "com.vrmc.vrmshaders": "0.101.1", + "com.vrmc.gltf": "0.101.1" }, "samples": [ { diff --git a/Assets/VRMShaders/package.json b/Assets/VRMShaders/package.json index 5d31a4137..819712424 100644 --- a/Assets/VRMShaders/package.json +++ b/Assets/VRMShaders/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.vrmshaders", - "version": "0.101.0", + "version": "0.101.1", "displayName": "VRM Shaders", "description": "VRM Shaders", "unity": "2019.4",