用C ++ 03編寫的微小但功能強大的單文件波沿OBJ加載器。除C ++ STL外,無依賴性。它可以用中等內存和時間解析超過1000萬多邊形。
tinyobjloader非常適合嵌入.OBJ加載器到您的(全局照明)渲染器;-)
如果您正在尋找C99版本,請參閱https://github.com/syoyo/tinyobjloader-c。
我們建議使用master ( main )分支。其v2.0釋放候選人。現在,大多數功能幾乎是強大且穩定的(版本V2.0的剩餘任務是拋光C ++和Python API,並修復了內置的三角測量代碼)。
我們已於2016年8月20日發布了新版本v1.0.0 v0.9.x
python Binding!以前的舊版本可在v0.9.x分支中找到。

TinyObjloader可以成功加載6M三角形Rungholt場景。 http://casual-effects.com/data/index.html

TinyObjLoader成功地用於...
TINYOBJLOADER_USE_DOUBLE多虧了雙重精度支持。
-3D引擎與現代圖形python文件夾。f ) l ) p ) TinyObjLoader已獲得MIT許可證的許可。
一種選擇是簡單地將標頭文件複製到項目中,並確保精確定義一次TINYOBJLOADER_IMPLEMENTATION 。
儘管不是建議的方法,但您可以使用VCPKG依賴項管理器下載並安裝TinyObjloader:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install tinyobjloader
VCPKG中的TinyObjloader端口由Microsoft團隊成員和社區貢獻者保持最新狀態。如果該版本已過時,請在VCPKG存儲庫上創建問題或拉出請求。
attrib_t包含頂點數據的單個和線性陣列(位置,正常和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 |
+-----------+-----------+-----------+-----------+ +-----------+
每個shape_t::mesh_t不包含頂點數據,而是包含attrib_t數組索引。有關更多詳細信息,請參見loader_example.cc 。
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) |
+----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
請注意,當tinyobj::LoadObj()參數中triangulate標誌為true時, num_face_vertices都充滿了3(三角形)。
現在,TinyObjloader使用real_t進行浮點數據類型。默認值為float(32bit) 。您可以使用TINYOBJLOADER_USE_DOUBLE define啟用double(64bit)精度。
當您啟用triangulation (默認值為默認值)時,TinyObjloader三角剖分多邊形(帶有4個或更多頂點的面部)。
內置的三角剖分代碼可能在某些多邊形形狀下無法正常工作。
您可以使用mapbox/earcut.hpp定義TINYOBJLOADER_USE_MAPBOX_EARCUT 。這需要C ++ 11編譯器。您需要將mapbox/earcut.hpp複製到您的項目。如果您的項目中有自己的mapbox/earcut.hpp文件,則可以定義TINYOBJLOADER_DONOT_INCLUDE_MAPBOX_EARCUT ,以便在tiny_obj_loader.h中不包含mapbox/earcut.hpp 。
# 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];
}
}
優化的多線程.OBJ加載器可在experimental/目錄上獲得。如果您希望絕對性能加載.OBJ數據,則此優化的加載程序將適合您的目的。請注意,優化的加載程序使用C ++ 11線程,並且會進行更少的錯誤檢查,但可能起作用大多數.OBJ數據。
這是一些基準結果。時間在MacBook 12(2016年初,M5 1.2GHz)上進行測量。
$ python -m pip install tinyobjloader
請參閱python/sample.py,例如使用python tinyobjloader的python結合。
每個GIT標籤事件的CibuildWheels + Twine上傳均在GitHub Action和Cirrus CI(ARM構建)中處理。
black應用於Python文件( python/sample.py )release 。確認CI構建還可以。v開頭(例如v2.1.0 )git push --tags單位測試在tests目錄中提供。有關詳細信息,請參見tests/README.md 。