Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
90beb04
docs: puree the moonshot specs until smooth
doublemover May 9, 2026
08af616
config: liquefy the reconstruction knobs
doublemover May 9, 2026
49b86b0
constraints: blend the user scribbles into shape law
doublemover May 9, 2026
68020a5
metrics: frappe the silhouettes until they tell the truth
doublemover May 9, 2026
29e6693
volume: crush the voxel cubes without making soup
doublemover May 9, 2026
f0f3d84
synthetic: puree fake shapes for real evidence
doublemover May 9, 2026
dfa4eb8
primitives: pulse the blender until ellipsoids behave
doublemover May 9, 2026
ea76761
blender-ops: set booleans to smoothie mode
doublemover May 9, 2026
f7749ed
reconstruction: whirl every backend in the pitcher
doublemover May 9, 2026
382e68d
bench: pulse the blender timer without splatter
doublemover May 9, 2026
8bdf7d0
tests: unjam the blender straw
doublemover May 9, 2026
0cb2b6c
render: blend the whole scene when asked
doublemover May 9, 2026
d7aac8d
e2e: keep the validation pitcher full
doublemover May 9, 2026
b1e2ea8
cli: puree every e2e mode button
doublemover May 9, 2026
f5e8c3d
tests: strain the chunky suite smoothie
doublemover May 9, 2026
803ab6a
chore: stop pureeing temp specs into git
doublemover May 9, 2026
b802730
backend: fold the ambitious modes into one smoothie
doublemover May 9, 2026
090e512
volume: carve the hull without blending the whole vat
doublemover May 9, 2026
a8b404a
synthetic: stock the blender with tiny truth cubes
doublemover May 9, 2026
fa16c46
research: whip primitives until they explain themselves
doublemover May 9, 2026
0a425d7
gates: make the blender refuse lumpy regressions
doublemover May 9, 2026
c959bb5
research: blend the last chunky moonshots smooth
doublemover May 9, 2026
5e6a535
chore: the blender checks its own power cord
doublemover May 9, 2026
9596426
feat: puree the refinement lab into shape
doublemover May 9, 2026
7238279
feat: the blender stops over-pureeing primitives
doublemover May 9, 2026
4dade4b
feat: the blender carves the hull without spilling voxels
doublemover May 9, 2026
5d63b87
feat: blend every candidate into an evaluation packet
doublemover May 9, 2026
8057171
feat: teach the blender to keep receipts for inputs
doublemover May 9, 2026
487557c
feat: the blender writes recipes before soup
doublemover May 9, 2026
e4d430c
feat: the blender labels every smoothie cup
doublemover May 9, 2026
9324bec
feat: the blender starts choosing its own next smoothie
doublemover May 9, 2026
b0bccd6
feat: the blender follows the recipe card
doublemover May 9, 2026
2098e13
feat: the blender measures the chunks after pouring
doublemover May 9, 2026
3776fb2
feat: the blender asks for a better angle
doublemover May 9, 2026
3626a90
test: the blender knows recipe mode is intentional
doublemover May 9, 2026
8e37130
feat: the blender times the fancy measuring cups
doublemover May 9, 2026
2f5a98e
feat: the blender judges the held-out smoothie photo
doublemover May 9, 2026
e05b44d
feat: the blender grades how editable the puree is
doublemover May 9, 2026
fc1c2b8
feat: the blender inspects the takeout cup
doublemover May 9, 2026
593f233
feat: the blender spins the silhouette recipe
doublemover May 9, 2026
6afb59a
feat: the blender refuses watery hull foam
doublemover May 9, 2026
6093752
feat: the blender rejects sour gradients
doublemover May 9, 2026
5c8ec8d
feat: the blender notices stale puree
doublemover May 9, 2026
4038b0a
feat: the blender counts the recipe crumbs
doublemover May 9, 2026
43a16d9
feat: the blender ships the smoothie and checks the cup
doublemover May 9, 2026
ef626f6
feat: the blender crops the chunky bits
doublemover May 9, 2026
ebaf731
feat: the blender labels every smoothie cup
doublemover May 9, 2026
37c1626
feat: the blender hires a patch sommelier
doublemover May 9, 2026
7d75326
feat: the blender straightens every patch straw
doublemover May 9, 2026
12da12f
feat: the blender rejects empty measuring cups
doublemover May 9, 2026
69dfa2d
feat: the blender reads the nutrition label
doublemover May 9, 2026
d9540a0
chore: the blender wipes the counter clockwise
doublemover May 9, 2026
2b98e53
feat: the blender reads its own tea leaves
doublemover May 9, 2026
5420b06
feat: the blender writes tomorrow's recipe
doublemover May 9, 2026
d11b1e3
feat: the blender reuses yesterday's smoothie
doublemover May 9, 2026
39af827
fix: the blender stops guessing the button
doublemover May 9, 2026
a28ff37
feat: the blender takes encore requests
doublemover May 9, 2026
44e4017
chore: the blender hides the tiny kitchen
doublemover May 9, 2026
1ae6f3b
chore: puree the optional deps into something smooth
doublemover May 9, 2026
40ca24e
blend the metrics until they stop lying
doublemover May 9, 2026
4095ea1
quality: puree the silhouette soup without stalling
doublemover May 9, 2026
bac3df3
metrics: blend the recoverable truth smoothie
doublemover May 9, 2026
76b8894
autopsy: ask for another blender angle
doublemover May 9, 2026
587c490
shape: whip residual patches into blender dough
doublemover May 9, 2026
5a875d7
topology: puree the mesh without inventing soup
doublemover May 9, 2026
4bfe042
gaussian: turn splats into blender dumplings
doublemover May 9, 2026
050827a
calibration: spin the suspicious viewport smoothie
doublemover May 9, 2026
485a5fe
mesh: smooth the blender batter with guardrails
doublemover May 9, 2026
9f11164
boundary: sharpen the blender lid before it leaks
doublemover May 9, 2026
ccc0673
plan: blend the autopsy into tomorrow's smoothie
doublemover May 9, 2026
6010c2f
schema: make the blender remember its recipe
doublemover May 9, 2026
1e92765
silhouette: stop the blender averaging away the leak
doublemover May 9, 2026
2ee8792
lineage: label every smoothie jar
doublemover May 9, 2026
6e90d44
rank: stop the blender crowning soup
doublemover May 9, 2026
1098fda
loop: teach the blender to taste twice
doublemover May 9, 2026
bbd322f
views: blend the disagreement into the next angle
doublemover May 9, 2026
58d20a2
grammar: make the blender speak fluent shapes
doublemover May 9, 2026
35db1a9
proxy: puree the ellipsoids into a field
doublemover May 9, 2026
bb99a67
topology: make the blender ask before smoothing
doublemover May 9, 2026
042ac34
loss: blend the edges until they confess
doublemover May 9, 2026
dd14e12
baseline: liquefy the goalposts responsibly
doublemover May 9, 2026
0ca3f83
metrics: make the blender flinch on purpose
doublemover May 9, 2026
219b117
cost: count every blender pulse
doublemover May 9, 2026
bae989f
profiles: blend the fuzzy edges into bands
doublemover May 9, 2026
0414b14
sdf: make the blender find the invisible rind
doublemover May 9, 2026
523f0b1
views: blend the novel angles into the scoreboard
doublemover May 9, 2026
cf7d79d
study: give the blender a sculptor scorecard
doublemover May 9, 2026
38c84da
cache: let the blender remember its chunks
doublemover May 9, 2026
ea92d8b
retopo: make the blender judge its own soup
doublemover May 9, 2026
29ab473
calib: let the blender scoot the shadows
doublemover May 9, 2026
f579da8
calib: put mask scooting on the blender menu
doublemover May 9, 2026
812bd49
cost: make the blender bill itself
doublemover May 9, 2026
8cc13ea
patches: make the blender touch up the lumpy bits
doublemover May 9, 2026
7e578c2
params: make the blender stop hiding the knobs
doublemover May 9, 2026
0b24df7
texture: make the blender stop painting over dents
doublemover May 9, 2026
c489599
shape: make the blender read the paint label
doublemover May 9, 2026
462d2bc
knobs: let the blender demand honest paint
doublemover May 9, 2026
8c1971b
adapt: make the blender panic about bad decals
doublemover May 9, 2026
10e7c8c
materials: teach the blender to read its labels
doublemover May 9, 2026
86c1227
lab: let the blender grade its paint job
doublemover May 9, 2026
cc4a340
patches: make the blender spot-treat silhouettes
doublemover May 9, 2026
8a3d7dd
views: pour held-out angles into the blender
doublemover May 9, 2026
cff8083
costs: make the blender count its own spins
doublemover May 9, 2026
0656c9e
curriculum: make the blender take harder exams
doublemover May 9, 2026
474f14c
surrogate: teach the blender to bet on winners
doublemover May 9, 2026
b7abd9c
pareto: make the blender stop picking only one smoothie
doublemover May 9, 2026
393effe
uncertainty: make the blender admit blurry edges
doublemover May 9, 2026
e4afdc4
config: blend the settings into smaller jars
doublemover May 10, 2026
da89204
refinement: whisk the e2e lab out of the pitcher
doublemover May 10, 2026
c5a7ea9
reconstruction: frappe the backend monoliths
doublemover May 10, 2026
0c9d633
benchmarks: pulse the moonshot smoothie button
doublemover May 10, 2026
cf5d4f8
benchmarks: puree the stopwatch into smaller cups
doublemover May 10, 2026
90a17d4
e2e: dice the cli onions without tears
doublemover May 10, 2026
a8f74dd
resfit: knead primitive fitting into layers
doublemover May 10, 2026
f847544
proxy: emulsify ellipsoids without curdling
doublemover May 10, 2026
3a9ec80
reconstruction: strain hulls and point clouds cleanly
doublemover May 10, 2026
0203485
refinement: whip adaptive loops into neat peaks
doublemover May 10, 2026
803f34f
resfit: blend the missing profile garnish
doublemover May 10, 2026
42fcb7c
blend output paths until they stop making a scene
doublemover May 10, 2026
6825472
blend the masks until they confess
doublemover May 10, 2026
65a3b91
blend torch until it stops smoking
doublemover May 10, 2026
d7e00bf
Keep the smoothie paths from overflowing the pitcher
doublemover May 11, 2026
dff9fdc
Stop pretending the smoothie has a lid
doublemover May 11, 2026
c7924e8
fix: stop making metric smoothies in the blender
doublemover May 11, 2026
3ac25fd
Blend it like you mean it
doublemover May 11, 2026
3796648
Whisk the metrics until they peak
doublemover May 11, 2026
f9aeaef
Pulse the no-ops until they confess
doublemover May 11, 2026
fc9d913
Give every primitive a turn in the puree
doublemover May 11, 2026
705ddc4
Blend the parents before they curdle
doublemover May 11, 2026
9a72b44
Teach the Gaussian blender to read the lid
doublemover May 11, 2026
97ae14f
Whip the SDF until it holds peaks
doublemover May 11, 2026
98573cf
Fold the chair before it folds itself
doublemover May 11, 2026
d1891dc
Stop the blender before the marathon
doublemover May 11, 2026
9f3f9dd
Measure the smoothie before the big blend
doublemover May 11, 2026
6624a2c
Reuse the puree without promoting the taste test
doublemover May 11, 2026
2750f28
Name the failed blend before tasting it
doublemover May 11, 2026
b918dcd
Label the geometry smoothie cup
doublemover May 11, 2026
86858b9
Keep proxy smoothies out of the trophy cup
doublemover May 11, 2026
d71a5f1
Repair the topology smoothie before serving
doublemover May 11, 2026
3b4c40e
Keep blocked blends in the diagnostic jar
doublemover May 11, 2026
73044de
Label the leftover blend before reusing it
doublemover May 11, 2026
71ae815
Count the cached smoothies in the receipt
doublemover May 11, 2026
69552ed
Teach the blender to cough up bad chunks
doublemover May 11, 2026
fbde785
Teach the blender to stop pureeing moonshot evidence
doublemover May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 5 additions & 5 deletions .github/workflows/blender-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
$BLENDER_PYTHON -m pip --version

