Merge pull request #118583 from YeldhamDev/gridmap_show_octants
Add octant visualization to `GridMap`
This commit is contained in:
@@ -380,6 +380,134 @@ bool GridMap::get_center_z() const {
|
||||
return center_z;
|
||||
}
|
||||
|
||||
void GridMap::set_debug_octant_color(const Color &p_color) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_octant_color == p_color) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug_octant_color = p_color;
|
||||
|
||||
if (debug_octant_line_material.is_valid()) {
|
||||
debug_octant_line_material->set_albedo(debug_octant_color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Color GridMap::get_debug_octant_color() const {
|
||||
return debug_octant_color;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void GridMap::_debug_update() {
|
||||
if (debug_dirty || !is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
debug_dirty = true;
|
||||
|
||||
callable_mp(this, &GridMap::_debug_update_octants).call_deferred();
|
||||
}
|
||||
|
||||
void GridMap::_debug_update_octants() {
|
||||
debug_dirty = false;
|
||||
|
||||
if (!debug_show_octants) {
|
||||
_debug_clear_octants();
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug_octant_line_material.is_null()) {
|
||||
debug_octant_line_material.instantiate();
|
||||
debug_octant_line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
|
||||
debug_octant_line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
|
||||
debug_octant_line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
|
||||
debug_octant_line_material->set_albedo(debug_octant_color);
|
||||
}
|
||||
|
||||
Array debug_mesh_arrays = _build_octant_line_mesh_arrays();
|
||||
|
||||
if (debug_octant_line_mesh_rid.is_null()) {
|
||||
debug_octant_line_mesh_rid = RS::get_singleton()->mesh_create();
|
||||
}
|
||||
RS::get_singleton()->mesh_clear(debug_octant_line_mesh_rid);
|
||||
RS::get_singleton()->mesh_add_surface_from_arrays(debug_octant_line_mesh_rid, RSE::PRIMITIVE_LINES, debug_mesh_arrays);
|
||||
RS::get_singleton()->mesh_surface_set_material(debug_octant_line_mesh_rid, 0, debug_octant_line_material->get_rid());
|
||||
|
||||
RID debug_scenario = get_world_3d()->get_scenario();
|
||||
const Transform3D &gridmap_xform = get_global_transform();
|
||||
|
||||
for (const KeyValue<OctantKey, Octant *> &ele : octant_map) {
|
||||
OctantKey octant_key = ele.key;
|
||||
HashMap<OctantKey, OctantDebug *, OctantKey>::Iterator E = debug_octant_map.find(octant_key);
|
||||
if (!E) {
|
||||
OctantDebug *octant_debug = memnew(OctantDebug);
|
||||
|
||||
RID debug_octant_line_instance_rid = RS::get_singleton()->instance_create();
|
||||
|
||||
RS::get_singleton()->instance_set_base(debug_octant_line_instance_rid, debug_octant_line_mesh_rid);
|
||||
RS::get_singleton()->instance_set_scenario(debug_octant_line_instance_rid, debug_scenario);
|
||||
|
||||
octant_debug->debug_line_instance_rid = debug_octant_line_instance_rid;
|
||||
|
||||
E = debug_octant_map.insert(octant_key, octant_debug);
|
||||
}
|
||||
|
||||
OctantDebug &octant_debug = *E->value;
|
||||
const Transform3D octant_transform = gridmap_xform * (Transform3D(Basis(), Vector3(octant_key.x, octant_key.y, octant_key.z) * octant_size * cell_size));
|
||||
|
||||
RS::get_singleton()->instance_set_scenario(octant_debug.debug_line_instance_rid, debug_scenario);
|
||||
RS::get_singleton()->instance_set_transform(octant_debug.debug_line_instance_rid, octant_transform);
|
||||
RS::get_singleton()->instance_set_visible(octant_debug.debug_line_instance_rid, is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
|
||||
void GridMap::_debug_clear_octants() {
|
||||
for (const KeyValue<OctantKey, Octant *> &ele : octant_map) {
|
||||
OctantKey octant_key = ele.key;
|
||||
HashMap<OctantKey, OctantDebug *, OctantKey>::Iterator E = debug_octant_map.find(octant_key);
|
||||
if (E) {
|
||||
OctantDebug &octant_debug = *E->value;
|
||||
|
||||
if (octant_debug.debug_line_mesh_rid.is_valid()) {
|
||||
RS::get_singleton()->free_rid(octant_debug.debug_line_mesh_rid);
|
||||
octant_debug.debug_line_mesh_rid = RID();
|
||||
}
|
||||
if (octant_debug.debug_line_instance_rid.is_valid()) {
|
||||
RS::get_singleton()->free_rid(octant_debug.debug_line_instance_rid);
|
||||
octant_debug.debug_line_instance_rid = RID();
|
||||
}
|
||||
|
||||
memdelete(&octant_debug);
|
||||
}
|
||||
}
|
||||
|
||||
debug_octant_map.clear();
|
||||
}
|
||||
|
||||
Array GridMap::_build_octant_line_mesh_arrays() const {
|
||||
AABB aabb;
|
||||
aabb.size = octant_size * cell_size;
|
||||
|
||||
Vector<Vector3> vertex_array;
|
||||
vertex_array.resize(24);
|
||||
Vector3 *vertex_array_ptrw = vertex_array.ptrw();
|
||||
int vertex_index = 0;
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
Vector3 a, b;
|
||||
aabb.get_edge(i, a, b);
|
||||
vertex_array_ptrw[vertex_index++] = a;
|
||||
vertex_array_ptrw[vertex_index++] = b;
|
||||
}
|
||||
|
||||
Array mesh_arrays;
|
||||
mesh_arrays.resize(Mesh::ARRAY_MAX);
|
||||
mesh_arrays[Mesh::ARRAY_VERTEX] = vertex_array;
|
||||
|
||||
return mesh_arrays;
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) {
|
||||
if (baked_meshes.size() && !recreating_octants) {
|
||||
//if you set a cell item, baked meshes go good bye
|
||||
@@ -1009,6 +1137,8 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
|
||||
g.navigation_debug_edge_connections_mesh.unref();
|
||||
}
|
||||
}
|
||||
|
||||
_debug_clear_octants();
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
@@ -1058,9 +1188,11 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
|
||||
g.navigation_debug_edge_connections_mesh.unref();
|
||||
}
|
||||
}
|
||||
|
||||
_debug_clear_octants();
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
//erase multimeshes
|
||||
// Erase multimeshes.
|
||||
|
||||
for (int i = 0; i < g.multimesh_instances.size(); i++) {
|
||||
RS::get_singleton()->free_rid(g.multimesh_instances[i].instance);
|
||||
@@ -1085,20 +1217,32 @@ void GridMap::_notification(int p_what) {
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_update();
|
||||
|
||||
#ifndef NAVIGATION_3D_DISABLED
|
||||
if (bake_navigation && NavigationServer3D::get_singleton()->get_debug_navigation_enabled()) {
|
||||
_update_navigation_debug_edge_connections();
|
||||
}
|
||||
#endif // defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
|
||||
#endif // NAVIGATION_3D_DISABLED
|
||||
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
_update_visibility();
|
||||
} break;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
_debug_clear_octants();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
Transform3D new_xform = get_global_transform();
|
||||
if (new_xform == last_transform) {
|
||||
break;
|
||||
}
|
||||
//update run
|
||||
|
||||
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
|
||||
_octant_transform(E.key);
|
||||
}
|
||||
@@ -1108,6 +1252,17 @@ void GridMap::_notification(int p_what) {
|
||||
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||
RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform());
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
for (const KeyValue<OctantKey, OctantDebug *> &E : debug_octant_map) {
|
||||
OctantKey octant_key = E.key;
|
||||
OctantDebug &octant_debug = *E.value;
|
||||
if (octant_debug.debug_line_instance_rid.is_valid()) {
|
||||
const Transform3D octant_transform = new_xform * (Transform3D(Basis(), Vector3(octant_key.x, octant_key.y, octant_key.z) * octant_size * cell_size));
|
||||
RS::get_singleton()->instance_set_transform(octant_debug.debug_line_instance_rid, octant_transform);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
@@ -1115,9 +1270,6 @@ void GridMap::_notification(int p_what) {
|
||||
_octant_exit_world(E.key);
|
||||
}
|
||||
|
||||
//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
|
||||
//_update_octants_callback();
|
||||
//_update_area_instances();
|
||||
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||
RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID());
|
||||
}
|
||||
@@ -1145,6 +1297,15 @@ void GridMap::_update_visibility() {
|
||||
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||
RS::get_singleton()->instance_set_visible(baked_meshes[i].instance, is_visible_in_tree());
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
for (const KeyValue<OctantKey, OctantDebug *> &E : debug_octant_map) {
|
||||
OctantDebug &octant_debug = *E.value;
|
||||
if (octant_debug.debug_line_instance_rid.is_valid()) {
|
||||
RS::get_singleton()->instance_set_visible(octant_debug.debug_line_instance_rid, is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridMap::_queue_octants_dirty() {
|
||||
@@ -1158,12 +1319,17 @@ void GridMap::_queue_octants_dirty() {
|
||||
|
||||
void GridMap::_recreate_octant_data() {
|
||||
recreating_octants = true;
|
||||
|
||||
HashMap<IndexKey, Cell, IndexKey> cell_copy(cell_map);
|
||||
_clear_internal();
|
||||
for (const KeyValue<IndexKey, Cell> &E : cell_copy) {
|
||||
set_cell_item(Vector3i(E.key), E.value.item, E.value.rot);
|
||||
}
|
||||
|
||||
recreating_octants = false;
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_update();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridMap::_clear_internal() {
|
||||
@@ -1178,6 +1344,10 @@ void GridMap::_clear_internal() {
|
||||
|
||||
octant_map.clear();
|
||||
cell_map.clear();
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_clear_octants();
|
||||
_debug_update();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridMap::clear() {
|
||||
@@ -1212,6 +1382,10 @@ void GridMap::_update_octants_callback() {
|
||||
|
||||
_update_visibility();
|
||||
awaiting_update = false;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_update_octants();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridMap::_bind_methods() {
|
||||
@@ -1302,6 +1476,12 @@ void GridMap::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes);
|
||||
ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_debug_show_octants", "enable"), &GridMap::set_debug_show_octants);
|
||||
ClassDB::bind_method(D_METHOD("get_debug_show_octants"), &GridMap::get_debug_show_octants);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_debug_octant_color", "color"), &GridMap::set_debug_octant_color);
|
||||
ClassDB::bind_method(D_METHOD("get_debug_octant_color"), &GridMap::get_debug_octant_color);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_library", PROPERTY_HINT_RESOURCE_TYPE, MeshLibrary::get_class_static()), "set_mesh_library", "get_mesh_library");
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material", PROPERTY_HINT_RESOURCE_TYPE, PhysicsMaterial::get_class_static()), "set_physics_material", "get_physics_material");
|
||||
@@ -1322,6 +1502,9 @@ void GridMap::_bind_methods() {
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
ADD_GROUP("Navigation", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
|
||||
ADD_GROUP("Debug", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_show_octants"), "set_debug_show_octants", "get_debug_show_octants");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_octant_color"), "set_debug_octant_color", "get_debug_octant_color");
|
||||
|
||||
BIND_CONSTANT(INVALID_CELL_ITEM);
|
||||
|
||||
@@ -1707,6 +1890,21 @@ RID GridMap::get_bake_mesh_instance(int p_idx) {
|
||||
return baked_meshes[p_idx].instance;
|
||||
}
|
||||
|
||||
void GridMap::set_debug_show_octants(bool p_enable) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_show_octants == p_enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug_show_octants = p_enable;
|
||||
_debug_update();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GridMap::get_debug_show_octants() const {
|
||||
return debug_show_octants;
|
||||
}
|
||||
|
||||
GridMap::GridMap() {
|
||||
set_notify_transform(true);
|
||||
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
|
||||
@@ -1902,10 +2100,16 @@ void GridMap::_navigation_map_changed(RID p_map) {
|
||||
|
||||
GridMap::~GridMap() {
|
||||
clear();
|
||||
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_clear_octants();
|
||||
|
||||
#ifndef NAVIGATION_3D_DISABLED
|
||||
NavigationServer3D::get_singleton()->disconnect("map_changed", callable_mp(this, &GridMap::_navigation_map_changed));
|
||||
NavigationServer3D::get_singleton()->disconnect("navigation_debug_changed", callable_mp(this, &GridMap::_update_navigation_debug_edge_connections));
|
||||
#endif // defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
|
||||
#endif // NAVIGATION_3D_DISABLED
|
||||
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
|
||||
|
||||
Reference in New Issue
Block a user