|
31 | 31 | #include "grid_map.h"
|
32 | 32 |
|
33 | 33 | #include "core/io/marshalls.h"
|
| 34 | +#include "core/math/convex_hull.h" |
| 35 | +#include "scene/resources/3d/box_shape_3d.h" |
| 36 | +#include "scene/resources/3d/capsule_shape_3d.h" |
| 37 | +#include "scene/resources/3d/concave_polygon_shape_3d.h" |
| 38 | +#include "scene/resources/3d/convex_polygon_shape_3d.h" |
| 39 | +#include "scene/resources/3d/cylinder_shape_3d.h" |
| 40 | +#include "scene/resources/3d/height_map_shape_3d.h" |
34 | 41 | #include "scene/resources/3d/mesh_library.h"
|
| 42 | +#include "scene/resources/3d/navigation_mesh_source_geometry_data_3d.h" |
| 43 | +#include "scene/resources/3d/primitive_meshes.h" |
| 44 | +#include "scene/resources/3d/shape_3d.h" |
| 45 | +#include "scene/resources/3d/sphere_shape_3d.h" |
35 | 46 | #include "scene/resources/physics_material.h"
|
36 | 47 | #include "scene/resources/surface_tool.h"
|
37 | 48 | #include "servers/navigation_server_3d.h"
|
38 | 49 | #include "servers/rendering_server.h"
|
39 | 50 |
|
| 51 | +Callable GridMap::_navmesh_source_geometry_parsing_callback; |
| 52 | +RID GridMap::_navmesh_source_geometry_parser; |
| 53 | + |
40 | 54 | bool GridMap::_set(const StringName &p_name, const Variant &p_value) {
|
41 | 55 | String name = p_name;
|
42 | 56 |
|
@@ -1336,6 +1350,143 @@ GridMap::GridMap() {
|
1336 | 1350 | #endif // DEBUG_ENABLED
|
1337 | 1351 | }
|
1338 | 1352 |
|
| 1353 | +void GridMap::navmesh_parse_init() { |
| 1354 | + ERR_FAIL_NULL(NavigationServer3D::get_singleton()); |
| 1355 | + if (!_navmesh_source_geometry_parser.is_valid()) { |
| 1356 | + _navmesh_source_geometry_parsing_callback = callable_mp_static(&GridMap::navmesh_parse_source_geometry); |
| 1357 | + _navmesh_source_geometry_parser = NavigationServer3D::get_singleton()->source_geometry_parser_create(); |
| 1358 | + NavigationServer3D::get_singleton()->source_geometry_parser_set_callback(_navmesh_source_geometry_parser, _navmesh_source_geometry_parsing_callback); |
| 1359 | + } |
| 1360 | +} |
| 1361 | + |
| 1362 | +void GridMap::navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_node) { |
| 1363 | + GridMap *gridmap = Object::cast_to<GridMap>(p_node); |
| 1364 | + |
| 1365 | + if (gridmap == nullptr) { |
| 1366 | + return; |
| 1367 | + } |
| 1368 | + |
| 1369 | + NavigationMesh::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type(); |
| 1370 | + uint32_t parsed_collision_mask = p_navigation_mesh->get_collision_mask(); |
| 1371 | + |
| 1372 | + if (parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES || parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_BOTH) { |
| 1373 | + Array meshes = gridmap->get_meshes(); |
| 1374 | + Transform3D xform = gridmap->get_global_transform(); |
| 1375 | + for (int i = 0; i < meshes.size(); i += 2) { |
| 1376 | + Ref<Mesh> mesh = meshes[i + 1]; |
| 1377 | + if (mesh.is_valid()) { |
| 1378 | + p_source_geometry_data->add_mesh(mesh, xform * (Transform3D)meshes[i]); |
| 1379 | + } |
| 1380 | + } |
| 1381 | + } |
| 1382 | + |
| 1383 | + else if ((parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_BOTH) && (gridmap->get_collision_layer() & parsed_collision_mask)) { |
| 1384 | + Array shapes = gridmap->get_collision_shapes(); |
| 1385 | + for (int i = 0; i < shapes.size(); i += 2) { |
| 1386 | + RID shape = shapes[i + 1]; |
| 1387 | + PhysicsServer3D::ShapeType type = PhysicsServer3D::get_singleton()->shape_get_type(shape); |
| 1388 | + Variant data = PhysicsServer3D::get_singleton()->shape_get_data(shape); |
| 1389 | + |
| 1390 | + switch (type) { |
| 1391 | + case PhysicsServer3D::SHAPE_SPHERE: { |
| 1392 | + real_t radius = data; |
| 1393 | + Array arr; |
| 1394 | + arr.resize(RS::ARRAY_MAX); |
| 1395 | + SphereMesh::create_mesh_array(arr, radius, radius * 2.0); |
| 1396 | + p_source_geometry_data->add_mesh_array(arr, shapes[i]); |
| 1397 | + } break; |
| 1398 | + case PhysicsServer3D::SHAPE_BOX: { |
| 1399 | + Vector3 extents = data; |
| 1400 | + Array arr; |
| 1401 | + arr.resize(RS::ARRAY_MAX); |
| 1402 | + BoxMesh::create_mesh_array(arr, extents * 2.0); |
| 1403 | + p_source_geometry_data->add_mesh_array(arr, shapes[i]); |
| 1404 | + } break; |
| 1405 | + case PhysicsServer3D::SHAPE_CAPSULE: { |
| 1406 | + Dictionary dict = data; |
| 1407 | + real_t radius = dict["radius"]; |
| 1408 | + real_t height = dict["height"]; |
| 1409 | + Array arr; |
| 1410 | + arr.resize(RS::ARRAY_MAX); |
| 1411 | + CapsuleMesh::create_mesh_array(arr, radius, height); |
| 1412 | + p_source_geometry_data->add_mesh_array(arr, shapes[i]); |
| 1413 | + } break; |
| 1414 | + case PhysicsServer3D::SHAPE_CYLINDER: { |
| 1415 | + Dictionary dict = data; |
| 1416 | + real_t radius = dict["radius"]; |
| 1417 | + real_t height = dict["height"]; |
| 1418 | + Array arr; |
| 1419 | + arr.resize(RS::ARRAY_MAX); |
| 1420 | + CylinderMesh::create_mesh_array(arr, radius, radius, height); |
| 1421 | + p_source_geometry_data->add_mesh_array(arr, shapes[i]); |
| 1422 | + } break; |
| 1423 | + case PhysicsServer3D::SHAPE_CONVEX_POLYGON: { |
| 1424 | + PackedVector3Array vertices = data; |
| 1425 | + Geometry3D::MeshData md; |
| 1426 | + |
| 1427 | + Error err = ConvexHullComputer::convex_hull(vertices, md); |
| 1428 | + |
| 1429 | + if (err == OK) { |
| 1430 | + PackedVector3Array faces; |
| 1431 | + |
| 1432 | + for (const Geometry3D::MeshData::Face &face : md.faces) { |
| 1433 | + for (uint32_t k = 2; k < face.indices.size(); ++k) { |
| 1434 | + faces.push_back(md.vertices[face.indices[0]]); |
| 1435 | + faces.push_back(md.vertices[face.indices[k - 1]]); |
| 1436 | + faces.push_back(md.vertices[face.indices[k]]); |
| 1437 | + } |
| 1438 | + } |
| 1439 | + |
| 1440 | + p_source_geometry_data->add_faces(faces, shapes[i]); |
| 1441 | + } |
| 1442 | + } break; |
| 1443 | + case PhysicsServer3D::SHAPE_CONCAVE_POLYGON: { |
| 1444 | + Dictionary dict = data; |
| 1445 | + PackedVector3Array faces = Variant(dict["faces"]); |
| 1446 | + p_source_geometry_data->add_faces(faces, shapes[i]); |
| 1447 | + } break; |
| 1448 | + case PhysicsServer3D::SHAPE_HEIGHTMAP: { |
| 1449 | + Dictionary dict = data; |
| 1450 | + ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights" |
| 1451 | + int heightmap_depth = dict["depth"]; |
| 1452 | + int heightmap_width = dict["width"]; |
| 1453 | + |
| 1454 | + if (heightmap_depth >= 2 && heightmap_width >= 2) { |
| 1455 | + const Vector<real_t> &map_data = dict["heights"]; |
| 1456 | + |
| 1457 | + Vector2 heightmap_gridsize(heightmap_width - 1, heightmap_depth - 1); |
| 1458 | + Vector3 start = Vector3(heightmap_gridsize.x, 0, heightmap_gridsize.y) * -0.5; |
| 1459 | + |
| 1460 | + Vector<Vector3> vertex_array; |
| 1461 | + vertex_array.resize((heightmap_depth - 1) * (heightmap_width - 1) * 6); |
| 1462 | + Vector3 *vertex_array_ptrw = vertex_array.ptrw(); |
| 1463 | + const real_t *map_data_ptr = map_data.ptr(); |
| 1464 | + int vertex_index = 0; |
| 1465 | + |
| 1466 | + for (int d = 0; d < heightmap_depth - 1; d++) { |
| 1467 | + for (int w = 0; w < heightmap_width - 1; w++) { |
| 1468 | + vertex_array_ptrw[vertex_index] = start + Vector3(w, map_data_ptr[(heightmap_width * d) + w], d); |
| 1469 | + vertex_array_ptrw[vertex_index + 1] = start + Vector3(w + 1, map_data_ptr[(heightmap_width * d) + w + 1], d); |
| 1470 | + vertex_array_ptrw[vertex_index + 2] = start + Vector3(w, map_data_ptr[(heightmap_width * d) + heightmap_width + w], d + 1); |
| 1471 | + vertex_array_ptrw[vertex_index + 3] = start + Vector3(w + 1, map_data_ptr[(heightmap_width * d) + w + 1], d); |
| 1472 | + vertex_array_ptrw[vertex_index + 4] = start + Vector3(w + 1, map_data_ptr[(heightmap_width * d) + heightmap_width + w + 1], d + 1); |
| 1473 | + vertex_array_ptrw[vertex_index + 5] = start + Vector3(w, map_data_ptr[(heightmap_width * d) + heightmap_width + w], d + 1); |
| 1474 | + vertex_index += 6; |
| 1475 | + } |
| 1476 | + } |
| 1477 | + if (vertex_array.size() > 0) { |
| 1478 | + p_source_geometry_data->add_faces(vertex_array, shapes[i]); |
| 1479 | + } |
| 1480 | + } |
| 1481 | + } break; |
| 1482 | + default: { |
| 1483 | + WARN_PRINT("Unsupported collision shape type."); |
| 1484 | + } break; |
| 1485 | + } |
| 1486 | + } |
| 1487 | + } |
| 1488 | +} |
| 1489 | + |
1339 | 1490 | #ifdef DEBUG_ENABLED
|
1340 | 1491 | void GridMap::_update_navigation_debug_edge_connections() {
|
1341 | 1492 | if (bake_navigation) {
|
|
0 commit comments