---
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.
