One room, thirteen kinds of 3D

Every 3D product we could build from a single iPhone LiDAR scan, side by side (2026-10-14)

한국어
What was done: one room (about 3.5 m × 3.65 m, ceiling 2.34 m) was scanned with the free Modelar app on a LiDAR iPhone, walking for about 11 minutes. The app's single export archive (544 MB) was moved to the arcAI server, and since it was the first try, every feasible method was run on its contents (thirteen, including a combination from the research, ⑪ with the strengths of all combined, ⑫ with its holes filled, and ⑬ as original-resolution tiles).

Open 3D tour (inside · dollhouse · floor plan) →

End-to-end pipeline

flowchart LR
  A["iPhone + Modelar app
~11 min walking scan"] --> B["One 544 MB archive
Windows D: → arcAI server"] B --> C["Format decoding
Cloud.log · Mesh.scn · camera json"] C --> M1["① App mesh
extracted as is"] C --> M2["② LiDAR points
padding removed"] C --> P["568 camera poses
ARKit → RS · COLMAP conventions"] P --> M3["③ RealityScan
locked poses → mesh → LiDAR colours"] P --> M4["④ Gaussian splat
gsplat 30k steps"] M2 --> M4 M2 --> M5["⑤ Splat + LiDAR depth
+ pose refinement"] P --> M5 M2 --> M6["⑥ LiDAR mesh
Open3D Poisson"] P --> M7["⑦ WebODM (ODM)
iPhone poses as fake GPS"] P --> M8["⑧ 2D Gaussian splat
surface-aligned"] M2 --> M8 C --> M9["⑨ VGGT (AI)
depth AI · pose iPhone · scale LiDAR"] P --> M9 M2 --> M9 M9 --> M10["⑩ Splat from VGGT points
+ depth + pose refinement"] M2 --> M11["⑪ TSDF mesh from 1,572 LiDAR depth frames + photo texture
texrecon area (ODM texture engine)"] P --> M11 M11 --> M12["⑫ ⑪ + holes filled with VGGT depth only
(where LiDAR missed, e.g. black objects)"] M9 --> M12 M11 --> M13["⑬ ⑪ as 3D Tiles
(original 4096 textures up close)"] M1 & M2 & M3 & M4 & M5 & M6 & M7 & M8 & M9 & M10 & M11 & M12 & M13 --> W["Web compression
GLB · PLY · splat · 3D Tiles"] W --> X["Cloudflare Pages
this page"] classDef app fill:#fef3c7,stroke:#f59e0b,stroke-width:3px,color:#78350f classDef lidar fill:#d1fae5,stroke:#10b981,stroke-width:3px,color:#064e3b classDef rs fill:#dbeafe,stroke:#3b82f6,stroke-width:3px,color:#1e3a8a classDef gs fill:#fce7f3,stroke:#ec4899,stroke-width:3px,color:#831843 classDef gsd fill:#ede9fe,stroke:#8b5cf6,stroke-width:3px,color:#4c1d95 classDef lmesh fill:#ccfbf1,stroke:#14b8a6,stroke-width:3px,color:#134e4a classDef odm fill:#fee2e2,stroke:#ef4444,stroke-width:3px,color:#7f1d1d classDef gs2d fill:#e0f2fe,stroke:#0ea5e9,stroke-width:3px,color:#0c4a6e classDef vggt fill:#ecfccb,stroke:#84cc16,stroke-width:3px,color:#365314 classDef gsf fill:#fae8ff,stroke:#d946ef,stroke-width:3px,color:#701a75 classDef best fill:#ffe4e6,stroke:#e11d48,stroke-width:3px,color:#881337 classDef fill fill:#ccfbf1,stroke:#0d9488,stroke-width:3px,color:#134e4a classDef tiles fill:#e0f2fe,stroke:#0284c7,stroke-width:3px,color:#0c4a6e class M1 app class M2 lidar class M3 rs class M4 gs class M5 gsd class M6 lmesh class M7 odm class M8 gs2d class M9 vggt class M10 gsf class M11 best class M12 fill class M13 tiles

Compare in 3D

Pick a tab to load that method. Drag to rotate, wheel to zoom, right-drag to pan. Two fingers on a phone. Splats (④⑤⑧) look most photographic near where photos were taken, so they open at the 'Capture viewpoint'.

Each method in detail

① App mesh

How it was made: The mesh Modelar builds live during capture, extracted as is. Its Mesh.scn is an Apple SceneKit archive no other tool reads, so its structure was decoded and the 94 parts merged (read_modelar_mesh.py).

Strengths
  • Zero extra processing; exactly what the app shows
  • Smallest file (1.2 MB)
  • Overall shape (room size, wall positions) is right
Weaknesses
  • Only 58k triangles; built on a 5 cm voxel grid
  • Colour only at vertices, so objects blur
  • No official way to export it; had to be decoded

What to look at

Numbers: 33,363 vertices / 58,319 triangles

② LiDAR points

How it was made: The app's LiDAR point file Cloud.log was decoded byte by byte (no public spec) and verified by matching the block point total to the app's own count (21,029,180). 8,896,675 of them (42.3%) were (0,0,0) padding and were removed. 1,300,000 random points are shown on the web.

Strengths
  • Measured by the sensor, so scale is real metres from the start
  • Every other result here shares its coordinates (RS mesh within a 1.5 cm median)
  • The most trustworthy source for measurements and floor plans
Weaknesses
  • Points, so gaps show up close
  • Range (5 m app setting) and resolution blur small object edges
  • Glass, mirrors and black surfaces drop or scatter points

What to look at

Numbers: 12,132,505 points (web 1,300,000, 19.5 MB)

③ RealityScan mesh

How it was made: 568 images went into RealityScan 2.2 for Linux on arcAI. Photos alone aligned only 65 images into one component, so the iPhone poses were converted to RS prior files (XMP) and locked. The iPhone rotation convention (column-major, camera-to-world, ARKit axes) was confirmed against the 65 images RS had aligned (median rotation difference 1.68°). Then mesh (Normal) → simplify to 1.5M triangles. RS exported only white, so each vertex takes the colour of its four nearest LiDAR points (97.7% of vertices).

Strengths
  • The densest surface; edges and small objects keep their shape
  • A mesh, so measuring and exporting to other tools is easy
  • Same frame as LiDAR, 1.5 cm median difference
Weaknesses
  • Textureless white walls and floors are weak for photogrammetry: bumpy or missing
  • Texture export fails in the Linux command line ('Feature not implemented') and vertex colours came out white, so LiDAR colours were borrowed: text and patterns blur
  • Poses were locked, so iPhone pose error stays in

What to look at

Numbers: 568/568 aligned · reprojection 1.03 px · align 60 s · mesh 192 s · colour 74 s · 1,499,250 triangles · web 6.35 MB

④ Gaussian splat

How it was made: Gaussian splatting represents the scene as millions of small translucent colour blobs trained to reproduce the photos. The iPhone poses were used directly (no photo alignment) and training started from 388,339 LiDAR points (2 cm grid). The gsplat 1.5.3 engine has no prebuilt package for this GPU, so it was built with CUDA 13. 30k steps; one image in eight was held out for evaluation. For the web it was reduced to .splat, base colour only.

Strengths
  • Looks like the photos, including shine, translucency and thin things (cables)
  • You can truly walk around inside
  • Smooth even where photogrammetry struggles, such as white walls
Weaknesses
  • Blobs, not surfaces, so hard to use for measuring or plans
  • Off the captured viewpoints you see blurry floaters
  • iPhone pose error becomes blur
  • Needs a GPU and tens of minutes

What to look at

Numbers: PSNR 15.43 · SSIM 0.76 · 2,723,832 gaussians · 35 min · web 48.0 MB

⑤ Splat + LiDAR depth

How it was made: Same data as ④ with two additions. (1) LiDAR points visible in each photo are linked so training also matches the distance to those points (depth supervision). (2) The iPhone camera poses are refined during training. Same idea as DN-Splatter, which research uses for indoor iPhone LiDAR. Same 30k steps and held-out images.

Strengths
  • Walls and floor should stick to LiDAR, reducing floaters
  • Pose refinement should reduce blur
  • Directly comparable with ④ (same held-out images)
Weaknesses
  • Still blobs, not for measuring
  • Where LiDAR is wrong (glass, black surfaces) it pulls toward wrong depths
  • One more setting, slightly slower

What to look at

Numbers: PSNR 18.33 · SSIM 0.8 · 3,385,261 gaussians · 55 min · web 48.0 MB

⑥ LiDAR mesh

How it was made: ② LiDAR points were thinned to a 1 cm grid (1.73M points), normals were estimated and flipped toward the nearest iPhone camera, and Open3D Poisson reconstruction wrapped a smooth surface. Fake surfaces in sparse areas (lowest 3% density) were removed and the mesh reduced to 1M triangles. Colours come from the LiDAR points.

Strengths
  • Surfaces from LiDAR alone, no photogrammetry: white walls come out straight and smooth
  • Dimensions are LiDAR's, ready for plans and areas (total area 94.7 m²)
  • Fast (CPU 2.7 min)
Weaknesses
  • Poisson tends to bulge surfaces to close holes, so phantom surfaces can appear past the door or behind furniture
  • Small items (cables, pens) are below LiDAR resolution and blur
  • Colour from points, blurrier than photos

What to look at

Numbers: 1,000,000 triangles · 2.7 min (CPU) · web 4.5 MB

⑦ WebODM

How it was made: The WebODM engine already on arcAI (ODM 3.8.3) processed the same 568 images. ODM only takes camera positions as GPS, so the iPhone poses were written into image copies as GPS around an arbitrary origin (lat 1°, lon 1°, unrelated to the real location) and run with --force-gps at 5 cm. No orthophoto indoors.

Strengths
  • Free and open source, mesh and texture from one command
  • Textures come straight from the photos (what RS on Linux could not do)
  • Same engine as the drone run, easy to compare
Weaknesses
  • CPU only, slow
  • Same photogrammetry limits as RS indoors on white walls
  • Needs the fake-GPS workaround for the iPhone poses

What to look at

Numbers: 568장 중 304장 정렬 · 텍스처 메시 81만 삼각형(149 조각) · 라이다까지 중앙 2.2 cm (90% 8.6 cm) · 60 min · web 12.5 MB

⑧ 2D Gaussian

How it was made: 2D Gaussian splatting (2DGS) trains flat discs that stick to surfaces. Run with gsplat's 2DGS trainer on the same data and steps (30k) as ④.

Strengths
  • Discs stick to surfaces, so shape is crisper than ④ (per the literature)
  • Fewer floaters on white walls and floors
Weaknesses
  • Slightly less photographic than ④
  • The web viewer is not 2DGS-specific, so it is approximated as regular splats

What to look at

Numbers: PSNR 18.06 · SSIM 0.79 · 66 min · web 48.0 MB

⑨ VGGT (AI)

How it was made: VGGT (Meta, 2025) estimates camera poses and depth from a set of photos in one pass. Only about 16 photos fit the 16 GB GPU, so two variants were tried. (a) Chunk stitching: 22 overlapping 16-frame chunks, with the AI poses fitted to the iPhone poses; six chunks off by more than 15 cm or 15° were dropped. (b) Fill (this tab): the AI poses are ignored and each photo is placed with depth from VGGT, position from the iPhone, scale from LiDAR. LiDAR points projected into each photo give the VGGT-to-LiDAR depth ratio; photos where the ratio varies by more than 15% are dropped (343 of 524 used). Same idea as MapAnything and Prompt Depth Anything from the research: photos + known poses + LiDAR together.

Strengths
  • Sharper objects than LiDAR, at photo resolution
  • Fast: whole room in 5 min 14 s (about 10 s per chunk)
  • Depth itself comes from photos alone; works for phones and cameras without LiDAR
Weaknesses
  • On its own it has no metric scale and cannot join chunks; the iPhone poses and LiDAR did that here
  • Photos per pass are limited by GPU memory
  • 35% of photos (181) disagreed with LiDAR and were dropped; AI pose estimation failed for 27% of chunks and entirely with spread-out frames (99 cm, 127°)

What to look at

Numbers: 채움 방식: 524장 중 343장 · 라이다 표면 84.7% 덮음 · 라이다까지 중앙 1.1 cm (90% 4.2 cm) · 5분 14초 / 묶음 방식: 60.0% · 3.6 cm (90% 19.0 cm)

⑩ Splat + VGGT

How it was made: An experiment from the research (VGGT-X: 'splats need a good starting point'). Same training as ⑤ (depth supervision + pose refinement, 30k steps), but the starting points and depth reference are ⑨'s VGGT fill points (photo resolution, LiDAR-scaled, 1 cm grid, 1.05M points) instead of LiDAR. That is the only change, so it compares directly with ⑤.

Strengths
  • Dense, photo-resolution starting points settle small objects early
  • Combines VGGT's sharpness with splats' photographic look
Weaknesses
  • Sparse start where VGGT dropped photos (35%)
  • Training time similar to ⑤

What to look at

Numbers: PSNR 17.82 · SSIM 0.79 · 58 min · web 48.0 MB

⑪ LiDAR mesh + photos

How it was made: The strengths of the ten methods combined. Shape: 1,572 LiDAR depth frames decoded from inside the Modelar export and fused with TSDF (improved 2026-10-15. The first version used ⑥'s point-based Poisson mesh, which invented surfaces in empty space: floating fragments and a phantom slab. TSDF also records 'this far was empty', so such surfaces do not form), camera poses from the iPhone record (within 1.68° and 2 cm of RS), and photo texturing by the texture engine inside ⑦ WebODM (texrecon), run on its own. For each triangle it picks the view among 568 photos that saw it largest (closest and most head-on: the 'area' rule, which matched the real photos better than the default 'sharpest view' rule), copies those pixels into texture atlases, rejects inconsistent colours (reflections, moved objects) and evens out brightness at seams. A camera file (.cam) was written for every photo. On the web, 'Walk mode' lets you walk at eye height.

Strengths
  • LiDAR shape, so dimensions are right and walls straight
  • Photo-resolution colour: text and patterns show (a texture, not vertex colours or points)
  • Fast: texturing in 7 min
  • A single mesh file, ready for game engines and other tools
Weaknesses
  • Where LiDAR reads poorly (black desk surfaces) the surface is thin or missing (97.7% screen coverage)
  • Objects smaller than LiDAR resolution (cables, pens) have no shape, only a painted image
  • Lighting and shadows are baked into the photos (no relighting like a game)
  • Textures were reduced for the web size limit

What to look at

Numbers: 1,390,645 triangles · texture atlases 94 · 7 min · web 19.0 MB · photo match PSNR 15.76 → 17.55 (sharp photos 16.18)

⑫ ⑪ + holes filled

How it was made: ⑪ with only the holes filled. Black cabinets, the black desk and speakers return too little light to the LiDAR, so their depth is missing and the mesh has holes. Per-photo depth from ⑨ VGGT (an AI that estimates depth from photos), scaled with LiDAR, was saved; then ⑪'s mesh was ray-cast from each view and only pixels where the mesh is missing or an object sits more than 8 cm in front were added to the same TSDF (276 views). Mixing VGGT in where LiDAR already measured creates double surfaces (in a 2026-10-15 test the score fell 15.76 → 14.80). Texturing is the same as ⑪.

Strengths
  • Screen coverage 97.7% → 99.2%: most holes at black objects are filled
  • Where LiDAR measured, shape and dimensions are unchanged from ⑪
Weaknesses
  • Filled areas use AI-estimated depth, so they are less accurate; ragged edges on boxes
  • Photo match is slightly lower (17.55 → 17.27): the newly filled areas (black objects) are hard to match and now count

What to look at

Numbers: 1,484,931 triangles · texture atlases 118 · 13 min · web 21.7 MB · photo match PSNR 17.27 · coverage 99.2%

⑬ ⑪ as 3D Tiles (original resolution)

How it was made: ⑪'s mesh and texture split into map-like tiles. ⑪'s web file reduced textures to 2048 px for the 25 MiB limit; here 4 regions first show with small textures (512 px), and moving closer swaps a region for its 94 pieces with original 4096 px textures. The pieces texrecon already split per atlas are used directly as tiles (tiles_from_pieces.py, first built for the pool scan).

Strengths
  • Text and patterns are sharper than ⑪ up close
  • Small initial download
Weaknesses
  • Brief flicker as tiles swap
  • Same shape and seams as ⑪

What to look at

Numbers: regions 4 · pieces 94 · files 98 · total 39.6 MB

At a glance

MethodExtra processingAppearanceMeasuring / plansWeb size
① App mesh0CoarseRough1.2 MB
② LiDAR pointsDecoding onlyPoints, gaps up closeMost trustworthy19.5 MB
③ RealityScan6 minGood shape, blurry colourGood (mesh)6.35 MB
④ Splat35 minPhotographicHard48.0 MB
⑤ Splat + depth55 minPhotographicHard48.0 MB
⑥ LiDAR mesh2.7 minSmooth, blurry colourGood (LiDAR dimensions)4.5 MB
⑦ WebODM60 min텍스처 있음Good (mesh)12.5 MB
⑧ 2D splat66 minPhotographic, crisper surfacesHard48.0 MB
⑨ VGGT (AI)5.2 minSharp pointsLiDAR-scaled (1.1 cm median)22.5 MB
⑩ Splat + VGGT58 minPhotographicHard48.0 MB
⑪ LiDAR mesh + photos7 minPhoto texture, walkableGood (LiDAR dimensions)19.0 MB
⑫ ⑪ + holes filled13 min⑪ + black objects filledGood (filled parts AI-estimated)21.7 MB
⑬ ⑪ as 3D Tiles3 min⑪ + original resolution up closeGood (LiDAR dimensions)39.6 MB

What went wrong on the way (kept as is)

Next