diff --git a/scene/3d/multimesh_instance_3d.cpp b/scene/3d/multimesh_instance_3d.cpp index 2158005f5ff..55d6e49e6ca 100644 --- a/scene/3d/multimesh_instance_3d.cpp +++ b/scene/3d/multimesh_instance_3d.cpp @@ -49,6 +49,26 @@ Ref MultiMeshInstance3D::get_multimesh() const { return multimesh; } +Array MultiMeshInstance3D::get_meshes() const { + if (multimesh.is_null() || multimesh->get_mesh().is_null() || multimesh->get_transform_format() != MultiMesh::TransformFormat::TRANSFORM_3D) { + return Array(); + } + + int count = multimesh->get_visible_instance_count(); + if (count == -1) { + count = multimesh->get_instance_count(); + } + + Ref mesh = multimesh->get_mesh(); + + Array results; + for (int i = 0; i < count; i++) { + results.push_back(multimesh->get_instance_transform(i)); + results.push_back(mesh); + } + return results; +} + AABB MultiMeshInstance3D::get_aabb() const { if (multimesh.is_null()) { return AABB(); diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h index cd18281b913..404f31d1e37 100644 --- a/scene/3d/multimesh_instance_3d.h +++ b/scene/3d/multimesh_instance_3d.h @@ -47,6 +47,8 @@ public: void set_multimesh(const Ref &p_multimesh); Ref get_multimesh() const; + Array get_meshes() const; + virtual AABB get_aabb() const override; MultiMeshInstance3D(); diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 43906b25865..8250083a9fc 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -314,9 +314,21 @@ Ref VoxelGI::get_camera_attributes() const { return camera_attributes; } +static bool is_node_voxel_bakeable(Node3D *p_node) { + if (!p_node->is_visible_in_tree()) { + return false; + } + + GeometryInstance3D *geometry = Object::cast_to(p_node); + if (geometry != nullptr && geometry->get_gi_mode() != GeometryInstance3D::GI_MODE_STATIC) { + return false; + } + return true; +} + void VoxelGI::_find_meshes(Node *p_at_node, List &plot_meshes) { MeshInstance3D *mi = Object::cast_to(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { + if (mi && is_node_voxel_bakeable(mi)) { Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); @@ -338,8 +350,15 @@ void VoxelGI::_find_meshes(Node *p_at_node, List &plot_meshes) { Node3D *s = Object::cast_to(p_at_node); if (s) { - if (s->is_visible_in_tree()) { - Array meshes = p_at_node->call("get_meshes"); + if (is_node_voxel_bakeable(s)) { + Array meshes; + MultiMeshInstance3D *multi_mesh = Object::cast_to(p_at_node); + if (multi_mesh) { + meshes = multi_mesh->get_meshes(); + } else { + meshes = p_at_node->call("get_meshes"); + } + for (int i = 0; i < meshes.size(); i += 2) { Transform3D mxf = meshes[i]; Ref mesh = meshes[i + 1]; diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index fec4bc2b05c..99392e9ba06 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -383,6 +383,8 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref p_material } void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref &p_mesh, const Vector> &p_materials, const Ref &p_override_material) { + ERR_FAIL_COND_MSG(!p_xform.is_finite(), "Invalid mesh bake transform."); + for (int i = 0; i < p_mesh->get_surface_count(); i++) { if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; //only triangles