--- name: surface_plot_3d kind: component lang: cpp domain: viz version: "2.0.0" purity: pure signature: "void surface_plot_3d(const char* title, const fn::SurfacePlot3DConfig& cfg)" description: "Superficie 3D ImPlot3D — malla z[nx*ny] row-major + ranges X/Y, eje rotatorio drag-to-orbit" tags: [implot3d, chart, visualization, gpu, surface, 3d, pendiente-usar] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [imgui, implot3d] tested: false tests: [] test_file_path: "" file_path: "cpp/functions/viz/surface_plot_3d.cpp" framework: imgui params: - name: title desc: "Titulo / id interno del plot" - name: cfg desc: "fn::SurfacePlot3DConfig — z (nx*ny row-major), nx, ny, x/y_min, x/y_max, labels, size, show_colormap" output: "Renderiza una superficie 3D dentro del frame ImGui actual; soporta orbit (drag), zoom (wheel) y pan via ImPlot3D" notes: "scaffolding/demo en primitives_gallery" --- # surface_plot_3d Superficie 3D renderizada con [ImPlot3D](https://github.com/brenocq/implot3d) (vendoreado en `cpp/vendor/implot3d/`, pinned v0.4 commit `41ae3e44`). La API toma una malla densa `z[nx*ny]` en row-major (`z[j*nx + i]` es la altura en el vertice `(x_i, y_j)`) y ranges para los ejes X / Y. Las coordenadas X / Y por vertice se generan internamente en lineal entre `[x_min, x_max]` y `[y_min, y_max]` — el caller solo necesita pasar el grid de alturas. Llamar dentro de un frame ImGui activo (lambda de `fn::run_app` o similar). El contexto de ImPlot3D lo crea / destruye `app_base` junto al de ImPlot. ## Caracteristicas - **Orbit**: drag con LMB rota la camara alrededor del centro del plot. - **Zoom**: scroll wheel. - **Pan**: drag con MMB. - **Colormap**: ImPlot3D aplica el colormap activo segun la altura Z. `show_colormap` esta reservado como contrato API por si se anyade colorbar externa. ## Ejemplo ```cpp #include "viz/surface_plot_3d.h" #include #include constexpr int N = 64; std::vector z(N * N); for (int j = 0; j < N; ++j) for (int i = 0; i < N; ++i) z[j*N + i] = std::sin(0.2f * i) * std::cos(0.2f * j); fn::SurfacePlot3DConfig cfg{}; cfg.z = z.data(); cfg.nx = N; cfg.ny = N; cfg.x_min = 0; cfg.x_max = float(N); cfg.y_min = 0; cfg.y_max = float(N); fn::surface_plot_3d("##terreno", cfg); ``` ## Limites practicos - Mallas hasta ~256×256 son fluidas a 60 FPS en GPUs modernas. Por encima de eso conviene downsamplear. - ImPlot3D dibuja los triangulos en CPU y los empuja al ImDrawList — no es shader-based.