Quick start
- Orbit: RMB-drag • Pan: LMB-drag empty space • Zoom: wheel (Ctrl = finer)
- Focus camera: F focuses selected vertices/edge endpoints; if nothing is selected, it focuses world origin. Shift+F always focuses origin.
- Align selection: Shift+A centers the selected bounding box on world X/Z origin and places its bottom on ground
y = 0. - Select: LMB short-click vertex/edge/filled face toggles it on/off. LMB click empty space = clear.
- Lasso (additive): hold Ctrl=verts / Alt=edges / Ctrl+Alt=both, then LMB-drag → release LMB.
- Move selection: start LMB-drag on selected geometry (moves on the dominant plane).
- Tools: Line C • Rotate R • Scale V • Revolve L • Bend S • Circle/Arc O • Bevel B • Face Ctrl+F
- Undo: Backspace • Redo: Shift+Backspace
- History/memory/performance panel: Tab toggles the hidden panel in the web build with scene size, undo/redo counts, estimated history memory, history-cap controls, FPS target controls, and live performance counters. In the native build, Tab prints the same summary/status information to the console.
- Target FPS: in the web build, use the Tab panel slider/number field. In the native build, use F6/F7 to lower/raise target FPS by 10, or Shift+F6/Shift+F7 by 1.
- Faces and visibility: Ctrl+F creates a filled face from 3 or 4 selected vertices. Use
Faces ON/OFF,Wire ON/OFF,Light ON/OFF, andNormals ON/OFFto inspect surfaces. - Orbit wire: use the
Orbit Wire ON/OFFtoolbar button to choose whether dense wire/marker overlays stay visible during RMB orbit.OFFhides the wire only while orbiting and restores it afterward. - HUD: top-left DOM text shows dominant plane and last vertex; tool instructions appear as bottom-left DOM helper hints.
Cancel / revert: RMB cancels an active drag/pan/tool interaction and restores the previous state. (Tools also usually cancel with Esc.)
Ortho “peek orbit”: in ortho, RMB-drag orbits temporarily; releasing RMB snaps back to the ortho-aligned view.
Controls
Mouse
- Orbit: RMB-drag
- Pan: LMB-drag empty space
- Zoom: wheel (Ctrl = finer; perspective changes distance, ortho changes zoom size)
- Select: LMB short-click toggles vertex/edge/filled face on/off; empty click clears
- Move: LMB-drag starting on selected geometry or a selected face (after a few pixels)
- Lasso: Ctrl/Alt/Ctrl+Alt + LMB-drag, release to finish; RMB cancels
Core keys
- V: Scale tool (when a selection exists) • otherwise overlay cycle: Off → Thin → Thick → Off
Orbit Wire ON/OFFtoolbar button: keeps dense wire/marker overlay visible during orbit, or hides it only while orbiting for better GPU performance. This does not change the normal overlay mode after orbit ends. In the native build, use Ctrl+Shift+W.- Native FPS shortcuts: F6/F7 target FPS −/+10; Shift+F6/Shift+F7 target FPS −/+1.
- 9/0 grid spacing −/+ (min 0.1); a small DOM status appears briefly after changing it
- F focus camera on selected geometry; if nothing is selected, focus world origin
- Shift+F focus camera on world origin
(0,0,0) - Shift+A align selected geometry: center X/Z on origin and put the lowest selected point on ground
- D duplicate exact selection (selected vertices + selected edges; selected edges duplicate their endpoints)
- Ctrl+F create a filled face from selected 3/4 vertices; Ctrl+Shift+F flips selected/last face winding
- Ctrl+Delete deletes selected/last faces; Ctrl+Shift+Delete clears all faces in the current object
- Delete delete selection • if nothing selected: clear all
- Space toggle ground clamp (blocks downward moves below
y = 0); a small DOM status appears briefly after toggling it
MMB select-all variants
- MMB all vertices + all edges
- Ctrl+MMB vertices only
- Shift+MMB edges only
Camera focus
- F focuses the camera on the current selection.
- If vertices are selected, the focus point is the center of their world-space bounding box.
- If edges are selected, their endpoints are included automatically.
- If nothing is selected, F focuses world origin
(0,0,0). - Shift+F always focuses world origin, even when geometry is selected.
- Perspective view adjusts camera distance to frame the selection; orthographic view adjusts zoom size.
Useful after zooming or editing dense areas: select a vertex/edge and press F to re-center the view without changing the model.
HUD, helper hints & panels
- Top-left DOM HUD: always shows the current dominant move plane and last clicked/created vertex. Axis names are color-coded: X, Y, Z.
- Temporary DOM messages: after 9/0, grid spacing appears briefly; after Space, ground-clamp state appears briefly.
- Bottom-left DOM helper hint: active tools show instruction/status text here, above the legal footer. It is used for long helper text that does not need to be anchored to geometry.
- WebGPU measurement labels: short numeric labels that belong to model geometry remain in the viewport, such as edge lengths, move distances, circle diameters, and bevel offsets.
- History / Memory / Performance panel: in the web build, press Tab to show or hide it. Buttons in the panel can switch between Manual 256 and Adaptive history caps or trim history immediately. The same panel also shows live performance counters such as FPS, target FPS, redraws, render passes, draw calls, vertices drawn, GPU uploads, mesh size, and overlay buffer size. In the native build, Tab prints a compact status/performance summary to the console.
Align selection to origin + ground
- Shift+A moves the current selection so its world-space bounding-box center is on
X = 0andZ = 0. - The same command also places the lowest selected point on the ground plane,
Y = 0. - Selected edges are handled through their endpoint vertices, the same as focus and move commands.
- The operation is undoable with Backspace.
Object-placement helper: this is not camera focus. It physically moves the selected geometry.
Move & snapping
Dominant plane
- Moves (drag + nudges) are constrained to a plane chosen from camera direction:
- XY if view is mostly along ±Z • XZ if mostly along ±Y • YZ if mostly along ±X
- The DOM HUD shows the dominant plane continuously; it updates only when the camera plane changes.
Drag snapping
- No modifiers: fine stable micro-step
- Shift: snap to 1.0 units
- Ctrl+Shift: snap to current grid spacing
Vertex snap & weld
- While dragging: near a non-selected vertex, movement can snap so the dragged anchor aligns.
- If you move a single vertex and release exactly onto another vertex position, it auto-welds (merges).
Nudging
- Arrows: nudge on dominant plane
- Shift+Arrows: nudge by 1.0
- Ctrl+Shift+Arrows: nudge by grid spacing
- Ctrl+Arrows: fine nudge
Tools
Line tool — create & divide (C)
- Anchors: selected vertices become anchors; else uses hovered vertex; else
(0,0,0)in current object. - Preview endpoint: computed on dominant plane; snaps to vertices / axes / grid.
- Commit: LMB click (press+release without dragging).
- Single-anchor chain: after a click, anchor moves to last endpoint (polyline drawing).
- Segments (creation): 1/2 −/+ segments; Shift = ±5; Shift+Ctrl = ±10. Press L to type an exact segment count (1–4096 while creating; 2–4096 while dividing), then Enter to leave segment entry.
- Typed length: while previewing a new line, type digits and
.to lock the line length; Backspace edits the length input. - Degree constraint: press D, click a nearby vertex/edge to choose the reference direction, then type degrees. The preview chooses the +/− side nearest the cursor; press D again to clear degree mode.
- Multi-line mode (multi-anchor): press C again to toggle Star ↔ Parallel.
- Mirror (single-anchor): M toggle mirrored line creation.
- Snapping modifiers inside Line: none=fine • Ctrl=1.0 steps • Shift=grid spacing.
- Edit vertices while active: LMB-drag a nearby vertex to move on dominant plane (mirrors if counterpart exists at exact mirrored position). Release to commit; Esc cancels.
- Divide selected edges: select edges → 1/2 enters divide preview with
n ≥ 2→ adjust with 1/2 or typed count via L → Enter or LMB click empty space applies → Esc/RMB click cancels. - Esc exits Line tool (also reverts vertex-edit preview).
Rotate tool (R)
- Requires a valid selection (typically ≥2 vertices, or any selected edges). Pivot starts at selected-vertex centroid.
- Stage 1 (pivot): LMB-drag pivot on dominant plane; snaps to nearby vertices; RMB cancels pivot drag; O snaps pivot to world origin; press R again for Stage 2.
- Stage 2 (axis + angle): X/Y/Z choose world axis. Type degrees (supports
/and*, e.g.360/8). Backspace edits typed angle (not undo). Enter apply; Esc cancel.
While Rotate is active (Stage 2), Backspace edits the angle input, so undo/redo resumes normally only after apply/cancel.
Scale tool — scale around a pivot (V)
- Requires: a valid selection (≥1 vertex). Pivot starts at the selected-vertex centroid in world space.
- Stage 1 (pivot): LMB-drag the pivot gizmo on the dominant plane. Pivot snaps to nearby vertices (within a few pixels); hold Shift to snap pivot to the world grid on the dominant plane. O snaps pivot to world origin. Press V again to enter Stage 2. Esc / RMB click (no drag) cancels.
- RMB while pivot-dragging cancels the pivot drag and restores the pivot to where the drag started (without exiting the tool).
- Stage 2 (scale %): type a percentage (e.g.
50= half size,200= double). Backspace edits the typed number. R resets preview to100%. - Interactive scaling: LMB-drag horizontally to scale. Hold Ctrl for fine control. Hold Shift to snap to 5% steps.
- Apply / exit: Enter or release LMB. Cancel: Esc / RMB click (no drag) / V (in Stage 2).
- Scaling is computed in world space around the pivot, then each vertex is transformed back into its owning object’s local space. Scale instructions/status are shown in the bottom-left DOM helper hint.
Revolve / lathe (L)
- Requires ≥1 selected vertex and selection must be within a single object.
- Defaults: pivot = selection centroid; axis = perpendicular to dominant plane (XY→Z, XZ→Y, YZ→X).
- [/] steps −/+ (Shift=±5, Shift+Ctrl=±10)
- -/= angle −/+ (1° default; Ctrl=5°; Shift=15°)
- X/Y/Z snap axis to world X/Y/Z
- M seam closed/open (wrap only for full 360°; partial turns add an end ring and don’t wrap)
- H toggle ring edges (connect rings along sweep)
- P toggle profile edge copying (edges among selected vertices; uses loose edges whose endpoints are selected)
- K snap pivot to vertex under cursor • E snap pivot to closest point on edge under cursor + set axis from that edge
- Enter apply (selects newly created vertices) • Esc cancel
- Revolve/lathe status and invalid-selection warnings are shown in the bottom-left DOM helper hint.
Bend tool (S)
- Bends a single loose edge into a curved chain (replaces it with multiple segments).
- Edge selection: select exactly one loose edge (recommended). Endpoints must be in the same object.
- Start / cycle modes: press S to start; press S again to cycle: Quad-handle → Quad-mid → Cubic → Arc → exit.
- Shape: move the mouse to position the control/bulge point on the dominant plane; it can snap to vertices or closest points on edges (same object).
- Segments: type digits to set segments (
0–1024); Backspace edits. (0effectively cancels on apply.) - Apply: LMB click (press+release without dragging) • Cancel: RMB click or Esc
- Modifiers:
- Ctrl: angle-lock in 45° steps (in-plane) for Quad, Cubic, and midpoint-bulge shaping.
- Cubic: press Shift to toggle the active cubic handle (H1/H2).
- Arc: D toggle diameter entry (digits +
.), M toggle major arc, Shift flips side.
- While Bend is active, normal left-click selection is suppressed (mouse is for shaping/committing). Bend mode and parameter status are shown in the bottom-left DOM helper hint.
Circle / Arc tool — create circles & arcs (O)
- Cycle: press O to cycle Circle → Oval → Off.
- Anchor:
- If you have selected vertices: anchor = their centroid (and the new geometry is created in that object).
- If exactly one vertex is selected: anchor = that vertex position (also used to choose the object).
- If nothing is selected: anchor = point under the cursor on the ground plane (
y = 0) when available, otherwise camera target fallback; current object is used.
- Preview target (where the mouse points): snaps to vertices/edges of the same object (within a few pixels). If nothing is close, it falls back to a point on the view plane through the anchor.
- Base radius from mouse: derived from distance anchor→target, with snapping:
- No modifiers: fine steps
- Ctrl: 1.0 steps
- Shift: snap to current grid spacing
- Typed diameter: type digits and
.to set a fixed diameter while the tool is active; Backspace edits the typed value. - Circle vs oval:
- Circle mode: major and minor radii stay equal.
- Oval mode: major and minor radii can differ.
- Editing with the mouse:
- LMB-drag an axis line to scale that axis.
- LMB-drag an axis end to rotate the frame.
- LMB-drag empty space to pan the camera (after a small threshold).
- RMB-drag orbits; in ortho it becomes the momentary “peek orbit” and snaps back on release.
- Keyboard size adjustment:
- ArrowUp/ArrowDown: adjust major radius
- ArrowLeft/ArrowRight: adjust minor radius in Oval mode
- Displayed diameter change per arrow press: none = 0.001, Ctrl = 0.01, Shift = 0.1, Ctrl+Shift = 1.0
- Segments: press S to toggle segment editing; type digits (3–4096). While segment-edit is active, Backspace edits the segment input.
- Arc modes: press A to cycle
OFF → Normal → Inverse → Centerline → OFF.
- When arc mode is ON: type degrees (0–360) to set arc angle; Backspace edits the arc input.
- Normal: sweeps forward from the start direction.
- Inverse: sweeps backward (negative sweep).
- Centerline: arc is centered around the start direction (symmetric).
- 360° behaves like a full closed circle.
- Roll axis (orientation): X/Y/Z toggles the roll reference axis; pressing the same key again returns to Auto. This stabilizes “which way is up” around the radius direction.
- Ground clamp interaction: if Space ground clamp is enabled, circles/arcs are constrained to stay above
y = 0. - Commit: Enter.
- Cancel: RMB click (no drag), Esc, or continue cycling with O until the tool turns off.
- The bottom-left DOM helper hint shows current mode (CIRCLE/OVAL), diameter/arc/segment controls, and roll-axis instructions. Short numeric
du/dvlabels remain anchored in the viewport.
Bevel / chamfer vertices (B)
- Purpose: chamfers selected vertices by cutting back along each connected loose edge (same object), then connecting the cut points around the corner (a closed loop for 3+ incident edges; a single segment for 2-edge corners).
- Start: select one or more vertices, then press B to enter Bevel preview.
- Adjust amount: move the mouse — the bevel distance
tincreases with cursor distance from where you started the tool. - Snapping while adjusting:
- No modifiers: very fine steps
- Alt: snap to
0.001units - Ctrl: snap to
0.1units
- Limits:
tis clamped so cuts don’t pass a neighboring vertex; if two selected corners share an edge, their cuts can meet at the midpoint. - Apply: LMB click or Enter
- Cancel: RMB, Esc, or press B again
- Notes: corners with fewer than 2 same-object edge neighbors are ignored. A small numeric label near the first corner shows the current
t.
Orthographic views & reference pictures
- Shift+O toggle Perspective ↔ Ortho Front
- In ortho: X=Right • Shift+X=Left • Y=Top • Z=Front • Shift+Z=Back
- Drop an image file onto the window/canvas to load a semi-transparent reference picture for the current ortho view. If you are already in ortho, it loads immediately; if you are in perspective, it is queued and loads after you switch to an ortho view.
- Ctrl+B lock/unlock picture to world space:
- Unlocked: screen-space quad (by default, newly loaded images are reset to fill the viewport)
- Locked: corners pinned in world space (stays anchored as you pan/zoom)
- Unlocking after being locked keeps the current on-screen quad shape/placement (it doesn’t automatically re-fill the viewport).
- Key sharing: if Rotate/Revolve/Circle is active, X/Y/Z control the tool (axis/roll) instead of view switching.
- Tip: Circle uses O (no Shift). Ortho toggle uses Shift+O.
Undo/redo & macros
- Most edits (move/delete/duplicate/create line/rotate/revolve/bend/circle/import/etc.) are recorded as commands.
- Backspace undo • Redo: Shift+Backspace
- Tab toggles the hidden History / Memory / Performance panel in the web build. In the native build, Tab prints the status summary to the console. The panel/status includes vertex count, edge count, undo stack size, redo stack size, estimated retained history memory, current cap mode, effective undo cap, target FPS, and live performance counters.
- Panel buttons:
Manual 256keeps the original fixed cap,Adaptivelowers the cap as the scene grows, andTrim nowimmediately trims old undo entries to the current effective cap. - History cap: Manual mode keeps up to 256 undo commands. Adaptive mode keeps 256 under 10k vertices, 64 over 10k, 32 over 50k, and 16 over 100k.
Performance counters in the Tab panel
- The web panel includes a Performance section that updates about once per second; the native build exposes comparable status through the console summary and FPS shortcut feedback.
- Counters include FPS, orbit/normal frames, mouse moves, redraw requests, screen-cache rebuilds, render passes, draw calls, vertices drawn, GPU buffer uploads, upload bandwidth, mesh vertices/edges, and current GPU buffer vertex counts.
- Use these numbers to compare overlay modes. Dense STL wire overlays can add many marker vertices;
Orbit Wire OFFcan reduce orbit GPU work by hiding that dense wire only during orbit.
Macro recorder
- F8 start/stop recording
- F9 play last macro
- Shift+F8 clear last macro + stop recording
OBJ/STL import/export
Web build (wasm32)
- Export OBJ: click the
OBJbutton to downloadwire.obj. Face records are preserved when present. - Export STL: click the
STLbutton to downloadwire.stl. Real faces are exported when present; loose wire edges fall back to tiny rectangular solid bars so STL viewers can display them. - Import: click
⬆to upload an OBJ or STL file. - Drag/drop import: dropping a non-image file onto the canvas queues it as a mesh import. Dropping an image queues it as a reference picture; it loads immediately in ortho, or after you switch to an ortho view.
- Imported geometry is added as a new object, selected automatically, and the camera frames it.
Native build
- Import OBJ/STL: press Ctrl+O to open a native file picker, or drag/drop an
.objor.stlfile onto the window. - Export OBJ: press Ctrl+E to open a native save dialog.
- Export STL: press Ctrl+Shift+E to open a native save dialog. Real faces are exported when present; loose wire edges fall back to tiny rectangular solid bars so STL viewers can display them.
- Orbit wire toggle: press Ctrl+Shift+W.
- Target FPS: press F6/F7 for −/+10 FPS, or Shift+F6/Shift+F7 for −/+1 FPS.
- History/status: press Tab to print the history, memory, FPS, and performance status to the console.
- Native file dialogs are provided by the native-only
rfddependency and are not included in the WASM build.
OBJ parsing rules
- Reads
vas vertices - Reads
las polyline edges - Reads
ffaces as real ordered face loops and also keeps their boundary edges visible - Duplicate edges are deduplicated
Import limits
- Files larger than 50 MB are rejected before parsing.
- STL imports are capped at 1,000,000 triangles.
- Imported geometry is capped at 2,000,000 vertices and 4,000,000 edges.
STL parsing rules
- Reads both ASCII STL and binary STL.
- Triangle vertices are deduplicated by position.
- Each triangle contributes its boundary edges; duplicate edges are deduplicated.
Faces / surfaces
- Ctrl+F: create a double-sided face from the currently selected 3 or 4 vertices. The face keeps its ordered winding separately from normalized wire edges.
- Click a filled face: select/deselect that face with immediate highlight. Multiple faces can be selected by short-clicking them, matching vertex/edge toggle behavior.
- Drag a selected face: moves all currently selected faces together; the clicked face point follows the cursor like vertex/edge dragging.
- Ctrl+Shift+F: flip all selected faces when face selection exists, otherwise flip the most recently created/imported face winding.
- Ctrl+Delete: delete all selected faces when face selection exists, otherwise delete the most recently created/imported face.
- Ctrl+Shift+Delete: clear all faces whose vertices belong to the current object.
- When creating a face, selected 3/4 vertices are auto-ordered around the best-fit face plane, so you do not need to select the corners in perimeter order.
- The HUD helper message reports the vertex indices used for each newly created face.
- The on-screen Faces ON/OFF, Wire ON/OFF, Light ON/OFF, and Orbit Wire ON/OFF buttons are compact one-line buttons stacked under the upload button.
- The on-screen Faces ON/OFF button shows/hides filled face surfaces without deleting them.
- Filled faces use efficient flat directional lighting: one normal is calculated per face, applied to each triangle vertex, and shaded in the GPU shader. Use the Light ON/OFF button to compare lit and flat face display. If face surfaces are hidden or the scene has none, this lighting path is not drawn.
- The on-screen Wire ON/OFF button shows/hides model wire edges and face-normal whiskers without deleting them.
- Yellow normal whiskers are drawn from face centers to reveal orientation problems immediately.
- OBJ import/export now preserves
frecords. STL import stores triangle faces; STL export uses real faces when present and falls back to thickened wire export otherwise.
Tips & troubleshooting
If picking or panning feels wrong
- Dense vertex areas should no longer be picked from far away; mouse picking uses the canvas framebuffer scale and ignores vertices outside the visible clip volume.
- LMB-drag empty space pans the camera. LMB-drag selected geometry moves it.
- Press F to re-center on the current selection, or Shift+F to return to origin.
If moving feels wrong
- Moves are constrained to the dominant plane (camera-dependent).
- Orbit a bit (RMB) to change which plane becomes dominant (XY/XZ/YZ).
- Use snapping modifiers: Shift (1.0) / Ctrl+Shift (grid).
If align moves the model unexpectedly
- Shift+A is an edit command, not a view command. It moves selected geometry to center it on the world origin and ground it at
y = 0. - Use F / Shift+F when you only want to move the camera.
If the app feels stuck
- RMB cancels an active drag/pan/preview immediately.
- Esc cancels most tool modes (Line/Rotate/Revolve/Bend/Circle/Divide).
When keys do the “wrong thing”
- X/Y/Z are shared by tools and Ortho switching.
- Inside Line, L means segment-count entry and D means degree constraint. Inside Revolve, M toggles seam closure.
- V is context-sensitive: with a selection it starts Scale; with no selection it can be used for overlay cycling. Rule of thumb: the currently active tool (or active selection tool-mode) wins.
- Rule of thumb: the currently active tool wins.
Performance
- Dense wire overlays can be expensive on large STL imports. Use V to cycle the normal overlay mode to Thin/Off when Scale is not active / no selection, depending on context.
- Use the
Orbit Wire ON/OFFtoolbar button to decide whether the dense wire overlay remains visible during orbit.Orbit Wire OFFhides wire/marker overlay only while orbiting, then restores the selected overlay mode after orbit stops. - Open the Tab panel in the web build to see performance counters such as FPS, target FPS, vertices drawn per second, render passes, draw calls, GPU uploads, and marker/overlay buffer size. In native builds, press Tab for console status and use F6/F7 to adjust target FPS.
HUD contents
- Always visible DOM HUD: dominant plane and last clicked vertex position.
- Brief DOM messages: grid spacing after 9/0, and ground clamp state after Space.
- Vertex count, history/memory details, and performance counters are in the hidden Tab panel.
- Mode helper/instruction hints are shown as DOM text at the bottom-left of the viewport, above the legal footer.
- Geometry-anchored numeric measurement labels remain in the WebGPU overlay because they follow points/edges in the viewport.