
threedee-parametric
by tazomatalax
A 3D project
SKILL.md
name: threedee-parametric description: Create and modify 3D parametric models in the threedee design environment. Use when: (1) creating new 3D objects, geometries, or meshes, (2) modifying parameters like dimensions, colors, materials, (3) adding primitives (boxes, spheres, cylinders, torus knots), (4) setting up lighting or camera, (5) exporting models to STL/OBJ/glTF, (6) working with Three.js code in this project. Triggers on requests involving 3D modeling, CAD-like operations, parametric design, or mesh creation.
threedee Parametric Design
A live-updating 3D viewport for parametric modeling with AI assistance. Edit code in VS Code, see results instantly in the browser.
Project Structure
threedee/
├── src/
│ ├── main.js # Main scene, camera, lighting, model loader
│ └── exporters.js # STL/OBJ/glTF export utilities
├── user/
│ ├── models/ # User's parametric model definitions (auto-discovered!)
│ └── exports/ # Generated mesh files (STL, OBJ, glTF)
└── index.html # Viewport UI with model selector
Creating New Models (Recommended Workflow)
Models are automatically discovered! Simply create a new .js file in user/models/ and it will appear in the UI dropdown after a page refresh.
Step 1: Create a Model File
Create a new file in user/models/ with a descriptive kebab-case name (e.g., my-bracket.js).
The filename becomes the model ID and is converted to Title Case in the UI.
Step 2: Export Required Functions
Every model file must export a createMesh() function:
// user/models/my-bracket.js
import * as THREE from 'three';
export const parameters = {
width: 40,
height: 20,
thickness: 5,
color: 0x4a90d9,
};
export function createMesh(userParams = {}) {
const params = { ...parameters, ...userParams };
const geometry = new THREE.BoxGeometry(
params.width,
params.height,
params.thickness
);
const material = new THREE.MeshStandardMaterial({ color: params.color });
const mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.y = params.height / 2; // Sit on ground plane
return mesh;
}
Step 3: Save and View
- Save the file
- The browser will hot-reload (or refresh if needed)
- Select your new model from the MODEL dropdown in the top-left
- Export when ready using the EXPORT MODEL panel
Quick Reference
Basic Primitives
const geometry = new THREE.BoxGeometry(2, 1, 3); // width, height, depth
const geometry = new THREE.SphereGeometry(1, 32, 32); // radius, segments
const geometry = new THREE.CylinderGeometry(1, 1, 2, 32); // topR, bottomR, height
const geometry = new THREE.TorusGeometry(1, 0.4, 16, 100); // radius, tube, segments
const geometry = new THREE.TorusKnotGeometry(1, 0.35, 128, 32);
Common Modifications
Change object color:
material.color.setHex(0x22d3ee); // cyan accent
Position object:
mesh.position.y = 1.5; // lift above ground
mesh.position.set(0, 1.5, 0); // x, y, z
Scale object:
mesh.scale.set(2, 1, 1); // stretch in x
Rotate object:
mesh.rotation.y = Math.PI / 4; // 45 degrees
Parametric Pattern
For reusable models, always merge with default parameters to handle partial updates correctly:
export const parameters = {
width: 40,
height: 20,
depth: 40,
color: 0x4a90d9,
};
export function createGeometry(userParams = {}) {
const params = { ...parameters, ...userParams };
return new THREE.BoxGeometry(params.width, params.height, params.depth);
}
export function createMesh(userParams = {}) {
const params = { ...parameters, ...userParams };
const geometry = createGeometry(params);
const material = new THREE.MeshStandardMaterial({ color: params.color });
return new THREE.Mesh(geometry, material);
}
Geometry Merging Best Practices
When combining different geometry types (e.g., mixing BoxGeometry with ExtrudeGeometry), they often have incompatible index buffers which causes mergeGeometries to fail.
Always convert to non-indexed before merging to ensure compatibility:
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
// ... create geometries ...
// Convert all to non-indexed before merging to avoid attribute/index conflicts
const compatibleGeometries = [geo1, geo2, geo3].map(g => g.toNonIndexed());
const merged = mergeGeometries(compatibleGeometries);
// Optional: Weld vertices afterwards if smooth shading is needed
// import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
// const smooth = mergeVertices(merged);
Exporting Models
Export the active 3D model to various formats using the browser console or programmatically:
Single Format Exports
// STL (3D printing)
threedeeExport.stl(mesh, "my-part") // Binary (recommended)
threedeeExport.stlAscii(mesh, "my-part") // ASCII text format
// General interchange
threedeeExport.obj(mesh, "my-part") // OBJ with UVs and normals
// Web and AR
threedeeExport.gltf(mesh, "my-part") // glTF (JSON)
threedeeExport.glb(mesh, "my-part") // GLB (binary, compact)
// CAD interchange
threedeeExport.step(mesh, "my-part") // STEP Faceted B-Rep
Batch Export (All Formats)
// Export to STL, OBJ, glTF, and STEP simultaneously
await threedeeExport.all(mesh, "my-part")
// Export to specific formats
await threedeeExport.all(mesh, "my-part", ['stl', 'step', 'obj'])
Export Notes
- Files are automatically timestamped:
my-part_2025-12-30_23-02-15.stl - Browser downloads are triggered automatically
- Console logs confirm successful exports
- The
meshvariable is always available in the console and accessible viawindow.mesh
Lighting Adjustment
keyLight.intensity = 1.5; // brighter
keyLight.position.set(10, 15, 10); // move light
rimLight.color.setHex(0xff6600); // orange rim
Advanced Modeling & Slicer Compatibility
When creating complex procedural shapes (like gyroids or lattices) intended for 3D printing, follow these best practices to ensure "watertight" models and high-quality exports.
Marching Cubes Best Practices
If using MarchingCubes, configure it for high resolution and clean boundaries:
- Polygon Budget: Always set a high
maxPolyCount(e.g.,1,000,000) for high-resolution meshes to prevent model sections from being "cut off" due to buffer limits. - Watertight Boundaries: Use padding in your scalar field. Never let the isosurface (boundary) sit exactly on the domain edge. Sample a slightly larger domain than the actual object size to ensure the Marching Cubes algorithm can "close" the mesh.
- Boundary Smoothing: When clipping shapes (e.g., using
Math.maxfor a cylinder boundary), use a multiplier (e.g.,* 5or* 10) for the boundary distance to create a smooth gradient that the interpolator can follow. - Vertex Welding: Always use
mergeVerticesfromBufferGeometryUtilsaftermc.update()to weld coincident vertices. This fixes "cracks" and "open edges" that slicers often report.
import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
// ... inside createMesh ...
const mc = new MarchingCubes(resolution, material, false, false, 1000000);
// ... fill field ...
mc.update();
// Weld and recompute normals
const welded = mergeVertices(mc.geometry, 1e-5);
welded.computeVertexNormals();
mc.geometry.dispose();
mc.geometry = welded;
Ensuring Export Quality
The src/exporters.js utilities include an automated preparation step for STL exports that handles:
- Coordinate system normalization (baking world transforms).
- Vertex welding and normal correction.
- Removal of degenerate (zero-area) triangles.
Workflow
Creating vs Iterating
IMPORTANT: When asked to improve, refine, or iterate on an existing model:
- DO: Edit the existing model file directly (e.g., modify
user/models/tree.js) - DON'T: Create new files like
tree-v2.js,tree-improved.js,realistic-tree.js
Only create a new file when the user explicitly asks for a new, separate model.
Standard Workflow
- User requests a new 3D object → Create a new file in
user/models/ - User requests improvements/changes → Edit the existing model file
- Save — the viewport hot-reloads instantly
- The user's selected model persists across page refreshes
- Export when ready via the EXPORT MODEL panel
Iteration Examples
User says: "Make the tree more realistic"
Action: Edit user/models/tree.js to improve the existing code
User says: "Add more branches and better textures"
Action: Edit user/models/tree.js to add the requested features
User says: "Create a pine tree (separate from the oak tree)"
Action: Create a new file user/models/pine-tree.js
Console Commands
Models can also be loaded programmatically:
// Load a model by ID (filename without .js)
await loadModel('shelf-bracket');
// List all available models
console.log(modelList);
// Access current mesh
window.mesh
Important Notes
- The viewport runs at
http://localhost:3002(or next available port) - Models are auto-discovered from
user/models/*.js— no manual registration needed! - Selected model persists across page refreshes via localStorage
- Model filenames use kebab-case (e.g.,
my-widget.js) and display as Title Case in the UI - Y-axis is up (standard Three.js convention)
- Objects should be positioned with
y > 0to sit above the grid - The
meshvariable is exported and accessible in console viawindow.mesh - All changes hot-reload instantly—no refresh needed
- When iterating: edit the existing file, don't create new versions
References
For advanced geometry and CSG operations, see references/geometry.md.
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です