A 3D parsing library with minimal dependencie. Currently supports the following formats:
I/O for multiple formats:
use pars3d;
let scene: pars3d::Scene = load("my_mesh.fbx").expect("Failed to load");
...
pars3d::save("new_mesh.fbx", scene).expect("Failed to save");
I/O for specific formats (varies per format):
use pars3d::fbx;
let fbx_scene = fbx::parser::load("my_mesh.fbx").expect("Failed to load");
...
let mut out = std::fs::File::create("new_mesh.fbx");
fbx::export::export_fbx(fbx_scene, std::io::BufWriter::new(out)).expect("Failed to save");
- .obj
- .glb (with
feature = "gltf"
, binary only) - .fbx (experimental export, binary only)
- .stl
- .ply
- .off
obj | glb | fbx | off | stl | ply | |
---|---|---|---|---|---|---|
import | Y | Y | Y | Y | Y | Y |
export | Y | Y | In progress | Y | Y | Y |
Unified Repr | Y | Y | Y | Y | Y | Y |
Unified Repr indicates that there is a single struct which can be used to interchange between each format.
Secondary formats are considered less important for maintenance.
If you want another format supported, please feel free to file an issue and I'll do my best to add it.
In addition to parsing 3D file formats, there is minimal support for visualization with vertex colors. This can be used to output PLY files with per edge colors.
Each file format has its own struct
which represents the data supported by that specific file
type. These structs are then unifiable into a single generic mesh representation.
Inspired by Assimp!
Unlike Assimp, each file format has its own representation, which can then be converted into a unified representation:
- On Import
File -> Tokenization/Parser -> Per Format Struct -> Unified
- On Export
Unified -> Per Format Struct -> Parser/Tokenization -> File
This is in contrast to Assimp, which instead has:
- On Import
File -> Tokenization/Parser -> Unified
- On Export
Unified -> Parser/Tokenization -> File
What I've noticed is that because there is no per format struct, it is difficult to maintain metadata which varies between each representation. It is also more difficult to distinguish bugs in the exporter itself and misrepresentations in the struct. By separating out each format, it makes it more clear what can be exported. This is also because it is much easier to make an importer and exporter for a single file format. This was inspired by intermediate representations (IRs) in compilers which allow for performing certain tasks more easily.
The one downside is that now there is more code to maintain. I believe this trade-off is worth it though.
This library may allocate more than necessary when deserializing. For many applications, deserialization is the final step, but if I/O is done in a long-living process this may be slower than necessary.
For FBX parsing, my philosophy is if there's something I didn't expect it should crash. Immediately. This is great for figuring out exactly what is wrong, but if your input FBX file doesn't fit what is expected it will not work at all. Better than silently being wrong though.
I started this library primarily for parsing 3D models for geometry processing. Initially, it started just for parsing OBJ files (one of the main formats used in research), but found that a lot of meshes I wanted to parse where in other formats, specifically FBX. Originally, I could not be arsed to make an FBX parser, and since Sketchfab also provided a GLTF export, I downloaded the models as GLTF files. For most models this is fine, but I realized thatthe GLTF format has a number of shortcomings for geometry processing, so I bit the bullet and started an FBX importer/exporter. I also added PLY because I wanted to be able to visualize values on edges/faces/vertices, and PLY has great support for vertex colors.
Assimp - C, I/O for FBX is a bit buggy, more feature complete than this library fbxcel - Rust, requires deep knowledge of the FBX file format, deprecated