use DefaultMaterial if gltfPrimitive.material is not exists or -1

This commit is contained in:
ousttrue
2024-06-07 18:19:01 +09:00
parent 33d8d42516
commit e7d850f51d
4 changed files with 64 additions and 19 deletions

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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
/// <summary>
/// MeshFilter + MeshRenderer もしくは SkinnedMeshRenderer を構築する
/// </summary>
public static Renderer CreateRenderer(VrmLib.Node node, GameObject go, ModelMap map,
IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo> 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();

View File

@@ -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<SubAssetKey, Material> m_externalMap;
public MaterialFactory(IReadOnlyDictionary<SubAssetKey, Material> externalMaterialMap)
MaterialDescriptor m_defaultMaterialParams;
/// <summary>
/// gltfPritmitive.material が無い場合のデフォルトマテリアル
/// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#default-material
/// </summary>
Material m_defaultMaterial;
public Material DefaultMaterial
{
get
{
if (m_defaultMaterial == null)
{
// default material にバリエーションがある?
var task = LoadAsync(m_defaultMaterialParams, (_x, _y) => Task.FromResult<Texture>(null), new ImmediateCaller());
task.Wait();
m_defaultMaterial = task.Result;
}
return m_defaultMaterial;
}
}
public MaterialFactory(IReadOnlyDictionary<SubAssetKey, Material> externalMaterialMap, MaterialDescriptor defaultMaterialParams)
{
m_externalMap = externalMaterialMap;
m_defaultMaterialParams = defaultMaterialParams;
}
public struct MaterialLoadInfo