| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  navigation_mesh_generator.cpp                                        */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifndef _3D_DISABLED
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | #include "navigation_mesh_generator.h"
 | 
					
						
							| 
									
										
										
										
											2020-02-06 21:51:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | #include "core/math/quick_hull.h"
 | 
					
						
							|  |  |  | #include "core/os/thread.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | #include "scene/3d/collision_shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/3d/mesh_instance_3d.h"
 | 
					
						
							|  |  |  | #include "scene/3d/physics_body_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/box_shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/capsule_shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/concave_polygon_shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/convex_polygon_shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/cylinder_shape_3d.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | #include "scene/resources/primitive_meshes.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | #include "scene/resources/shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/sphere_shape_3d.h"
 | 
					
						
							|  |  |  | #include "scene/resources/world_margin_shape_3d.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 21:51:36 +01:00
										 |  |  | #include "modules/modules_enabled.gen.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							|  |  |  | #include "editor/editor_node.h"
 | 
					
						
							|  |  |  | #include "editor/editor_settings.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-13 13:29:43 +02:00
										 |  |  | #ifdef MODULE_CSG_ENABLED
 | 
					
						
							|  |  |  | #include "modules/csg/csg_shape.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-08-18 12:03:29 +02:00
										 |  |  | #ifdef MODULE_GRIDMAP_ENABLED
 | 
					
						
							|  |  |  | #include "modules/gridmap/grid_map.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | NavigationMeshGenerator *NavigationMeshGenerator::singleton = nullptr; | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	p_verticies.push_back(p_vec3.x); | 
					
						
							|  |  |  | 	p_verticies.push_back(p_vec3.y); | 
					
						
							|  |  |  | 	p_verticies.push_back(p_vec3.z); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) { | 
					
						
							| 
									
										
										
										
											2019-12-10 05:13:02 +01:00
										 |  |  | 	int current_vertex_count; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < p_mesh->get_surface_count(); i++) { | 
					
						
							| 
									
										
										
										
											2017-10-09 13:14:27 +01:00
										 |  |  | 		current_vertex_count = p_verticies.size() / 3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		int index_count = 0; | 
					
						
							|  |  |  | 		if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) { | 
					
						
							|  |  |  | 			index_count = p_mesh->surface_get_array_index_len(i); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			index_count = p_mesh->surface_get_array_len(i); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_CONTINUE((index_count == 0 || (index_count % 3) != 0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int face_count = index_count / 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Array a = p_mesh->surface_get_arrays(i); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 		Vector<Vector3> mesh_vertices = a[Mesh::ARRAY_VERTEX]; | 
					
						
							|  |  |  | 		const Vector3 *vr = mesh_vertices.ptr(); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) { | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 			Vector<int> mesh_indices = a[Mesh::ARRAY_INDEX]; | 
					
						
							|  |  |  | 			const int *ir = mesh_indices.ptr(); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 21:10:08 +01:00
										 |  |  | 			for (int j = 0; j < mesh_vertices.size(); j++) { | 
					
						
							|  |  |  | 				_add_vertex(p_xform.xform(vr[j]), p_verticies); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 21:10:08 +01:00
										 |  |  | 			for (int j = 0; j < face_count; j++) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 				// CCW
 | 
					
						
							| 
									
										
										
										
											2019-02-12 21:10:08 +01:00
										 |  |  | 				p_indices.push_back(current_vertex_count + (ir[j * 3 + 0])); | 
					
						
							|  |  |  | 				p_indices.push_back(current_vertex_count + (ir[j * 3 + 2])); | 
					
						
							|  |  |  | 				p_indices.push_back(current_vertex_count + (ir[j * 3 + 1])); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			face_count = mesh_vertices.size() / 3; | 
					
						
							| 
									
										
										
										
											2019-02-12 21:10:08 +01:00
										 |  |  | 			for (int j = 0; j < face_count; j++) { | 
					
						
							|  |  |  | 				_add_vertex(p_xform.xform(vr[j * 3 + 0]), p_verticies); | 
					
						
							|  |  |  | 				_add_vertex(p_xform.xform(vr[j * 3 + 2]), p_verticies); | 
					
						
							|  |  |  | 				_add_vertex(p_xform.xform(vr[j * 3 + 1]), p_verticies); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				p_indices.push_back(current_vertex_count + (j * 3 + 0)); | 
					
						
							|  |  |  | 				p_indices.push_back(current_vertex_count + (j * 3 + 1)); | 
					
						
							|  |  |  | 				p_indices.push_back(current_vertex_count + (j * 3 + 2)); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) { | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 	int face_count = p_faces.size() / 3; | 
					
						
							|  |  |  | 	int current_vertex_count = p_verticies.size() / 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int j = 0; j < face_count; j++) { | 
					
						
							|  |  |  | 		_add_vertex(p_xform.xform(p_faces[j * 3 + 0]), p_verticies); | 
					
						
							|  |  |  | 		_add_vertex(p_xform.xform(p_faces[j * 3 + 1]), p_verticies); | 
					
						
							|  |  |  | 		_add_vertex(p_xform.xform(p_faces[j * 3 + 2]), p_verticies); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		p_indices.push_back(current_vertex_count + (j * 3 + 0)); | 
					
						
							|  |  |  | 		p_indices.push_back(current_vertex_count + (j * 3 + 2)); | 
					
						
							|  |  |  | 		p_indices.push_back(current_vertex_count + (j * 3 + 1)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::_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) { | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 	if (Object::cast_to<MeshInstance3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { | 
					
						
							|  |  |  | 		MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(p_node); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 		Ref<Mesh> mesh = mesh_instance->get_mesh(); | 
					
						
							|  |  |  | 		if (mesh.is_valid()) { | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 			_add_mesh(mesh, p_accumulated_transform * mesh_instance->get_transform(), p_verticies, p_indices); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-13 13:29:43 +02:00
										 |  |  | #ifdef MODULE_CSG_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 	if (Object::cast_to<CSGShape3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { | 
					
						
							|  |  |  | 		CSGShape3D *csg_shape = Object::cast_to<CSGShape3D>(p_node); | 
					
						
							| 
									
										
										
										
											2019-06-13 13:29:43 +02:00
										 |  |  | 		Array meshes = csg_shape->get_meshes(); | 
					
						
							|  |  |  | 		if (!meshes.empty()) { | 
					
						
							|  |  |  | 			Ref<Mesh> mesh = meshes[1]; | 
					
						
							|  |  |  | 			if (mesh.is_valid()) { | 
					
						
							|  |  |  | 				_add_mesh(mesh, p_accumulated_transform * csg_shape->get_transform(), p_verticies, p_indices); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 	if (Object::cast_to<StaticBody3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) { | 
					
						
							|  |  |  | 		StaticBody3D *static_body = Object::cast_to<StaticBody3D>(p_node); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (static_body->get_collision_layer() & p_collision_mask) { | 
					
						
							|  |  |  | 			for (int i = 0; i < p_node->get_child_count(); ++i) { | 
					
						
							|  |  |  | 				Node *child = p_node->get_child(i); | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 				if (Object::cast_to<CollisionShape3D>(child)) { | 
					
						
							|  |  |  | 					CollisionShape3D *col_shape = Object::cast_to<CollisionShape3D>(child); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					Transform transform = p_accumulated_transform * static_body->get_transform() * col_shape->get_transform(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					Ref<Mesh> mesh; | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					Ref<Shape3D> s = col_shape->get_shape(); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					BoxShape3D *box = Object::cast_to<BoxShape3D>(*s); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 					if (box) { | 
					
						
							|  |  |  | 						Ref<CubeMesh> cube_mesh; | 
					
						
							|  |  |  | 						cube_mesh.instance(); | 
					
						
							|  |  |  | 						cube_mesh->set_size(box->get_extents() * 2.0); | 
					
						
							|  |  |  | 						mesh = cube_mesh; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					CapsuleShape3D *capsule = Object::cast_to<CapsuleShape3D>(*s); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 					if (capsule) { | 
					
						
							|  |  |  | 						Ref<CapsuleMesh> capsule_mesh; | 
					
						
							|  |  |  | 						capsule_mesh.instance(); | 
					
						
							|  |  |  | 						capsule_mesh->set_radius(capsule->get_radius()); | 
					
						
							|  |  |  | 						capsule_mesh->set_mid_height(capsule->get_height() / 2.0); | 
					
						
							|  |  |  | 						mesh = capsule_mesh; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					CylinderShape3D *cylinder = Object::cast_to<CylinderShape3D>(*s); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 					if (cylinder) { | 
					
						
							|  |  |  | 						Ref<CylinderMesh> cylinder_mesh; | 
					
						
							|  |  |  | 						cylinder_mesh.instance(); | 
					
						
							|  |  |  | 						cylinder_mesh->set_height(cylinder->get_height()); | 
					
						
							|  |  |  | 						cylinder_mesh->set_bottom_radius(cylinder->get_radius()); | 
					
						
							|  |  |  | 						cylinder_mesh->set_top_radius(cylinder->get_radius()); | 
					
						
							|  |  |  | 						mesh = cylinder_mesh; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					SphereShape3D *sphere = Object::cast_to<SphereShape3D>(*s); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 					if (sphere) { | 
					
						
							|  |  |  | 						Ref<SphereMesh> sphere_mesh; | 
					
						
							|  |  |  | 						sphere_mesh.instance(); | 
					
						
							|  |  |  | 						sphere_mesh->set_radius(sphere->get_radius()); | 
					
						
							|  |  |  | 						sphere_mesh->set_height(sphere->get_radius() * 2.0); | 
					
						
							|  |  |  | 						mesh = sphere_mesh; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					ConcavePolygonShape3D *concave_polygon = Object::cast_to<ConcavePolygonShape3D>(*s); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 					if (concave_polygon) { | 
					
						
							|  |  |  | 						_add_faces(concave_polygon->get_faces(), transform, p_verticies, p_indices); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 					ConvexPolygonShape3D *convex_polygon = Object::cast_to<ConvexPolygonShape3D>(*s); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 					if (convex_polygon) { | 
					
						
							|  |  |  | 						Vector<Vector3> varr = Variant(convex_polygon->get_points()); | 
					
						
							|  |  |  | 						Geometry::MeshData md; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						Error err = QuickHull::build(varr, md); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (err == OK) { | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 							PackedVector3Array faces; | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							for (int j = 0; j < md.faces.size(); ++j) { | 
					
						
							|  |  |  | 								Geometry::MeshData::Face face = md.faces[j]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								for (int k = 2; k < face.indices.size(); ++k) { | 
					
						
							|  |  |  | 									faces.push_back(md.vertices[face.indices[0]]); | 
					
						
							|  |  |  | 									faces.push_back(md.vertices[face.indices[k - 1]]); | 
					
						
							|  |  |  | 									faces.push_back(md.vertices[face.indices[k]]); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							_add_faces(faces, transform, p_verticies, p_indices); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (mesh.is_valid()) { | 
					
						
							|  |  |  | 						_add_mesh(mesh, transform, p_verticies, p_indices); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 12:03:29 +02:00
										 |  |  | #ifdef MODULE_GRIDMAP_ENABLED
 | 
					
						
							|  |  |  | 	if (Object::cast_to<GridMap>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { | 
					
						
							|  |  |  | 		GridMap *gridmap_instance = Object::cast_to<GridMap>(p_node); | 
					
						
							|  |  |  | 		Array meshes = gridmap_instance->get_meshes(); | 
					
						
							|  |  |  | 		Transform xform = gridmap_instance->get_transform(); | 
					
						
							|  |  |  | 		for (int i = 0; i < meshes.size(); i += 2) { | 
					
						
							|  |  |  | 			Ref<Mesh> mesh = meshes[i + 1]; | 
					
						
							|  |  |  | 			if (mesh.is_valid()) { | 
					
						
							|  |  |  | 				_add_mesh(mesh, p_accumulated_transform * xform * meshes[i], p_verticies, p_indices); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 	if (Object::cast_to<Node3D>(p_node)) { | 
					
						
							|  |  |  | 		Node3D *spatial = Object::cast_to<Node3D>(p_node); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 		p_accumulated_transform = p_accumulated_transform * spatial->get_transform(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 11:33:47 +02:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) { | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 	Vector<Vector3> nav_vertices; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < p_detail_mesh->nverts; i++) { | 
					
						
							|  |  |  | 		const float *v = &p_detail_mesh->verts[i * 3]; | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 		nav_vertices.push_back(Vector3(v[0], v[1], v[2])); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	p_nav_mesh->set_vertices(nav_vertices); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < p_detail_mesh->nmeshes; i++) { | 
					
						
							|  |  |  | 		const unsigned int *m = &p_detail_mesh->meshes[i * 4]; | 
					
						
							|  |  |  | 		const unsigned int bverts = m[0]; | 
					
						
							|  |  |  | 		const unsigned int btris = m[2]; | 
					
						
							|  |  |  | 		const unsigned int ntris = m[3]; | 
					
						
							|  |  |  | 		const unsigned char *tris = &p_detail_mesh->tris[btris * 4]; | 
					
						
							|  |  |  | 		for (unsigned int j = 0; j < ntris; j++) { | 
					
						
							|  |  |  | 			Vector<int> nav_indices; | 
					
						
							|  |  |  | 			nav_indices.resize(3); | 
					
						
							| 
									
										
										
										
											2019-05-10 18:33:25 +03:00
										 |  |  | 			// Polygon order in recast is opposite than godot's
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 			nav_indices.write[0] = ((int)(bverts + tris[j * 4 + 0])); | 
					
						
							| 
									
										
										
										
											2019-05-10 18:33:25 +03:00
										 |  |  | 			nav_indices.write[1] = ((int)(bverts + tris[j * 4 + 2])); | 
					
						
							|  |  |  | 			nav_indices.write[2] = ((int)(bverts + tris[j * 4 + 1])); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 			p_nav_mesh->add_polygon(nav_indices); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::_build_recast_navigation_mesh( | 
					
						
							|  |  |  | 		Ref<NavigationMesh> p_nav_mesh, | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							|  |  |  | 		EditorProgress *ep, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		rcHeightfield *hf, | 
					
						
							|  |  |  | 		rcCompactHeightfield *chf, | 
					
						
							|  |  |  | 		rcContourSet *cset, | 
					
						
							|  |  |  | 		rcPolyMesh *poly_mesh, | 
					
						
							|  |  |  | 		rcPolyMeshDetail *detail_mesh, | 
					
						
							|  |  |  | 		Vector<float> &vertices, | 
					
						
							|  |  |  | 		Vector<int> &indices) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	rcContext ctx; | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Setting up Configuration..."), 1); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-18 21:37:17 +01:00
										 |  |  | 	const float *verts = vertices.ptr(); | 
					
						
							|  |  |  | 	const int nverts = vertices.size() / 3; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	const int *tris = indices.ptr(); | 
					
						
							|  |  |  | 	const int ntris = indices.size() / 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float bmin[3], bmax[3]; | 
					
						
							|  |  |  | 	rcCalcBounds(verts, nverts, bmin, bmax); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rcConfig cfg; | 
					
						
							|  |  |  | 	memset(&cfg, 0, sizeof(cfg)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cfg.cs = p_nav_mesh->get_cell_size(); | 
					
						
							|  |  |  | 	cfg.ch = p_nav_mesh->get_cell_height(); | 
					
						
							|  |  |  | 	cfg.walkableSlopeAngle = p_nav_mesh->get_agent_max_slope(); | 
					
						
							|  |  |  | 	cfg.walkableHeight = (int)Math::ceil(p_nav_mesh->get_agent_height() / cfg.ch); | 
					
						
							|  |  |  | 	cfg.walkableClimb = (int)Math::floor(p_nav_mesh->get_agent_max_climb() / cfg.ch); | 
					
						
							|  |  |  | 	cfg.walkableRadius = (int)Math::ceil(p_nav_mesh->get_agent_radius() / cfg.cs); | 
					
						
							|  |  |  | 	cfg.maxEdgeLen = (int)(p_nav_mesh->get_edge_max_length() / p_nav_mesh->get_cell_size()); | 
					
						
							|  |  |  | 	cfg.maxSimplificationError = p_nav_mesh->get_edge_max_error(); | 
					
						
							|  |  |  | 	cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size()); | 
					
						
							|  |  |  | 	cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size()); | 
					
						
							|  |  |  | 	cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly(); | 
					
						
							|  |  |  | 	cfg.detailSampleDist = p_nav_mesh->get_detail_sample_distance() < 0.9f ? 0 : p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(); | 
					
						
							|  |  |  | 	cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cfg.bmin[0] = bmin[0]; | 
					
						
							|  |  |  | 	cfg.bmin[1] = bmin[1]; | 
					
						
							|  |  |  | 	cfg.bmin[2] = bmin[2]; | 
					
						
							|  |  |  | 	cfg.bmax[0] = bmax[0]; | 
					
						
							|  |  |  | 	cfg.bmax[1] = bmax[1]; | 
					
						
							|  |  |  | 	cfg.bmax[2] = bmax[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Calculating grid size..."), 2); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Creating heightfield..."), 3); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	hf = rcAllocHeightfield(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!hf); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!rcCreateHeightfield(&ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Marking walkable triangles..."), 4); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		Vector<unsigned char> tri_areas; | 
					
						
							|  |  |  | 		tri_areas.resize(ntris); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_COND(tri_areas.size() == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-25 00:07:54 -03:00
										 |  |  | 		memset(tri_areas.ptrw(), 0, ntris * sizeof(unsigned char)); | 
					
						
							|  |  |  | 		rcMarkWalkableTriangles(&ctx, cfg.walkableSlopeAngle, verts, nverts, tris, ntris, tri_areas.ptrw()); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (p_nav_mesh->get_filter_low_hanging_obstacles()) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 		rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (p_nav_mesh->get_filter_ledge_spans()) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 		rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (p_nav_mesh->get_filter_walkable_low_height_spans()) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 		rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Constructing compact heightfield..."), 5); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	chf = rcAllocCompactHeightfield(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!chf); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!rcBuildCompactHeightfield(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf, *chf)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rcFreeHeightField(hf); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	hf = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Eroding walkable area..."), 6); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Partitioning..."), 7); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) { | 
					
						
							|  |  |  | 		ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf)); | 
					
						
							|  |  |  | 		ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea)); | 
					
						
							|  |  |  | 	} else if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) { | 
					
						
							|  |  |  | 		ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea)); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Creating contours..."), 8); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cset = rcAllocContourSet(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!cset); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!rcBuildContours(&ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Creating polymesh..."), 9); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	poly_mesh = rcAllocPolyMesh(); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!poly_mesh); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!rcBuildPolyMesh(&ctx, *cset, cfg.maxVertsPerPoly, *poly_mesh)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	detail_mesh = rcAllocPolyMeshDetail(); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!detail_mesh); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!rcBuildPolyMeshDetail(&ctx, *poly_mesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *detail_mesh)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rcFreeCompactHeightfield(chf); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	chf = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	rcFreeContourSet(cset); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	cset = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Converting to native navigation mesh..."), 10); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rcFreePolyMesh(poly_mesh); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	poly_mesh = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	rcFreePolyMeshDetail(detail_mesh); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	detail_mesh = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | NavigationMeshGenerator *NavigationMeshGenerator::get_singleton() { | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 	return singleton; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | NavigationMeshGenerator::NavigationMeshGenerator() { | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 	singleton = this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | NavigationMeshGenerator::~NavigationMeshGenerator() { | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	ERR_FAIL_COND(!p_nav_mesh.is_valid()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	EditorProgress *ep(nullptr); | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 	if (Engine::get_singleton()->is_editor_hint()) { | 
					
						
							|  |  |  | 		ep = memnew(EditorProgress("bake", TTR("Navigation Mesh Generator Setup:"), 11)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Parsing Geometry..."), 0); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-18 21:37:17 +01:00
										 |  |  | 	Vector<float> vertices; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	Vector<int> indices; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 11:33:47 +02:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 18:49:16 -03:00
										 |  |  | 	Transform navmesh_xform = Object::cast_to<Node3D>(p_node)->get_transform().affine_inverse(); | 
					
						
							| 
									
										
										
										
											2019-10-16 11:33:47 +02:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-18 21:37:17 +01:00
										 |  |  | 	if (vertices.size() > 0 && indices.size() > 0) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		rcHeightfield *hf = nullptr; | 
					
						
							|  |  |  | 		rcCompactHeightfield *chf = nullptr; | 
					
						
							|  |  |  | 		rcContourSet *cset = nullptr; | 
					
						
							|  |  |  | 		rcPolyMesh *poly_mesh = nullptr; | 
					
						
							|  |  |  | 		rcPolyMeshDetail *detail_mesh = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		_build_recast_navigation_mesh( | 
					
						
							|  |  |  | 				p_nav_mesh, | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							|  |  |  | 				ep, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 				hf, | 
					
						
							|  |  |  | 				chf, | 
					
						
							|  |  |  | 				cset, | 
					
						
							|  |  |  | 				poly_mesh, | 
					
						
							|  |  |  | 				detail_mesh, | 
					
						
							|  |  |  | 				vertices, | 
					
						
							|  |  |  | 				indices); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 		rcFreeHeightField(hf); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		hf = nullptr; | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rcFreeCompactHeightfield(chf); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		chf = nullptr; | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rcFreeContourSet(cset); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		cset = nullptr; | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rcFreePolyMesh(poly_mesh); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		poly_mesh = nullptr; | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rcFreePolyMeshDetail(detail_mesh); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		detail_mesh = nullptr; | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		ep->step(TTR("Done!"), 11); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ep) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 		memdelete(ep); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) { | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	if (p_nav_mesh.is_valid()) { | 
					
						
							|  |  |  | 		p_nav_mesh->clear_polygons(); | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 		p_nav_mesh->set_vertices(Vector<Vector3>()); | 
					
						
							| 
									
										
										
										
											2017-02-28 12:10:29 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | void NavigationMeshGenerator::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("bake", "nav_mesh", "root_node"), &NavigationMeshGenerator::bake); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("clear", "nav_mesh"), &NavigationMeshGenerator::clear); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:37:58 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |