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