The shape picker is the modal for choosing a primitive or importing a model. It renders through a portal into document.body with a full-screen backdrop.
| Type | Label | Description |
|---|---|---|
| box | Box | A solid rectangular cuboid with flat faces |
| sphere | Sphere | A perfect round ball with smooth surface |
| cylinder | Cylinder | A tube shape with circular top and bottom |
| torus | Torus | A donut shape with a hole through the center |
| cone | Cone | A pointed shape tapering from a circular base |
| capsule | Capsule | A cylinder capped with hemispheres at both ends |
Each entry has a custom inline SVG icon on a 44x44 viewBox, defined in the same file.
Pressing Escape closes the picker. The handler is registered on window with no capture option, so a parent calling stopPropagation() would prevent it from firing.
ThreeDShapePreview creates a temporary ThreeDEngine in a small container, adds the selected primitive, disables orbit controls and runs a continuous camera orbit:
const animate = () => {
angleRef.current += 0.012;
const r = 4;
engine.setCameraPosition(
{ x: Math.sin(angleRef.current) * r, y: 1.5, z: Math.cos(angleRef.current) * r },
{ x: 0, y: 0, z: 0 }
);
engine.markDirty();
rafRef.current = requestAnimationFrame(animate);
};The camera orbits at a radius of 4 units and a fixed height of 1.5, at 0.012 radians per frame. When the geometryType prop changes, the engine is disposed and recreated with the new primitive.