3D Studio

Parametric 3D models from shapes, holes, arrays, and templates, with print checks and STL/3MF/OBJ/GLB/SVG export — built so the agent can design, measure, and verify models as well as people can.

What it does

3d-studio is an optional bundled module (React renderer, not installed by default) for simple, printable 3D objects. People build models Tinkercad-style from shapes and holes in the browser; the agent builds and edits the same models through model3d_* tools. Models are workspace-global: every signed-in user sees and edits every model (created_by / updated_by are attribution only).

  • Model list — searchable list with thumbnails, size, and date; new models start empty or from a template; the shared file context menu offers rename, copy, delete, share, downloads (STL, 3MF, OBJ, GLB, SVG), and "save to Dokumente" (3MF).
  • Editor — WebGL 2 viewport with the print bed and a 10 mm grid, translucent hole "ghosts", move/rotate/scale handles with snapping, box selection, perspective or orthographic views, and view presets (iso, top, bottom, front, back, left, right).
  • Inspector — object tree (hide, lock, hole badge), the selected object's fields (every numeric field accepts a number or a parameter expression such as width - 2 * wall), position, rotation, scale, mirror, colour, lock, and a dimension readout; with two objects selected it shows their gap or overlap. Without a selection it edits the model parameters and the printer build volume.
  • Print checks — live size, volume, PLA weight estimate, thinnest wall, and warnings: empty model, separate bodies, exceeds the build volume, holes that cut nothing, overhangs over 45°, walls thinner than 0.8 mm, parts thinner than 0.8 mm, missing text glyphs.
  • Import — STL, OBJ, and 3MF files become mesh objects (welded, checked for watertightness, centred); SVG files become extruded outlines (with holes) in one group.
  • Export — STL and 3MF for slicers (placed on the build plate: lowest point at z = 0, centred), OBJ, GLB (coloured, Y-up metres for viewers/AR), and SVG (top-view outline in mm for laser cutters). STL and 3MF can also be saved directly to Dokumente.
  • Agent prompt — an AI row above the viewport sends a request to the chat agent with the open model as page context; the floating and docked chat show 3D Studio quick actions (create a model, check printability, export as STL).

Dokumente previews STL and 3MF files with the same 3D viewer (web and, through /model3d-viewer, the iOS/macOS Documents screen).

Shapes and containers

TypeFields (mm unless noted)Notes
boxsize [x,y,z], radius or chamfer, edges vertical|top|alltop keeps a flat, sharp bottom
cylinderdiameter, height, top_diameter, fillet or chamfer, edges both|top|bottom, segmentstop_diameter: 0 is a cone
tubediameter, wall or inner_diameter, height
sphere, hemispherediameter (height for a squashed dome)hemisphere rests on its flat side
torusdiameter (centre line), tube_diameter
wedge, roof, half_cylinder, pyramid, heartsize [x,y,z]wedge: vertical face at −Y; roof and half cylinder run along X
prismsides, diameter or across_flats, heighta flat always faces −Y; across_flats sizes nut traps
paraboloiddiameter, height
starpoints, diameter, inner_diameter, height
polygonpoints [[x,y]…], holes, height, twist, top_scaleextruded along Z, centred on z = 0
revolvepoints [[r,z]…], anglerevolved around Z
texttext, size (capital height), height (depth), align, line_spacingbundled Noto Sans (Latin-1)
meshasset_idimported STL/OBJ/3MF
groupchildren, operation union|hull|intersection
arraychildren, count, step, count2, step2linear or grid copies
radial_arraychildren, count, anglecopies rotated around the container's Z axis

