mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-07 03:01:55 +00:00
New L3 crate over pdfcraft-prc: assemble places every product-tree tessellation into world space with its colours (pure `place` does the transform), Camera fits a view to the model, and render fills depth-buffered triangles with headlight or unlit shading into an RGBA image. Opaque triangles draw first, translucent ones blend over them; perspective views clip at a near plane. Never panics: MAX_RENDER_PIXELS and MAX_ASSEMBLED_TRIANGLES cap the work, every pixel and vertex index is checked, and damage returns RenderError. Single-threaded. Tests: 24 unit tests (two drive the product-tree placement path) plus an end-to-end one that builds a synthetic PRC stream in-test, renders it, and checks the background, the nearer triangle and the farther one by pixel; every truncation of that stream parses and assembles without panicking. Reverting the depth test or the placement transform fails the matching tests. Adapted from pdfcer (MIT, same author) at 912437c3, trimmed to the camera, raster and headlight parts and rewritten to the pdfcraft-prc types. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
pdfcraft-prc-render
A headless CPU renderer for PRC 3D models read by pdfcraft-prc: placed meshes in world space, a fitted camera, a
depth-buffered triangle fill and headlight shading, into a straight-RGBA image.
- Layer: L3. Depends on
pdfcraft-prconly. - Licence: MIT OR Apache-2.0.
#![forbid(unsafe_code)]. Never panics on input: image size, triangle count and every index are checked, and damage returnsRenderError.
API
assemble(&PrcFile) -> Result<Vec<WorldMesh>, RenderError> // every placement's mesh moved into the world and coloured
place(&TriangleMesh, &Matrix, colour, triangle_colours) -> WorldMesh
Camera::fit(&Bounds, direction, up, perspective, aspect) / Camera::fit_meshes(&[WorldMesh], ...)
render(&[WorldMesh], &Camera, &RenderOptions) -> Result<Image, RenderError>
- With no product tree, each tessellated mesh is drawn where it lies, in the default colour.
- A triangle's own colour wins over its mesh's, which wins over
RenderOptions::colour. - Opaque triangles are drawn first, then translucent ones blended over them; alpha 0 is not drawn.
Lighting::Headlight(default) shades by the angle to the view direction;Lighting::Unlitdraws flat colour.- Perspective triangles are clipped at a near plane; orthographic views are not clipped.
MAX_RENDER_PIXELS(2^24, about 16 MP) bounds the image: at most 64 MB of RGBA plus 128 MB of depth.MAX_ASSEMBLED_TRIANGLES(2^24) bounds oneassemblecall. Neither bounds time: a model of many large triangles at full size is a long CPU render, so callers on a UI thread should render small or off-thread.- Not yet: shadows, ambient occlusion, specular light, scene lights, textures, wires and markups.