Mesh, image, volume, and DICOM I/O library for the VertexNova ecosystem
vneio is a C++20 asset I/O library extracted from VertexNova core. It does not provide rendering, windowing, or GPU state — your application loads files and receives plain C++ structs (Mesh, Image, Volume, DicomSeries) ready for upload or further processing.
It is independent of vnescene, vnemath, and vneevents. vnelogging and vnecommon are required; they follow the same deps/internal layout as other VertexNova repos.
- Mesh —
AssimpLoaderwraps the Assimp import library. The default vendored Assimp build disables all importers by default and enables OBJ, STL, and PLY only (see rootCMakeLists.txtAssimp flags). FBX, glTF 2.0, Collada, and other formats require enabling additional Assimp importers or linking another Assimp build.AssimpLoaderOptions(assimp_loader.h) controls triangulation, normals/tangents, UV flip, winding, barycentrics, and normalization. OBJ export included. - Image —
StbImageLoaderand theImageclass wrap stb_image; supports PNG, JPG, BMP, TGA, HDR.Imageprovides resize, flip, and raw pixel access for GPU upload. - Volume —
NrrdLoaderandMhdLoaderimplementIVolumeLoaderusing Teem NrrdIO; loads 3D voxel data with full spatial metadata (dims, spacing, origin, direction matrix, pixel type). NRRD export and MHD export included. - DICOM —
vneioships theIDicomLoaderinterface andDicomSeriestype (Volume + metadata map). No GDCM/DCMTK or other DICOM decoder is built in-tree. UseAssetIO::registerDicomLoader()to register an externally provided backend if your project supplies one. - Unified registry —
AssetIOregisters any combination of loaders and routesLoadRequestby asset type and file extension. - Stable error model — Every call returns
LoadResult<T>withStatus(stableErrorCodeenum, message, path, subsystem). No exceptions. - Cross-platform — Linux, macOS, Windows; mobile and Web follow vnescene / vnemath toolchains where those targets are enabled.
System, class, component, and runtime pipeline diagrams live in Architecture & usage (sources under docs/vertexnova/io/diagrams/).
git submodule add https://github.com/vertexnova/vneio.git deps/vneio
# Ensure Assimp, stb_image, and NrrdIO are available (see deps/external/ layout).In your CMakeLists.txt:
add_subdirectory(deps/vneio)
target_link_libraries(your_target PRIVATE vne::io)
# Or selectively: vne::io::mesh, vne::io::imageinclude(FetchContent)
FetchContent_Declare(
vneio
GIT_REPOSITORY https://github.com/vertexnova/vneio.git
GIT_TAG main
)
set(VNEIO_BUILD_EXAMPLES OFF)
FetchContent_MakeAvailable(vneio)
target_link_libraries(your_target PRIVATE vne::io)git clone --recursive https://github.com/vertexnova/vneio.git
cd vneio
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build build
cmake --install buildgit clone --recursive https://github.com/vertexnova/vneio.git
cd vneio
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildFor local development (examples + tests enabled):
cmake -B build -DVNEIO_DEV=ON
cmake --build buildHelper scripts (Linux, macOS, Windows): see scripts/README.md.
| Option | Default | Description |
|---|---|---|
VNEIO_BUILD_MESH |
ON |
Build mesh component (requires Assimp) |
VNEIO_BUILD_IMAGE |
ON |
Build image + volume component (stb_image + NrrdIO) |
VNEIO_BUILD_TESTS |
OFF |
Build unit tests (GoogleTest) |
VNEIO_BUILD_EXAMPLES |
OFF |
Build headless example programs |
VNEIO_DEV |
ON (top-level) |
Dev preset: tests and examples ON |
VNEIO_CI |
OFF |
CI preset: tests ON, examples OFF |
VNEIO_LIB_TYPE |
static |
Library type: static or shared |
VNEIO_USE_STB_IMAGE_RESIZE |
OFF |
stb_image_resize for quality resize |
ENABLE_DOXYGEN |
OFF |
Build API documentation (Doxygen) |
ENABLE_COVERAGE |
OFF |
Enable code coverage reporting |
ENABLE_ASAN |
OFF |
AddressSanitizer + UBSan (GCC/Clang, Linux/macOS) |
Default is static (VNEIO_LIB_TYPE=static). Use shared for a separate dylib/DLL. In static mode, vnelogging is embedded in the archive when the submodule is present.
#include <vertexnova/io/vneio.h>
vne::io::AssetIO io;
io.registerMeshLoader(std::make_unique<vne::mesh::AssimpLoader>());
auto result = io.loadMesh(vne::io::LoadRequest{vne::io::AssetType::eMesh, "model.obj"});
if (result.ok()) {
// result.value: mesh.vertices, mesh.indices, mesh.parts, mesh.materials
}With loader options:
vne::mesh::AssimpLoaderOptions opts;
opts.generate_barycentrics = true;
io.registerMeshLoader(std::make_unique<vne::mesh::AssimpLoader>(opts));#include <vertexnova/io/image/image.h>
vne::image::Image img("texture.png");
if (!img.isEmpty()) {
int w = img.getWidth(), h = img.getHeight();
const uint8_t* data = img.getData(); // ready for GPU upload
}#include <vertexnova/io/image/nrrd_loader.h>
vne::image::NrrdLoader loader;
auto result = loader.loadVolume(vne::io::LoadRequest{vne::io::AssetType::eVolume, "scan.nrrd"});
if (result.ok()) {
const auto& vol = result.value;
float voxel = vol.readVoxelAt<float>(x, y, z);
}#include <vertexnova/io/vneio.h>
vne::io::AssetIO io;
io.registerMeshLoader(std::make_unique<vne::mesh::AssimpLoader>());
io.registerImageLoader(std::make_unique<vne::image::StbImageLoader>());
io.registerVolumeLoader(std::make_unique<vne::image::NrrdLoader>());
auto mesh = io.loadMesh(vne::io::LoadRequest{vne::io::AssetType::eMesh, "robot.glb"});
auto image = io.loadImage(vne::io::LoadRequest{vne::io::AssetType::eImage, "albedo.png"});See examples/01_library_info for format and capability listing, and examples/README.md for the full numbered index.
All examples are headless (no window or GPU required). Each folder has its own main.cpp and a shared header.
| Example | Description |
|---|---|
| 01_library_info | Enumerate supported formats, pixel types, and error codes |
| 02_image_loading | Load, inspect, resize, and save 2D images |
| 03_volume_loading | Load NRRD/MHD volumes and inspect metadata |
| 04_volume_export | Save volumes to NRRD and MHD formats |
| 05_mesh_loading | Load meshes, inspect geometry, export OBJ, round-trip |
| 06_asset_registry | Multi-loader AssetIO registry pattern |
| 07_performance | Benchmarking load times across formats |
Build examples with:
cmake -B build -DVNEIO_BUILD_EXAMPLES=ON
cmake --build build- Architecture & usage — Module design, diagrams, integration, and build configuration.
- API documentation — Doxygen template and how to generate HTML; optional
doc_doxygentarget whenenable_doxygen()is wired (seedocs/README.md). - CONTRIBUTING.md — Contribution guidelines.
- CODING_GUIDELINES.md — Project conventions (aligned with other VertexNova libraries).
Each tagged release publishes install trees as vneio-v{VERSION}-{platform}.tar.gz.
platform |
Contents |
|---|---|
linux-gcc |
Shared library, headers, LICENSE, CHANGELOG |
macos |
Shared library, headers, LICENSE, CHANGELOG |
windows |
Shared library / DLL, headers, LICENSE, CHANGELOG |
web-emscripten |
Emscripten build (mesh disabled in CI/release) |
ios-static |
Static .a, headers, LICENSE, CHANGELOG (arm64) |
| Platform | Status | Notes |
|---|---|---|
| Linux | Supported | GCC 10+, Clang 10+ |
| macOS | Supported | Xcode 12+, Apple Clang |
| Windows | Supported | MSVC 2019+, MinGW |
| iOS / visionOS | Supported | Via vnescene / vnemath toolchain |
| Android / Web | Experimental | Via vnescene / vnemath |
- C++20
- CMake 3.16+
- Compiler: GCC 10+, Clang 10+, MSVC 2019+
- Assimp (mesh component; submodule or system install)
- NrrdIO (image/volume component; submodule or system install)
- stb_image (image component; auto-fetched if absent)
- Google Test (tests; vendored via
deps/external/googletest) - vnecommon (common utilities and shared infrastructure)
- vnelogging (logging utilities)
See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and CODING_GUIDELINES.md. PRs use .github/PULL_REQUEST_TEMPLATE.md; releases and changelog are driven by release-please (Conventional Commits).
Apache License 2.0 — see LICENSE for details.
Part of the VertexNova project