summaryrefslogtreecommitdiff
path: root/editor/import/resource_importer_scene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/import/resource_importer_scene.cpp')
-rw-r--r--editor/import/resource_importer_scene.cpp116
1 files changed, 95 insertions, 21 deletions
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 22a11e11cb..3eb12353b5 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -39,6 +39,7 @@
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_region_3d.h"
+#include "scene/3d/occluder_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/vehicle_body_3d.h"
#include "scene/animation/animation_player.h"
@@ -371,10 +372,10 @@ static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r
}
}
-Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames) {
+Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames) {
// Children first.
for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map, r_node_renames);
+ Node *r = _pre_fix_node(p_node->get_child(i), p_root, r_collision_map, r_occluder_arrays, r_node_renames);
if (!r) {
i--; // Was erased.
}
@@ -498,14 +499,14 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
if (mesh.is_valid()) {
Vector<Ref<Shape3D>> shapes;
- if (collision_map.has(mesh)) {
- shapes = collision_map[mesh];
+ if (r_collision_map.has(mesh)) {
+ shapes = r_collision_map[mesh];
} else if (_teststr(name, "colonly")) {
_pre_gen_shape_list(mesh, shapes, false);
- collision_map[mesh] = shapes;
+ r_collision_map[mesh] = shapes;
} else if (_teststr(name, "convcolonly")) {
_pre_gen_shape_list(mesh, shapes, true);
- collision_map[mesh] = shapes;
+ r_collision_map[mesh] = shapes;
}
if (shapes.size()) {
@@ -560,8 +561,8 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
if (mesh.is_valid()) {
Vector<Ref<Shape3D>> shapes;
- if (collision_map.has(mesh)) {
- shapes = collision_map[mesh];
+ if (r_collision_map.has(mesh)) {
+ shapes = r_collision_map[mesh];
} else {
_pre_gen_shape_list(mesh, shapes, true);
}
@@ -586,14 +587,14 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
if (mesh.is_valid()) {
Vector<Ref<Shape3D>> shapes;
String fixed_name;
- if (collision_map.has(mesh)) {
- shapes = collision_map[mesh];
+ if (r_collision_map.has(mesh)) {
+ shapes = r_collision_map[mesh];
} else if (_teststr(name, "col")) {
_pre_gen_shape_list(mesh, shapes, false);
- collision_map[mesh] = shapes;
+ r_collision_map[mesh] = shapes;
} else if (_teststr(name, "convcol")) {
_pre_gen_shape_list(mesh, shapes, true);
- collision_map[mesh] = shapes;
+ r_collision_map[mesh] = shapes;
}
if (_teststr(name, "col")) {
@@ -635,7 +636,31 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
p_node->replace_by(nmi);
memdelete(p_node);
p_node = nmi;
+ } else if (_teststr(name, "occ") || _teststr(name, "occonly")) {
+ if (isroot) {
+ return p_node;
+ }
+ ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
+ if (mi) {
+ Ref<ImporterMesh> mesh = mi->get_mesh();
+ if (mesh.is_valid()) {
+ if (r_occluder_arrays) {
+ OccluderInstance3D::bake_single_node(mi, 0.0f, r_occluder_arrays->first, r_occluder_arrays->second);
+ }
+ if (_teststr(name, "occ")) {
+ String fixed_name = _fixstr(name, "occ");
+ if (!fixed_name.is_empty()) {
+ if (mi->get_parent() && !mi->get_parent()->has_node(fixed_name)) {
+ mi->set_name(fixed_name);
+ }
+ }
+ } else {
+ memdelete(p_node);
+ p_node = nullptr;
+ }
+ }
+ }
} else if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
//last attempt, maybe collision inside the mesh data
@@ -644,16 +669,21 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
Ref<ImporterMesh> mesh = mi->get_mesh();
if (!mesh.is_null()) {
Vector<Ref<Shape3D>> shapes;
- if (collision_map.has(mesh)) {
- shapes = collision_map[mesh];
+ if (r_collision_map.has(mesh)) {
+ shapes = r_collision_map[mesh];
} else if (_teststr(mesh->get_name(), "col")) {
_pre_gen_shape_list(mesh, shapes, false);
- collision_map[mesh] = shapes;
+ r_collision_map[mesh] = shapes;
mesh->set_name(_fixstr(mesh->get_name(), "col"));
} else if (_teststr(mesh->get_name(), "convcol")) {
_pre_gen_shape_list(mesh, shapes, true);
- collision_map[mesh] = shapes;
+ r_collision_map[mesh] = shapes;
mesh->set_name(_fixstr(mesh->get_name(), "convcol"));
+ } else if (_teststr(mesh->get_name(), "occ")) {
+ if (r_occluder_arrays) {
+ OccluderInstance3D::bake_single_node(mi, 0.0f, r_occluder_arrays->first, r_occluder_arrays->second);
+ }
+ mesh->set_name(_fixstr(mesh->get_name(), "occ"));
}
if (shapes.size()) {
@@ -677,10 +707,10 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
return p_node;
}
-Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) {
+Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) {
// children first
for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps);
+ Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_occluder_arrays, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps);
if (!r) {
i--; //was erased
}
@@ -883,6 +913,32 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
}
}
+ if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
+ ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
+
+ Ref<ImporterMesh> m = mi->get_mesh();
+
+ if (m.is_valid()) {
+ if (node_settings.has("generate/occluder")) {
+ int occluder_mode = node_settings["generate/occluder"];
+
+ if (occluder_mode != OCCLUDER_DISABLED) {
+ float simplification_dist = 0.0f;
+ if (node_settings.has("occluder/simplification_distance")) {
+ simplification_dist = node_settings["occluder/simplification_distance"];
+ }
+
+ OccluderInstance3D::bake_single_node(mi, simplification_dist, r_occluder_arrays.first, r_occluder_arrays.second);
+
+ if (occluder_mode == OCCLUDER_OCCLUDER_ONLY) {
+ memdelete(p_node);
+ p_node = nullptr;
+ }
+ }
+ }
+ }
+ }
+
if (Object::cast_to<AnimationPlayer>(p_node)) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
@@ -1255,6 +1311,9 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "primitive/radius", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1.0));
r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3()));
r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3()));
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/occluder", PROPERTY_HINT_ENUM, "Disabled,Mesh + Occluder,Occluder Only", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "occluder/simplification_distance", PROPERTY_HINT_RANGE, "0.0,2.0,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0.1f));
} break;
case INTERNAL_IMPORT_CATEGORY_MESH: {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
@@ -1376,6 +1435,11 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor
(physics_shape == SHAPE_TYPE_CYLINDER ||
physics_shape == SHAPE_TYPE_CAPSULE);
}
+
+ if (p_option == "occluder/simplification_distance") {
+ // Show only if occluder generation is enabled
+ return p_options.has("generate/occluder") && p_options["generate/occluder"].operator signed int() != OCCLUDER_DISABLED;
+ }
} break;
case INTERNAL_IMPORT_CATEGORY_MESH: {
if (p_option == "save_to_file/path" || p_option == "save_to_file/make_streamable") {
@@ -1869,7 +1933,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) {
Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map;
List<Pair<NodePath, Node *>> node_renames;
- _pre_fix_node(scene, scene, collision_map, node_renames);
+ _pre_fix_node(scene, scene, collision_map, nullptr, node_renames);
return scene;
}
@@ -1944,15 +2008,16 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
Set<Ref<ImporterMesh>> scanned_meshes;
Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map;
+ Pair<PackedVector3Array, PackedInt32Array> occluder_arrays;
List<Pair<NodePath, Node *>> node_renames;
- _pre_fix_node(scene, scene, collision_map, node_renames);
+ _pre_fix_node(scene, scene, collision_map, &occluder_arrays, node_renames);
for (int i = 0; i < post_importer_plugins.size(); i++) {
post_importer_plugins.write[i]->pre_process(scene, p_options);
}
- _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps);
+ _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps);
String root_type = p_options["nodes/root_type"];
root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class.
@@ -1989,6 +2054,15 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
scene->set_name(p_save_path.get_file().get_basename());
}
+ if (!occluder_arrays.first.is_empty() && !occluder_arrays.second.is_empty()) {
+ Ref<ArrayOccluder3D> occ = memnew(ArrayOccluder3D);
+ occ->set_arrays(occluder_arrays.first, occluder_arrays.second);
+ OccluderInstance3D *occluder_instance = memnew(OccluderInstance3D);
+ occluder_instance->set_occluder(occ);
+ scene->add_child(occluder_instance, true);
+ occluder_instance->set_owner(scene);
+ }
+
bool gen_lods = bool(p_options["meshes/generate_lods"]);
bool create_shadow_meshes = bool(p_options["meshes/create_shadow_meshes"]);
int light_bake_mode = p_options["meshes/light_baking"];