Alexandre Bordereau
A Montreal brick house rebuilt as a point cloud

Lab · Blender add-on · Geometry Nodes

Model to Point Cloud Generator

A Blender add-on that turns a model, a collection or a whole scene into a live point cloud. Edit the house and the cloud follows; every setting can be animated.

Software
Blender 4.5
Engine
Geometry Nodes
Presets
8
License
GPL-3.0
Reading
4 min

The brief fit in one sentence: “a Blender add-on that takes a model or a whole scene and turns it into a point cloud, with lots of settings you can tweak live”.

The cloud above comes straight out of it: 324,007 points in the LiDAR preset, exported by the add-on from a house made with my other generator, Montreal House Generator, then displayed here in WebGL.

Log 01 / 05

All in nodes

Architecture

A single node group does all the work. Python only orchestrates: creating the object, handling materials, export and the interface.

There were two possible approaches: compute the cloud in Python with numpy, or build it in Geometry Nodes. The “tweakable live” requirement settled it.

Python + numpyGeometry Nodes
Computationonce, on clickon every change, in multithreaded C++
Live settingsrecompute everything in Pythonnative: a modifier input
Animationnoevery setting can be keyframed
Follows the sourcenoyes, editing the house updates the cloud
~150
Nodes in the main group.
37
Modifier inputs, all adjustable live.
4
Sampling methods: surface, even surface, vertices, volume.

I could have drawn the group by hand and shipped it in a .blend file. I built it in code instead: every node change becomes a line in a commit, the group rebuilds itself when its version changes, and a small builder turns node construction into formulas.

PythonThe node builder
# Instead of 6 lines per Math node (new, operation, inputs, links…):
density = b.math('MULTIPLY', b.math('MINIMUM', b.inp("Density"), surface_cap), viewport)
axis_t  = b.math('DIVIDE', b.math('SUBTRACT', proj, axis_min), axis_len)

Log 02 / 05

Grey points

The big one: materials

The first test on the house ran without a single error. And every point was grey.

The goal sounded simple: the cloud of a brick house should look like a brick house. It took more iterations than anything else, because every blocker came from an API behaviour the documentation doesn’t mention.

  1. 01

    Slots ignored

    A point cloud produced by a modifier ignores the object’s material slots. The material has to be set inside the nodes, with Set Material.

  2. 02

    Implicit UVs

    An image texture with no Vector input reads the “default UV”, which doesn’t exist on points. The UVMap attribute is there, though: it just has to be read explicitly.

  3. 03

    Lost index

    Sampling drops material_index but carries face attributes. So a small modifier tags every face with its material index beforehand.

  4. 04

    One material only

    In Blender 4.5 a point cloud carries a single material. The fix: one point cloud per material, output as instances, each with its own point-ready copy.

PythonThe probe that explains it all
# 3 point groups, 3 different Set Material nodes, then Join Geometry
print([m.name for m in pointcloud.materials])   # → ['C']
The same house as a textured point cloudThe house as a meshModelPoint cloud
Fig. 01Drag to compare. Brick, stone, grass and metal end up on the points, in Cycles and EEVEE alike, without ever touching the sources.

Log 03 / 05

The district

Scaling up

What works on a two-metre object breaks on a hundred-and-sixty-metre district.

At 2,000 points per square metre, a district would exceed a hundred million points. So the Max Points input caps the density right inside the nodes, from the total face area.

But a cap spreads points apart, and a fixed radius can’t keep up: on the house, 3 mm gives tiny points and a cloud that fades away. Auto Radius computes the actual spacing between points and derives their size from it.

Readable cloud with Auto RadiusSparse, almost invisible cloud with a fixed radiusFixed radius · 3 mmAuto Radius
Fig. 02Same house, same density. Radius = spacing × 0.6: points overlap just enough to close the surface.
313
Meshes in a generated district block.
234
Materials, all carried onto the points.
3,5 M
Points for the whole district.
The district as a point cloud, LiDAR preset
Fig. 03The district in LiDAR. Scan lines are counted relative to the scene’s extent, not in metres, so they stay readable at any scale.
HouseDistrict
Meshes / materials10 / 33313 / 234
Cloud creation1 s21–52 s
Evaluation0.4 s for 1 M points11 s for 3 M points
First EEVEE render9 s80–240 s
Measured on a Mac, Blender 4.5.5, headless.

Log 04 / 05

Eight looks

Presets and effects

A preset should describe a look, not a size. Everything that depends on scale is relative to the scene.

Textured ScanLiDARHologramVoxelsThermalDustVolume FillBlueprint

Dense, evenly spaced points with the source materials.

Fig. 04The eight presets, rendered by the add-on on the same house and from the same camera.

On top of the presets come animatable effects. Reveal builds the cloud along an axis, with a noise-broken edge; the same principle builds the house at the top of this page. 4D noise makes points ripple without sliding, scan lines slice the scene, and the voxel grid gives it a video game look.

{ "fr": "Formule", "en": "Formula" }Reveal
t = (proj − min) / (2 · h · |n|)        ∈ [0, 1]   // position along the axis
delete if  t·(1 − r) + noise·r > Reveal              // r = Reveal Noise
Animation of the Reveal effect on the house
Fig. 05Reveal animated from 0 to 1, noise-broken edge, EEVEE render.

Log 05 / 05

The tool

Interface and method

A panel in the viewport, and a method: never guess, always measure.

The Point Cloud Generator panel in Blender’s sidebar
Fig. 0601 / 06
  1. Everything is set from the Point Cloud tab in the sidebar. The panel is drawn from the same table as the node group: adding an input makes it appear in both places.

  2. Create from

    Start from a selection, a collection or the whole scene. Selecting a generator’s parent brings its whole hierarchy along.

  3. Presets · Bake · Export PLY

    Presets reset the look, never the source or the point cap. Bake freezes the cloud into real Point Cloud objects, Export PLY writes it as coloured binary: a million points in under a second.

  4. Sampling

    Method, density, cap, minimum distance. The viewport only shows 25% of the points by default: you work on a light preview, the render uses them all.

  5. Auto Radius

    The checkbox that saved the district. Irrelevant fields hide depending on context: Radius only appears when Auto Radius is off.

  6. Voxelize · Reveal · Scan Lines · Crop

    The effects, collapsed by default, with their checkbox right in the panel header. Every value is a modifier input, so it can be keyframed.

All development happened headless, with a simple loop: a twenty-line probe that asks the API a single question, the code, a render, and looking at the render. Half the bugs in this project came from undocumented behaviours no amount of reading would have revealed.

  1. 01

    Measure

    A twenty-line probe reveals in seconds what the docs don’t say.

  2. 02

    Look

    “It doesn’t crash” never meant “it works”.

  3. 03

    Think relative

    Caps, radii and spacings derive from the scene, never from hard-coded values.

  4. 04

    Break nothing

    Material copies, a tagging modifier: everything is additive and reversible.

Project
Personal
Compatibility
Blender 4.5+ · Cycles · EEVEE
Tested on
Montreal House Generator
License
GPL-3.0-or-later
  • Geometry Nodes
  • Python
  • numpy
  • PLY
  • Headless rendering

Next: evaluate procedural colours on export, follow animated sources with the Bake node, and vary point size with camera distance.

The cloud isn’t done moving.

— Alexandre Bordereau