From e575b27b151e289067994f266cc00a0cc321e275 Mon Sep 17 00:00:00 2001 From: Lyuma Date: Mon, 1 Nov 2021 23:14:02 -0700 Subject: [PATCH] 3.x backport glTF: Fix override materials and non-empty arrays Keep track of MeshInstance and GeometryInstance override materials in the GLTFMesh object. Ensure all arrays are non-empty to conform with "minItems":1 in glTF spec. --- modules/gltf/doc_classes/GLTFMesh.xml | 2 ++ modules/gltf/gltf_document.cpp | 41 +++++++++++++++++++++++++-- modules/gltf/gltf_mesh.cpp | 11 +++++++ modules/gltf/gltf_mesh.h | 3 ++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/modules/gltf/doc_classes/GLTFMesh.xml b/modules/gltf/doc_classes/GLTFMesh.xml index 8d86eefbd87..e12d40631b8 100644 --- a/modules/gltf/doc_classes/GLTFMesh.xml +++ b/modules/gltf/doc_classes/GLTFMesh.xml @@ -11,6 +11,8 @@ + + diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index ab971d78ded..f10f9b09344 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -739,6 +739,9 @@ Error GLTFDocument::_encode_buffer_glb(Ref state, const String &p_pat gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); } + if (!buffers.size()) { + return OK; + } state->json["buffers"] = buffers; return OK; @@ -843,6 +846,9 @@ Error GLTFDocument::_encode_buffer_views(Ref state) { buffers.push_back(d); } print_verbose("glTF: Total buffer views: " + itos(state->buffer_views.size())); + if (!buffers.size()) { + return OK; + } state->json["bufferViews"] = buffers; return OK; } @@ -942,6 +948,9 @@ Error GLTFDocument::_encode_accessors(Ref state) { accessors.push_back(d); } + if (!accessors.size()) { + return OK; + } state->json["accessors"] = accessors; ERR_FAIL_COND_V(!state->json.has("accessors"), ERR_FILE_CORRUPT); print_verbose("glTF: Total accessors: " + itos(state->accessors.size())); @@ -2287,6 +2296,7 @@ Error GLTFDocument::_serialize_meshes(Ref state) { if (import_mesh.is_null()) { continue; } + Array instance_materials = state->meshes.write[gltf_mesh_i]->get_instance_materials(); Array primitives; Dictionary gltf_mesh; Array target_names; @@ -2531,8 +2541,14 @@ Error GLTFDocument::_serialize_meshes(Ref state) { targets.push_back(t); } } - - Ref mat = import_mesh->surface_get_material(surface_i); + Variant v; + if (surface_i < instance_materials.size()) { + v = instance_materials.get(surface_i); + } + Ref mat = v; + if (!mat.is_valid()) { + mat = import_mesh->surface_get_material(surface_i); + } if (mat.is_valid()) { Map, GLTFMaterialIndex>::Element *material_cache_i = state->material_cache.find(mat); if (material_cache_i && material_cache_i->get() != -1) { @@ -2576,6 +2592,9 @@ Error GLTFDocument::_serialize_meshes(Ref state) { meshes.push_back(gltf_mesh); } + if (!meshes.size()) { + return OK; + } state->json["meshes"] = meshes; print_verbose("glTF: Total meshes: " + itos(meshes.size())); @@ -3442,6 +3461,9 @@ Error GLTFDocument::_serialize_materials(Ref state) { } materials.push_back(d); } + if (!materials.size()) { + return OK; + } state->json["materials"] = materials; print_verbose("Total materials: " + itos(state->materials.size())); @@ -4835,6 +4857,9 @@ Error GLTFDocument::_serialize_animations(Ref state) { } } + if (!animations.size()) { + return OK; + } state->json["animations"] = animations; print_verbose("glTF: Total animations '" + itos(state->animations.size()) + "'."); @@ -5066,6 +5091,18 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref state, MeshInst } Ref gltf_mesh; gltf_mesh.instance(); + Array instance_materials; + for (int32_t surface_i = 0; surface_i < import_mesh->get_surface_count(); surface_i++) { + Ref mat = import_mesh->surface_get_material(surface_i); + if (p_mesh_instance->get_surface_material(surface_i).is_valid()) { + mat = p_mesh_instance->get_surface_material(surface_i); + } + if (p_mesh_instance->get_material_override().is_valid()) { + mat = p_mesh_instance->get_material_override(); + } + instance_materials.append(mat); + } + gltf_mesh->set_instance_materials(instance_materials); gltf_mesh->set_mesh(import_mesh); gltf_mesh->set_blend_weights(blend_weights); GLTFMeshIndex mesh_i = state->meshes.size(); diff --git a/modules/gltf/gltf_mesh.cpp b/modules/gltf/gltf_mesh.cpp index 0628f2bec9c..ea8bedd072f 100644 --- a/modules/gltf/gltf_mesh.cpp +++ b/modules/gltf/gltf_mesh.cpp @@ -35,9 +35,12 @@ void GLTFMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &GLTFMesh::set_mesh); ClassDB::bind_method(D_METHOD("get_blend_weights"), &GLTFMesh::get_blend_weights); ClassDB::bind_method(D_METHOD("set_blend_weights", "blend_weights"), &GLTFMesh::set_blend_weights); + ClassDB::bind_method(D_METHOD("get_instance_materials"), &GLTFMesh::get_instance_materials); + ClassDB::bind_method(D_METHOD("set_instance_materials", "instance_materials"), &GLTFMesh::set_instance_materials); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh"), "set_mesh", "get_mesh"); ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "blend_weights"), "set_blend_weights", "get_blend_weights"); // Vector + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "instance_materials"), "set_instance_materials", "get_instance_materials"); } Ref GLTFMesh::get_mesh() { @@ -48,6 +51,14 @@ void GLTFMesh::set_mesh(Ref p_mesh) { mesh = p_mesh; } +Array GLTFMesh::get_instance_materials() { + return instance_materials; +} + +void GLTFMesh::set_instance_materials(Array p_instance_materials) { + instance_materials = p_instance_materials; +} + Vector GLTFMesh::get_blend_weights() { return blend_weights; } diff --git a/modules/gltf/gltf_mesh.h b/modules/gltf/gltf_mesh.h index 5f9a2f6928d..3d0825a0399 100644 --- a/modules/gltf/gltf_mesh.h +++ b/modules/gltf/gltf_mesh.h @@ -41,6 +41,7 @@ class GLTFMesh : public Resource { private: Ref mesh; Vector blend_weights; + Array instance_materials; protected: static void _bind_methods(); @@ -50,5 +51,7 @@ public: void set_mesh(Ref p_mesh); Vector get_blend_weights(); void set_blend_weights(Vector p_blend_weights); + Array get_instance_materials(); + void set_instance_materials(Array p_instance_materials); }; #endif // GLTF_MESH_H