Every node has id, optional name, mode (solid/hole), position (centre of the shape's own bounding box; for polygon, revolve, and arrays the local origin), rotation (degrees, X then Y then Z), scale, mirror (["x"] …), color, hidden, and locked (editor-only). Holes subtract from the solids of the same container; a container marked as hole, or holding only holes, cuts its siblings. Z is up, units are millimetres.

Keyboard and mouse

"Mod" is ⌘ on macOS and Ctrl elsewhere; the in-app help (? or the keyboard button) lists everything.

KeysAction
Click / Shift- or Mod-clickselect / add or remove from the selection
Drag on empty space (Shift: add)box selection
Alt-clickselect a part inside a group
Right-drag, Alt+drag · Shift+right-drag, middle-drag · scrollorbit · pan · zoom
Mod+A, Escselect all, clear selection
Mod+Z, Mod+Shift+Z / Mod+Yundo, redo
Mod+C, Mod+X, Mod+Vcopy, cut, paste (clipboard works across models)
Mod+Dduplicate in place; pressing it again on the moved copy repeats the move (Tinkercad duplicate-and-repeat)
Delete / Backspacedelete (locked objects are kept)
Mod+G, Mod+Shift+Ggroup, ungroup
H, Smake hole, make solid
W, E, Rmove, rotate, scale handles
Arrow keys (Shift: ×10)nudge along X/Y by the snap step
Mod+↑/↓, PageUp/PageDownraise / lower along Z
Ddrop onto the build plate
L, Malign menu, mirror menu
Mod+Shift+H, Mod+Shift+Ahide, show all
Mod+Llock / unlock
F, Home, Ofit selection or model, home view, orthographic toggle
Mod+S, ?save now, shortcut help

Agent tools

model3d_list_models, model3d_list_templates, model3d_get_model, model3d_create_model, model3d_update_model, model3d_measure, model3d_render_image (vision), model3d_import_mesh, model3d_export_model, model3d_delete_model (approval-gated). The contracts are in Agent Tool Contracts. Design choices that make agent output reliable:

  • Structured document, no code execution — the agent edits the same JSON model as the editor; writes are validated and evaluated with the Manifold kernel before saving, and rejected with path-precise errors (nodes[2] (lid).size[0]: …) when anything is invalid. Nothing is saved on error.
  • Geometry-aware operations — place_on (put a part on a face of another), align (to the selection, the bed, or a node), drop_to_bed, center_on_bed, translate, duplicate with a step, group/ungroup, plus arrays and parameter expressions, so placement never depends on hand-computed coordinates.
  • Numeric feedback on every write — world bounding box of every node, metrics (size, volume, bodies, genus, overhang area, thinnest wall and its location), and warnings.
  • Measuring — model3d_measure returns boxes, gap/overlap per node pair, and the wall report.
  • Visual verification — model3d_render_image renders up to six views with a mm grid; highlight_node_ids tints parts, focus_node_id frames a close-up, and section cuts the model open (the kept half faces the iso camera by default).
  • Templates as worked examples — name tag, storage box, box with lid (with clearance), cable clip, wall hook (supports-free side profile), knob (radial grip array, D-shaft hole group), battery holder (grid array), spacer with nut trap (across_flats), and washer. Every template evaluates without warnings in CI.

The page capability rule tells the agent to start from templates, plan in millimetres with printable walls and clearances, place parts with operations, verify with measure and render for at most about three rounds, and export only on request. Outside the module, requests about 3D printing, STL/3MF, or 3D models route the model3d tool family (resolveRoutedToolBundles).

Storage and API

Module migration 001_create_3d_studio_schema.sql creates studio3d_models (title, document JSONB, metrics, thumbnail_png, revision, attribution) and studio3d_assets (imported meshes as float32 positions + uint32 indices). The handler re-applies the idempotent schema on first use. Core migration 340_3d_studio_module_default_off.sql keeps the module opt-in under the legacy_all install policy.

Module API (/api/modules/3d-studio/api, session or agent-system token):

  • GET models?q=&limit= — list; POST models — create {title, document, metrics?, thumbnail_png?}
  • GET|PATCH|DELETE models/:id — PATCH accepts base_revision and returns 409 with current_revision when the model changed meanwhile (the editor offers reload or overwrite)
  • POST models/:id/duplicate, GET thumbnail/:id
  • POST assets (positions_b64, indices_b64, name, format, size), GET assets?ids=, GET assets/:id

App routes:

  • POST /api/modules/3d-studio/export — {model_id | document, format: stl|3mf|obj|glb|svg, target: download|documents, folder_id?}
  • POST /api/modules/3d-studio/import — multipart file (STL/OBJ/3MF, up to 50 MB and 300,000 triangles) or {document_id}
  • GET /api/modules/3d-studio/manifold-wasm — the Manifold kernel for the editor (ETag revalidated)
  • GET /api/modules/3d-studio/font — the text glyph outlines for the editor (ETag revalidated)
  • POST /api/modules/3d-studio/evaluate — editor backend for the native apps: applies edits (the agent operations plus add_shape and paste), evaluates, optionally saves with metrics and thumbnail, and returns the document plus the mesh (base64 float32/uint32 with per-node runs), hole meshes, node boxes, metrics, and warnings
  • GET /api/modules/3d-studio/templates — template ids, default titles, and parameters
  • /model3d-viewer?document=&format=&title= — chromeless STL/3MF viewer for Apple Documents previews

Limits: 300 nodes, 8 container levels, 400 copies per array, 2,000 points per outline, 80 characters per text node, dimensions 0.01–2,000 mm, Dokumente exports up to 8 MB.

Implementation

  • Geometry, validation, operations, rendering, and file formats: src/lib/model3d/* (isomorphic except files.ts, service.ts, and manifold-server.ts). The editor evaluates in the browser with the same code the server and the agent tools use.
  • Editor UI: src/components/modules/studio3d-module.tsx and src/components/modules/studio3d/*.
  • Agent tools: src/lib/model3d/agent-tools.ts, wired through src/lib/agent-runtime/tool-proxy.ts and services/clapilot-agent/src/tool-definitions.mjs.
  • Viewer: a small purpose-built WebGL 2 renderer, orbit camera, and move/rotate/scale gizmo in src/lib/model3d/gl/* (used by the editor and the STL/3MF preview; no general 3D engine is bundled). SVG import parses outlines itself (src/lib/model3d/svg-outline.ts); STL/OBJ/3MF parsing is shared by the server and the browser (src/lib/model3d/mesh-parse.ts).
  • Dependencies: manifold-3d (Apache-2.0, WASM mesh kernel). Text uses Noto Sans (SIL OFL 1.1) glyph outlines stored in src/lib/model3d/fonts/; the server kernel loader imports them and the browser loads them from the font route with the kernel, so neither is part of the JS bundle.

iOS and macOS

The Apple clients have a native SwiftUI 3D Studio screen in the side menu (MainAppSection.studio3d, route /modules/3d-studio, shown only while the 3d-studio module is installed; Views/Studio3dView.swift and the Studio3d* files next to it). It never loads the web page. Geometry is evaluated by the server kernel through POST /api/modules/3d-studio/evaluate: the app keeps the model document as returned, sends every change as the same operations the web editor and the agent use (coalesced into one request while one is in flight), and each request re-evaluates and saves the model with the revision check. Undo and redo replay whole documents.

  • Model list — thumbnails, size, and date, with search; the + menu creates an empty model or one from a template. A long-press or right-click menu renames, duplicates, exports (STL, 3MF, OBJ, GLB, SVG via the save panel on macOS and the share sheet on iOS), saves STL/3MF to Dokumente, or deletes (with confirmation).
  • Viewport — RealityKit on iOS 18 / macOS 15 and later: flat-shaded parts in their colours, translucent holes, the bed with a 10 mm grid, and an accent box around the selection. Touch: one finger orbits, two fingers pan, pinch zooms, tap selects (the toolbar's multi-select switch makes taps add or remove), double-tap fits. Mouse and trackpad: drag orbits, Shift- or right-drag pans, scroll wheel, ⌘-scroll, or pinch zooms, click selects, Shift/⌘-click adds, Option-click picks a part inside a group, double-click fits. Picking uses the same camera math as the renderer.
  • Toolbar — add shapes (basic shapes, more shapes, hole), hole/solid, duplicate (duplicating the copy again repeats the offset, like Tinkercad), delete (locked objects are kept), group/ungroup, align (per axis, to the selection or the bed, centre on the bed), mirror, drop to bed, undo/redo, view presets and fit, export, import of STL/OBJ/3MF meshes, and the save state. The keyboard shortcuts of the web editor work on macOS and iPad keyboards (the help sheet lists them).
  • Inspector — print checks and warnings (tap a warning to select its object), the object tree with hide toggles, the selected object's fields (numbers or parameter expressions, per type as on the web), position, rotation, scale, mirror, colour, and lock; without a selection the model parameters and the build volume. It is a trailing column on macOS and iPad and a sheet on iPhone (opened from the toolbar or the selection chip).
  • Agent — the AI row below the viewport sends a request with the model as page context: into the docked chat on macOS and to the chat on iPhone. The docked chat shows 3D Studio quick actions (create a model, check printability, export as STL). Page context uses the web keys (studio3dModelId, studio3dSelectedNodeIds, …).
  • Links — /modules/3d-studio?model=<id> opens that model in the native editor.

The Documents screen previews STL/3MF files with the web viewer (/model3d-viewer).