Pequeño pero potente cargador OBJ de marco de un solo archivo escrito en C ++ 03. Sin dependencia excepto C ++ STL. Puede analizar más de 10 millones de polígonos con memoria y tiempo moderados.
tinyobjloader es bueno para integrar .BJ Loader a su renderizador (global de iluminación) ;-)
Si está buscando la versión C99, consulte https://github.com/syoyo/tinyobjloader-c.
Recomendamos usar la rama master ( main ). Su candidato de liberación v2.0. La mayoría de las características ahora son casi robustas y estables (la tarea restante para la versión v2.0 está puliendo la API C ++ y Python, y corrige el código de triangulación incorporado).
Hemos lanzado una nueva versión v1.0.0 el 20 de agosto de 2016. La versión anterior está disponible como v0.9.x rama https://github.com/syoyo/tinyobjloader/tree/v0.9.x
python . Ver también https://pypi.org/project/tinyobjloader/) La versión anterior anterior está disponible en la rama v0.9.x

TinyObjLoader puede cargar con éxito la escena de rungholt de triángulos de 6 m. http://casual-effects.com/data/index.html

TinyobjLoader se usa con éxito en ...
TINYOBJLOADER_USE_DOUBLE gracias a noma
- Motor 3D con gráficos modernospython .f ) l ) p ) TinyobjLoader tiene licencia bajo la licencia MIT.
Una opción es simplemente copiar el archivo de encabezado en su proyecto y asegurarse de que TINYOBJLOADER_IMPLEMENTATION se define exactamente una vez.
Aunque no es una forma recomendada, puede descargar e instalar TinyOBJLoader utilizando el Administrador de dependencias VCPKG:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install tinyobjloader
El puerto TinyobjLoader en VCPKG se mantiene actualizado por los miembros del equipo de Microsoft y los contribuyentes comunitarios. Si la versión está desactualizada, cree un problema o extraiga la solicitud en el repositorio de VCPKG.
attrib_t contiene una matriz única y lineal de datos de vértice (posición, normal y texcoord).
attrib_t::vertices => 3 floats per vertex
v[0] v[1] v[2] v[3] v[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+-----------+-----------+-----------+-----------+ +-----------+
attrib_t::normals => 3 floats per vertex
n[0] n[1] n[2] n[3] n[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+-----------+-----------+-----------+-----------+ +-----------+
attrib_t::texcoords => 2 floats per vertex
t[0] t[1] t[2] t[3] t[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| u | v | u | v | u | v | u | v | .... | u | v |
+-----------+-----------+-----------+-----------+ +-----------+
attrib_t::colors => 3 floats per vertex(vertex color. optional)
c[0] c[1] c[2] c[3] c[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+-----------+-----------+-----------+-----------+ +-----------+
Cada shape_t::mesh_t no contiene datos de vértice, pero contiene índice de matriz a attrib_t . Consulte loader_example.cc para obtener más detalles.
mesh_t::indices => array of vertex indices.
+----+----+----+----+----+----+----+----+----+----+ +--------+
| i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | ... | i(n-1) |
+----+----+----+----+----+----+----+----+----+----+ +--------+
Each index has an array index to attrib_t::vertices, attrib_t::normals and attrib_t::texcoords.
mesh_t::num_face_vertices => array of the number of vertices per face(e.g. 3 = triangle, 4 = quad , 5 or more = N-gons).
+---+---+---+ +---+
| 3 | 4 | 3 | ...... | 3 |
+---+---+---+ +---+
| | | |
| | | +-----------------------------------------+
| | | |
| | +------------------------------+ |
| | | |
| +------------------+ | |
| | | |
|/ |/ |/ |/
mesh_t::indices
| face[0] | face[1] | face[2] | | face[n-1] |
+----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
| i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | ... | i(n-3) | i(n-2) | i(n-1) |
+----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
Tenga en cuenta que cuando la bandera triangulate es verdadera en el argumento tinyobj::LoadObj() , num_face_vertices están llenos de 3 (triángulo).
TinyObjLoader ahora usa real_t para el tipo de datos de punto flotante. El valor predeterminado es float(32bit) . Puede habilitar la precisión double(64bit) usando TINYOBJLOADER_USE_DOUBLE Define.
Cuando habilita triangulation (el valor predeterminado está habilitado), los polígonos triangulados de TinyObjLoader (caras con 4 o más vértices).
El código de triangulación incorporado puede no funcionar bien en forma de polígono.
Puede definir TINYOBJLOADER_USE_MAPBOX_EARCUT para una triangulación robusta usando mapbox/earcut.hpp . Sin embargo, esto requiere el compilador C ++ 11. Y debe copiar mapbox/earcut.hpp a su proyecto. Si tiene su propio archivo mapbox/earcut.hpp incado en su proyecto, puede definir TINYOBJLOADER_DONOT_INCLUDE_MAPBOX_EARCUT para que mapbox/earcut.hpp no esté incluido dentro de tiny_obj_loader.h .
# define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
// Optional. define TINYOBJLOADER_USE_MAPBOX_EARCUT gives robust triangulation. Requires C++11
// #define TINYOBJLOADER_USE_MAPBOX_EARCUT
# include " tiny_obj_loader.h "
std::string inputfile = " cornell_box.obj " ;
tinyobj:: attrib_t attrib;
std::vector<tinyobj:: shape_t > shapes;
std::vector<tinyobj:: material_t > materials;
std::string warn;
std::string err;
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, inputfile.c_str());
if (!warn.empty()) {
std::cout << warn << std::endl;
}
if (!err.empty()) {
std::cerr << err << std::endl;
}
if (!ret) {
exit ( 1 );
}
// Loop over shapes
for ( size_t s = 0 ; s < shapes.size(); s++) {
// Loop over faces(polygon)
size_t index_offset = 0 ;
for ( size_t f = 0 ; f < shapes[s]. mesh . num_face_vertices . size (); f++) {
size_t fv = size_t (shapes[s]. mesh . num_face_vertices [f]);
// Loop over vertices in the face.
for ( size_t v = 0 ; v < fv; v++) {
// access to vertex
tinyobj:: index_t idx = shapes[s]. mesh . indices [index_offset + v];
tinyobj:: real_t vx = attrib. vertices [ 3 * size_t (idx. vertex_index )+ 0 ];
tinyobj:: real_t vy = attrib. vertices [ 3 * size_t (idx. vertex_index )+ 1 ];
tinyobj:: real_t vz = attrib. vertices [ 3 * size_t (idx. vertex_index )+ 2 ];
// Check if `normal_index` is zero or positive. negative = no normal data
if (idx. normal_index >= 0 ) {
tinyobj:: real_t nx = attrib. normals [ 3 * size_t (idx. normal_index )+ 0 ];
tinyobj:: real_t ny = attrib. normals [ 3 * size_t (idx. normal_index )+ 1 ];
tinyobj:: real_t nz = attrib. normals [ 3 * size_t (idx. normal_index )+ 2 ];
}
// Check if `texcoord_index` is zero or positive. negative = no texcoord data
if (idx. texcoord_index >= 0 ) {
tinyobj:: real_t tx = attrib. texcoords [ 2 * size_t (idx. texcoord_index )+ 0 ];
tinyobj:: real_t ty = attrib. texcoords [ 2 * size_t (idx. texcoord_index )+ 1 ];
}
// Optional: vertex colors
// tinyobj::real_t red = attrib.colors[3*size_t(idx.vertex_index)+0];
// tinyobj::real_t green = attrib.colors[3*size_t(idx.vertex_index)+1];
// tinyobj::real_t blue = attrib.colors[3*size_t(idx.vertex_index)+2];
}
index_offset += fv;
// per-face material
shapes[s]. mesh . material_ids [f];
}
}
# define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
// Optional. define TINYOBJLOADER_USE_MAPBOX_EARCUT gives robust triangulation. Requires C++11
// #define TINYOBJLOADER_USE_MAPBOX_EARCUT
# include " tiny_obj_loader.h "
std::string inputfile = " cornell_box.obj " ;
tinyobj::ObjReaderConfig reader_config;
reader_config.mtl_search_path = " ./ " ; // Path to material files
tinyobj::ObjReader reader;
if (!reader.ParseFromFile(inputfile, reader_config)) {
if (!reader. Error (). empty ()) {
std::cerr << " TinyObjReader: " << reader. Error ();
}
exit ( 1 );
}
if (!reader.Warning().empty()) {
std::cout << " TinyObjReader: " << reader. Warning ();
}
auto & attrib = reader.GetAttrib();
auto & shapes = reader.GetShapes();
auto & materials = reader.GetMaterials();
// Loop over shapes
for ( size_t s = 0 ; s < shapes.size(); s++) {
// Loop over faces(polygon)
size_t index_offset = 0 ;
for ( size_t f = 0 ; f < shapes[s]. mesh . num_face_vertices . size (); f++) {
size_t fv = size_t (shapes[s]. mesh . num_face_vertices [f]);
// Loop over vertices in the face.
for ( size_t v = 0 ; v < fv; v++) {
// access to vertex
tinyobj:: index_t idx = shapes[s]. mesh . indices [index_offset + v];
tinyobj:: real_t vx = attrib. vertices [ 3 * size_t (idx. vertex_index )+ 0 ];
tinyobj:: real_t vy = attrib. vertices [ 3 * size_t (idx. vertex_index )+ 1 ];
tinyobj:: real_t vz = attrib. vertices [ 3 * size_t (idx. vertex_index )+ 2 ];
// Check if `normal_index` is zero or positive. negative = no normal data
if (idx. normal_index >= 0 ) {
tinyobj:: real_t nx = attrib. normals [ 3 * size_t (idx. normal_index )+ 0 ];
tinyobj:: real_t ny = attrib. normals [ 3 * size_t (idx. normal_index )+ 1 ];
tinyobj:: real_t nz = attrib. normals [ 3 * size_t (idx. normal_index )+ 2 ];
}
// Check if `texcoord_index` is zero or positive. negative = no texcoord data
if (idx. texcoord_index >= 0 ) {
tinyobj:: real_t tx = attrib. texcoords [ 2 * size_t (idx. texcoord_index )+ 0 ];
tinyobj:: real_t ty = attrib. texcoords [ 2 * size_t (idx. texcoord_index )+ 1 ];
}
// Optional: vertex colors
// tinyobj::real_t red = attrib.colors[3*size_t(idx.vertex_index)+0];
// tinyobj::real_t green = attrib.colors[3*size_t(idx.vertex_index)+1];
// tinyobj::real_t blue = attrib.colors[3*size_t(idx.vertex_index)+2];
}
index_offset += fv;
// per-face material
shapes[s]. mesh . material_ids [f];
}
}
El cargador .OBJ de múltiples subprocesos optimizado está disponible en experimental/ directorio. Si desea un rendimiento absoluto para cargar datos .OBJ, este cargador optimizado se ajustará a su propósito. Tenga en cuenta que el cargador optimizado usa el hilo C ++ 11 y hace menos verificaciones de error, pero puede funcionar la mayoría de los datos .OBJ.
Aquí hay algún resultado de referencia. El tiempo se mide en MacBook 12 (principios de 2016, Core M5 1.2GHz).
$ python -m pip install tinyobjloader
Consulte Python/Sample.py, por ejemplo, el uso de la unión de Python de TinyObjLoader.
Cibuildwheels + Twine Carga para cada evento de etiquetado GIT se maneja en acciones de GitHub y Cirrus CI (construcciones de brazo).
black a Python ( python/sample.py )release . Confirmar que la compilación CI está bien.v (por ejemplo, v2.1.0 )git push --tags Las pruebas unitarias se proporcionan en el directorio tests . Consulte tests/README.md para más detalles.