@nfcard/card3d
v0.1.0
Published
Real-time 3D card render core for NFCard (plain Three.js) — shared by the web 3D preview and the print-station kiosk.
Downloads
53
Readme
@nfcard/card3d
The real-time 3D card render core, as plain Three.js (no React). Hand it a
canvas and a CardDesign; it owns the renderer, camera, lighting (IBL), the
perforated card mesh, PBR materials + procedural relief, and the content decal
(text / wordmark / QR / logo).
It is shared, unforked, between two front-ends:
- nfcard-web — the React
Card3DViewwrapper (stays in the web app) mounts this core for the in-configurator 3D preview. - nfcard-station — the Tauri print kiosk calls
buildCardScenedirectly from vanilla TS for an always-on high-tier preview (NFCARD-229 / T3).
Hole geometry is not duplicated here — it comes from
@nfcard/pattern-engine, the same engine the 2D
configurator uses.
Public API
import { buildCardScene, detectTier } from '@nfcard/card3d'
const tier = detectTier() // 'low' | 'mid' | 'high' (+ QualityProfile)
const scene = buildCardScene(canvas, design, { profile: tier })
// scene: CardSceneController — { update(design), resize(), dispose(), ... }| Export | Purpose |
| --- | --- |
| buildCardScene(canvas, design, opts) → CardSceneController | Full scene: renderer + camera + lights + render loop |
| buildCardMesh / disposeCardMesh | The perforated card mesh on its own |
| buildCardMaterial, reliefFromCardgen | Per-material PBR + relief |
| buildFieldReliefTexture | Procedural decorative relief → normal map |
| buildContentDecal | Text / wordmark / QR / logo onto the face |
| detectTier, isMobile | Device capability → quality profile |
| SAMPLE_CARD_DESIGN, DENSE_CARD_DESIGN, CONTENT_CARD_DESIGN | Demo fixtures |
three is a peer dependency (>=0.176) so the host app owns the single
Three.js instance — install it alongside this package.
Render parity
This is the preview renderer (the TS pattern engine). Manufacturing geometry
comes from cardgen (Python). The two are intentionally distinct — the
relationship gated by NFCARD-172 — so a 3D preview is representative, not a
manufacturing source of truth.
Build
pnpm build # tsup → dist/index.js (ESM, three/qrcode external) + dist/index.d.ts