From c67275007852f5b3a4d743f6301ff07da28adeae Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 7 Jun 2024 16:20:28 +0900 Subject: [PATCH 1/4] skip null --- Assets/VRM10/Runtime/IO/Model/ModelExporter.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs b/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs index dd9e3d044..b7f3302e9 100644 --- a/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs @@ -112,6 +112,10 @@ namespace UniVRM10 var materials = renderer.sharedMaterials; // avoid copy foreach (var material in materials) { + if (material == null) + { + continue; + } if (Materials.Contains(material)) { continue; From c7f2104d2dbaaed20b84657f3dbdbb01189bd132 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 7 Jun 2024 16:58:44 +0900 Subject: [PATCH 2/4] =?UTF-8?q?MATERIALS=5FCONTAINS=5FNULL=20=E3=82=92=20w?= =?UTF-8?q?arn=20=E3=81=AB=E6=A0=BC=E4=B8=8B=E3=81=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs index 91061f642..fba3887a2 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs @@ -90,7 +90,7 @@ namespace UniGLTF if (info.Materials.Take(info.Mesh.subMeshCount).Any(x => x == null)) { // material に null が含まれる(unity で magenta になっているはず) - yield return Validation.Error(Messages.MATERIALS_CONTAINS_NULL.Msg(), ValidationContext.Create(info.Renderers[0].Item1)); + yield return Validation.Warning(Messages.MATERIALS_CONTAINS_NULL.Msg(), ValidationContext.Create(info.Renderers[0].Item1)); } } From 33d8d42516154a00e597130a6b3e02ba28a420f4 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 7 Jun 2024 17:02:55 +0900 Subject: [PATCH 3/4] =?UTF-8?q?glTFPrimitives.material=20=E3=82=92=20int?= =?UTF-8?q?=3F=20=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniGLTF/Format/GltfSerializer.g.cs | 4 +- .../Runtime/UniGLTF/Format/glTFMesh.cs | 2 +- .../Runtime/UniGLTF/IO/ImporterContext.cs | 3 +- .../Runtime/UniGLTF/IO/MeshIO/MeshData.cs | 12 +++--- .../UniGLTF/IO/MeshIO/MeshExportUtil.cs | 2 +- .../Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs | 2 +- Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs | 4 +- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 41 +++++++++++++++++-- Assets/VRM10/vrmlib/Runtime/Mesh.cs | 6 +-- 9 files changed, 56 insertions(+), 20 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/Format/GltfSerializer.g.cs b/Assets/UniGLTF/Runtime/UniGLTF/Format/GltfSerializer.g.cs index 326834f80..b4227c291 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/Format/GltfSerializer.g.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/Format/GltfSerializer.g.cs @@ -972,9 +972,9 @@ public static void Serialize_gltf_meshes__primitives_ITEM(JsonFormatter f, glTFP Serialize_gltf_meshes__primitives__attributes(f, value.attributes); } - if(value.material>=0){ + if(value.material.HasValidIndex()){ f.Key("material"); - f.Value(value.material); + f.Value(value.material.Value); } if(value.targets!=null&&value.targets.Count>=1){ diff --git a/Assets/UniGLTF/Runtime/UniGLTF/Format/glTFMesh.cs b/Assets/UniGLTF/Runtime/UniGLTF/Format/glTFMesh.cs index 9d945e064..bc65a325c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/Format/glTFMesh.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/Format/glTFMesh.cs @@ -85,7 +85,7 @@ namespace UniGLTF public glTFAttributes attributes; [JsonSchema(Minimum = 0)] - public int material; + public int? material; [JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)] [ItemJsonSchema(SkipSchemaComparison = true)] diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index e05d60b09..fba947b0e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -313,7 +313,8 @@ namespace UniGLTF { using (MeasureTime("BuildMesh")) { - var meshWithMaterials = await MeshUploader.BuildMeshAndUploadAsync(awaitCaller, meshData, MaterialFactory.GetMaterial); + var meshWithMaterials = await MeshUploader.BuildMeshAndUploadAsync(awaitCaller, meshData, + (int? materialIndex) => materialIndex.HasValidIndex() ? MaterialFactory.GetMaterial(materialIndex.Value) : null); var mesh = meshWithMaterials.Mesh; // mesh name diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs index 2bffd253a..b96f05c9f 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshData.cs @@ -12,16 +12,16 @@ namespace UniGLTF { private int _currentVertexCount = 0; private int _currentIndexCount = 0; - + private NativeArray _indices; private NativeArray _vertices0; private NativeArray _vertices1; private NativeArray _vertices2; - + private readonly List _subMeshes = new List(); - private readonly List _materialIndices = new List(); + private readonly List _materialIndices = new List(); private readonly List _blendShapes = new List(); - + public NativeArray Vertices0 => _vertices0.GetSubArray(0, _currentVertexCount); public NativeArray Vertices1 => _vertices1.GetSubArray(0, _currentVertexCount); public NativeArray Vertices2 => _vertices2.GetSubArray(0, _currentVertexCount); @@ -29,7 +29,7 @@ namespace UniGLTF public NativeArray Indices => _indices.GetSubArray(0, _currentIndexCount); public IReadOnlyList SubMeshes => _subMeshes; - public IReadOnlyList MaterialIndices => _materialIndices; + public IReadOnlyList MaterialIndices => _materialIndices; public IReadOnlyList BlendShapes => _blendShapes; @@ -336,7 +336,7 @@ namespace UniGLTF var texCoord1 = texCoords1 != null ? texCoords1.Value[i].ReverseUV() : Vector2.zero; var color = colors != null ? colors.Value[i] : Color.white; - + _vertices0[_currentVertexCount] = new MeshVertex0( position, normal diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshExportUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshExportUtil.cs index e796b4fb2..133ad6c11 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshExportUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshExportUtil.cs @@ -110,7 +110,7 @@ namespace UniGLTF m_weights.Add(new Vector4(boneWeight.weight0, boneWeight.weight1, boneWeight.weight2, boneWeight.weight3)); } - public glTFPrimitives ToGltfPrimitive(ExportingGltfData data, int materialIndex, IEnumerable indices) + public glTFPrimitives ToGltfPrimitive(ExportingGltfData data, int? materialIndex, IEnumerable indices) { var indicesAccessorIndex = data.ExtendBufferAndGetAccessorIndex(indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER); var positions = m_positions.ToArray(); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs index 5540a6df3..9fefcc477 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshUploader.cs @@ -91,7 +91,7 @@ namespace UniGLTF public static async Task BuildMeshAndUploadAsync( IAwaitCaller awaitCaller, MeshData data, - Func materialFromIndex) + Func materialFromIndex) { //Debug.Log(prims.ToJson()); diff --git a/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs b/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs index 73c9e7c07..d2770cd22 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs @@ -602,10 +602,10 @@ namespace UniGLTF Assert.AreEqual(2, gltf.meshes.Count); - var red = gltf.materials[gltf.meshes[0].primitives[0].material]; + var red = gltf.materials[gltf.meshes[0].primitives[0].material.Value]; Assert.AreEqual(new float[] { 1, 0, 0, 1 }, red.pbrMetallicRoughness.baseColorFactor); - var blue = gltf.materials[gltf.meshes[1].primitives[0].material]; + var blue = gltf.materials[gltf.meshes[1].primitives[0].material.Value]; Assert.AreEqual(new float[] { 0, 0, 1, 1 }, blue.pbrMetallicRoughness.baseColorFactor); Assert.AreEqual(2, gltf.nodes.Count); diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index 98d7ac94b..e75572cb6 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -188,7 +188,19 @@ namespace UniVRM10 Meshes.Add(new MeshWithMaterials { Mesh = mesh, - Materials = src.Meshes[0].Submeshes.Select(x => MaterialFactory.Materials[x.Material].Asset).ToArray(), + Materials = src.Meshes[0].Submeshes.Select( + x => + { + if (x.Material.HasValidIndex()) + { + return MaterialFactory.Materials[x.Material.Value].Asset; + } + else + { + return null; + } + } + ).ToArray(), }); @@ -825,12 +837,35 @@ namespace UniVRM10 } else if (node.MeshGroup.Meshes.Count == 1) { - var materials = node.MeshGroup.Meshes[0].Submeshes.Select(x => materialLoadInfos[x.Material].Asset).ToArray(); + var materials = node.MeshGroup.Meshes[0].Submeshes.Select( + x => + { + if (x.Material.HasValidIndex()) + { + return materialLoadInfos[x.Material.Value].Asset; + } + else + { + return null; + } + } + ).ToArray(); renderer.sharedMaterials = materials; } else { - var materials = node.MeshGroup.Meshes.Select(x => materialLoadInfos[x.Submeshes[0].Material].Asset).ToArray(); + var materials = node.MeshGroup.Meshes.Select(x => + { + if (x.Submeshes[0].Material.HasValidIndex()) + { + return materialLoadInfos[x.Submeshes[0].Material.Value].Asset; + } + else + { + return null; + } + } + ).ToArray(); renderer.sharedMaterials = materials; } diff --git a/Assets/VRM10/vrmlib/Runtime/Mesh.cs b/Assets/VRM10/vrmlib/Runtime/Mesh.cs index ceb69e45e..2a7e7790f 100644 --- a/Assets/VRM10/vrmlib/Runtime/Mesh.cs +++ b/Assets/VRM10/vrmlib/Runtime/Mesh.cs @@ -35,18 +35,18 @@ namespace VrmLib { public int Offset; public int DrawCount; - public int Material; + public int? Material; public override string ToString() { return $"{Material}({DrawCount})"; } - public Submesh(int material) : this(0, 0, material) + public Submesh(int? material) : this(0, 0, material) { } - public Submesh(int offset, int drawCount, int material) + public Submesh(int offset, int drawCount, int? material) { Offset = offset; DrawCount = drawCount; From e7d850f51d8805931408d1a76ea728ebffc570f6 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 7 Jun 2024 18:19:01 +0900 Subject: [PATCH 4/4] use DefaultMaterial if gltfPrimitive.material is not exists or -1 --- .../Runtime/Extensions/IndexExtensions.cs | 19 +++++++++++++ .../Runtime/UniGLTF/IO/ImporterContext.cs | 24 ++++++++++------- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 13 +++++---- .../Material/Importer/MaterialFactory.cs | 27 +++++++++++++++++-- 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/Assets/UniGLTF/Runtime/Extensions/IndexExtensions.cs b/Assets/UniGLTF/Runtime/Extensions/IndexExtensions.cs index 7599e5b95..e855768a5 100644 --- a/Assets/UniGLTF/Runtime/Extensions/IndexExtensions.cs +++ b/Assets/UniGLTF/Runtime/Extensions/IndexExtensions.cs @@ -15,5 +15,24 @@ namespace UniGLTF } return true; } + + public static bool HasValidIndex(this int? self, int collectionLength) + { + if (!self.HasValue) + { + return false; + } + if (self.Value < 0) + { + // 古いモデルで index の無効値に -1 を使っている場合がある + return false; + } + if (self.Value >= collectionLength) + { + // ついでに上限もチェック + return false; + } + return true; + } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index fba947b0e..a2605d732 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -49,7 +49,8 @@ namespace UniGLTF Data.MigrationFlags.IsRoughnessTextureValueSquared); MaterialFactory = new MaterialFactory(ExternalObjectMap .Where(x => x.Value is Material) - .ToDictionary(x => x.Key, x => (Material)x.Value)); + .ToDictionary(x => x.Key, x => (Material)x.Value), + MaterialDescriptorGenerator.GetGltfDefault()); AnimationClipFactory = new AnimationClipFactory(ExternalObjectMap .Where(x => x.Value is AnimationClip) .ToDictionary(x => x.Key, x => (AnimationClip)x.Value)); @@ -285,14 +286,7 @@ namespace UniGLTF throw new ArgumentNullException(); } - if (Data.GLTF.materials == null || Data.GLTF.materials.Count == 0) - { - // no material. work around. - // TODO: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#default-material - var param = MaterialDescriptorGenerator.GetGltfDefault(); - await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync, awaitCaller); - } - else + if (Data.GLTF.materials != null) { for (int i = 0; i < Data.GLTF.materials.Count; ++i) { @@ -314,7 +308,17 @@ namespace UniGLTF using (MeasureTime("BuildMesh")) { var meshWithMaterials = await MeshUploader.BuildMeshAndUploadAsync(awaitCaller, meshData, - (int? materialIndex) => materialIndex.HasValidIndex() ? MaterialFactory.GetMaterial(materialIndex.Value) : null); + (int? materialIndex) => + { + if (materialIndex.HasValidIndex()) + { + return MaterialFactory.GetMaterial(materialIndex.Value); + } + else + { + return MaterialFactory.DefaultMaterial; + } + }); var mesh = meshWithMaterials.Mesh; // mesh name diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index e75572cb6..352e8807d 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -240,7 +240,7 @@ namespace UniVRM10 continue; } - CreateRenderer(node, go, map, MaterialFactory.Materials); + CreateRenderer(node, go, map, MaterialFactory); await awaitCaller.NextFrame(); } } @@ -802,8 +802,7 @@ namespace UniVRM10 /// /// MeshFilter + MeshRenderer もしくは SkinnedMeshRenderer を構築する /// - public static Renderer CreateRenderer(VrmLib.Node node, GameObject go, ModelMap map, - IReadOnlyList materialLoadInfos) + public static Renderer CreateRenderer(VrmLib.Node node, GameObject go, ModelMap map, MaterialFactory materialFactory) { Renderer renderer = null; var hasBlendShape = node.MeshGroup.Meshes[0].MorphTargets.Any(); @@ -842,11 +841,11 @@ namespace UniVRM10 { if (x.Material.HasValidIndex()) { - return materialLoadInfos[x.Material.Value].Asset; + return materialFactory.Materials[x.Material.Value].Asset; } else { - return null; + return materialFactory.DefaultMaterial; } } ).ToArray(); @@ -858,11 +857,11 @@ namespace UniVRM10 { if (x.Submeshes[0].Material.HasValidIndex()) { - return materialLoadInfos[x.Submeshes[0].Material.Value].Asset; + return materialFactory.Materials[x.Submeshes[0].Material.Value].Asset; } else { - return null; + return materialFactory.DefaultMaterial; } } ).ToArray(); diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Material/Importer/MaterialFactory.cs b/Assets/VRMShaders/GLTF/IO/Runtime/Material/Importer/MaterialFactory.cs index 882818fbb..0e578c92c 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/Material/Importer/MaterialFactory.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Material/Importer/MaterialFactory.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using UnityEngine; @@ -13,9 +12,33 @@ namespace VRMShaders { private readonly IReadOnlyDictionary m_externalMap; - public MaterialFactory(IReadOnlyDictionary externalMaterialMap) + MaterialDescriptor m_defaultMaterialParams; + + /// + /// gltfPritmitive.material が無い場合のデフォルトマテリアル + /// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#default-material + /// + Material m_defaultMaterial; + + public Material DefaultMaterial + { + get + { + if (m_defaultMaterial == null) + { + // default material にバリエーションがある? + var task = LoadAsync(m_defaultMaterialParams, (_x, _y) => Task.FromResult(null), new ImmediateCaller()); + task.Wait(); + m_defaultMaterial = task.Result; + } + return m_defaultMaterial; + } + } + + public MaterialFactory(IReadOnlyDictionary externalMaterialMap, MaterialDescriptor defaultMaterialParams) { m_externalMap = externalMaterialMap; + m_defaultMaterialParams = defaultMaterialParams; } public struct MaterialLoadInfo