--- name: mesh_viewer kind: component lang: cpp domain: viz version: "1.1.0" purity: impure signature: "void mesh_viewer(const char* id, const MeshViewerConfig& cfg)" description: "Renderiza un MeshGpu (3D) en un FBO interno cacheado por id, con orbit camera, iluminacion Lambert headlight, depth test correcto (GL_DEPTH_COMPONENT24), opcion wireframe. Drag/wheel del mouse mueven la camara." tags: [imgui, opengl, mesh, 3d, viewer, viz, fbo, cpp-dashboard-viz] uses_functions: ["gl_framebuffer_cpp_gfx", "gl_loader_cpp_gfx", "gl_shader_cpp_gfx", "mesh_gpu_cpp_gfx", "orbit_camera_cpp_core"] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [imgui, GL/gl.h] tested: false tests: [] test_file_path: "" file_path: "cpp/functions/viz/mesh_viewer.cpp" framework: imgui emits: ["camera_drag", "camera_zoom"] params: - name: id desc: "ID estable de ImGui para cachear el FBO y el programa shader. Cambiar el id entre frames acumula recursos (leak). Usar IDs constantes." - name: cfg desc: "MeshViewerConfig con mesh (MeshGpu*), cam (OrbitCamera*), size (ImVec2, -1 = full width), wireframe (bool), color (ImU32 RGBA)." output: "Renderiza una imagen del mesh dentro del frame ImGui actual; muta cfg.cam in-place segun drag/wheel del mouse cuando el panel esta active/hovered." --- # mesh_viewer Componente de viz para inspeccionar geometria 3D dentro de cualquier panel ImGui. Internamente: 1. Compila/cachea (por `id`) un programa shader Lambert headlight (vertex + fragment). 2. Cachea un `Framebuffer` con depth renderbuffer por `id` y lo redimensiona segun `cfg.size`. 3. Cada frame: bind FBO, clear color+depth, draw `cfg.mesh` con depth test activo, mostrar la textura via `ImGui::Image`. 4. Si el panel esta active → llama `orbit_camera_handle_drag` con `MouseDelta`. 5. Si el panel esta hovered y hay scroll → ajusta zoom. ## Ejemplo ```cpp static fn::core::OrbitCamera cam; fn::viz::MeshViewerConfig cfg{}; cfg.mesh = &gpu; // MeshGpu valido cfg.cam = &cam; cfg.size = {-1, 480}; cfg.wireframe = false; cfg.color = IM_COL32(160, 200, 255, 255); fn::viz::mesh_viewer("##teapot_view", cfg); ``` ## Cuando usarla Cuando necesites inspeccionar geometria 3D (OBJ, STL, cualquier MeshGpu) dentro de un panel ImGui existente, con orbit camera interactiva y auto-oclusion correcta de caras. ## Gotchas - **Cache por id**: si el `id` cambia dinamicamente entre frames, se acumulan FBOs y programas en memoria (leak). Usar IDs estables (`"##nombre_fijo"`). - **Wireframe**: usa `glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)` — no disponible en GL ES; protegido con `#ifndef __EMSCRIPTEN__`. - **Iluminacion**: Lambert con luz fija en `+Z` view-space ("headlight"), suficiente para inspeccion. Sin specular, sin sombras. - **Matrices**: row-major desde `orbit_camera_matrices`; se suben con `transpose=GL_TRUE` (GL espera column-major). - **Estado GL**: salva y restaura `GL_FRAMEBUFFER_BINDING`, `GL_VIEWPORT` y `GL_DEPTH_TEST` antes/despues del render. No contamina el estado del frame ImGui principal. ## Notas - **Depth renderbuffer activo** (GL_DEPTH_COMPONENT24): auto-oclusion correcta en meshes solidos. `glEnable(GL_DEPTH_TEST)` + `glDepthFunc(GL_LESS)` dentro del render del FBO. - Usa `fb_init_depth` de `gl_framebuffer_cpp_gfx` (v1.1.0+). ## Capability growth log v1.1.0 (2026-05-28) — depth renderbuffer via fb_init_depth, fix auto-oclusion en meshes solidos