2
0
Эх сурвалжийг харах

Merge pull request #32863 from JFonS/navmesh_from_group

Add option to create navmesh from objects in group
Rémi Verschelde 5 жил өмнө
parent
commit
f5dd4d574f

+ 4 - 0
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">

+ 20 - 4
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) {
 

+ 1 - 1
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,

+ 35 - 0
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;

+ 16 - 0
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;