A multi-mode OpenSCAD code generator that converts natural language descriptions into 3D models. Supports multiple generation modes including mechanical parts, voxel-style objects, and mazes.
-
π§ BOSL Generator - Mechanical parts using BOSL2 library
- Bolts, nuts, washers, screws
- Mechanical components with precise dimensions
- Threading and standard hardware
-
π§ Cube Generator - Voxel-style objects using only cubes
- Minecraft-like blocky creations
- Buildings, characters, objects made from cubes
- Pixel art in 3D
-
π Maze Generator - Generate various types of mazes
- Rectangular and circular mazes
- Configurable difficulty levels
- Multi-level mazes with decorative elements
- Algorithmic generation with recursive backtracking
-
π Two-Stage Generator - Advanced AI-powered generation
- Design stage: Creative conceptualization using optimized model
- Code stage: Technical implementation with specialized model
- Improved code quality and variable validation
-
π¬ Conversational Generator - Interactive design sessions
- Ask clarifying questions about your design needs
- Iterative refinement through conversation
- Progressive design development with feedback
- Handles timeouts gracefully with intelligent fallbacks
- Command Line Interface - Simple CLI with speech recognition and conversational mode
- Web Interface - Browser-based UI with STL generation and interactive conversations
- Direct API - Python module for integration
git clone <repository>
cd nl-cad
pip install -r requirements.txt# BOSL mode (default) - mechanical parts
python main.py -d "M8 x 25 bolt"
# Generate using speech input π€
python3 main.py --speech
# Quick speech input (no confirmation)
python3 main.py --quick-speech
# Using make commands
make speech # Speech with confirmation
make quick-speech # Quick speech mode
make run DESCRIPTION="M6 bolt" # Text input
# Run test cases to see examples
python3 main.py --testWhat You Can Generate:
- Fasteners: "M8 x 25 bolt", "M10 nut", "3/8 inch washer"
- Shapes: "cuboid 20mm 30mm 40mm", "cyl length 40mm diameter 25mm"
- π€ Speech Input: Just speak naturally: "Create an M8 bolt 25 millimeters long"
How It Works:
- You type: "M8 x 25 bolt"
- AI figures out: size=8, length=25, coarse=true
- Output: Minimal OpenSCAD code with BOSL includes
Examples:
| What you want | Type this | Gets this |
|---|---|---|
| M6 bolt, 20mm long | "M6 x 20 bolt" |
metric_bolt(size=6, l=20, coarse=true) |
| 3/8 inch washer | "3/8 inch washer" |
metric_washer(size=9.525) |
| 20x30x40 cube | "cuboid 20mm 30mm 40mm" |
cuboid(size=[20,30,40]) |
Abstract Examples (AI-Powered):
"i need a bolt the width of a king-sized bed and is 200 long"β AI interprets as ~152mm diameter and 200mm length"box roughly the size of a smartphone"β AI interprets as ~70x140mm
Advanced Features:
- π€ Speech Recognition: Speak your CAD requests naturally
- AI Integration: Uses Ollama for complex, abstract descriptions
- Dual Input Modes: Type or speak - your choice!
Limits:
- Simple shapes (no complex assemblies)
Troubleshooting:
- "No component found" β Try simpler words: "bolt" instead of "hex head fastener"
- Missing length β Include it: "M6 x 25 bolt" not just "M6 bolt"
- AI not working β Check if Ollama is running:
ollama list - π€ Speech not working β Install audio dependencies:
pip install SpeechRecognition pyaudio - Microphone issues β Test with:
python3 speech/speech_recognizer.py
Project Structure:
Hackathon/
βββ main.py # Main program (just run this)
βββ generation/
β βββ bosl_generator.py # The AI logic and parameter extraction
βββ speech/ # π€ Speech recognition module
β βββ __init__.py
β βββ speech_recognizer.py # Speech-to-text functionality
βββ data/
β βββ bosl_catalog.json # BOSL component definitions
β βββ openscad_catalog.json # Basic OpenSCAD primitives
βββ config/
β βββ creative/ # Creative AI generation prompts
β β βββ system_prompt.txt # Spatial reasoning & OpenSCAD rules
β β βββ user_prompt.txt # Creative generation instructions
β βββ catalog/ # Catalog-based generation prompts
β β βββ system_prompt.txt # Parameter extraction rules
β β βββ user_prompt.txt # Catalog matching instructions
β βββ system_prompt.txt # BOSL generation instructions
β βββ user_prompt.txt # BOSL user prompts
βββ output/ # Generated .scad files
Testing:
python3 main.py --test
**For Developers:**
- **Adding Components**: Edit `data/bosl_catalog.json`
- **Adjusting AI Behavior**:
- Creative generation: Modify `config/creative/system_prompt.txt` and `config/creative/user_prompt.txt`
- Catalog generation: Modify `config/catalog/system_prompt.txt` and `config/catalog/user_prompt.txt`
- BOSL generation: Modify `config/system_prompt.txt` and `config/user_prompt.txt`
- **Extending Logic**: Modify `generation/bosl_generator.py`
# Cube mode - voxel objects
python main.py -m cube -d "simple house"
# Maze mode - generate mazes
python main.py -m maze -d "10x10 maze with dead ends"
# Two-stage mode - enhanced AI generation
python main.py -m two-stage -d "modern coffee mug with handle"
# Conversational mode - interactive design
python main.py -m conversation -d "I want to create something special"
# Save to file
python main.py -m maze -d "circular maze" -o output/my_maze.scad
# Voice input
python main.py --speech -m cube
python web_app.py
# Open http://localhost:5000# Test all generators
python main.py --test
# Test maze generation specifically
python simple_maze_test.pypython main.py -d "M8 x 25 bolt"
python main.py -d "cuboid 20mm 30mm 40mm"
python main.py -d "cylinder diameter 25mm height 40mm"
python main.py -d "M10 nut"
python main.py -d "3/8 inch washer"python main.py -m cube -d "simple house"
python main.py -m cube -d "castle tower"
python main.py -m cube -d "robot figure"
python main.py -m cube -d "tree"
python main.py -m cube -d "car"python main.py -m maze -d "simple 5x5 maze"
python main.py -m maze -d "complex 10x10 maze with dead ends"
python main.py -m maze -d "beginner maze with base platform"
python main.py -m maze -d "advanced maze with pillars and roof"
python main.py -m maze -d "circular maze"
python main.py -m maze -d "multi-level maze"python main.py -m two-stage -d "modern coffee mug with handle"
python main.py -m two-stage -d "decorative vase with Greek patterns"
python main.py -m two-stage -d "desk organizer with compartments"
python main.py -m two-stage -d "phone charging stand"
python main.py -m two-stage -d "storage box with hinged lid"# Start interactive design session
python main.py -m conversation -d "I want to design a treasure chest"
python main.py -m conversation -d "help me create a custom container"
python main.py -m conversation -d "I need something decorative"
# The system will ask clarifying questions like:
# - What dimensions do you need?
# - What style preferences do you have?
# - Any specific functional requirements?
# - Materials and appearance preferences?The system uses a base class architecture:
BaseGenerator- Abstract base class for all generatorsBOSLGenerator- Inherits from BaseGenerator, handles mechanical partsCubeGenerator- Inherits from BaseGenerator, cube-only objectsMazeGenerator- Inherits from BaseGenerator, maze generation
- Recursive Backtracking Algorithm - Creates perfect mazes with single solution paths
- Configurable Difficulty - Beginner, intermediate, and advanced modes
- Multiple Maze Types - Rectangular, circular, and multi-level mazes
- Size: Grid dimensions (e.g., 5x5, 10x10, 15x8)
- Wall Properties: Height (20 units), thickness (2 units), path width (10 units)
- Features: Base platforms, decorative pillars, roofs, rooms
- Rectangular Mazes - Standard grid-based mazes
- Circular Mazes - Radial maze layouts (planned)
- Multi-level Mazes - Stacked maze levels with connections
Generated files are saved to the output/ directory:
.scadfiles - OpenSCAD source code.stlfiles - 3D printable models (via web interface)
# Ollama Configuration (for LLM-based generation)
export OLLAMA_MODEL="deepseek-coder:6.7b"
export OLLAMA_BASE_URL="http://localhost:11434"
export OLLAMA_NUM_PREDICT="2500"
export OLLAMA_CONNECT_TIMEOUT="10"
export OLLAMA_READ_TIMEOUT="600"Each generator uses customizable prompt files in the config/ directory:
system_prompt.txt/user_prompt.txt- BOSL generatorcube_system_prompt.txt/cube_user_prompt.txt- Cube generatormaze_system_prompt.txt/maze_user_prompt.txt- Maze generator
# Run all generator tests
python main.py --test
# Test specific maze generation
python simple_maze_test.py- Generate a maze:
python main.py -m maze -d "5x5 simple maze" -o test.scad - Open
test.scadin OpenSCAD - Press F5 to preview or F6 to render
- You should see a 3D maze with walls and paths
A successful maze generation will create:
- Boundary walls forming the maze perimeter
- Internal walls creating the maze paths
- Entrance and exit openings
- Optional features (base, pillars, roof) if requested
- Create a new generator class inheriting from
BaseGenerator - Implement required abstract methods:
_get_default_prompt()generate()_validate_and_clean_code()
- Add the generator to
main.pyandweb_app.py - Create prompt files in
config/
The maze generator supports multiple algorithms:
- β Recursive Backtracking (implemented)
- π Binary Tree (planned)
- π Eller's Algorithm (planned)
- π Wilson's Algorithm (planned)
- "Module not found" errors - Install requirements:
pip install -r requirements.txt - Empty maze output - Check that the algorithmic fallback is working
- OpenSCAD errors - Verify the generated code syntax in OpenSCAD
- Speech recognition fails - Install additional dependencies:
pip install SpeechRecognition pyaudio
Enable verbose output by running with Python's -v flag:
python -v main.py -m maze -d "test maze"A typical 5x5 maze generates approximately:
- 45 lines of OpenSCAD code
- 1500+ characters
- Boundary walls (4 pieces)
- Internal walls (15-25 pieces depending on maze complexity)
- Entrance and exit openings
- Fork the repository
- Create a feature branch
- Add tests for new generators
- Submit a pull request
[License information here]