debug_draw.cpp

cross platform rendering playground

src/editor/debug_draw.cpp

3.63 KB
#ifdef ENABLE_EDITOR
#include "editor.h"

#include "core/math_rtm.h"
#include "passes/debug/debug_draw.h"
#include "renderer.h"
#include "scene/scene.h"
#include "shaders/renderer_types.h"

namespace editor {

void apply_debug_settings(const Editor &e, DebugDraw &draw) {
    draw.force_xray = e.force_xray;
    u32 mask = 0;
    if (e.show_cat_default) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_DEFAULT);
    }
    if (e.show_cat_grid) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_GRID);
    }
    if (e.show_cat_proxy) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_PROXY);
    }
    if (e.show_cat_selection) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_SELECTION);
    }
    if (e.show_cat_light) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_LIGHT);
    }
    if (e.show_cat_ddgi) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_DDGI);
    }
    if (e.show_cat_gizmo) {
        mask |= DebugDraw::category_bit(DEBUG_CAT_GIZMO);
    }
    draw.category_mask = mask;
}

void debug_draw_selection(DebugDraw &draw, const Scene &scene, const RenderData &rd, int selected_node) {
    if (selected_node < 0 || (u32)selected_node >= scene.scene_graph.node_count) {
        return;
    }
    if (!scene.scene_graph.is_node_alive((u32)selected_node)) {
        return;
    }
    u32 node = (u32)selected_node;
    const SceneGraph &sg = scene.scene_graph;
    const mat4 base_world = sg.worlds[node];
    const u32 inst_count = sg.instance_count[node];
    const u32 inst_base = sg.instance_base[node];
    bool drew = false;
    for (const RenderItemGPU &item : rd.render_items) {
        // entity_id is node+1 (see create_render_data); match selection.
        if (item.entity_id != node + 1) {
            continue;
        }
        if (item.submesh_index >= rd.submeshes.size()) {
            continue;
        }
        // Per-instance world (Scene::instance_world, same composition as
        // upload_transforms); node base when not instanced.
        mat4 world = base_world;
        if (inst_count > 0) {
            if (item.instance_id < inst_base) {
                continue;
            }
            u32 k = item.instance_id - inst_base;
            if (k >= inst_count) {
                continue;
            }
            world = scene.instance_world(node, k);
        }
        const SubmeshGPU &sm = rd.submeshes[item.submesh_index];
        vec3 mn = sm.local_aabb_min;
        vec3 mx = sm.local_aabb_max;
        auto xform = [](vec3 p, const mat4 &m) {
            vec4 h = transform_point(p, m);
            return vec3(h.x, h.y, h.z);
        };
        // 8 corners of the local AABB into world -> world AABB (conservative).
        vec3 wmn = vec3(1e30f);
        vec3 wmx = vec3(-1e30f);
        for (u32 c = 0; c < 8; ++c) {
            vec3 corner = vec3((c & 1) ? mx.x : mn.x, (c & 2) ? mx.y : mn.y, (c & 4) ? mx.z : mn.z);
            vec3 w = xform(corner, world);
            wmn.x = wmn.x < w.x ? wmn.x : w.x;
            wmn.y = wmn.y < w.y ? wmn.y : w.y;
            wmn.z = wmn.z < w.z ? wmn.z : w.z;
            wmx.x = wmx.x > w.x ? wmx.x : w.x;
            wmx.y = wmx.y > w.y ? wmx.y : w.y;
            wmx.z = wmx.z > w.z ? wmx.z : w.z;
        }
        draw.aabb(wmn, wmx, vec4(4.0f, 1.4f, 0.4f, 1.0f), DEBUG_CAT_SELECTION, DEBUG_DEPTH_TEST, 3.0f);
        drew = true;
    }
    if (!drew) {
        // Node without mesh (light/camera/empty): small cross at its origin.
        vec4 h = transform_point(vec3(0.0f), base_world);
        draw.sphere(
            vec3(h.x, h.y, h.z), 0.3f, vec4(4.0f, 1.4f, 0.4f, 1.0f), DEBUG_CAT_SELECTION, DEBUG_DEPTH_TEST, 3.0f
        );
    }
}

} // namespace editor

#endif // ENABLE_EDITOR