Переглянути джерело

Fix VoxelGI MultiMesh and CSG mesh baking

bitsawer 1 рік тому
батько
коміт
cbb39f4b6e

+ 20 - 0
scene/3d/multimesh_instance_3d.cpp

@@ -49,6 +49,26 @@ Ref<MultiMesh> 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> 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();

+ 2 - 0
scene/3d/multimesh_instance_3d.h

@@ -47,6 +47,8 @@ public:
 	void set_multimesh(const Ref<MultiMesh> &p_multimesh);
 	Ref<MultiMesh> get_multimesh() const;
 
+	Array get_meshes() const;
+
 	virtual AABB get_aabb() const override;
 
 	MultiMeshInstance3D();

+ 22 - 3
scene/3d/voxel_gi.cpp

@@ -314,9 +314,21 @@ Ref<CameraAttributes> 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<GeometryInstance3D>(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<PlotMesh> &plot_meshes) {
 	MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(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> 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<PlotMesh> &plot_meshes) {
 
 	Node3D *s = Object::cast_to<Node3D>(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<MultiMeshInstance3D>(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> mesh = meshes[i + 1];

+ 2 - 0
scene/3d/voxelizer.cpp

@@ -383,6 +383,8 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
 }
 
 void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &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