1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Combined TileMapLayer debug quadrant shapes to a surface

Create a combined mesh surface for all mesh faces and mesh lines in the TileMapLayer debug quadrant. Before it created a new mesh surface for each shape crashing into the mesh surface limit of 256 quickly.
This commit is contained in:
smix8
2025-04-06 14:15:06 +02:00
parent a210fe6dbd
commit 33fe4a2d87

View File

@@ -33,6 +33,7 @@
#include "core/io/marshalls.h"
#include "core/math/geometry_2d.h"
#include "core/math/random_pcg.h"
#include "core/templates/a_hash_map.h"
#include "scene/2d/tile_map.h"
#include "scene/gui/control.h"
#include "scene/resources/2d/navigation_mesh_source_geometry_data_2d.h"
@@ -1043,9 +1044,7 @@ void TileMapLayer::_physics_draw_quadrant_debug(const RID &p_canvas_item, DebugQ
RenderingServer *rs = RenderingServer::get_singleton();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
Color debug_collision_color = get_tree()->get_debug_collisions_color();
Vector<Color> color;
color.push_back(debug_collision_color);
const Color &debug_collision_color = get_tree()->get_debug_collisions_color();
RandomPCG rand;
rand.seed(hash_murmur3_one_real(r_debug_quadrant.quadrant_coords.y, hash_murmur3_one_real(r_debug_quadrant.quadrant_coords.x)));
@@ -1061,6 +1060,15 @@ void TileMapLayer::_physics_draw_quadrant_debug(const RID &p_canvas_item, DebugQ
Vector2i first_physics_quadrant_coords = _coords_to_quadrant_coords(covered_cell_area.get_position() - Vector2i(1, 1), physics_quadrant_size) + Vector2i(1, 1);
Vector2i last_physics_quadrant_coords = _coords_to_quadrant_coords(covered_cell_area.get_end() - Vector2i(1, 1), physics_quadrant_size) + Vector2i(1, 1);
LocalVector<Vector2> face_vertex_array;
LocalVector<Color> face_color_array;
LocalVector<int32_t> face_index_array;
LocalVector<Vector2> line_vertex_array;
LocalVector<Color> line_color_array;
AHashMap<Vector2, int> vertex_map;
// Arrays to generate a mesh.
for (int x = first_physics_quadrant_coords.x; x < last_physics_quadrant_coords.x; x++) {
for (int y = first_physics_quadrant_coords.y; y < last_physics_quadrant_coords.y; y++) {
@@ -1074,18 +1082,33 @@ void TileMapLayer::_physics_draw_quadrant_debug(const RID &p_canvas_item, DebugQ
const Vector2 debug_quadrant_pos = tile_set->map_to_local(r_debug_quadrant.quadrant_coords * TILE_MAP_DEBUG_QUADRANT_SIZE);
Transform2D global_to_debug_quadrant = (get_global_transform() * Transform2D(0, debug_quadrant_pos)).affine_inverse();
// Clear arrays for new quadrant while keeping allocated memory.
face_vertex_array.clear();
face_color_array.clear();
face_index_array.clear();
line_vertex_array.clear();
line_color_array.clear();
vertex_map.clear();
for (const KeyValue<PhysicsQuadrant::PhysicsBodyKey, PhysicsQuadrant::PhysicsBodyValue> &kvbody : physics_quadrant->bodies) {
const RID &body = kvbody.value.body;
Transform2D body_to_quadrant = global_to_debug_quadrant * Transform2D(ps->body_get_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM));
int shape_count = ps->body_get_shape_count(body);
if (shape_count == 0) {
continue;
}
const Transform2D body_to_quadrant = global_to_debug_quadrant * Transform2D(ps->body_get_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM));
Color random_variation_color;
random_variation_color.set_hsv(
Color face_random_variation_color;
face_random_variation_color.set_hsv(
debug_collision_color.get_h() + rand.random(-1.0, 1.0) * 0.05,
debug_collision_color.get_s(),
debug_collision_color.get_v() + rand.random(-1.0, 1.0) * 0.1,
debug_collision_color.a);
const Color line_random_variation_color = face_random_variation_color.lightened(0.2);
int shape_count = ps->body_get_shape_count(body);
for (int shape_index = 0; shape_index < shape_count; shape_index++) {
const RID &shape = ps->body_get_shape(body, shape_index);
const Transform2D &shape_xform = ps->body_get_shape_transform(body, shape_index);
@@ -1093,48 +1116,108 @@ void TileMapLayer::_physics_draw_quadrant_debug(const RID &p_canvas_item, DebugQ
if (type == PhysicsServer2D::SHAPE_CONVEX_POLYGON) {
PackedVector2Array outline = ps->shape_get_data(shape);
PackedVector2Array vertex_array;
vertex_array.resize(outline.size() + 1);
PackedColorArray face_color_array;
face_color_array.resize(outline.size() + 1);
PackedInt32Array face_index_array;
face_index_array.resize((outline.size() - 2) * 3);
PackedColorArray line_color_array;
line_color_array.resize(outline.size() + 1);
for (int i = 0; i < outline.size() + 1; i++) {
Vector2 vertex = (body_to_quadrant * shape_xform).xform(outline[i % outline.size()]);
vertex_array.write[i] = vertex;
face_color_array.write[i] = random_variation_color;
line_color_array.write[i] = random_variation_color.lightened(0.2);
}
for (int i = 0; i < outline.size() - 2; i++) {
face_index_array.write[i * 3] = 0;
face_index_array.write[i * 3 + 1] = i + 1;
face_index_array.write[i * 3 + 2] = i + 2;
const int outline_size = outline.size();
if (outline_size < 3) {
continue;
}
Array face_mesh_array;
face_mesh_array.resize(Mesh::ARRAY_MAX);
face_mesh_array[Mesh::ARRAY_VERTEX] = vertex_array;
face_mesh_array[Mesh::ARRAY_INDEX] = face_index_array;
face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array;
rs->mesh_add_surface_from_arrays(r_debug_quadrant.physics_mesh, RS::PRIMITIVE_TRIANGLES, face_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
const Transform2D outline_xform = body_to_quadrant * shape_xform;
Array line_mesh_array;
line_mesh_array.resize(Mesh::ARRAY_MAX);
line_mesh_array[Mesh::ARRAY_VERTEX] = vertex_array;
line_mesh_array[Mesh::ARRAY_COLOR] = line_color_array;
// Adds debug mesh lines.
Vector2 previous_line_vertex = outline_xform.xform(outline[outline_size - 1]);
for (int i = 0; i < outline_size; i++) {
Vector2 line_vertex = outline_xform.xform(outline[i]);
line_vertex_array.push_back(previous_line_vertex);
line_vertex_array.push_back(line_vertex);
previous_line_vertex = line_vertex;
line_color_array.push_back(line_random_variation_color);
line_color_array.push_back(line_random_variation_color);
}
// Adds debug mesh faces.
const Vector2 vertex1 = outline_xform.xform(outline[0]);
const Vector2 vertex2 = outline_xform.xform(outline[1]);
Vector2 vertex3;
int vertex1_index = -1;
int vertex2_index = -1;
int vertex3_index = -1;
int last_vertex3_index = -1;
// Find triangle fan anchor vertex1 index.
{
AHashMap<Vector2, int>::Iterator E = vertex_map.find(vertex1);
if (!E) {
E = vertex_map.insert(vertex1, vertex_map.size());
face_vertex_array.push_back(vertex1);
face_color_array.push_back(face_random_variation_color);
}
vertex1_index = E->value;
}
// Find starting vertex2 index.
{
AHashMap<Vector2, int>::Iterator E = vertex_map.find(vertex2);
if (!E) {
E = vertex_map.insert(vertex2, vertex_map.size());
face_vertex_array.push_back(vertex2);
face_color_array.push_back(face_random_variation_color);
}
vertex2_index = E->value;
}
// Create mesh triangle face fan from outline vertices using vertex_map indices.
for (int i = 1; i < outline_size - 1; i++) {
if (i > 1) {
vertex2_index = last_vertex3_index;
}
vertex3 = outline_xform.xform(outline[i + 1]);
{
AHashMap<Vector2, int>::Iterator E = vertex_map.find(vertex3);
if (!E) {
E = vertex_map.insert(vertex3, vertex_map.size());
face_vertex_array.push_back(vertex3);
face_color_array.push_back(face_random_variation_color);
}
vertex3_index = E->value;
last_vertex3_index = vertex3_index;
}
face_index_array.push_back(vertex1_index);
face_index_array.push_back(vertex2_index);
face_index_array.push_back(vertex3_index);
}
rs->mesh_add_surface_from_arrays(r_debug_quadrant.physics_mesh, RS::PRIMITIVE_LINE_STRIP, line_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
} else {
WARN_PRINT("Wrong shape type for a tile, should be SHAPE_CONVEX_POLYGON.");
}
}
}
if (face_index_array.size() > 2) {
Array face_mesh_array;
face_mesh_array.resize(Mesh::ARRAY_MAX);
face_mesh_array[Mesh::ARRAY_VERTEX] = Vector<Vector2>(face_vertex_array);
face_mesh_array[Mesh::ARRAY_INDEX] = Vector<int32_t>(face_index_array);
face_mesh_array[Mesh::ARRAY_COLOR] = Vector<Color>(face_color_array);
rs->mesh_add_surface_from_arrays(r_debug_quadrant.physics_mesh, RS::PRIMITIVE_TRIANGLES, face_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
Array line_mesh_array;
line_mesh_array.resize(Mesh::ARRAY_MAX);
line_mesh_array[Mesh::ARRAY_VERTEX] = Vector<Vector2>(line_vertex_array);
line_mesh_array[Mesh::ARRAY_COLOR] = Vector<Color>(line_color_array);
rs->mesh_add_surface_from_arrays(r_debug_quadrant.physics_mesh, RS::PRIMITIVE_LINES, line_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
}
}
}
rs->canvas_item_add_mesh(p_canvas_item, r_debug_quadrant.physics_mesh, Transform2D());