Shadow Lamp reverse-engineers 3D-printable models from 2D object outlines and target shadows. It includes a PyQt6 desktop designer, a command-line workflow, and a browser-based version that runs without a backend.
Given an object mask A, a target shadow mask B, and a point-light position, Shadow Lamp computes a height field whose projected shadow approximates the target. The result is converted into a watertight, flat-bottom mesh suitable for inspection and 3D printing.
| Object mask A | Target shadow B |
|---|---|
![]() |
![]() |
- Interactive desktop editor with real-time 3D preview
- Linked design and locked-model validation modes
- Adjustable light position, light height, shadow scale, smoothing, and thickness
- Per-component height controls for enclosed object regions
- Target-versus-simulated shadow comparison with IoU and F1 metrics
- Watertight STL and OBJ export with a flat printable base
- Blender import script generation
- English and Chinese desktop interfaces
- Offline-capable browser implementation with vendored Three.js assets
- GUI lifecycle and printable-mesh regression tests
The self-contained Windows x64 build is produced as:
release/Shadow-Lamp.exe
The executable does not require Python or a virtual environment on the target machine. It is currently unsigned, so Windows SmartScreen may show an unknown-publisher warning when it is opened for the first time.
For public distribution, upload Shadow-Lamp.exe as a GitHub Release asset rather than committing it to the repository.
- Python 3.10 or newer
- An OpenGL-capable desktop environment for the VisPy preview
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txtOn macOS or Linux, activate the environment with source .venv/bin/activate.
python main.pyThe bundled star example is loaded automatically at startup. Select different object and shadow images from the input panel, then adjust the design and print parameters before exporting the model.
Both inputs are converted to grayscale and thresholded at 128:
- Black pixels represent the object or shadow.
- White pixels represent the background.
- Image A should contain a valid closed object silhouette or outline.
- Image B should contain a filled shadow region with a white border.
- If the image dimensions differ, B is resized to match A.
PNG is recommended for sharp binary edges. JPEG input is supported but may introduce compression artifacts near the boundary.
Generate a model from the bundled example:
python main.py --cli --output-dir outputUse custom inputs:
python main.py --cli --image-a path/to/object.png --image-b path/to/shadow.png --lx 128 --ly 128 --width-mm 120 --output-dir outputThe default export contains:
output/
|-- model.stl
|-- model.obj
|-- model.mtl
`-- import_to_blender.py
Run python main.py --cli --help for all options. Add --no-export to compute and validate without writing model files, or --render to open the interactive preview after solving.
The static application in web/ runs entirely in the browser. No API server or remote JavaScript dependency is required.
python -m http.server 8000 --directory webOpen http://localhost:8000. For static hosting, use web/ as the publish directory.
Generate comparison reports for the included solver variants:
python compare_methods.py --demo --output-dir output_methodsThis produces interactive HTML reports and model exports in the selected output directory.
python -m unittest discover -s tests -p "test_*.py" -vThe GUI lifecycle tests use Qt's offscreen platform automatically and do not open an interactive window.
Shadow-Lamp/
|-- main.py # Desktop and CLI entry point
|-- design_core.py # Design-state computation pipeline
|-- solver.py # Shadow geometry and height solving
|-- mesh_export.py # Printable mesh construction and export
|-- designer_gui.py # PyQt6 desktop interface
|-- rt_render.py # VisPy real-time preview
|-- i18n.py # English and Chinese interface strings
|-- images/ # Bundled binary-mask examples
|-- web/ # Static browser implementation
|-- tests/ # Regression test suite
|-- requirements.txt # Python runtime dependencies
`-- LICENCE # MIT license text
Generated meshes, reports, Python caches, temporary build environments, and local release binaries are excluded from Git.

