mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-14 06:19:47 -05:00
Merge pull request #2315 from ousttrue/export_null_material
Export null material
This commit is contained in:
commit
47ee539554
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -313,7 +307,18 @@ namespace UniGLTF
|
|||
{
|
||||
using (MeasureTime("BuildMesh"))
|
||||
{
|
||||
var meshWithMaterials = await MeshUploader.BuildMeshAndUploadAsync(awaitCaller, meshData, MaterialFactory.GetMaterial);
|
||||
var meshWithMaterials = await MeshUploader.BuildMeshAndUploadAsync(awaitCaller, meshData,
|
||||
(int? materialIndex) =>
|
||||
{
|
||||
if (materialIndex.HasValidIndex())
|
||||
{
|
||||
return MaterialFactory.GetMaterial(materialIndex.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MaterialFactory.DefaultMaterial;
|
||||
}
|
||||
});
|
||||
var mesh = meshWithMaterials.Mesh;
|
||||
|
||||
// mesh name
|
||||
|
|
|
|||
|
|
@ -12,16 +12,16 @@ namespace UniGLTF
|
|||
{
|
||||
private int _currentVertexCount = 0;
|
||||
private int _currentIndexCount = 0;
|
||||
|
||||
|
||||
private NativeArray<int> _indices;
|
||||
private NativeArray<MeshVertex0> _vertices0;
|
||||
private NativeArray<MeshVertex1> _vertices1;
|
||||
private NativeArray<MeshVertex2> _vertices2;
|
||||
|
||||
|
||||
private readonly List<SubMeshDescriptor> _subMeshes = new List<SubMeshDescriptor>();
|
||||
private readonly List<int> _materialIndices = new List<int>();
|
||||
private readonly List<int?> _materialIndices = new List<int?>();
|
||||
private readonly List<BlendShape> _blendShapes = new List<BlendShape>();
|
||||
|
||||
|
||||
public NativeArray<MeshVertex0> Vertices0 => _vertices0.GetSubArray(0, _currentVertexCount);
|
||||
public NativeArray<MeshVertex1> Vertices1 => _vertices1.GetSubArray(0, _currentVertexCount);
|
||||
public NativeArray<MeshVertex2> Vertices2 => _vertices2.GetSubArray(0, _currentVertexCount);
|
||||
|
|
@ -29,7 +29,7 @@ namespace UniGLTF
|
|||
public NativeArray<int> Indices => _indices.GetSubArray(0, _currentIndexCount);
|
||||
|
||||
public IReadOnlyList<SubMeshDescriptor> SubMeshes => _subMeshes;
|
||||
public IReadOnlyList<int> MaterialIndices => _materialIndices;
|
||||
public IReadOnlyList<int?> MaterialIndices => _materialIndices;
|
||||
|
||||
public IReadOnlyList<BlendShape> 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
|
||||
|
|
|
|||
|
|
@ -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<int> indices)
|
||||
public glTFPrimitives ToGltfPrimitive(ExportingGltfData data, int? materialIndex, IEnumerable<int> indices)
|
||||
{
|
||||
var indicesAccessorIndex = data.ExtendBufferAndGetAccessorIndex(indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
|
||||
var positions = m_positions.ToArray();
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ namespace UniGLTF
|
|||
public static async Task<MeshWithMaterials> BuildMeshAndUploadAsync(
|
||||
IAwaitCaller awaitCaller,
|
||||
MeshData data,
|
||||
Func<int, Material> materialFromIndex)
|
||||
Func<int?, Material> materialFromIndex)
|
||||
{
|
||||
|
||||
//Debug.Log(prims.ToJson());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -228,7 +240,7 @@ namespace UniVRM10
|
|||
continue;
|
||||
}
|
||||
|
||||
CreateRenderer(node, go, map, MaterialFactory.Materials);
|
||||
CreateRenderer(node, go, map, MaterialFactory);
|
||||
await awaitCaller.NextFrame();
|
||||
}
|
||||
}
|
||||
|
|
@ -790,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();
|
||||
|
|
@ -825,12 +836,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 materialFactory.Materials[x.Material.Value].Asset;
|
||||
}
|
||||
else
|
||||
{
|
||||
return materialFactory.DefaultMaterial;
|
||||
}
|
||||
}
|
||||
).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 materialFactory.Materials[x.Submeshes[0].Material.Value].Asset;
|
||||
}
|
||||
else
|
||||
{
|
||||
return materialFactory.DefaultMaterial;
|
||||
}
|
||||
}
|
||||
).ToArray();
|
||||
renderer.sharedMaterials = materials;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user