Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bake navigation meshes by groups as alternative to NavigationMeshInstance-Children #15110

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/classes/NavigationMeshInstance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
</member>
<member name="navmesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
</member>
<member name="bakemode_type" type="int" setter="set_bake_mode_type" getter="get_bake_mode_type">
</member>
<member name="groupname" type="StringName" setter="set_navmesh_groupname" getter="get_navmesh_groupname">
</member>
</members>
<constants>
</constants>
Expand Down
38 changes: 30 additions & 8 deletions modules/recast/navigation_mesh_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,24 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform
}
}

void NavigationMeshGenerator::_parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices) {
void NavigationMeshGenerator::_parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int bake_selection_mode, Set<Node *> *_processedNodes, const StringName &navmesh_groupname) {

if (Object::cast_to<MeshInstance>(p_node)) {

MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(p_node);
Ref<Mesh> mesh = mesh_instance->get_mesh();
if (mesh.is_valid()) {
if (mesh.is_valid() && (!_processedNodes || !_processedNodes->has(p_node)) // not already processed
&& (bake_selection_mode == NavigationMeshInstance::BAKE_SELECTION_MODE_NAVMESH_CHILDREN || bake_selection_mode == NavigationMeshInstance::BAKE_SELECTION_MODE_GROUPS_WITH_CHILDREN || p_node->is_in_group(navmesh_groupname))) {
if (_processedNodes)
_processedNodes->insert(p_node);
_add_mesh(mesh, p_base_inverse * mesh_instance->get_global_transform(), p_verticies, p_indices);
}
}

for (int i = 0; i < p_node->get_child_count(); i++) {
_parse_geometry(p_base_inverse, p_node->get_child(i), p_verticies, p_indices);
// explicit groups get called indiviually, so don't iterate over the children
if (bake_selection_mode != NavigationMeshInstance::BAKE_SELECTION_MODE_GROUPS_EXPLICIT) {
for (int i = 0; i < p_node->get_child_count(); i++) {
_parse_geometry(p_base_inverse, p_node->get_child(i), p_verticies, p_indices, bake_selection_mode, _processedNodes, navmesh_groupname);
}
}
}

Expand All @@ -126,9 +131,9 @@ void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(con
for (unsigned int j = 0; j < ntris; j++) {
Vector<int> nav_indices;
nav_indices.resize(3);
nav_indices.write[0] = ((int)(bverts + tris[j * 4 + 0]));
nav_indices.write[2] = ((int)(bverts + tris[j * 4 + 0]));
nav_indices.write[1] = ((int)(bverts + tris[j * 4 + 1]));
nav_indices.write[2] = ((int)(bverts + tris[j * 4 + 2]));
nav_indices.write[0] = ((int)(bverts + tris[j * 4 + 2]));
p_nav_mesh->add_polygon(nav_indices);
}
}
Expand Down Expand Up @@ -266,7 +271,24 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
Vector<float> vertices;
Vector<int> indices;

_parse_geometry(Object::cast_to<Spatial>(p_node)->get_global_transform().affine_inverse(), p_node, vertices, indices);
NavigationMeshInstance *navigationMeshInstance = Object::cast_to<NavigationMeshInstance>(p_node);
int bake_selection_mode = navigationMeshInstance->get_bake_selection_mode();
StringName navmesh_groupname = navigationMeshInstance->get_navmesh_groupname();

if (bake_selection_mode == NavigationMeshInstance::BAKE_SELECTION_MODE_NAVMESH_CHILDREN) { // use all mesh-based-children of the navigationmeshinstance-node
_parse_geometry(Object::cast_to<Spatial>(p_node)->get_global_transform().affine_inverse(), p_node, vertices, indices);
} else {
// get nodes based on group
List<Node *> groupNodes;
Set<Node *> processedNodes;

// retrieve all nodes in the current tree that are in the group specified by the navmesh_groupname-parameter
p_node->get_tree()->get_nodes_in_group(navmesh_groupname, &groupNodes);
for (const List<Node *>::Element *E = groupNodes.front(); E; E = E->next()) {
Node *groupNode = E->get();
_parse_geometry(Object::cast_to<Spatial>(p_node)->get_global_transform().affine_inverse(), groupNode, vertices, indices, bake_selection_mode, &processedNodes, navmesh_groupname);
}
}

if (vertices.size() > 0 && indices.size() > 0) {

Expand Down
2 changes: 1 addition & 1 deletion modules/recast/navigation_mesh_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NavigationMeshGenerator {
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 _parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices);
static void _parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int bake_selection_mode = NavigationMeshInstance::BAKE_SELECTION_MODE_NAVMESH_CHILDREN, Set<Node *> *_processedList = 0, const StringName &navmesh_groupname = "navmesh");

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,
Expand Down
33 changes: 32 additions & 1 deletion scene/3d/navigation_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,23 @@ bool NavigationMeshInstance::is_enabled() const {
return enabled;
}

void NavigationMeshInstance::set_bake_selection_mode(int p_value) {
ERR_FAIL_COND(p_value > BAKE_SELECTION_MODE_GROUPS_EXPLICIT);
bake_selection_mode = static_cast<BakeSelectionMode>(p_value);
}

int NavigationMeshInstance::get_bake_selection_mode() const {
Copy link
Member

@akien-mga akien-mga Jul 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not return the enum directly to avoid having to cast it? Then it would also properly be documented as returning values from said enum.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm,..I did this for the UI-Mapping. Not sure how to bind an enum directly. Any sample for that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Search for BIND_ENUM_CONSTANT in the code base.

return static_cast<int>(bake_selection_mode);
}

void NavigationMeshInstance::set_navmesh_groupname(const StringName &name) {
navmesh_groupname = name;
}

StringName NavigationMeshInstance::get_navmesh_groupname() {
return navmesh_groupname;
}

/////////////////////////////

void NavigationMeshInstance::_notification(int p_what) {
Expand Down Expand Up @@ -606,15 +623,27 @@ String NavigationMeshInstance::get_configuration_warning() const {
}

void NavigationMeshInstance::_bind_methods() {

ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationMeshInstance::set_navigation_mesh);
ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationMeshInstance::get_navigation_mesh);

ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationMeshInstance::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationMeshInstance::is_enabled);

ClassDB::bind_method(D_METHOD("set_bake_selection_mode", "bake_mode_type"), &NavigationMeshInstance::set_bake_selection_mode);
ClassDB::bind_method(D_METHOD("get_bake_selection_mode"), &NavigationMeshInstance::get_bake_selection_mode);

ClassDB::bind_method(D_METHOD("set_navmesh_groupname", "navmesh_groupname"), &NavigationMeshInstance::set_navmesh_groupname);
ClassDB::bind_method(D_METHOD("get_navmesh_groupname"), &NavigationMeshInstance::get_navmesh_groupname);

ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");

BIND_CONSTANT(BAKE_SELECTION_MODE_NAVMESH_CHILDREN);
BIND_CONSTANT(BAKE_SELECTION_MODE_GROUPS_WITH_CHILDREN);
BIND_CONSTANT(BAKE_SELECTION_MODE_GROUPS_EXPLICIT);

ADD_PROPERTY(PropertyInfo(Variant::INT, "selection_mode", PROPERTY_HINT_ENUM, "navmesh children,group with children,group explicit"), "set_bake_selection_mode", "get_bake_selection_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "navmesh_groupname"), "set_navmesh_groupname", "get_navmesh_groupname");
}

NavigationMeshInstance::NavigationMeshInstance() {
Expand All @@ -623,5 +652,7 @@ NavigationMeshInstance::NavigationMeshInstance() {
navigation = NULL;
nav_id = -1;
enabled = true;
bake_selection_mode = BAKE_SELECTION_MODE_NAVMESH_CHILDREN;
navmesh_groupname = "navmesh";
set_notify_transform(true);
}
20 changes: 20 additions & 0 deletions scene/3d/navigation_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,21 @@ class NavigationMeshInstance : public Spatial {

GDCLASS(NavigationMeshInstance, Spatial);

public:
enum BakeSelectionMode {
// select meshes for baking that are child of the NavigationMeshInstnace
BAKE_SELECTION_MODE_NAVMESH_CHILDREN = 0,
// select meshes and their children(recusive) for baking that have the are in the specified group
BAKE_SELECTION_MODE_GROUPS_WITH_CHILDREN,
// select only those meshes that are in the specified group (and not their children automatically)
BAKE_SELECTION_MODE_GROUPS_EXPLICIT
};

private:
bool enabled;
BakeSelectionMode bake_selection_mode;
StringName navmesh_groupname;

int nav_id;
Navigation *navigation;
Ref<NavigationMesh> navmesh;
Expand All @@ -179,6 +193,12 @@ class NavigationMeshInstance : public Spatial {
void set_enabled(bool p_enabled);
bool is_enabled() const;

void set_bake_selection_mode(int p_value);
int get_bake_selection_mode() const;

void set_navmesh_groupname(const StringName &name);
StringName get_navmesh_groupname();

void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh);
Ref<NavigationMesh> get_navigation_mesh() const;

Expand Down