summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfons <joan.fonssanchez@gmail.com>2019-10-16 11:33:47 +0200
committerjfons <joan.fonssanchez@gmail.com>2019-10-16 12:01:10 +0200
commit298bd3f88a42c57bad4a793542d8f843f889a75b (patch)
treedb1be36c6a1fc46a31299ad8f2fb2215c62ca040
parenta1033aea51515cd5f831cedf9834ea376200356a (diff)
Add option to create navmesh from objects in group
Adds a new NavigationMesh property to select which objects will be taken into account for the generation. By default it will use all the NavigationMeshInstance children to keep compatibility. The new modes allow to build the NavigationMesh from all the nodes belonging to a specific group, and optionally include their children too.
-rw-r--r--doc/classes/NavigationMesh.xml4
-rw-r--r--modules/recast/navigation_mesh_generator.cpp24
-rw-r--r--modules/recast/navigation_mesh_generator.h2
-rw-r--r--scene/3d/navigation_mesh.cpp35
-rw-r--r--scene/3d/navigation_mesh.h16
5 files changed, 76 insertions, 5 deletions
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index f6c7a7d1b5..6528704bb5 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -107,6 +107,10 @@
</member>
<member name="geometry/parsed_geometry_type" type="int" setter="set_parsed_geometry_type" getter="get_parsed_geometry_type" default="0">
</member>
+ <member name="geometry/source_geometry_mode" type="int" setter="set_source_geometry_mode" getter="get_source_geometry_mode" default="0">
+ </member>
+ <member name="geometry/source_group_name" type="String" setter="set_source_group_name" getter="get_source_group_name">
+ </member>
<member name="polygon/verts_per_poly" type="float" setter="set_verts_per_poly" getter="get_verts_per_poly" default="6.0">
</member>
<member name="region/merge_size" type="float" setter="set_region_merge_size" getter="get_region_merge_size" default="20.0">
diff --git a/modules/recast/navigation_mesh_generator.cpp b/modules/recast/navigation_mesh_generator.cpp
index c5b60f2dca..320591cf7c 100644
--- a/modules/recast/navigation_mesh_generator.cpp
+++ b/modules/recast/navigation_mesh_generator.cpp
@@ -131,7 +131,7 @@ void EditorNavigationMeshGenerator::_add_faces(const PoolVector3Array &p_faces,
}
}
-void EditorNavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask) {
+void EditorNavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children) {
if (Object::cast_to<MeshInstance>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
@@ -263,8 +263,10 @@ void EditorNavigationMeshGenerator::_parse_geometry(Transform p_accumulated_tran
p_accumulated_transform = p_accumulated_transform * spatial->get_transform();
}
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _parse_geometry(p_accumulated_transform, p_node->get_child(i), p_verticies, p_indices, p_generate_from, p_collision_mask);
+ if (p_recurse_children) {
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _parse_geometry(p_accumulated_transform, p_node->get_child(i), p_verticies, p_indices, p_generate_from, p_collision_mask, p_recurse_children);
+ }
}
}
@@ -439,7 +441,21 @@ void EditorNavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p
Vector<float> vertices;
Vector<int> indices;
- _parse_geometry(Object::cast_to<Spatial>(p_node)->get_transform().affine_inverse(), p_node, vertices, indices, p_nav_mesh->get_parsed_geometry_type(), p_nav_mesh->get_collision_mask());
+ List<Node *> parse_nodes;
+
+ if (p_nav_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
+ parse_nodes.push_back(p_node);
+ } else {
+ p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes);
+ }
+
+ Transform navmesh_xform = Object::cast_to<Spatial>(p_node)->get_transform().affine_inverse();
+ for (const List<Node *>::Element *E = parse_nodes.front(); E; E = E->next()) {
+ int geometry_type = p_nav_mesh->get_parsed_geometry_type();
+ uint32_t collision_mask = p_nav_mesh->get_collision_mask();
+ bool recurse_children = p_nav_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
+ _parse_geometry(navmesh_xform, E->get(), vertices, indices, geometry_type, collision_mask, recurse_children);
+ }
if (vertices.size() > 0 && indices.size() > 0) {
diff --git a/modules/recast/navigation_mesh_generator.h b/modules/recast/navigation_mesh_generator.h
index 30a6e3c835..f19622a4a9 100644
--- a/modules/recast/navigation_mesh_generator.h
+++ b/modules/recast/navigation_mesh_generator.h
@@ -47,7 +47,7 @@ protected:
static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies);
static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
static void _add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
- static void _parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask);
+ static void _parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh);
static void _build_recast_navigation_mesh(Ref<NavigationMesh> p_nav_mesh, EditorProgress *ep,
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
index f82543b789..496dc4b411 100644
--- a/scene/3d/navigation_mesh.cpp
+++ b/scene/3d/navigation_mesh.cpp
@@ -108,6 +108,24 @@ bool NavigationMesh::get_collision_mask_bit(int p_bit) const {
return get_collision_mask() & (1 << p_bit);
}
+void NavigationMesh::set_source_geometry_mode(int p_geometry_mode) {
+ ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX);
+ source_geometry_mode = static_cast<SourceGeometryMode>(p_geometry_mode);
+ _change_notify();
+}
+
+int NavigationMesh::get_source_geometry_mode() const {
+ return source_geometry_mode;
+}
+
+void NavigationMesh::set_source_group_name(StringName p_group_name) {
+ source_group_name = p_group_name;
+}
+
+StringName NavigationMesh::get_source_group_name() const {
+ return source_group_name;
+}
+
void NavigationMesh::set_cell_size(float p_value) {
cell_size = p_value;
}
@@ -387,6 +405,12 @@ void NavigationMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &NavigationMesh::set_collision_mask_bit);
ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &NavigationMesh::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_source_geometry_mode", "mask"), &NavigationMesh::set_source_geometry_mode);
+ ClassDB::bind_method(D_METHOD("get_source_geometry_mode"), &NavigationMesh::get_source_geometry_mode);
+
+ ClassDB::bind_method(D_METHOD("set_source_group_name", "mask"), &NavigationMesh::set_source_group_name);
+ ClassDB::bind_method(D_METHOD("get_source_group_name"), &NavigationMesh::get_source_group_name);
+
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationMesh::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationMesh::get_cell_size);
@@ -462,6 +486,8 @@ void NavigationMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type/sample_partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_sample_partition_type", "get_sample_partition_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/source_geometry_mode", PROPERTY_HINT_ENUM, "Navmesh Children, Group With Children, Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry/source_group_name"), "set_source_group_name", "get_source_group_name");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell/size", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell/height", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_height", "get_cell_height");
@@ -489,6 +515,13 @@ void NavigationMesh::_validate_property(PropertyInfo &property) const {
return;
}
}
+
+ if (property.name == "geometry/source_group_name") {
+ if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
+ property.usage = 0;
+ return;
+ }
+ }
}
NavigationMesh::NavigationMesh() {
@@ -509,6 +542,8 @@ NavigationMesh::NavigationMesh() {
partition_type = SAMPLE_PARTITION_WATERSHED;
parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES;
collision_mask = 0xFFFFFFFF;
+ source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN;
+ source_group_name = "navmesh";
filter_low_hanging_obstacles = false;
filter_ledge_spans = false;
filter_walkable_low_height_spans = false;
diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h
index 5fbf3998ff..8467f80f0e 100644
--- a/scene/3d/navigation_mesh.h
+++ b/scene/3d/navigation_mesh.h
@@ -77,6 +77,13 @@ public:
PARSED_GEOMETRY_MAX
};
+ enum SourceGeometryMode {
+ SOURCE_GEOMETRY_NAVMESH_CHILDREN = 0,
+ SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN,
+ SOURCE_GEOMETRY_GROUPS_EXPLICIT,
+ SOURCE_GEOMETRY_MAX
+ };
+
protected:
float cell_size;
float cell_height;
@@ -96,6 +103,9 @@ protected:
ParsedGeometryType parsed_geometry_type;
uint32_t collision_mask;
+ SourceGeometryMode source_geometry_mode;
+ StringName source_group_name;
+
bool filter_low_hanging_obstacles;
bool filter_ledge_spans;
bool filter_walkable_low_height_spans;
@@ -114,6 +124,12 @@ public:
void set_collision_mask_bit(int p_bit, bool p_value);
bool get_collision_mask_bit(int p_bit) const;
+ void set_source_geometry_mode(int p_source_mode);
+ int get_source_geometry_mode() const;
+
+ void set_source_group_name(StringName p_group_name);
+ StringName get_source_group_name() const;
+
void set_cell_size(float p_value);
float get_cell_size() const;