Files
pdfcraft/crates/engine/src/model3d.rs
T
KenM76andClaude Opus 5.5 ae1b28cf1d M12: model3d_render, a 3D annotation's PRC model drawn to a PNG
pdfcraft-annot reads a page's 3D annotations and the model each shows:
the /3DD stream, or the stream a /3DRef names (at most four deep, so a
cycle ends), decoded within 256 MB and typed PRC or U3D by /Subtype.
pdfcraft-engine exposes both on Document.

The automation tool model3d_render picks a page's Nth 3D model, parses
PRC with pdfcraft-prc, assembles and frames it with pdfcraft-prc-render
from a chosen direction (default an isometric-style view, Z up), and
returns the image as a PNG. U3D gives an error until a decoder lands.
parity misc.3d-view moves to partial.

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

20 lines
887 B
Rust

//! The 3D models on a page (ISO 32000-2 §13.6), read so a renderer can draw them.
pub use pdfcraft_annot::{MAX_MODEL_BYTES, Model3d, Model3dKind};
use crate::Document;
impl Document {
/// The `/Annots` positions of the 3D annotations on 0-based `page`, in order.
pub fn model_3d_annotations(&self, page: usize) -> Result<Vec<usize>, String> {
let editor = self.editor.as_ref().ok_or("the document can't be read")?;
pdfcraft_annot::model_3d_annotations(&editor.cos, page).map_err(|e| e.to_string())
}
/// The decoded model of the 3D annotation at `/Annots` position `index` on 0-based `page`.
pub fn model_3d(&self, page: usize, index: usize) -> Result<Model3d, String> {
let editor = self.editor.as_ref().ok_or("the document can't be read")?;
pdfcraft_annot::model_3d(&editor.cos, page, index).map_err(|e| e.to_string())
}
}