No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗See your dream room before you buy anything.
Photograph your room — one shot per surface — and RoomDraft rebuilds it as real 3D geometry: four walls, floor and ceiling, each textured from the photo that saw it. Put your actual bed, desk and wardrobe in, then drop in aesthetic decor that is sized to its true centimetres, snaps to your real walls, rests on your real desk, and refuses to clip through anything.
npm install
npm run dev # http://localhost:3000
Node 20+. No API keys, no accounts. It runs entirely in the browser.
There is a Python service in backend/ that reads depth and finds
furniture, turning the corner-marking step from a guess into a correction.
pip install -r backend/requirements.txt
npm run api # http://localhost:8000
The app does not need it. If nothing is listening, onboarding solves the perspective in the browser exactly as before — the service is an upgrade to one step, not a dependency, and that is enforced by the order the code runs in rather than by a try/catch: the local solve runs first and unconditionally, so a usable answer is already on screen before the service is even asked. A cold or wedged backend costs the user a 25-second timeout at worst.
Most "room designer" tools either make you build a floor plan by hand or paste flat PNG stickers over your photo. RoomDraft does neither. It builds a metric room, so a 60 x 90 cm poster is literally 0.6 x 0.9 world units against a wall of known width. Every downstream feature - automatic scaling, snapping, collision, stacking, the before/after - falls out of that one decision.
The good path. Shoot each wall square-on, plus the floor and the ceiling, and mark four corners in each. Every surface is then textured from the frame that actually saw it: no grazing angles, no stretched pixels, no blank walls.
Rectification - lib/room/homography.ts
Four marked corners define a homography from the surface's unit square onto the
photo. That is exact - no camera pose, no focal length, no assumption about
where the photographer stood. A surface with no photo simply renders as clean
paint, so skipping the ceiling costs nothing.
Scale - typed, not inferred Six independent photos share no camera to solve scale from, and a per-photo estimate would compound error across six surfaces into a visibly out-of-proportion room. So the dimensions are measured and typed, with a live plan view that makes a typo obvious.
For trying it out. One image, perspective solved, a room built around it: the wall you shot looks right and the rest is clean paint. Projects created this way keep working and can have surface photos added later.
With the analysis service running, this path gets measured rather than estimated: depth fixes the room's real proportions, the four corners arrive already on the wall, and furniture the detector recognised is placed at its true size. What was measured and what was assumed is shown, not averaged into one confident-looking number — see backend/README.md for why that distinction is the interesting part.
1. Vanishing point - lib/room/perspective.ts
Downscale, Sobel, then a gradient-guided Hough transform (each edge pixel votes
only near its own gradient direction, ~90x cheaper than a full sweep), keeping
the diagonal lines - in a room photo those are the receding edges - and
intersecting them by weighted least squares. ~40 ms, no model weights, no
network call.
2. Back wall - the user confirms it Four draggable corners over the photo, seeded from the estimate along the rays from the vanishing point to the image corners (the "spidery mesh" of Tour Into The Picture, Horry et al. 1997).
3. Metric scale - one honest assumption A single image cannot determine absolute scale. RoomDraft fixes it with the camera's height above the floor, exposed as a slider rather than hidden as a magic number, and derives everything else from the pinhole geometry.
lib/room/mesh.tsEach surface is subdivided into a grid and every vertex solved exactly -
through a homography in full mode, through the reconstructed camera in quick
mode. Mapping a plane into an image is projective, but GPUs interpolate UVs
affinely per triangle, so two triangles per wall gives a visible crease down the
diagonal of a foreshortened floor. Each vertex also carries a coverage weight,
and the room material dissolves from photo texture into flat palette colour
exactly where no photo reached.
A room full of decor floating in an empty box is not your room. Furniture
(lib/catalog/furniture.ts) puts the real volumes in:
lib/room/wallPlacement.ts. Draw a box around your
wardrobe in a wall photo and the wall's homography converts those pixels back
to metres: real width, real height, real position along that wall, with the
traced crop textured onto its face.Furniture reuses the Product shape deliberately, so placement, collision,
stacking, gravity and undo all work on it unchanged. Heights are the surface
height, not the silhouette - a bed is 50 cm because that is where a book would
land; headboards and chair backs are drawn above the box on purpose.
The payoff is that you can now put a lamp on your desk. Small objects prefer a real tabletop over the floor, ranked by what the furniture is for - a desk and a nightstand exist to have things on them, a bed does not.
The gap between "a 3D box with shapes in it" and "my room with that lamp in it" is almost entirely lighting and contact. The things that close it here:
This is the beginning of the README. Read the rest at the original. Read the full README ↗