# Install dependencies
$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt

# Verify installation
$BLENDER_PYTHON -c "import numpy, cv2, PIL, scipy; print('Dependencies installed')"
$BLENDER_PYTHON -c "import numpy, cv2, PIL, scipy, skimage, open3d; print('Dependencies installed')"

- name: Run test suite
run: |
Expand Down Expand Up @@ -76,8 +76,8 @@ jobs:
run: |
BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*' | head -1)
echo "Blender Python: $BLENDER_PYTHON"
$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
$BLENDER_PYTHON -c "import numpy, cv2, PIL, scipy; print('Dependencies installed')"
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt
$BLENDER_PYTHON -c "import numpy, cv2, PIL, scipy, skimage, open3d; print('Dependencies installed')"

- name: Run test suite
run: |
Expand Down Expand Up @@ -107,7 +107,7 @@ jobs:
- name: Install dependencies
run: |
BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*' | head -1)
$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt

- name: Run quick tests
run: |
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ stacked_cubes.py
__pycache__/
*.py[cod]
*$py.class
.venv/
.venv*/
venv/

# Blender temp files
*.blend1
*.blend2

# Generated test artifacts
temp/
test_output/
test_images/
blender_blocking/test_images/
blender_blocking/test_output/
Expand Down
53 changes: 51 additions & 2 deletions blender_blocking/BLENDER_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Complete guide to configuring Blender's Python environment to use the blocking t

## The Challenge

Blender bundles its own Python interpreter, which doesn't have access to your virtual environment by default. We need to make the dependencies (numpy, opencv-python, Pillow, scipy) available to Blender's Python.
Blender bundles its own Python interpreter, which doesn't have access to your virtual environment by default. We need to make the dependencies (numpy, opencv-python, Pillow, scipy, scikit-image, and Open3D) available to Blender's Python.

## REQUIRED Setup: Install to Blender's Python

Expand Down Expand Up @@ -69,6 +69,8 @@ import numpy as np
import cv2
from PIL import Image
import scipy
import skimage
import open3d

print("✓ All dependencies available!")

Expand Down Expand Up @@ -122,9 +124,56 @@ Or install for user only:

Version mismatch between numpy and Blender's Python. Install a compatible version:
```bash
$BLENDER_PYTHON -m pip install "numpy<2.0" opencv-python Pillow scipy
$BLENDER_PYTHON -m pip install -r /path/to/blendslop/blender_blocking/requirements.txt
```

### Visual hull only emits point clouds instead of meshes

Install or repair `scikit-image` in Blender's Python. Visual hull marching-cubes extraction requires `skimage.measure.marching_cubes`.

```bash
$BLENDER_PYTHON -m pip install scikit-image
```

### Poisson postprocess is skipped

Install or repair `open3d` in Blender's Python. Poisson and screened-Poisson postprocess modes are explicit optional stages and will report a structured skip when Open3D is unavailable.

```bash
$BLENDER_PYTHON -m pip install open3d
```

### LPIPS / torch / torchvision are unavailable

`torch`, `torchvision`, and `lpips` are optional research dependencies used by LPIPS novel-view scoring and some experimental differentiable paths. On Windows/Blender 5, use the repository repair command instead of a loose `pip install torch`, because newer CPU wheels can import in Blender's standalone `python.exe` but fail once loaded inside the Blender process.

```powershell
$BLENDER_PYTHON = "C:\Program Files\Blender Foundation\Blender 5.0\5.0\python\bin\python.exe"
& $BLENDER_PYTHON blender_blocking\verify_setup.py --install-research-deps
```

Dry-run the exact commands first:

```powershell
& $BLENDER_PYTHON blender_blocking\verify_setup.py --install-research-deps --dry-run
```

The supported plan installs the CPU-only `torch==2.5.1+cpu` / `torchvision==0.20.1+cpu` pair, `sympy==1.13.1`, and `lpips==0.1.4` into the active Blender Python user site. This is appropriate for AMD/non-CUDA machines. It does not install `nvdiffrast`.

On Windows, Open3D and CPU PyTorch can load incompatible native runtimes inside the same Blender process. The setup verifier probes the LPIPS/PyTorch stack in isolated Blender subprocesses so availability reporting cannot crash the main process. If you need both Open3D postprocessing and LPIPS metrics for one asset, run those phases in separate Blender invocations.

### OpenVDB export is skipped

OpenVDB is optional. The tool probes both `pyopenvdb` and `openvdb` bindings and falls back to sparse NPZ interchange when neither binding is available. A plain `pip install openvdb` often has no Windows wheel, so direct `.vdb` export usually requires a compatible Blender-bundled binding, conda package, or source-built OpenVDB Python binding for the exact Python runtime.

Use `require_openvdb=true`, `openvdb_required=true`, `fail_on_openvdb_skip=true`, or `export_openvdb_required=true` only when a missing direct `.vdb` binding should fail the candidate instead of recording a structured NPZ fallback.

### nvdiffrast is unavailable

`nvdiffrast` is NVIDIA's differentiable rasterizer. It is optional and not a normal dependency for this project. The `differentiable_refine` backend always has the deterministic `cpu_soft_silhouette` path; the `nvdiffrast` path is only for machines with the NVIDIA CUDA stack and the source-built NVlabs extension.

There is no official ROCm version of `nvdiffrast`. On AMD/ROCm machines, keep using `cpu_soft_silhouette` for mesh/primitive refinement, or treat ROCm GSplat-style Gaussian splatting as a separate research backend instead of a drop-in replacement.

### Different Python versions

If you see errors about missing extensions or binary incompatibility, your venv and Blender are using different Python versions. This is why you MUST install directly into Blender's Python - the compiled extensions must match Blender's Python version exactly.
Expand Down
56 changes: 49 additions & 7 deletions blender_blocking/CI_CD.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ Exit codes:
- `1`: One or more tests failed
- `2`: Test runner error (not running in Blender, etc.)

Pure-Python refinement lab coverage is included in the pure phase:

```bash
python blender_blocking/test_runner.py --phase pure --no-progress
```

Full refinement sweeps are intentionally not part of default CI because they generate reports, renders, and per-variant artifacts. Keep those under ignored `temp/refinement-runs/` and upload them only as ad hoc diagnostic artifacts when a workflow explicitly asks for them.

## GitHub Actions Workflow

Create `.github/workflows/blender-tests.yml`:
Expand Down Expand Up @@ -57,7 +65,7 @@ jobs:
echo "Blender Python: $BLENDER_PYTHON"

# Install dependencies
$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt

- name: Run tests
run: |
Expand Down Expand Up @@ -87,7 +95,7 @@ jobs:
run: |
BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*')
echo "Blender Python: $BLENDER_PYTHON"
$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt

