MeshForge is an end-to-end pipeline that converts 2D CAD floor plans (DWG/DXF) into unified 3D mesh models. The pipeline is split into four sequential phases, each implemented as a standalone Jupyter notebook designed to run on Google Colab with GPU support.
DWG/DXF Floor Plan
|
v
Phase 1: Segmentation (SAM)
|
v
Phase 2: ControlNet Rendering
|
v
Phase 3: 3D Mesh Generation (Hunyuan3D)
|
v
Phase 4: Mesh Stitching
|
v
Unified 3D Mesh (.glb)
Notebook: phase 1.ipynb
Reads a DXF floor plan and segments it into meaningful regions using Meta's Segment Anything Model (SAM). The process works as follows:
- Parses the DXF file and renders it to a high-resolution overview image via custom SVG-to-PNG conversion.
- Builds a multi-scale density map using Gaussian blurring to locate areas with concentrated geometry.
- Applies watershed segmentation to identify distinct region candidates.
- Classifies regions by size: normal regions are fed to SAM with box prompts, large regions are kept as-is for downstream handling, and noise (tiny fragments) is discarded.
- For each valid region, renders a high-resolution tile from the original DXF data.
- Computes spatial adjacency between segments for use in Phase 4.
Key outputs: segments_meta.json (segment IDs, DXF bounding boxes, adjacency graph), tile PNGs in density_tiles/.
Main dependencies: ezdxf, cairosvg, segment-anything, torch, opencv-python, scipy
Notebook: phase 2.ipynb
Transforms 2D CAD wireframe tile images into realistic 3D-looking rendered images using Stable Diffusion 1.5 with ControlNet (lineart conditioning). Each tile from Phase 1 is processed to produce a clean SolidWorks-style 3D render that Hunyuan3D can interpret in Phase 3.
- Extracts a line-art control map from the input CAD tile using the LineartDetector.
- Runs the ControlNet-conditioned Stable Diffusion pipeline with a prompt engineered for clean, studio-lit CAD renders on a white background.
- Generates multiple render variants per tile and saves results to Google Drive for persistence.
Key outputs: Rendered PNG images in /content/outputs/ and backed up to Google Drive.
Main dependencies: diffusers, transformers, controlnet-aux, accelerate, torch
Requires: GPU runtime (T4 or better). A runtime restart is needed after installing packages.
Notebook: phase 3.ipynb
Converts the rendered 2D images from Phase 2 into 3D mesh geometry using Tencent's Hunyuan3D-2 Mini model. Each rendered tile image is turned into a .glb mesh file.
- Removes the image background using
rembg(or a simple white-threshold fallback). - Loads the Hunyuan3D-2 Mini pipeline with weights cached to Google Drive (~25 GB on first run).
- Runs single-image-to-3D inference with 30 diffusion steps and octree resolution of 380.
- Exports the resulting trimesh geometry as a GLB file.
Key outputs: .glb mesh files in /content/mesh_results/.
Main dependencies: hunyuan3d (hy3dgen), trimesh, rembg, torch, safetensors, pymeshlab
Requires: GPU runtime. Model weights are downloaded once and cached on Google Drive.
Notebook: phase 4.ipynb
Assembles all individual segment meshes from Phase 3 into a single unified 3D model using the spatial metadata from Phase 1.
- Loads all
.obj/.glbmesh files and matches them to segments viasegments_meta.json. - Transforms each mesh from its local normalized coordinate space into global DXF coordinates using the bounding boxes from Phase 1.
- Resolves overlaps between neighboring segments by clipping meshes at the midpoint of overlap zones.
- Detects boundary vertices near segment edges and aligns them between neighboring meshes using a KD-tree nearest-neighbor search.
- Concatenates all meshes, welds duplicate vertices, and performs Laplacian boundary smoothing.
- Cleans up degenerate/duplicate faces, fixes normals, and exports the final unified mesh.
Key outputs: unified_mesh.glb, unified_mesh_preview.png (multi-view matplotlib render).
Main dependencies: trimesh, scipy, numpy, networkx
- A Google account with ~30 GB of free Drive space (for model weight caching).
- Upload all four notebooks (
phase 1.ipynbthroughphase 4.ipynb) to Google Colab.
Runtime: CPU is enough, but GPU speeds up SAM inference.
- Open
phase 1.ipynbin Colab. - Run Cell 1 — installs
ezdxf,cairosvg,segment-anything, etc. - Run Cell 2 — downloads the SAM
vit_hcheckpoint (~2.5 GB). Skips if already present. - Run Cell 3 — imports libraries.
- Run Cell 4 — you will be prompted to upload your
.dxffile. - The cell also sets all pipeline parameters:
OVERVIEW_PX = 2048— resolution of the overview render.TILE_LONG_EDGE_PX = 8192— resolution of each segment tile.DENSITY_THRESHOLD = 0.06— sensitivity for region detection.- No changes needed for the test file; defaults work out of the box.
- Run Cells 5–12 sequentially (Run All is fine). The pipeline will:
- Render the full DXF as a 2048 px overview image.
- Build a density map and detect region candidates.
- Run SAM on each normal-sized region to refine masks.
- Save high-res tiles and compute segment adjacency.
- Run Cell 13 — downloads
density_sam_results.zipcontaining:
| Output file | What it is |
|---|---|
segments_meta.json |
Segment IDs, DXF bounding boxes, neighbor lists — needed by Phase 4 |
density_tiles/tile_0000.png, tile_0001.png, ... |
High-res tile PNGs of each segment — feed these into Phase 2 |
density_overlay.png |
Color overlay showing all detected segments |
density_comparison.png |
Side-by-side of overview vs. segmented overlay |
Save segments_meta.json and the density_tiles/ PNGs — you will need both later.
Runtime: GPU required (T4 or better). Change via Runtime → Change runtime type → T4 GPU.
You must run Phase 2 once per tile from Phase 1. Pick a tile to start (e.g., tile_0000.png).
- Open
phase 2.ipynbin Colab. - Run Cell 1 — installs
diffusers,transformers,controlnet-aux, etc. After this cell finishes, restart the runtime (Runtime → Restart session). - Run Cell 2 — mounts Google Drive and sets up the model cache directory at
MyDrive/colab_model_cache/. First run downloads ~5 GB of model weights to Drive; subsequent runs load from cache. - Run Cell 3 — before running, upload your tile PNG to Colab and update the path:
The other parameters can stay at their defaults:
INPUT_IMAGE_PATH = "/content/tile_0000.png" # <-- change to your tile filename
NUM_IMAGES = 4— generates 4 render variants to choose from.TARGET_SIZE = 768— resize resolution for Stable Diffusion.GUIDANCE_SCALE = 12.0andCONTROLNET_CONDITIONING_SCALE = 1.3— tuned for CAD input.
- Run Cells 4–7 — loads models and generates rendered images (~2–3 minutes on T4).
- Run Cell 8 — displays all renders and saves them:
/content/outputs/render_01.pngthroughrender_04.png- Also backed up to
MyDrive/colab_model_cache/renders/.
Pick the best render (cleanest 3D appearance, no artifacts) for each tile. Save these render PNGs — they are the input for Phase 3.
Repeat for each tile from Phase 1.
Runtime: GPU required (T4 or better).
You must run Phase 3 once per rendered image from Phase 2.
- Open
phase 3.ipynbin Colab. - Run Cell 1 — mounts Google Drive. Cache directory:
MyDrive/3D_Models_Cache/. - Run Cell 2 — installs
trimesh,rembg,pymeshlab, etc. - Run Cell 3 — before running, upload your best render PNG to
/content/input/or just upload it when prompted. The cell auto-detects images in/content/input/. - Run Cell 4 — downloads Hunyuan3D-2 Mini weights (~25 GB) to Google Drive on first run. Cached for future runs.
- Run Cell 5 — runs the image-to-3D pipeline:
- Removes the background with
rembg. - Generates a 3D mesh using 30 inference steps at octree resolution 380.
- Exports the mesh as
hunyuan3d_output.glbin/content/mesh_results/.
- Removes the background with
- Run Cell 6 — zips and downloads the result.
Save the .glb file. Name it to match the segment (e.g., rename hunyuan3d_output.glb to seg_0000.glb) so Phase 4 can match it to segments_meta.json.
Repeat for each rendered tile.
Runtime: CPU is enough.
- Open
phase 4.ipynbin Colab. - Run Cell 1 — installs
trimesh,scipy,networkx. - Run Cell 2 — sets configuration. The defaults are fine:
MESHES_DIR = '/content/meshes' SEGMENTS_META_PATH = '/content/segments_meta.json' UPLOAD_FILES = True OUTPUT_FILENAME = 'unified_mesh.glb'
- Run Cell 3 — you will be prompted to upload files in two steps:
- First prompt: upload all your
.glbmesh files from Phase 3 (e.g.,seg_0000.glb,seg_0001.glb, ...). - Second prompt: upload
segments_meta.jsonfrom Phase 1.
- First prompt: upload all your
- Run Cells 4–14 sequentially. The pipeline will:
- Match each mesh to its segment ID using the metadata.
- Transform meshes from local space to global DXF coordinates.
- Clip overlapping meshes at their shared boundaries.
- Align and weld boundary vertices between neighbors.
- Smooth boundary seams and clean up the final mesh.
- Run Cell 15 — renders a multi-view preview (top, front, perspective).
- Run Cell 16 — downloads the final outputs:
| Output file | What it is |
|---|---|
unified_mesh.glb |
The final stitched 3D model — open in any GLB viewer (e.g., glTF Viewer) |
unified_mesh_preview.png |
Multi-angle matplotlib preview |
- Python 3.8+
- Google Colab with GPU runtime (T4 or better recommended)
- Google Drive (for model weight caching in Phases 2 and 3)
- ~30 GB Drive space for model weights on first run