[Feature]: express an off-centre hinge, so creased and folded subjects are buildable
Before submitting
- I searched existing issues and did not find a duplicate.
- I confirmed this preserves the code-only procedural reconstruction contract.
Problem to solve
The generator centres every mesh on its own pivot, so a component can only rotate about its own centre. A creased carton is the opposite case: each panel turns about an edge that is not its centre. There is no way to express an off-centre hinge in a spec today.
That blocks a whole class of subject — folding cartons, boxes with lids, doors, books, clamshells, anything die-cut and creased.
Concretely, rebuilding a printed folding carton with a spine fold, a cover fold and a two-crease tuck flap: the generated factory could not represent any of the three folds. The build fell back to hand-authored geometry for the entire object, and the 181 KB factory the generator emitted for it ended up dead code that nothing imports.
Minimal repro: author two box components joined along one edge, generate, and try to open
the fold. The only rotation available is about each panel's own centre, so the panels swing
through each other instead of opening about the shared crease.
Proposed outcome
A component can declare a hinge — an axis line in the parent's frame — and the generator
emits a pivot group on that line with the mesh offset inside it, so a single rotation
means the fold angle and a chain of hinges composes the way a real carton does.
"hinge": { "axisStart": [x, y, z], "axisEnd": [x, y, z], "restAngleDeg": 0 }The generator emits a Group at axisStart, oriented to the axis, with the component's
mesh translated by -axisStart inside it.
This needs no new dependency and downloads nothing — it is pivot placement in emitted code, so the code-only promise is untouched.
Reference examples or alternatives
Workaround, for anyone hitting this before it lands. Do not nest the folds. Place every folded part from an absolute angle each frame, walked along a shared cross-section polyline, so each part's world position is computed rather than accumulated through parents:
spine strip H -> H + T*u(alpha) alpha = 90 + phi/2
front panel S -> S + W*u(beta) beta = phi
flap wrap M -> M + T*u(gamma) gamma = beta - 90*(1-f)
flap F -> F + D*u(delta) delta = beta - 180*(1-f)A chain of nested rotations cannot be checked with a bounding box; absolute placement can. That matters because at least one fold sign is invisible at rest: taking a flap the long way round through delta = 90 drives it straight through the object, yet the closed and open poses are identical either way. Only a swept test catches it.
Nearest existing issues, neither of which covers pivot placement: #91 (attachment endpoints
turning non-limb parts into cylinders) and #108 (transform.scale discarding dimensions).
Source: img2threejs/img2threejs