OS Support for rapidobj
masterrapidobj supports the following operating systems:
- Windows
- macOS
- Linux
repository·master·Indexed 42 days ago
https://github.com/guybrush77/rapidobjA high-performance, single-header C++17 library for fast parsing of Wavefront .obj files, optimized for modern hardware and large 3D models. It provides functionality to parse files and streams, handle material libraries (.mtl), and triangulate meshes.
rapidobj supports the following operating systems:
The rapidobj::MaterialLibrary object controls how .mtl files are located and loaded during parsing. It can be used to specify search paths (relative or absolute), provide material definitions as raw strings, or instruct the parser to ignore materials entirely.
Default(): For ParseFile, searches the .obj file's directory. For ParseStream, ignores materials but populates Mesh::material_ids.SearchPath(path, policy): Specifies a single search path. Relative paths are relative to the .obj file's parent folder and only work with ParseFile.SearchPaths(paths, policy): Specifies multiple paths to be searched in order. The first match is used.String(text): Provides material definitions directly via a string.Ignore(): Completely ignores all material libraries; Materials and Mesh::material_ids will be empty.// Search multiple paths in order
MaterialLibrary mtllib = MaterialLibrary::SearchPaths({ "materials", "../materials", "." });
Result result = ParseFile("/home/user/teapot/teapot.obj", mtllib);
// Define materials via string
static constexpr auto materials = R"(
newmtl red
Kd 1 0 0
)";
Result result = ParseFile("/home/user/teapot/teapot.obj", MaterialLibrary::String(materials));Result object is the primary return value from the ParseFile and ParseStream functions. It acts as a container for the parsed data, holding both the .obj and .mtl file data in a binary format. It provides access to the parsed Shape (which can be a Mesh, Lines, or Points) and the Materials array.Parsed .obj data often requires additional processing before it can be used for GPU/hardware rendering. While rapidobj provides rapidobj::Triangulate to convert polygons to triangles, developers are responsible for implementing other common rendering preparation steps, such as:
.obj file, potentially using smoothing groups for higher quality.The Attributes class stores vertex data in four linear arrays of 32-bit floats. Only positions are mandatory; texcoords, normals, and colors may be empty. Data is interleaved as follows:
Attributes::positions: { x, y, z } per vertex.Attributes::normals: { x, y, z } per vertex.Attributes::texcoords: { u, v } per vertex.Attributes::colors: { r, g, b } per vertex.Both Lines and Points use an indices array of Index objects to reference vertex attributes:
Lines::num_line_vertices stores the number of vertices in each polyline (2 or more). Index::normal_index is always set to an invalid index (-1). Index::texcoord_index is optional (uses -1 if absent).Points::indices defines the points. Index::normal_index is always set to an invalid index (-1). Index::texcoord_index is optional (uses -1 if absent).A Mesh represents a polyhedral object. Its geometry is defined by two main arrays:
Mesh::indices: A flat array of Index objects. Each Index contains a position_index (mandatory), and optional texcoord_index and normal_index. If an optional attribute is not used, its index is set to -1.Mesh::num_face_vertices: An array storing the number of vertices for each face (ranging from 3 to 255). This allows the indices array to be flat while still supporting polygons like triangles, quads, or pentagons.Additionally, Mesh provides:
Mesh::material_ids: Indices into the Materials array for each face.Mesh::smoothing_group_ids: IDs used for normal interpolation.You can install rapidobj to your system directories using CMake. This allows you to use find_package in your own projects.
cmake -B build .cd build && sudo make installOnce installed, use find_package to link against the rapidobj::rapidobj target. Note that the header is placed in a rapidobj subfolder.
Note: When using the system installation, the include directive must be #include "rapidobj/rapidobj.hpp".
# Build and install
cmake -B build .
cd build
sudo make installadd_executable(my_app my_src.cpp)
find_package(RapidObj REQUIRED)
target_link_libraries(my_app PRIVATE rapidobj::rapidobj)// Required include path for system installation
#include "rapidobj/rapidobj.hpp"If you want to install rapidobj to a specific folder (e.g., in your home directory) instead of system directories, use the RAPIDOBJ_INCLUDE_DIR and RAPIDOBJ_CMAKE_DIR CMake cache variables.
cmake -B build -DRAPIDOBJ_INCLUDE_DIR=${HOME}/local/include -DRAPIDOBJ_CMAKE_DIR=${HOME}/local/cmake .sudo required):
cd build && make installSince the installation is in a non-standard location, you must provide a hint to find_package using the HINTS argument pointing to your custom CMake directory.
# Configure for local installation
cmake -B build -DRAPIDOBJ_INCLUDE_DIR=${HOME}/local/include -DRAPIDOBJ_CMAKE_DIR=${HOME}/local/cmake .
# Install
cd build
make installadd_executable(my_app my_src.cpp)
# Use HINTS to locate the custom installation
find_package(RapidObj REQUIRED HINTS $ENV{HOME}/local/cmake)
target_link_libraries(my_app PRIVATE rapidobj::rapidobj)The simplest way to use rapidobj is to copy the single-header file rapidobj.hpp into your project's include path.
libpthread. If using GCC 8, you must also link against libstdc++fs because std::filesystem is not part of libstdc++ until GCC 9.#include "rapidobj.hpp"# Example compilation with g++
g++ -std=c++17 my_src.cpp -pthread -o my_app
# For GCC 8 specifically:
g++ -std=c++17 my_src.cpp -pthread -lstdc++fs -o my_appYou can include rapidobj directly within your project structure without a system-wide installation. There are two primary methods:
thirdparty folder in your project root.add_subdirectory in your CMakeLists.txt.Use CMake's FetchContent module to automatically download and integrate rapidobj from its GitHub repository during the configuration step.
# Method 1: Manual subdirectory
add_executable(my_app my_src.cpp)
add_subdirectory(thirdparty/rapidobj)
target_link_libraries(my_app PRIVATE rapidobj::rapidobj)# Method 2: FetchContent
add_executable(my_app my_src.cpp)
include(FetchContent)
FetchContent_Declare(rapidobj
GIT_REPOSITORY https://github.com/guybrush77/rapidobj.git
GIT_TAG origin/master)
FetchContent_MakeAvailable(rapidobj)
target_link_libraries(my_app PRIVATE rapidobj::rapidobj)To calculate the total number of triangles in an .obj file, use rapidobj::ParseFile to load the data, followed by rapidobj::Triangulate to ensure all faces are converted to triangles. You can then iterate through the result.shapes and sum the size of shape.mesh.num_face_vertices to get the total triangle count.
#include "rapidobj/rapidobj.hpp"
#include <iostream>
int main()
{
rapidobj::Result result = rapidobj::ParseFile("/path/to/my.obj");
if (result.error) {
std::cout << result.error.code.message() << '\n';
return EXIT_FAILURE;
}
bool success = rapidobj::Triangulate(result);
if (!success) {
std::cout << result.error.code.message() << '\n';
return EXIT_FAILURE;
}
size_t num_triangles{};
for (const auto& shape : result.shapes) {
num_triangles += shape.mesh.num_face_vertices.size();
}
std::cout << "Shapes: " << result.shapes.size() << '\n';
std::cout << "Materials: " << result.materials.size() << '\n';
std::cout << "Triangles: " << num_triangles << '\n';
return EXIT_SUCCESS;
}