nanoPRC is licensed under the GNU Affero General Public License v3.0. See THIRD_PARTY_NOTICES.md for third-party attribution and license summaries. See https://nanoprc.org for more details.
For commercial integrations, closed-source desktop software, or embedded enterprise platform applications where AGPLv3 compliance is not viable, a proprietary B2B OEM Commercial License program is available. Please contact sales@cascadiavoxel.com for custom licensing terms and architecture verification bundles.
- Contribution guide: CONTRIBUTING.md
- Contributor legal terms and copyright assignment: CLA.md
Ensure all submodules are checked out:
git submodule update --init --recursiveThen, generate the build system using CMake:
mkdir build
cd build
cmake ..Finally, build the project with the generated build system. You may specify your desired build system by selecting a generator via the -G flag when running cmake. For example:
cmake -G "Visual Studio 16 2019" ..The build process in the case of windows is done by opening the solution file in the build directory and building the projects.
Executables are built to the bin directory and libraries to the lib directory from within the build directory.
In the case of Linux, your milage may vary. See https://wiki.libsdl.org/SDL3/README-linux#build-dependencies for the dependencies needed for the demo viewer and your flavor of Linux. The dependencies for just the library are very limited. You will need to make sure you have cmake installed. After the cmake .. command above, you will run make in the build directory to compile the code. The viewer has been succesfully built and run on WSL.
On macOS, the process is the same but you should not need to do anything special with SDL dependencies. You will need to make sure you have cmake and likely the xcode tools. After the cmake .. command above you will run make in the build directory. The viewer has been built and run on Intel and Apple silicon machines.
nanoPRC includes several source-code demonstrations that showcase how to use the core library.
| Location | Description |
|---|---|
| demos/quick_start | A simple example on how to open, parse, and make use of the PRC contents |
| demos/viewer | A basic 3D interactive viewer to display PRC models |
| demos/json_export | A utility to create a JSON dump from a PRC model |
| demos/stl_export | A utility to create binary STL mesh files from a PRC model |
| demos/obj_export | A utility to create OBJ files from a PRC model with MTL and textures |
| demos/teapot_write | A utility to generate a PRC file of the Utah teapot from 32 bicubic NURBS patches, demonstrating the write API below |
| demos/stl_import | A utility to import binary or ASCII STL mesh files into PRC/PDF, with vertex welding and automatic multi-part detection |
nanoPRC can also write PRC content, using only the public API in include/prc_api.h (see the "Write
facility" section of that header for the current, authoritative list of what is and isn't implemented).
prc_api_write_prc_file/prc_api_write_prc_buffer encode a product/part tree and tessellation data to
a PRC stream; prc_api_pdf_embed_prc embeds that stream in a minimal 3D-annotated PDF. Tessellation
can be written as uncompressed triangles, wire geometry, or the fully compressed format. Geometry is
always tessellated before writing -- PRC also supports writing exact NURBS/B-Rep surfaces directly, but
nanoPRC does not do that yet. Materials/colors/styles are not yet exposed through the write API either.
Various internal PRC_DIAG_*/PRC_TRACE_*/PRC_FUZZ_* environment variables gate development-only
tracing and behavior overrides used while debugging specific issues (see inline comments at each call
site in src//demos/stl_import/ for what an individual one does). By default these hooks don't exist
in the compiled binary at all -- not just inert, actually absent, so there's no runtime cost and no
discoverable/settable surface in a normal build. Enable them at configure time if you need to use one:
cmake -S . -B build -DPRC_ENABLE_DIAG_ENV=ONOne of these hooks is documented here rather than only in-source, because it answers a question about
the format itself rather than about a particular bug. Setting PRC_DIAG_HUFF_DUMP to a path makes the
decoder append, for every Huffman-coded array it reads, the producer's own stored code table together
with the symbol frequencies implied by the decoded array:
A <tag> <seq> <num_bits> <elem_size> <num_leaves> <max_code_length> <num_values>
L <leaf_value> <code_length> <code_value> <frequency>
PRC_DIAG_HUFF_TAG sets the label in the A record; the dump is appended, so a corpus can be swept
into one file by running per input with a per-input tag.
The stored table is otherwise unobservable — it is read, used to build the decoding tree, and freed —
and pairing it with the frequencies makes every array in a real file a labelled test case: these
frequencies produced this table. ISO 14739 §10.2 declares HuffmanTreeCalculation and never defines
it, so the tree an encoder is expected to build is not specified, and real files are the only evidence
available.
tests/internal/dump_huffman_tables drives this and reports a census of the results, including the
Kraft sum of the stored code lengths — the property that distinguishes a textbook-optimal tree (sum 1)
from the phantom-wrapped shape real PRC producers emit (sum exactly 1/2, one wasted leading bit).
For robustness testing of parser error paths, you can fuzz only the unzipped PRC section buffers
(schema_globals_unzipped, tree_unzipped, tessellation_unzipped, geometry_unzipped,
extra_geometry_unzipped, model_unzipped).
Enable the feature at configure time:
cmake -S . -B build -DPRC_ENABLE_UNZIPPED_FUZZ=ONRuntime controls (environment variables):
PRC_FUZZ_SEED: integer seed for deterministic replay (same input + same seed = same mutations)PRC_FUZZ_RATE: average mutation spacing in bytes (default512; lower = more mutations)PRC_FUZZ_MAX_MUTATIONS: per-buffer mutation cap (default64)PRC_FUZZ_SECTION: choose which section(s) to mutate. Options:schema,tree,tessellation,geometry,extra,model,all(default). Multiple values can be comma-separated.PRC_FUZZ_SECTION_MASK: optional numeric bitmask override (1=schema,2=tree,4=tessellation,8=geometry,16=extra,32=model)PRC_FUZZ_LOG: optional log path (defaultprc_unzipped_fuzz.log)
Example:
PRC_FUZZ_SEED=12345 PRC_FUZZ_SECTION=model PRC_FUZZ_RATE=1024 PRC_FUZZ_MAX_MUTATIONS=32 ./your_appThe log records seed and per-buffer mutation events so failures can be reproduced exactly.
This repository uses Git-tag-driven versioning:
- Create release tags in the format
vMAJOR.MINOR.PATCH(example:v1.4.0). - CI derives build metadata from
git describe --tags --dirty --always. - Local and CI CMake config generates
prc_version.hwith:PRC_VERSIONPRC_GIT_DESCRIBE
If no matching tag is present, the fallback version is v0.1.0.
- Checklist: RELEASE_CHECKLIST.md
- CI tag policy guard: .github/workflows/tag-policy.yaml
Generate API documentation locally with Doxygen:
doxygen DoxyfileThis writes HTML output to docs/doxygen/html.
For strict public API doc checks used in CI (parameter-doc focused):
doxygen Doxyfile.publicWarnings are written to docs/doxygen/warnings-public.log and fail the strict check when present.