1
CustomizableSpinner is a single-file Three.js construction and object-design application. It keeps the original interaction idea: Spin Mode rotates the construction, Camera Mode moves the camera, and Move Mode moves selected objects by drag-and-drop on a selected move plane.
The left panel contains creation tools, script input, grid controls, and settings. The right panel contains the object list, property inspector, and templates. Use Hide Tools and Hide Objects in the top bar to collapse either side. The scene automatically expands into the freed space. The advertising banner always remains visible: when the object panel is open, it sits beside it; when the panel is closed, it stays on the right screen edge.
Spin Mode rotates the complete construction around the configured Spin Center. Drag horizontally to rotate around the enabled Y axis and vertically to rotate around the enabled X axis. The horizontal and vertical drag axes are configurable in Settings. Hold Shift while dragging to rotate around the remaining third axis. Spin sensitivity, damping, maximum speed, enabled axes and automatic rotation are configured under Settings.
The optional Spin System axes make the spin pivot and its current orientation visible. Red represents X, green represents Y and blue represents Z. They are centered exactly on the Spin Center, rotate together with the construction, cannot be selected and are not stored as scene objects. Use Settings → Spin Center & Behavior → Show Spin Axes to show or hide them and Spin Axes Length to change their size.
Camera Mode changes only the view. Left-drag orbits the camera around the Viewport Center, right-drag moves that center sideways or vertically, and the mouse wheel zooms. The arrow keys also move the Viewport Center relative to the current view: Up moves forward in the viewing direction, Down moves backward, and Left/Right move sideways. Shift uses the fast camera keyboard step. Plus and minus are not used in Camera Mode.
Move Mode changes the position of the selected object. Drag the object on the move plane selected under Coordinates/Grid. Fixed objects stay in world space during Spin Mode and remain movable in Move Mode. The keyboard can move the selected object with Left/Right on X, Up/Down on Y and Plus/Minus on Z. Shift uses the fast object-move step. The normal and fast step sizes are configured under Settings.
The Custom Builder tab creates geometry that is not limited to the built-in primitives. Vertex Mesh accepts explicit 3D vertices and triangular faces. Vertices are numbered from zero in their input order, and every face references three vertex indices. Extruded 2D Path turns an ordered closed X/Y outline into a solid object with configurable depth and bevel. Lathe Profile revolves ordered radius/Y points around the Y axis, which is useful for bottles, handles, wheels, columns and other rotational forms.
Use Validate before adding complex data. Consistent triangle winding is important because it determines the visible face direction and computed normals. Custom definitions can be added directly, saved as templates, stored with the project and converted into executable script commands.
The script language supports stateful builders:
MESHBEGIN, VERTEX, FACE and
MESHBUILD create arbitrary triangle meshes;
PATHBEGIN, POINT and
PATHBUILD create extruded outlines;
LATHEBEGIN, PROFILEPOINT and
LATHEBUILD create rotational forms. Compact one-line
alternatives are available through CUSTOMMESH,
CUSTOMPATH and CUSTOMLATHE. Builder names
only exist during the current script execution and are removed after
their object is built.
The Object Designer creates parametric definitions instead of anonymous mesh data. Choose a type, set dimensions, color, material-related values, transform, and Fixed state, then add the object to the scene or save it as a template. Definitions can later be re-edited through the Inspector.
The application supports Box, Sphere, Cylinder, Cone, Torus, Plane, Ring, Tube, Extrude, Lathe, Shape, CustomShape, and construction forms such as Beam, Post, Plate, Pipe, and Frame. GUI buttons and scripts both create the same definition format.
The Object List shows every scene object with its name, type, Fixed state, and color. Click an object to select it. The General tab contains common object information such as name, type, color, material and Fixed state. Position & Scale sits directly below General and edits position, rotation and scale. Object Properties focuses on parametric geometry parameters.
The Coordinates/Grid tab controls the XZ, XY, and YZ grids, grid spacing, coordinate-system size, origin, grid color, floor visibility, axes, and the drag-and-drop move plane. Coordinate System Size defines how large the grid helper is drawn. Floor / Work Area Size defines the visible construction floor and the blue work-area border. For Move Mode, choose XZ for ground movement, XY for wall-style movement, or YZ for side-plane movement. The coordinate not included in the selected plane is automatically fixed to the selected object's current value. The floor is hidden by default so the scene starts clean; enable it when you want a visible work surface.
The Settings tab contains a Spin Center & Behavior section. Spin Center X/Y/Z defines the world-space pivot around which the complete construction rotates. Changing this pivot does not alter the stored positions of individual objects. Sensitivity controls how strongly mouse movement accelerates the spin. Damping controls how long inertial motion continues after releasing the mouse. Maximum Speed limits very fast throws. X, Y and Z can be enabled independently. Auto X/Y/Z adds continuous rotation in degrees per second. Reset Spin Center restores the origin, while Reset Spin Rotation stops inertia and restores the presentation rotation to zero.
The Settings tab contains a Lighting section. Ambient Intensity controls the global base light. Directional Intensity controls the main sun-like light. Light Position X/Y/Z moves this directional light in the scene, and Light Color changes the light tint. The Camera Limits section defines Minimum Distance and Maximum Distance for mouse-wheel zoom. Near Clip and Far Clip control the camera clipping planes for very small or very large constructions. In Camera Mode, left-drag orbits around the viewport center and right-drag moves that center. The current center is displayed and editable numerically under Settings → Viewport Center; use Reset Viewport there to return the center to X 0, Y 0 and Z 0.
Save writes the construction, object definitions, templates and settings as JSON into this browser's LocalStorage. The project is stored locally for the current website origin and browser profile. Clearing browser data, using private browsing or opening the application under a different origin can make the saved data unavailable.
The Storage tab shows the total LocalStorage usage, the estimated remaining LocalStorage space, the estimated LocalStorage maximum and the size of the current saved project. To estimate the maximum, the application briefly writes temporary test data and removes it immediately. The result depends on the browser and can change with browser policies or settings. A separate expandable section shows the browser's broader origin-storage estimate, which may also include IndexedDB, caches and other storage systems.
The Storage tab can display the exact saved project JSON on demand, copy it to the clipboard, export it as a JSON file, or replace the saved project from pasted JSON. A future version may switch to a local browser database such as IndexedDB. The current version still uses LocalStorage. Temporary image tests are not saved.
The General tab lets you load a local image file as a temporary test texture or temporary image plane. This is useful for checking signs, decals, reference images or material ideas. The image data is never stored inside the project JSON and disappears when the page is reloaded.
The Script tab creates and edits scene content without operating the
user interface manually. Commands are processed in order. Every
command ends with a semicolon, fields are separated by
|, and lines beginning with # may be used
as comments. Empty lines are ignored. Decimal points are
recommended. Rotations use degrees, colors use hexadecimal notation
such as #4aa3ff, and Boolean values normally use
1 for enabled or fixed and 0 for disabled
or not fixed.
NameOrId means that an existing object may be addressed either by its unique object name or by its internal ID. For scripts generated by an AI, unique descriptive names are strongly recommended because IDs are not normally known in advance. Commands are executed sequentially, so an object must already exist before commands such as MOVE, ROTATE, SET, DELETE or MERGE can refer to it.
;.|.ADD|Type|Name|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed;
ADD creates one built-in or parametric object and inserts it into the scene.
Type: supported object type, for example Box, Sphere,
Cylinder, Beam, Frame, Gear or Spiral.
Name: unique, descriptive scene-object name.PosX/PosY/PosZ: absolute world position.RotX/RotY/RotZ: absolute rotation in degrees.ScaleX/ScaleY/ScaleZ: object scaling;
1|1|1 keeps the original size.
Color: hexadecimal color such as
#8b5a2b.
Fixed: 1 keeps the object in world space while the construction spins; 0 lets it rotate with the spinner. Both states remain movable in Move Mode.
ADD|Box|Workbench Top|0|1.2|0|0|0|0|1|1|1|#8b5a2b|1; SET|Workbench Top|param|width|3; SET|Workbench Top|param|height|0.2; SET|Workbench Top|param|depth|1.4;
Geometry-specific dimensions should normally be set afterward with SET param, because scale changes the complete generated geometry while geometry parameters rebuild the actual shape.
MOVE|NameOrId|X|Y|Z;
Replaces the object's world position. It does not move the object relative to its current position.
MOVE|Workbench Top|0|1.35|-0.5;
ROTATE|NameOrId|XGrad|YGrad|ZGrad;
Replaces the object's rotation. All three values are degrees. For example, rotating a Plane by -90 degrees around X commonly turns it into a horizontal surface.
ROTATE|Sign Plate|-90|0|0;
SCALE|NameOrId|X|Y|Z;
Replaces the scale on all three axes. Values smaller than 1 shrink the object; values greater than 1 enlarge it. Negative scale values mirror geometry and can invert visible face orientation.
SCALE|Workshop Gear|1.5|1.5|0.5;
COLOR|NameOrId|#hex;
Changes the selected object's color. Use a six-digit hexadecimal color for predictable AI-generated scripts.
COLOR|Workshop Gear|#3f4852;
SET|NameOrId|param|ParameterName|Value;
Updates one geometry-specific parameter and rebuilds the object. The parameter must be valid for that object type. Examples include width, height, depth, radius, radiusTop, radiusBottom, tube, length, thickness, innerRadius, outerRadius and segments.
SET|Main Frame|param|width|6; SET|Main Frame|param|height|3; SET|Main Frame|param|thickness|0.18;
PARAM|NameOrId|ParameterName|Value; is accepted as a
shorter equivalent, but SET|...|param|... is the
explicit form documented here.
Consecutive SET commands accumulate. Setting
radiusTop, then radiusBottom, then
height preserves all three values. A later parameter
command changes only the named parameter and does not reset the
other geometry parameters.
SET|NameOrId|name|New Name;
Changes the object's name. Later commands must use the new name. DUPLICATE no longer needs a later rename because the required target name is supplied directly in the DUPLICATE command.
SET|Temporary Post|name|Left Post;
DELETE|NameOrId;
Removes the addressed scene object. Later commands cannot refer to the removed object.
DUPLICATE|SourceNameOrId|NewObjectName;
Creates a separate copy of the source object and assigns the requested name during creation. The copy keeps the source geometry, geometry parameters, transform, color, material-related data and Fixed state, receives a new internal ID, and is offset by 0.5 units on X and Z so it does not occupy exactly the same position as the source.
NewObjectName is mandatory and must be unique. The
command fails when the source cannot be found, the new name is
empty, or another object already uses that name. No automatic
copy name is created by scripts, and no following
SET|...|name|... command is required.
DUPLICATE|Left Post|Right Post; MOVE|Right Post|2|1.25|0; ROTATE|Right Post|0|0|0; COLOR|Right Post|#46d38b;
For several copies, repeat the command with a different target name each time:
DUPLICATE|Micro Star|Star 001; MOVE|Star 001|-5|8|-12; DUPLICATE|Micro Star|Star 002; MOVE|Star 002|3|11|-15;
CLONE|SourceNameOrId|NewObjectName;
CLONE places the source and all of its clones in
one internal THREE.InstancedMesh bucket.
Finish every geometry parameter, color and material change on the
source before the first CLONE command.
After cloning, neither the source nor any clone may receive
individual geometry, color or material changes. Clone members may
still be moved, rotated, scaled, renamed, deleted and switched
between Fixed/not fixed. Use DUPLICATE when any
copy must later differ in appearance or geometry. CLONE currently
supports single-mesh object types only.
CLONE|Window Base|Window 001; MOVE|Window 001|2|3|0; CLONE|Window Base|Window 002; MOVE|Window 002|4|3|0;
TEMPLATE|SAVE|NameOrId;
Saves the selected object's definition as a reusable template.
Templates are stored with project data. The script engine also
supports TEMPLATE|LOAD|TemplateName; to instantiate a
saved template, although the requested command list focuses on
saving.
MERGE|NewCompoundName|ObjectNameA,ObjectNameB,ObjectNameC;
Combines multiple existing scene objects into one saved compound object. Source names are comma-separated inside the third field. All listed objects must already exist. Use MERGE for assemblies such as a door frame, machine housing or furniture module that should become one reusable object.
MERGE|Door Frame|Left Post,Right Post,Top Beam,Bottom Beam;
SHADOWS|1;
Sets global shadow rendering. Use 1 or
true to enable it, and 0 or
false to disable it.
VIEWCENTER|X|Y|Z;
Sets the point around which Camera Mode orbits and toward which the composition is viewed. It does not move scene objects.
VIEWCENTER|0|1.5|0;
LIGHT|AmbientIntensity|DirectionalIntensity|#hex;
Sets ambient-light intensity, directional-light intensity and the shared ambient/directional light color. Typical useful intensity values are around 0 to 2, although larger values are technically possible.
LIGHT|0.6|1.2|#ffffff;
SETTING|SettingName|Value;
Updates a setting by its documented internal setting key. The current setting type determines whether the value is interpreted as a number, Boolean or text. Never invent setting keys. Unknown names have no guaranteed visual effect and should not be used in AI-generated scripts.
SETTING|shadowMapSize|2048;
Useful keys include shadowMapSize,
shadowCameraSize, shadowCameraNear,
shadowCameraFar, shadowBias,
shadowNormalBias, shadowRadius,
cameraMinDistance, cameraMaxDistance,
cameraNear, cameraFar,
spinSensitivity, spinDamping,
spinMaxSpeed, autoSpinX,
autoSpinY and autoSpinZ. Vector-valued
settings such as the complete light position are not suitable for
this single-value form.
The stateful mesh builder is best for arbitrary triangle geometry that is easier to read across many lines. The workflow is: begin a builder, add vertices, add triangular faces, then build the final scene object.
MESHBEGIN|BuilderName;
Creates or resets a temporary mesh builder under the supplied name.
VERTEX|BuilderName|X|Y|Z;
Adds one 3D vertex. Vertex indices start at zero in insertion order.
FACE|BuilderName|A|B|C;
Adds one triangle using three vertex indices. Face winding controls the normal direction: viewed from the visible front side, keep the index order consistent across the mesh. Invalid indices can produce missing or broken faces.
MESHBUILD|BuilderName|ObjectName|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed;
Creates the finished CustomMesh object using all stored vertices and faces, applies its transform and appearance, and removes the temporary builder.
MESHBEGIN|PyramidMesh; VERTEX|PyramidMesh|-1|0|-1; VERTEX|PyramidMesh|1|0|-1; VERTEX|PyramidMesh|1|0|1; VERTEX|PyramidMesh|-1|0|1; VERTEX|PyramidMesh|0|2|0; FACE|PyramidMesh|0|1|4; FACE|PyramidMesh|1|2|4; FACE|PyramidMesh|2|3|4; FACE|PyramidMesh|3|0|4; FACE|PyramidMesh|0|3|2; FACE|PyramidMesh|0|2|1; MESHBUILD|PyramidMesh|Custom Pyramid|0|0|0|0|0|0|1|1|1|#d6a84b|1;
The path builder creates a 3D solid by extruding an ordered 2D X/Y outline along its local depth direction. Supply at least three points and keep the outline ordered around its perimeter. Do not repeat the first point at the end unless the particular shape requires it.
PATHBEGIN|BuilderName;
Creates or resets a temporary path builder.
POINT|BuilderName|X|Y;
Adds one 2D outline point in local X/Y coordinates.
PATHBUILD|BuilderName|ObjectName|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed|Depth|BevelEnabled|BevelSize|BevelThickness|CurveSegments;
Depth: extrusion depth.BevelEnabled: 1 enables beveled edges;
0 disables them.
BevelSize: horizontal size of the bevel.BevelThickness: bevel depth.CurveSegments: smoothness for curved sections.
BuilderName identifies temporary path data;
ObjectName is the permanent name of the completed scene
object.
PATHBEGIN|ArrowPath; POINT|ArrowPath|-1|-0.4; POINT|ArrowPath|0.2|-0.4; POINT|ArrowPath|0.2|-0.9; POINT|ArrowPath|1.2|0; POINT|ArrowPath|0.2|0.9; POINT|ArrowPath|0.2|0.4; POINT|ArrowPath|-1|0.4; PATHBUILD|ArrowPath|Extruded Arrow|0|1|0|0|0|0|1|1|1|#4aa3ff|0|0.3|1|0.04|0.04|12;
The lathe builder revolves a sequence of radius/Y profile points around the local Y axis. It is ideal for bottles, vases, columns, knobs, wheels and other rotational forms. Radius should normally be zero or positive, and profile points should be ordered from bottom to top or top to bottom without erratic jumps.
LATHEBEGIN|BuilderName;
Creates or resets a temporary lathe-profile builder.
PROFILEPOINT|BuilderName|Radius|Y;
Adds one profile point. Radius is the distance from the Y axis; Y is the vertical coordinate.
LATHEBUILD|BuilderName|ObjectName|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed|Segments;
Builds the final CustomLathe object and deletes the temporary builder. More segments create a smoother circumference but increase geometry cost.
LATHEBEGIN|VaseProfile; PROFILEPOINT|VaseProfile|0.2|0; PROFILEPOINT|VaseProfile|0.7|0.2; PROFILEPOINT|VaseProfile|0.9|1.2; PROFILEPOINT|VaseProfile|0.45|2; PROFILEPOINT|VaseProfile|0.35|2.4; LATHEBUILD|VaseProfile|Blue Vase|0|0|0|0|0|0|1|1|1|#356fa8|0|48;
The compact commands create custom geometry without a temporary builder. They are useful for small, self-contained shapes and AI-generated scripts, while stateful builders are usually easier to inspect and debug for large data sets. Semicolons never separate coordinates: every compact tuple is enclosed in round brackets and tuples follow one another directly.
Semicolons are reserved exclusively for ending commands. Compact
custom commands therefore group every vertex, face, path point or
profile point in its own pair of round brackets. Tuples follow each
other directly without an additional separator. Examples:
(0,0)(1,0)(0,1) for 2D points and
(0,0,0)(1,0,0)(0,1,0) for 3D vertices. A command
contains exactly one semicolon, placed at its very end.
CUSTOMMESH|Name|(x,y,z)(x,y,z)|(a,b,c)(a,b,c)|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed;
The second field contains the vertex list; the third contains triangular face-index triples. Indices start at zero.
CUSTOMMESH|Triangle Prism|(0,0,0)(1,0,0)(0,1,0)(0,0,1)|(0,1,2)(0,3,1)(0,2,3)(1,3,2)|0|0|0|0|0|0|1|1|1|#ff8844|0;
CUSTOMPATH|Name|(x,y)(x,y)(x,y)|Depth|BevelEnabled|BevelSize|BevelThickness|CurveSegments|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed;
The point list defines the ordered closed outline. Remaining values match PATHBUILD.
Coordinate behavior: The outline lies in local X/Y and Depth is centered equally around local Z. Position therefore always refers to the geometric center, including after rotation.
CUSTOMPATH|Hex Sign|(-1,0)(-0.5,-0.86)(0.5,-0.86)(1,0)(0.5,0.86)(-0.5,0.86)|0.2|1|0.03|0.03|12|0|1.5|0|0|0|0|1|1|1|#ffd166|1;
CUSTOMLATHE|Name|(radius,y)(radius,y)|Segments|PosX|PosY|PosZ|RotX|RotY|RotZ|ScaleX|ScaleY|ScaleZ|Color|Fixed;
The profile list contains radius/Y pairs. Remaining values match LATHEBUILD.
CUSTOMLATHE|Column|(0.45,0)(0.55,0.15)(0.4,0.3)(0.4,2.7)(0.55,2.85)(0.45,3)|48|0|0|0|0|0|0|1|1|1|#d8d1c4|1;
CLONE, then reposition, rotate or scale each clone.
Use DUPLICATE instead when a copy must later receive
different geometry, color or material.
Use one consistent convention throughout a complete construction: X is left/right, Y is vertical height, and Z is forward/backward depth or travel. MOVE writes an absolute world position. ROTATE writes absolute Euler angles in degrees. SCALE writes absolute scale multipliers.
Center reusable custom geometry around its local origin whenever
practical. Centered geometry rotates, duplicates and mirrors
predictably. For example, prefer
(-2,-0.1)(2,-0.1)(2,0.1)(-2,0.1) over an equivalent
outline running only from 0 to 4.
A visible slope angle is not automatically the correct Euler angle.
First identify the object's original local long axis. A beam drawn
along local X normally uses the pitch angle directly in the plane in
which it slopes. A beam drawn along local Y may require the
complementary angle, such as 90° − pitch. Always
calculate from endpoints rather than guessing from appearance.
A CUSTOMPATH outline must be one simple, closed, non-self-intersecting perimeter. List points continuously clockwise or counter-clockwise around the outer boundary. Do not describe disconnected stair-step fragments in one outline, and do not close a complex profile with a long diagonal that creates an unintended filled wall. Use CUSTOMMESH for shapes whose perimeter would be ambiguous or self-intersecting.
Keep Scale at 1|1|1 whenever the intended physical
dimensions can be defined by geometry parameters or custom
coordinates. For parametric types use
SET|Object|param|.... For custom objects, model the
required dimensions directly in the vertices, outline or profile.
Use SCALE only for an intentional later resize of the entire
finished object.
The Object Properties inspector and script SET validation use the same central mapping. Only parameters that rebuild the selected type meaningfully are shown and accepted.
Box, Beam, Post, Plate, Wedge: width, height, depth Sphere: radius, segments Cylinder: radiusTop, radiusBottom, height, segments Cone, Pyramid: radius, height, segments Torus: radius, tube, segments Plane: width, height Ring: innerRadius, outerRadius, segments Tube: length, tube, segments Pipe: radius, length, segments Extrude, Heart: width, height, depth Lathe: radius, height, segments Shape, CustomShape: radius, segments, depth Frame: width, height, depth, thickness Capsule: radius, length, segments Star, Gear: innerRadius, outerRadius, segments, depth Spiral: radius, tube, length, segments Tetrahedron, Octahedron, Dodecahedron, Icosahedron: radius CustomMesh, CustomPath, CustomLathe, Compound: no inspector geometry parameters
Custom geometry is edited by changing and rerunning its builder or compact custom command. Showing unrelated fallback properties would be misleading, so those fields are intentionally hidden.
Before writing commands, define each stair flight internally: center
X, start Y, start Z, step count, rise, run, stair width and travel
direction. For step index i beginning at zero:
Positive-Z flight: StepY = StartY + i × Rise StepZ = StartZ + i × Run Negative-Z flight: StepY = StartY + i × Rise StepZ = StartZ − i × Run
Parallel or returning flights must have different center-X values and must not overlap. Treads and landings remain horizontal. Posts remain vertical in world Y. Stringers and handrails follow the calculated stair slope.
HorizontalTravel = (StepCount − 1) × Run VerticalRise = (StepCount − 1) × Rise DiagonalLength = sqrt(HorizontalTravel² + VerticalRise²) PitchFromHorizontal = atan(VerticalRise / HorizontalTravel) in degrees
A landing must be thin in local Y, wide in local X and use CUSTOMPATH Depth for its horizontal Z extension. Its usable depth should normally be at least the stair width. Verify that the first and last treads meet the landing without a gap or collision.
Settings → Selection → Select object on viewport click controls whether a click on geometry in the 3D viewport changes the active selection and highlights the corresponding Object List entry. When disabled, select objects through the Object List. In Move Mode, only the already selected object can be dragged. The separate double-click option controls whether double-clicking an Object List entry changes the Viewport Center.
All prompt examples below are assembled from one JavaScript text
variable named AI_SYSTEM_SPECIFICATION. Each task is
stored separately in AI_PROMPT_TASKS and combined
through buildAIPrompt(task). The visible prompt
therefore always contains the complete syntax and geometry
specification and can be copied into a new AI chat without hidden
context.
const finalPrompt = buildAIPrompt(AI_PROMPT_TASKS.uStair);
Prompt is assembled from the shared specification when the manual opens.
Prompt is assembled from the shared specification when the manual opens.
Prompt is assembled from the shared specification when the manual opens.
Prompt is assembled from the shared specification when the manual opens.