A C++ application for loading, skinning, and saving 3D meshes using bone weights and pose data. This tool processes .obj
files with skinning information provided via JSON files, applies transformations using skeletal animation techniques, and outputs the result as a new .obj
file. Built with performance in mind, it leverages OpenMP for parallel processing and GLM for matrix operations.
- Loads 3D meshes from
.obj
files usingtinyobjloader
. - Applies skinning transformations based on bone weights, inverse bind poses, and new poses from JSON files.
- Supports up to 4 bone influences per vertex.
- Parallelized skinning with OpenMP for improved performance.
- Saves the skinned mesh to a new
.obj
file. - Includes error handling for file I/O and data consistency.
- tinyobjloader: Loads
.obj
files (v2.0.0rc13). - nlohmann/json: Parses JSON data (v3.11.3).
- glm: Handles vector and matrix math (v1.0.1).
- OpenMP: Enables parallel processing (requires compiler support, e.g.,
-fopenmp
for GCC/Clang).
- CMake 3.15 or higher
- A C++17-compatible compiler (e.g., GCC, Clang, MSVC)
- Git (for cloning and fetching dependencies)
- Clone the Repository
git clone https://github.com/<your-username>/skinned-mesh-processor.git cd skinned-mesh-processor
- Create a Build Directory
mkdir build
cd build
- Run CMake
cmake ..
-
Build the Project
- Linux/macOS:
make
- Windows (Visual Studio): Open the generated ``.sln` file in Visual Studio and build, or use:
cmake --build . --config Release
The executable will be placed in `build/bin/``.
Run the program with a folder containing the required input files:
./bin/ObjSkinning <folder_path>
Place these files in the specified <folder_path>
:
test_mesh.obj
: The input 3D mesh.bone_weight.json
: Bone indices and weights for each vertex.inverse_bind_pose.json
: Inverse bind pose matrices for each bone.new_pose.json
: New pose matrices for each bone.
The program generates <base_filename>_skinned.obj
(e.g., test_mesh_skinned.obj
) in the same folder and prints the execution time in microseconds.
./bin/ObjSkinning ./test
- Input:
data/test_mesh.obj
,data/bone_weight.json
, etc. - Output:
data/test_mesh_skinned.obj
- Multithreading: Initial attempts with
std::thread
were replaced with OpenMP, reducing overhead and improving execution time by a few milliseconds. - SIMD Potential: Intel SSE intrinsics (
immintrin.h
) showed promise but were excluded for portability. Future work could explore cross-platform SIMD. - Granularity: The skinning operation benefits from OpenMP’s lightweight parallelism but may not scale well with coarse thread pools.
skinned-mesh-processor/
├── src/
│ └── main.cpp # Core implementation
├── CMakeLists.txt # Build configuration
└── README.md # This file
Below is a comparison of the original and processed meshes:
Original Mesh | Processed Mesh |
---|---|
![]() |
![]() |