Skip to content

Repository files navigation

nanoPRC

CI Badges

build python-wheels python-publish python-verify-testpypi python-verify-pypi

License

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.

Commercial Licensing

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.

Contributing

Building

Ensure all submodules are checked out:

git submodule update --init --recursive

Then, 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.

quick_start

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

Writing PRC files

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.

Diagnostic Environment-Variable Hooks

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=ON

Dumping Huffman code tables

One 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).

Deterministic Unzipped-Section Fuzzing

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=ON

Runtime 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 (default 512; lower = more mutations)
  • PRC_FUZZ_MAX_MUTATIONS: per-buffer mutation cap (default 64)
  • 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 (default prc_unzipped_fuzz.log)

Example:

PRC_FUZZ_SEED=12345 PRC_FUZZ_SECTION=model PRC_FUZZ_RATE=1024 PRC_FUZZ_MAX_MUTATIONS=32 ./your_app

The log records seed and per-buffer mutation events so failures can be reproduced exactly.

Versioning (AGPL Repository)

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.h with:
    • PRC_VERSION
    • PRC_GIT_DESCRIBE

If no matching tag is present, the fallback version is v0.1.0.

Release Process

Documentation

Generate API documentation locally with Doxygen:

doxygen Doxyfile

This writes HTML output to docs/doxygen/html.

For strict public API doc checks used in CI (parameter-doc focused):

doxygen Doxyfile.public

Warnings are written to docs/doxygen/warnings-public.log and fail the strict check when present.

About

AGPLv3 PRC parsing library and rendering demo

Topics

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages