Case study — 3D placement pipeline

A 3D placement pipeline from Blender to render farm

Designers drop smart furniture slots into Blender scenes; a placement engine matches real products and a serverless GPU farm renders the finished interiors.

Try the live demo30 seconds · representative sample data · nothing leaves your browser
Year
2025–2026
Role
Plugin · engine · infrastructure
Status
In production
Stack
Blender 4.2 Extension API · Python · FastAPI · AWS ECS Fargate · Redis · Cloudflare R2
Relationship
Selected delivery work; the public case uses a functional project name.
Market
3D interior-production workflow; client identity is not disclosed publicly.

The problem

Interior renders don't scale by hand.

A visualization team furnishing apartment scenes manually places every bed, sofa, and lamp — then re-places all of it for the next layout variation, and the next product swap. At catalog scale that's thousands of designer-hours spent dragging furniture.

The brief: let designers define where furniture goes and what class it is once, then let software choose the right catalog product, place it, and render the finished room — repeatably, for any SKU combination.

The system

How it fits together.

Blender pluginsmart slots · SKUsScene exportGLB + JSONPlacement enginecatalog matchRender queueRedisGPU render farmECS FargateDeliveryR2 presigned

simplified public map of implemented components and boundaries

Try it

Place the furniture yourself.

Drag the slots around the room. The bounds validation is the plugin's real AABB logic, the usage classes and dimension ranges come from the production category map, and the JSON panel shows the exact export format the placement engine consumes. Put the lamp somewhere it doesn't belong and watch it complain.

Interactive demo — representative data in your browser
window6.0m × 4.5mArea rugBedSofaCoffee tableTable lamp

drag to move · tap to select · arrow keys to nudge — bounds validation is the plugin's real AABB logic

Live export · the engine's real input format

{
 "apartment": "demo_studio_01",
 "designer": "zawish.site visitor",
 "slots": [
  {
   "slot_id": "slot_room1a_Bed_Generic_01",
   "usage_class": "Bed_Generic",
   "sku": "BED-1042",
   "pivot": "bottom",
   "position_m": [
    1.1,
    1.35
   ],
   "dims_min": [
    1.1065,
    0.0762,
    1.27
   ],
   "dims_max": [
    1.6256,
    2.1336,
    1.4478
   ],
   "valid": true
  },
  {
   "slot_id": "slot_room1a_Seating_Large_02",
   "usage_class": "Seating_Large",
   "sku": "SOF-2210",
   "pivot": "bottom",
   "position_m": [
    4.2,
    3.8
   ],
   "dims_min": [
    1.2192,
    0.5588,
    0.6096
   ],
   "dims_max": [
    2.8448,
    1.6766,
    0.9131
   ],
   "valid": true
  },
  {
   "slot_id": "slot_room1a_Surface_Low_03",
   "usage_class": "Surface_Low",
   "sku": "TBL-0870",
   "pivot": "bottom",
   "position_m": [
    4.2,
    2.5
   ],
   "dims_min": [
    1.2192,
    0.508,
    0.4582
   ],
   "dims_max": [
    1.2192,
    0.508,
    0.4582
   ],
   "valid": true
  },
  {
   "slot_id": "slot_room1a_Decor_Rug_04",
   "usage_class": "Decor_Rug",
   "sku": "RUG-3301",
   "pivot": "bottom",
   "position_m": [
    4.2,
    2.9
   ],
   "dims_min": [
    0.6096,
    0.9144,
    0.0254
   ],
   "dims_max": [
    3.048,
    4.2672,
    0.0254
   ],
   "valid": true
  },
  {
   "slot_id": "slot_room1a_Lighting_Tabletop_05",
   "usage_class": "Lighting_Tabletop",
   "sku": "LMP-0114",
   "pivot": "tabletop",
   "position_m": [
    4.2,
    2.5
   ],
   "dims_min": [
    0.3709,
    0.2127,
    0.5153
   ],
   "dims_max": [
    0.5066,
    0.3709,
    0.5564
   ],
   "valid": true
  }
 ]
}

The build

One pipeline, three systems.

01

Smart slots instead of meshes

Inside Blender, designers place MetaFurniture bundles — a metadata anchor, a proxy shape, and min/max bounding boxes per usage class. A bed slot knows it's a bed, what sizes are acceptable, and which room volume it sits in (point-in-bounds AABB detection).
Blender 4.2 · N-panel UI
02

A placement engine that shops the catalog

The exported JSON + GLB feed an engine that matches each slot against a 257-product library across 42 usage classes — filtering by category, fitting by bounds, and loading the winning model into the scene.
FastAPI · GLB loader · raycasting
03

Queued rendering without idle workers

Finished scenes queue into serverless GPU containers that spin up per job, run Blender headless, upload frames to storage, and terminate. This keeps interactive preparation separate from compute-heavy rendering.
ECS Fargate · Redis · R2
04

Validation before anything renders

Scale checks, collision checks, and SKU verification run at export — a bad scene fails in the designer's viewport in seconds, not on a GPU thirty minutes later. The demo above enforces the same rule.
export gate · schema validation

Implementation evidence

Usage classesplacement intent is expressed independently of individual products
GLB + JSONgeometry and placement intent travel as a small explicit contract
Queued workersremote rendering is isolated from interactive scene preparation

Constraint

Scene intent had to survive the handoff from an artist tool to a catalog matcher and remote render workers.

Tradeoff

A small, explicit GLB and JSON contract is used instead of coupling Blender files directly to the rendering service.

The public demo shows the placement contract and export behavior with representative products; operational volume is intentionally not claimed.

For your business

Discuss a related system.

If your business produces repeatable 3D content — real estate, furniture, product visualization, e-commerce staging — this pipeline pattern replaces per-image artist time with a system: author once, render every variation. We build the plugin, the engine, and the infrastructure.

Next caseA production suite for AI campaign visuals →