Commit Graph
3 Commits
Author SHA1 Message Date
KenM76andClaude Opus 5.5 51b68a8b35 M12: prc-render: overflow-free projection and edges, shared near cuts, decode ceiling
- View::project divides by z (or the orthographic half-height) before it
  multiplies, so an on-screen corner no longer turns NaN when x times the
  focal length, or the half-height times the aspect ratio, overflows.
- View::clip cuts each edge from the same end whichever triangle meets it,
  so two triangles sharing an edge across the near plane get one cut point.
- Scene::draw takes each edge with vec3::span, which halves the
  difference when it overflows, so a finite triangle wider than f64::MAX
  keeps its face normal.
- assemble charges each file structure's meshes to the assembly ceilings
  as they are decoded, so decoding stops at the structure that passes one.

Tests, each shown failing with its fix reverted:
a_shared_edge_is_cut_at_the_same_point_from_either_triangle,
an_on_screen_triangle_is_drawn_when_projecting_it_would_overflow,
a_triangle_whose_edges_overflow_is_drawn,
span_keeps_the_direction_of_a_difference_that_overflows,
decoding_stops_at_the_structure_that_passes_the_ceiling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-04 05:12:00 -05:00
KenM76andClaude Opus 5.5 ce393b276b M12: prc-render review fixes (missing tessellations, vertex ceiling, seams, perspective shade)
- assemble: a placement naming a tessellation its file structure does not
  have is now PrcError::Malformed instead of a silently missing part;
  wires, markups and compressed tessellations are still skipped.
- assemble: positions, normals and texture coordinates are charged against
  a new MAX_ASSEMBLED_VERTICES (2^24) with RenderError::TooManyVertices, so
  a one-triangle mesh with many vertices placed many times cannot outgrow
  the triangle ceiling's memory bound. A refused mesh spends nothing.
- raster: a field of view too small for a finite focal length is a Camera
  error, not a background-only image.
- raster: a pixel centre exactly on an edge belongs to one triangle only
  (the side the triangle lies on, +x first, then +y), so translucent
  quads no longer blend their diagonal twice.
- raster: under a perspective camera the shade is interpolated with the
  1/z depth key, so it follows the surface rather than the screen.
- vec3: normalize divides by the largest component first, so a cross
  product above ~1e154 (or a subnormal one) still normalizes.
- render docs and README state the near plane: 1/10,000 of the
  eye-to-target distance.

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-03 21:41:05 -05:00
KenM76andClaude Opus 5.5 ea6d0c6bfb M12: pdfcraft-prc-render, a headless renderer for PRC models
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
2026-11-03 20:50:36 -05:00