chore: auto-commit (43 archivos)
- .mcp.json - bash/functions/infra/write_mcp_jupyter_config.md - bash/functions/infra/write_mcp_jupyter_config.sh - cpp/CMakeLists.txt - cpp/apps/chart_demo - cpp/apps/shaders_lab - cpp/functions/gfx/gl_framebuffer.cpp - cpp/functions/gfx/gl_framebuffer.h - cpp/functions/gfx/gl_framebuffer.md - cpp/functions/gfx/mesh_gpu.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
---
|
||||
group: mesh-3d
|
||||
description: "Carga, parse y upload a GPU de meshes 3D (OBJ, GLB/glTF 2.0). Flujo CPU→GPU para apps ImGui."
|
||||
---
|
||||
|
||||
# mesh-3d — Capability Group
|
||||
|
||||
Cluster de funciones para cargar geometria 3D desde disco o memoria (CPU) y subirla a GPU con OpenGL. El flujo canonico es: **loader → `fn::gfx::Mesh` → `mesh_gpu_upload`**.
|
||||
|
||||
## Funciones
|
||||
|
||||
| ID | Firma corta | Que hace |
|
||||
|---|---|---|
|
||||
| `gltf_load_mesh_cpp_gfx` | `Mesh gltf_load_mesh_from_file(path)` | Carga primer mesh de un GLB 2.0. Genera normales si faltan. |
|
||||
| `mesh_obj_load_cpp_gfx` | `Mesh mesh_obj_load(path); Mesh mesh_obj_parse(buf, len)` | Carga/parsea Wavefront .obj. Genera normales por face si faltan. |
|
||||
| `mesh_gpu_cpp_gfx` | `MeshGpu mesh_gpu_upload(mesh); void mesh_gpu_destroy(gpu)` | Sube `fn::gfx::Mesh` CPU a VAO+VBO+EBO OpenGL. |
|
||||
|
||||
## Struct compartido
|
||||
|
||||
```cpp
|
||||
// cpp/functions/gfx/mesh_obj_load.h
|
||||
namespace fn::gfx {
|
||||
struct Mesh {
|
||||
std::vector<float> positions; // xyz stride=3
|
||||
std::vector<float> normals; // xyz stride=3, mismo length que positions
|
||||
std::vector<uint32_t> indices; // tri-list, multiplo de 3
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Ejemplo canonico end-to-end
|
||||
|
||||
```cpp
|
||||
#include "gfx/gltf_load_mesh.h" // gltf_load_mesh_from_file
|
||||
#include "gfx/mesh_obj_load.h" // Mesh (struct)
|
||||
#include "gfx/mesh_gpu.h" // mesh_gpu_upload, mesh_gpu_destroy
|
||||
|
||||
// -- Cargar desde GLB (ej. output de TripoSR/trimesh) --
|
||||
auto cpu = fn::gfx::gltf_load_mesh_from_file("model.glb");
|
||||
if (cpu.positions.empty()) {
|
||||
fprintf(stderr, "load failed: %s\n", fn::gfx::gltf_load_last_error());
|
||||
return;
|
||||
}
|
||||
|
||||
// -- Alternativamente desde OBJ --
|
||||
// auto cpu = fn::gfx::mesh_obj_load("model.obj");
|
||||
|
||||
// -- Subir a GPU (requiere contexto GL activo) --
|
||||
auto gpu = fn::gfx::mesh_gpu_upload(cpu);
|
||||
if (!gpu.ok()) return;
|
||||
|
||||
// -- Render --
|
||||
glUseProgram(prog);
|
||||
glBindVertexArray(gpu.vao);
|
||||
glDrawElements(GL_TRIANGLES, gpu.index_count, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// -- Cleanup --
|
||||
fn::gfx::mesh_gpu_destroy(gpu);
|
||||
```
|
||||
|
||||
## Shader esperado (layout)
|
||||
|
||||
```glsl
|
||||
#version 330 core
|
||||
layout(location = 0) in vec3 a_pos;
|
||||
layout(location = 1) in vec3 a_normal;
|
||||
```
|
||||
|
||||
## Fronteras
|
||||
|
||||
- Sin texturas/UV — mesh viewer usa color uniforme o shading por normal.
|
||||
- Sin animaciones ni skinning.
|
||||
- `gltf_load_mesh`: solo GLB binario (no .gltf+.bin separado, no data-URI base64). Solo primer mesh/primitive.
|
||||
- `mesh_obj_load`: solo tris y quads; N-gons ignorados.
|
||||
- `mesh_gpu`: asume contexto OpenGL 3.3+ activo. Sin streaming (GL_STATIC_DRAW).
|
||||
|
||||
## Prerequisitos
|
||||
|
||||
- `mesh_gpu_upload` requiere contexto GL activo (llama a `glGenVertexArrays`, etc.).
|
||||
- `gltf_load_mesh` requiere `cpp/vendor/nlohmann/json.hpp`.
|
||||
- `mesh_obj_load` solo stdlib — sin dependencias extra.
|
||||
Reference in New Issue
Block a user