mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-24 12:47:12 +01:00
Make the NavigationMesh generator and the TileMapNavigationGeometryParser use the new Clipper2 module. (Note that the clipper2 module is only temporary, it only exists to help with backporting the code.)
This commit is contained in:
parent
a65ad4d279
commit
a5c03b77c1
@ -14,3 +14,9 @@ env_navigation.add_source_files(module_obj, "geometry_parser_2d/*.cpp")
|
||||
env_navigation.add_source_files(module_obj, "geometry_parser_3d/*.cpp")
|
||||
|
||||
env.modules_sources += module_obj
|
||||
|
||||
# Temp TODO Remove
|
||||
if env_navigation.msvc:
|
||||
env_navigation.Append(CXXFLAGS=['/std:c++17'])
|
||||
else:
|
||||
env_navigation.Append(CXXFLAGS=['-std=c++17'])
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "scene/resources/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/navigation_polygon.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||
#endif // CLIPPER_ENABLED
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "scene/resources/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/navigation_polygon.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||
#endif // CLIPPER_ENABLED
|
||||
|
@ -32,12 +32,16 @@
|
||||
|
||||
//#include "scene/2d/tile_map.h"
|
||||
|
||||
#include "scene/resources/navigation_polygon.h"
|
||||
#include "modules/tile_map/tile_map.h"
|
||||
#include "modules/tile_map/tile_set.h"
|
||||
#include "scene/resources/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/navigation_polygon.h"
|
||||
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||
#endif // CLIPPER_ENABLED
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
#ifdef MODULE_CLIPPER2_ENABLED
|
||||
#include "modules/clipper2/lib/include/clipper2/clipper.h"
|
||||
#endif // MODULE_CLIPPER2_ENABLED
|
||||
|
||||
bool TileMap2DNavigationGeometryParser2D::parses_node(Node *p_node) {
|
||||
//return (Object::cast_to<TileMap>(p_node) != nullptr);
|
||||
@ -45,61 +49,51 @@ bool TileMap2DNavigationGeometryParser2D::parses_node(Node *p_node) {
|
||||
}
|
||||
|
||||
void TileMap2DNavigationGeometryParser2D::parse_geometry(Node *p_node, Ref<NavigationPolygon> p_navigation_polygon, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry) {
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#ifdef MODULE_CLIPPER2_ENABLED
|
||||
TileMap *tilemap = Object::cast_to<TileMap>(p_node);
|
||||
NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_polygon->get_parsed_geometry_type();
|
||||
uint32_t navigation_polygon_collision_mask = p_navigation_polygon->get_collision_mask();
|
||||
//NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_polygon->get_parsed_geometry_type();
|
||||
//uint32_t navigation_polygon_collision_mask = p_navigation_polygon->get_collision_mask();
|
||||
|
||||
if (tilemap) {
|
||||
if (tilemap->get_layers_count() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int tilemap_layer = 0; // only main tile map layer is supported
|
||||
|
||||
Ref<TileSet> tile_set = tilemap->get_tileset();
|
||||
if (!tile_set.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int physics_layers_count = tile_set->get_physics_layers_count();
|
||||
int navigation_layers_count = tile_set->get_navigation_layers_count();
|
||||
|
||||
if (physics_layers_count <= 0 && navigation_layers_count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Transform2D tilemap_xform = tilemap->get_transform();
|
||||
TypedArray<Vector2i> used_cells = tilemap->get_used_cells(tilemap_layer);
|
||||
Array used_cells = tilemap->get_used_cells();
|
||||
|
||||
for (int used_cell_index = 0; used_cell_index < used_cells.size(); used_cell_index++) {
|
||||
const Vector2i &cell = used_cells[used_cell_index];
|
||||
Vector2 cell = used_cells[used_cell_index];
|
||||
|
||||
const TileData *tile_data = tilemap->get_cell_tile_data(tilemap_layer, cell, false);
|
||||
int cell_id = tilemap->get_cell(cell.x, cell.y);
|
||||
|
||||
Transform2D tile_transform;
|
||||
tile_transform.set_origin(tilemap->map_to_local(cell));
|
||||
tile_transform.set_origin(tilemap->to_local(cell));
|
||||
|
||||
const Transform2D tile_transform_offset = tilemap_xform * tile_transform;
|
||||
|
||||
if (navigation_layers_count > 0) {
|
||||
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(tilemap_layer);
|
||||
Ref<NavigationPolygon> navigation_polygon = tile_set->tile_get_navigation_polygon(cell_id);
|
||||
if (navigation_polygon.is_valid()) {
|
||||
for (int outline_index = 0; outline_index < navigation_polygon->get_outline_count(); outline_index++) {
|
||||
Vector<Vector2> traversable_outline = navigation_polygon->get_outline(outline_index);
|
||||
PoolVector<Vector2> traversable_outline = navigation_polygon->get_outline(outline_index);
|
||||
|
||||
Vector<Vector2> traversable_outline_new;
|
||||
traversable_outline_new.resize(traversable_outline.size());
|
||||
|
||||
for (int traversable_outline_index = 0; traversable_outline_index < traversable_outline.size(); traversable_outline_index++) {
|
||||
traversable_outline.write[traversable_outline_index] = tile_transform_offset.xform(traversable_outline[traversable_outline_index]);
|
||||
traversable_outline_new.write[traversable_outline_index] = tile_transform_offset.xform(traversable_outline[traversable_outline_index]);
|
||||
}
|
||||
|
||||
p_source_geometry->_add_traversable_outline(traversable_outline);
|
||||
}
|
||||
p_source_geometry->_add_traversable_outline(traversable_outline_new);
|
||||
}
|
||||
}
|
||||
|
||||
if (physics_layers_count > 0 && parsed_geometry_type != NavigationPolygon::PARSED_GEOMETRY_MESH_INSTANCES && (tile_set->get_physics_layer_collision_layer(tilemap_layer) & navigation_polygon_collision_mask)) {
|
||||
for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(tilemap_layer); collision_polygon_index++) {
|
||||
Vector<Vector2> obstruction_outline = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index);
|
||||
/*
|
||||
TODO
|
||||
if (parsed_geometry_type != NavigationPolygon::PARSED_GEOMETRY_MESH_INSTANCES && (tilemap->get_collision_layer() & navigation_polygon_collision_mask)) {
|
||||
for (int collision_polygon_index = 0; collision_polygon_index < tile_set->tile_get_shape_count(cell_id); collision_polygon_index++) {
|
||||
Vector<Vector2> obstruction_outline = tile_set->get_collision_polygon_points(collision_polygon_index);
|
||||
|
||||
for (int obstruction_outline_index = 0; obstruction_outline_index < obstruction_outline.size(); obstruction_outline_index++) {
|
||||
obstruction_outline.write[obstruction_outline_index] = tile_transform_offset.xform(obstruction_outline[obstruction_outline_index]);
|
||||
@ -108,7 +102,8 @@ void TileMap2DNavigationGeometryParser2D::parse_geometry(Node *p_node, Ref<Navig
|
||||
p_source_geometry->_add_obstruction_outline(obstruction_outline);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif // CLIPPER_ENABLED
|
||||
}
|
||||
#endif // MODULE_CLIPPER2_ENABLED
|
||||
|
@ -47,5 +47,11 @@ if env["tools"]:
|
||||
|
||||
env.modules_sources += module_obj
|
||||
|
||||
# Temp TODO Remove
|
||||
if env_navigation_mesh_generator.msvc:
|
||||
env_navigation_mesh_generator.Append(CXXFLAGS=['/std:c++17'])
|
||||
else:
|
||||
env_navigation_mesh_generator.Append(CXXFLAGS=['-std=c++17'])
|
||||
|
||||
# Needed to force rebuilding the module files when the thirdparty library is updated.
|
||||
#env.Depends(module_obj, thirdparty_obj)
|
||||
|
@ -44,10 +44,12 @@
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||
#include "thirdparty/misc/polypartition.h"
|
||||
#endif // CLIPPER_ENABLED
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
#ifdef MODULE_CLIPPER2_ENABLED
|
||||
#include "modules/clipper2/lib/include/clipper2/clipper.h"
|
||||
#include "modules/clipper2/polypartition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
#include <Recast.h>
|
||||
@ -290,7 +292,7 @@ void PandemoniumNavigationMeshGenerator::_static_parse_2d_source_geometry_data(R
|
||||
}
|
||||
|
||||
// rewrite this to use clipper 1
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#ifdef MODULE_CLIPPER2_ENABLED
|
||||
static void _recursive_process_polytree_items(List<TPPLPoly> &p_tppl_in_polygon, const Clipper2Lib::PolyPath64 *p_polypath_item) {
|
||||
using namespace Clipper2Lib;
|
||||
|
||||
@ -319,18 +321,18 @@ static void _recursive_process_polytree_items(List<TPPLPoly> &p_tppl_in_polygon,
|
||||
_recursive_process_polytree_items(p_tppl_in_polygon, polypath_item);
|
||||
}
|
||||
}
|
||||
#endif // CLIPPER_ENABLED
|
||||
#endif // MODULE_CLIPPER2_ENABLED
|
||||
|
||||
void PandemoniumNavigationMeshGenerator::_static_bake_2d_from_source_geometry_data(Ref<NavigationPolygon> p_navigation_polygon, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data) {
|
||||
ERR_FAIL_COND_MSG(!p_navigation_polygon.is_valid(), "Invalid navigation polygon.");
|
||||
ERR_FAIL_COND_MSG(!p_source_geometry_data.is_valid(), "Invalid source geometry data.");
|
||||
ERR_FAIL_COND_MSG(p_navigation_polygon->get_outline_count() == 0 && !p_source_geometry_data->has_data(), "NavigationMeshSourceGeometryData2D is empty. Parse source geometry first.");
|
||||
|
||||
//const Vector<Vector<Vector2>> &traversable_outlines = p_source_geometry_data->_get_traversable_outlines();
|
||||
//const Vector<Vector<Vector2>> &obstruction_outlines = p_source_geometry_data->_get_obstruction_outlines();
|
||||
const Vector<Vector<Vector2>> &traversable_outlines = p_source_geometry_data->_get_traversable_outlines();
|
||||
const Vector<Vector<Vector2>> &obstruction_outlines = p_source_geometry_data->_get_obstruction_outlines();
|
||||
|
||||
// rewrite this to use clipper 1
|
||||
#ifdef CLIPPER_ENABLED
|
||||
#ifdef MODULE_CLIPPER2_ENABLED
|
||||
using namespace Clipper2Lib;
|
||||
|
||||
Paths64 traversable_polygon_paths;
|
||||
@ -338,27 +340,39 @@ void PandemoniumNavigationMeshGenerator::_static_bake_2d_from_source_geometry_da
|
||||
|
||||
int outline_count = p_navigation_polygon->get_outline_count();
|
||||
for (int i = 0; i < outline_count; i++) {
|
||||
const Vector<Vector2> &traversable_outline = p_navigation_polygon->get_outline(i);
|
||||
PoolVector<Vector2> traversable_outline = p_navigation_polygon->get_outline(i);
|
||||
Path64 subject_path;
|
||||
for (const Vector2 &traversable_point : traversable_outline) {
|
||||
|
||||
for (int j = 0; j < traversable_outline.size(); ++j) {
|
||||
Vector2 traversable_point = traversable_outline[j];
|
||||
|
||||
const Point64 &point = Point64(traversable_point.x, traversable_point.y);
|
||||
subject_path.push_back(point);
|
||||
}
|
||||
traversable_polygon_paths.push_back(subject_path);
|
||||
}
|
||||
|
||||
for (const Vector<Vector2> &traversable_outline : traversable_outlines) {
|
||||
for (int i = 0; i < traversable_outlines.size(); i++) {
|
||||
Vector<Vector2> traversable_outline = traversable_outlines[i];
|
||||
|
||||
Path64 subject_path;
|
||||
for (const Vector2 &traversable_point : traversable_outline) {
|
||||
for (int j = 0; j < traversable_outline.size(); ++j) {
|
||||
Vector2 traversable_point = traversable_outline[j];
|
||||
|
||||
const Point64 &point = Point64(traversable_point.x, traversable_point.y);
|
||||
subject_path.push_back(point);
|
||||
}
|
||||
traversable_polygon_paths.push_back(subject_path);
|
||||
}
|
||||
|
||||
for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) {
|
||||
for (int i = 0; i < obstruction_outlines.size(); i++) {
|
||||
const Vector<Vector2> &obstruction_outline = obstruction_outlines[i];
|
||||
|
||||
Path64 clip_path;
|
||||
for (const Vector2 &obstruction_point : obstruction_outline) {
|
||||
|
||||
for (int j = 0; j < obstruction_outline.size(); ++j) {
|
||||
const Vector2 &obstruction_point = obstruction_outline[j];
|
||||
|
||||
const Point64 &point = Point64(obstruction_point.x, obstruction_point.y);
|
||||
clip_path.push_back(point);
|
||||
}
|
||||
@ -420,30 +434,39 @@ void PandemoniumNavigationMeshGenerator::_static_bake_2d_from_source_geometry_da
|
||||
}
|
||||
//path_solution = RamerDouglasPeucker(path_solution, 0.025); //
|
||||
|
||||
Vector<Vector<Vector2>> new_baked_outlines;
|
||||
Vector<PoolVector<Vector2>> new_baked_outlines;
|
||||
|
||||
for (uint32_t i = 0; i < path_solution.size(); i++) {
|
||||
const Path64 &scaled_path = path_solution[i];
|
||||
|
||||
PoolVector<Vector2> polypath;
|
||||
for (uint32_t j = 0; j < scaled_path.size(); ++j) {
|
||||
const Point64 &scaled_point = scaled_path[j];
|
||||
|
||||
for (const Path64 &scaled_path : path_solution) {
|
||||
Vector<Vector2> polypath;
|
||||
for (const Point64 &scaled_point : scaled_path) {
|
||||
polypath.push_back(Vector2(static_cast<real_t>(scaled_point.x), static_cast<real_t>(scaled_point.y)));
|
||||
}
|
||||
|
||||
new_baked_outlines.push_back(polypath);
|
||||
}
|
||||
|
||||
p_navigation_polygon->internal_set_baked_outlines(new_baked_outlines);
|
||||
p_navigation_polygon->set_baked_outlines(new_baked_outlines);
|
||||
|
||||
if (new_baked_outlines.size() == 0) {
|
||||
p_navigation_polygon->set_vertices(Vector<Vector2>());
|
||||
p_navigation_polygon->internal_set_polygons(Vector<Vector<int>>());
|
||||
p_navigation_polygon->set_vertices(PoolVector<Vector2>());
|
||||
p_navigation_polygon->set_polygons(Vector<Vector<int>>());
|
||||
p_navigation_polygon->commit_changes();
|
||||
return;
|
||||
}
|
||||
|
||||
Paths64 polygon_paths;
|
||||
|
||||
for (const Vector<Vector2> &baked_outline : new_baked_outlines) {
|
||||
for (int i = 0; i < new_baked_outlines.size(); i++) {
|
||||
const PoolVector<Vector2> &baked_outline = new_baked_outlines[i];
|
||||
|
||||
Path64 polygon_path;
|
||||
for (const Vector2 &baked_outline_point : baked_outline) {
|
||||
for (int j = 0; j < baked_outline.size(); ++j) {
|
||||
const Vector2 &baked_outline_point = baked_outline[j];
|
||||
|
||||
const Point64 &point = Point64(baked_outline_point.x, baked_outline_point.y);
|
||||
polygon_path.push_back(point);
|
||||
}
|
||||
@ -468,13 +491,13 @@ void PandemoniumNavigationMeshGenerator::_static_bake_2d_from_source_geometry_da
|
||||
TPPLPartition tpart;
|
||||
if (tpart.ConvexPartition_HM(&tppl_in_polygon, &tppl_out_polygon) == 0) { //failed!
|
||||
ERR_PRINT("NavigationPolygon Convex partition failed. Unable to create a valid NavigationMesh from defined polygon outline paths.");
|
||||
p_navigation_polygon->set_vertices(Vector<Vector2>());
|
||||
p_navigation_polygon->internal_set_polygons(Vector<Vector<int>>());
|
||||
p_navigation_polygon->set_vertices(PoolVector<Vector2>());
|
||||
p_navigation_polygon->set_polygons(Vector<Vector<int>>());
|
||||
p_navigation_polygon->commit_changes();
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<Vector2> new_vertices;
|
||||
PoolVector<Vector2> new_vertices;
|
||||
Vector<Vector<int>> new_polygons;
|
||||
|
||||
HashMap<Vector2, int> points;
|
||||
@ -484,20 +507,20 @@ void PandemoniumNavigationMeshGenerator::_static_bake_2d_from_source_geometry_da
|
||||
Vector<int> new_polygon;
|
||||
|
||||
for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
|
||||
HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
|
||||
HashMap<Vector2, int>::Element *E = points.find(tp[i]);
|
||||
if (!E) {
|
||||
E = points.insert(tp[i], new_vertices.size());
|
||||
new_vertices.push_back(tp[i]);
|
||||
}
|
||||
new_polygon.push_back(E->value);
|
||||
new_polygon.push_back(E->value());
|
||||
}
|
||||
|
||||
new_polygons.push_back(new_polygon);
|
||||
}
|
||||
|
||||
p_navigation_polygon->set_vertices(new_vertices);
|
||||
p_navigation_polygon->internal_set_polygons(new_polygons);
|
||||
#endif // CLIPPER_ENABLED
|
||||
p_navigation_polygon->set_polygons(new_polygons);
|
||||
#endif // MODULE_CLIPPER2_ENABLED
|
||||
p_navigation_polygon->commit_changes();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user