- name: Run tests
run: |
Expand Down Expand Up @@ -121,7 +129,7 @@ test:blender-5:
before_script:
- BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*')
- echo "Installing dependencies in Blender Python $BLENDER_PYTHON"
- $BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
- $BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt
script:
- cd blender_blocking
- blender --background --python test_runner.py
Expand All @@ -140,7 +148,7 @@ test:blender-4:
image: "nytimes/blender:4.2-cpu-ubuntu22.04"
before_script:
- BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*')
- $BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
- $BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt
script:
- cd blender_blocking
- blender --background --python test_runner.py
Expand Down Expand Up @@ -177,7 +185,7 @@ docker run --rm \
nytimes/blender:5.0-cpu-ubuntu22.04 \
bash -c "
BLENDER_PYTHON=\$(blender --background --python-expr 'import sys; print(sys.executable)' 2>&1 | grep -oP '/[^ ]+python[0-9.]*')
\$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
\$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt
blender --background --python test_runner.py
"
```
Expand All @@ -191,7 +199,7 @@ FROM nytimes/blender:5.0-cpu-ubuntu22.04

# Install Python dependencies
RUN BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*') && \
$BLENDER_PYTHON -m pip install numpy opencv-python Pillow scipy
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt

# Set working directory
WORKDIR /workspace
Expand Down Expand Up @@ -219,6 +227,40 @@ Test against multiple Blender versions to catch compatibility issues early:

**Recommendation**: Test against current + previous LTS release minimum.

## Optional Refinement Diagnostics Job

Use this only for manual workflow dispatch or a failing reconstruction branch. It runs one small refinement smoke and uploads the ignored run root for inspection:

```yaml
refinement-smoke:
name: Refinement lab smoke
runs-on: ubuntu-latest
container:
image: nytimes/blender:5.0-cpu-ubuntu22.04
if: github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- name: Install dependencies in Blender Python
run: |
BLENDER_PYTHON=$(blender --background --python-expr "import sys; print(sys.executable)" 2>&1 | grep -oP '/[^ ]+python[0-9.]*')
$BLENDER_PYTHON -m pip install -r blender_blocking/requirements.txt
- name: Run refinement smoke
run: |
blender --background --python blender_blocking/test_e2e_validation.py -- \
--refinement-suite default-vase \
--refinement-track profile-loft-refinement \
--refinement-max-runs 1 \
--refinement-result-root temp/refinement-runs/ci-smoke-profile \
--refinement-html-report \
--no-progress
- name: Upload refinement artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: refinement-smoke
path: temp/refinement-runs/ci-smoke-profile
```

## What Tests Must Verify

Critical tests that must run in actual Blender:
Expand Down Expand Up @@ -296,7 +338,7 @@ chmod +x .git/hooks/pre-commit
python3 -m ensurepip --default-pip

# Or use system pip with target
pip install --target=/path/to/blender/python/lib numpy opencv-python Pillow scipy
pip install --target=/path/to/blender/python/lib -r blender_blocking/requirements.txt
```

### Tests timeout in CI
Expand Down
2 changes: 1 addition & 1 deletion blender_blocking/E2E_TESTING_FEASIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def test_reconstruction_accuracy():

# Render orthogonal views
print("Rendering orthogonal views...")
rendered_paths = render_orthogonal_views('test_output/renders/')
rendered_paths = render_orthogonal_views('../temp/renders/')

# Compare each view
print("Comparing rendered views to references...")
Expand Down
2 changes: 1 addition & 1 deletion blender_blocking/E2E_VALIDATION_SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ jobs:
uses: actions/upload-artifact@v2
with:
name: failed-renders
path: blender_blocking/test_output/e2e_renders/
path: temp/e2e/renders/
```

## Benefits
Expand Down
35 changes: 33 additions & 2 deletions blender_blocking/INTEGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ The integration combines image processing, shape analysis, and 3D primitive plac
### 6. Main Integration (`main_integration.py`)
- **BlockingWorkflow** - Main workflow class that orchestrates the entire pipeline

### 7. Refinement Lab (`refinement_lab/`)
- **contracts.py** - Typed experiment cases, variants, results, and run manifests
- **presets.py** - Built-in suites and parameter tracks
- **matrix.py** - Deterministic grid, random, coordinate, and successive-halving plan construction
- **runner.py** - In-process and subprocess execution against the E2E CLI
- **parameter_search.py** - Objective scoring and ranking
- **candidate_autopsy.py** - Structured failure diagnosis
- **bounds_debug.py** - Visual-hull transform, projection, and bounds diagnostics
- **artifact_report.py** - Static HTML reports and overlay/diff assets
- **human_labels.py** - Reviewer labels that influence human-adjusted ranking
- **cli.py** - Pure command line interface for list/plan/run/report/rank/autopsy/label/promote

## Dependencies

### Python Packages
Expand All @@ -45,13 +57,13 @@ scipy

Install Python dependencies:
```bash
pip install numpy opencv-python Pillow scipy
pip install -r requirements.txt
```

For Blender's Python environment:
```bash
# macOS example (adjust path for your Blender version)
/Applications/Blender.app/Contents/Resources/4.2/python/bin/python3.11 -m pip install numpy opencv-python Pillow scipy
/Applications/Blender.app/Contents/Resources/4.2/python/bin/python3.11 -m pip install -r /path/to/blendslop/blender_blocking/requirements.txt
```

## Usage
Expand Down Expand Up @@ -132,6 +144,24 @@ workflow.analyze_shapes()
workflow.create_3d_blockout(num_slices=15, primitive_type='CYLINDER')
```

