--- name: mesh_obj_load kind: function lang: cpp domain: gfx version: "1.0.0" purity: pure signature: "Mesh mesh_obj_parse(const char* obj_text, size_t len); Mesh mesh_obj_load(const char* path)" description: "Parser minimal de Wavefront .obj — soporta v, vn, f (tris y quads). Genera normales por face si faltan. mesh_obj_parse es puro; mesh_obj_load es helper impuro que lee fichero y delega." tags: [obj, mesh, parser, wavefront, loader, geometry, 3d] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [fstream, sstream, cmath] tested: false tests: [] test_file_path: "" file_path: "cpp/functions/gfx/mesh_obj_load.cpp" framework: opengl params: - name: obj_text desc: "Buffer de texto .obj. Lineas reconocidas: v, vn, f. Comentarios con #. UTF-8 plano." - name: len desc: "Longitud del buffer en bytes" - name: path desc: "Ruta absoluta o relativa del .obj a leer (mesh_obj_load impuro)" output: "Mesh con positions/normals (stride 3, mismo length) y indices (tri-list, multiplo de 3). Si no hay vn, normales por face (flat shading) y vertices duplicados por face. Mesh vacio si parse falla." notes: "scaffolding/demo en primitives_gallery" --- # mesh_obj_load Parser pequeno de Wavefront `.obj` para inspeccion de geometria. KISS: cubre el subconjunto que la mayoria de exporters genera (Blender default, MeshLab, etc). ## Soporta - `v x y z` — vertice (xyz; w opcional ignorado) - `vn x y z` — normal - `f a b c` y `f a b c d` — tris y quads (los quads se dividen en 2 tris) - Indices `v`, `v/t`, `v//n`, `v/t/n` (vt se ignora; t no afecta) - Indices 1-based positivos y negativos (relative-to-end, conforme spec) - Lineas en blanco y comentarios con `#` ## NO soporta (en este issue) - N-gons con mas de 4 vertices → silenciosamente descartados - `vt` (coordenadas de textura) — el indice se parsea pero el dato se ignora - `mtllib`, `usemtl`, `o`, `g`, `s` — se saltan - Lineas de polilineas (`l`) - Curvas, superficies, `vp` ## Generacion de normales Si el `.obj` no tiene `vn` (o si alguna face no las referencia), se generan normales por face (flat shading). Esto duplica vertices entre faces que comparten posicion pero no normal — es el comportamiento esperado para inspeccion. Cuando todas las faces tienen normales explicitas, se hace dedup `(v_idx, n_idx)` con un linear-scan simple. Para meshes inspeccion (<<100k verts unicos) es perf-OK; meshes mas grandes se beneficiarian de un hashmap. ## Errores Si el archivo no tiene vertices o no tiene faces, devuelve `Mesh{}` (positions/indices vacios). El caller puede chequear con `mesh.positions.empty()`. ## Test inline (cubo) ```cpp const char* obj = "v -1 -1 -1\nv 1 -1 -1\nv 1 1 -1\nv -1 1 -1\n" "v -1 -1 1\nv 1 -1 1\nv 1 1 1\nv -1 1 1\n" "f 1 2 3 4\nf 5 6 7 8\nf 1 2 6 5\n" "f 4 3 7 8\nf 1 4 8 5\nf 2 3 7 6\n"; Mesh m = mesh_obj_parse(obj, std::strlen(obj)); // 6 quads -> 12 tris -> 36 indices. // Sin vn -> face normals -> 36 verts emitidos (duplicados por face). assert(m.indices.size() == 36); ```