Files
pdfcraft/crates/prc-render/README.md
T
KenM76andClaude Opus 5.5 c336c59cfb M12: prc-render: scale-safe lengths, a render work ceiling, fit fixes
- vec3: length divides by the largest component before squaring, so
  a camera 1e200 away keeps a finite near plane; unit_cross normalizes
  each edge first, so edges of very different sizes keep their normal.
- render: MAX_RENDER_WORK (2^31) caps the pixel centres one render
  tests, charged per triangle's clipped bounding box before scanning;
  past it, RenderError::TooMuchWork.
- Bounds::centre halves each end before adding, finite for any finite
  box. Bounds::of and fit_meshes use only corners of triangles render
  draws. Camera::frame builds its basis from the direction, not from
  points near the model, so a small model far from the origin fits.

Each new test fails with its fix reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-04 00:03:28 -05:00

30 lines
1.9 KiB
Markdown

# 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-prc` only.
- **Licence:** MIT OR Apache-2.0.
- `#![forbid(unsafe_code)]`. Never panics on input: image size, triangle count and every index are checked, and
damage returns `RenderError`.
## API
```rust
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::Unlit` draws flat colour.
- Perspective triangles are clipped at a near plane 1/10,000 of the eye-to-target distance from the eye; 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` and `MAX_ASSEMBLED_VERTICES` (2^24 each) bound one `assemble` call. `MAX_RENDER_WORK` (2^31) bounds
the pixel centres one `render` tests, summed over each triangle's clipped bounding box; past it the render returns
`RenderError::TooMuchWork`. That is still seconds of CPU at the top, 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.