### Refinement Lab Workflow

Use the lab when comparing reconstruction strategies or diagnosing a bad output. The lab builds a plan, executes variants, writes structured results, and ranks them by objective:

```bash
python -m blender_blocking.refinement_lab.cli list-suites
python -m blender_blocking.refinement_lab.cli list-tracks
python -m blender_blocking.refinement_lab.cli plan --suite default-vase --track visual-hull-transform --max-runs 4 --out temp/refinement-runs/plan-smoke.json
```

Run through Blender:

```bash
blender --background --python blender_blocking/test_e2e_validation.py -- --refinement-suite default-vase --refinement-track visual-hull-transform --refinement-search coordinate --refinement-max-runs 48 --refinement-result-root temp/refinement-runs/default-vase-vh-transform --refinement-bounds-debug --refinement-autopsy --no-progress
```

The run root includes `manifest.json`, `plan.json`, `index.jsonl`, `leaderboard.md`, `report.html`, per-variant `result.json`, optional `autopsy.json`, and optional `bounds-debug.json`. Generated run roots are ignored and must not be committed.

## Workflow Steps

The integration follows these steps:
Expand All @@ -153,6 +183,7 @@ The integration follows these steps:
7. **Place Primitives** - Position and scale primitives for each slice
8. **Boolean Union** - Join all primitives into single mesh
9. **Scene Setup** - Add camera and lighting for rendering
10. **Optional Refinement Loop** - Sweep candidate parameters, inspect report/autopsy output, label winners, and promote the best reproducible configuration

## Example Output

Expand Down
29 changes: 29 additions & 0 deletions blender_blocking/QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,30 @@ mesh = workflow.run_full_workflow(num_slices=20)
mesh = workflow.run_full_workflow(num_slices=8)
```

## Refining Reconstruction Quality

When a result is close but not good enough, use the refinement lab instead of hand-editing one knob at a time. It sweeps reconstruction modes and parameters, ranks candidates, writes autopsies, and produces an HTML report under ignored `temp/refinement-runs/`.

Plan a small run without opening Blender:

```bash
python -m blender_blocking.refinement_lab.cli plan --suite default-vase --track profile-loft-refinement --max-runs 4 --out temp/refinement-runs/plan-smoke.json
```

Run one actual Blender refinement smoke:

```powershell
& "C:\Program Files\Blender Foundation\Blender 5.0\blender.exe" --background --python blender_blocking\test_e2e_validation.py -- `
--refinement-suite default-vase `
--refinement-track profile-loft-refinement `
--refinement-max-runs 1 `
--refinement-result-root temp\refinement-runs\smoke-profile `
--refinement-html-report `
--no-progress
```

See [REFINEMENT_LAB.md](REFINEMENT_LAB.md) for visual-hull diagnostics, ranking, labels, and promotion commands.

## Troubleshooting

### "No module named numpy" or dependency errors
Expand Down Expand Up @@ -193,6 +217,11 @@ Pillow has compiled C extensions that must match Blender's Python version exactl
- Reduce `num_slices` to 8 or 10
- Check that your images have clear silhouettes

### Visual hull mesh extraction is skipped
- Install `scikit-image` into Blender's Python; visual hull marching cubes needs `skimage.measure`.
- If Poisson postprocess is skipped, install `open3d` into Blender's Python.
- Run `verify_setup.py` from Blender's Python console to confirm both packages are visible to Blender.

### Import errors

Make sure you:
Expand Down
Loading