Importing, filtering, and surfacing laser-scan point clouds in Blender.
This guide walks through installing the add-on, finding its panels, and completing the common tasks, with a reference for every control. For a terse feature list, see README.md.
Contents
- Overview
- Installation
- Quick start
- Import Point Cloud
- Filter Point Cloud
- Create Ground Surface
- Create 3D Surface
- Documentation & provenance report
- Optional dependencies
- Tips & troubleshooting
- License & support
A note on values: defaults are shown in parentheses. Distance controls follow the scene's unit system in Blender; their defaults are given here in metres, Blender's base unit (1 unit = 1 m).
Overview
Point Cloud Toolkit adds an EDC Toolkits tab to the 3D View sidebar (press the N key) with four tool sections that share one point-cloud selection:
| Section |
What it does |
| Import Point Cloud | Multi-format import — PLY (ASCII or binary), PTX, E57, LAS/LAZ, and PCD — as a coloured mesh with a Geometry Nodes point display |
| Filter Point Cloud | Voxel subsampling and Statistical Outlier Removal, always to a new cloud (the original is never modified) |
| Create Ground Surface | Drape a regular grid over the cloud: per-cell ground-percentile height sampling, spike rejection, hole filling, clip-to-object, and a colour texture baked from the cloud |
| Create 3D Surface | Full 3D reconstruction via Open3D (Poisson / Ball Pivoting / Alpha Shape) for vertical and overhanging geometry, with automatic texture baking, tiling, and bulge trimming |
The add-on targets Blender 4.x and is numpy-vectorized throughout, so it stays fast on million-point clouds.
Installation
- In Blender, open Edit → Preferences → Add-ons → Install… and select the
PointCloudToolkit-<version>.zip file.
- Enable Point Cloud Toolkit in the add-ons list.
- Open the 3D View sidebar with the N key and select the EDC Toolkits tab.
The add-on's preferences let you rename the sidebar tab — set it to an existing tab's name to share a tab with other add-ons.
On Blender 4.2+ the same zip also installs as an extension (Preferences → Get Extensions → Install from Disk), and updates automatically when added from the EDC Software repository.
Quick start
- In Import Point Cloud, click Import Point Cloud and load a scan. The imported cloud is selected automatically as the source for the other sections.
- *(Optional)* Set Clip To Object to restrict surfacing to a boundary mesh.
- *(Optional)* In Filter Point Cloud, enable Subsample (Voxel) and/or Remove Outliers (SOR), then click Filter → Create New Point Cloud.
- For drivable ground, use Create Ground Surface; save the
.blend first so the texture JPG can be written next to it.
- For vertical or overhanging geometry, use Create 3D Surface (Poisson is the all-rounder). Afterwards, Trim Bulges (To Cloud) removes invented geometry and Rebake Texture re-fits the texture.
Import Point Cloud
Imports PLY (ASCII or binary), PTX, E57, LAS/LAZ, and PCD files as a coloured mesh point cloud displayed through a Geometry Nodes modifier (also available on File → Import). The imported cloud is automatically selected as the Point Cloud source used by the other sections.
- Points Visible % (100) — a display-only control on the imported cloud that thins the viewport display to keep it responsive on dense clouds. Lower draws fewer points (smoother navigation); 100 shows all. It never touches the data; filtering and baking always use every point.
- Point Size — the displayed radius of each point, in scene units. Display-only, like Points Visible %; raise it to make sparse clouds read as a solid surface, lower it for crisp detail.
- Each imported cloud gets its own Geometry Nodes display tree, so Points Visible % and Point Size are independent per cloud — adjusting one import never changes another.
- Source Units / Scale — pick the units the file is stored in (Meters, Feet, US Survey Feet, Inches, cm, mm) and the importer sets Scale to convert the cloud into metres (Blender's 1 unit = 1 m). Choose Custom to type any multiplier yourself. Scale is applied to the coordinates on import.
- Global Shift (Auto) — georeferenced scans (UTM, state plane) store coordinates in the millions, where Blender's float32 mesh storage loses precision and the cloud looks jittery. Shifting the cloud back near the world origin fixes that; the removed offset is recorded on the object (custom properties
pct_global_shift / pct_import_scale) so the original coordinates can be recovered — the same idea as CloudCompare's Global Shift. Three modes:
- Auto (default) — recenter only when the coordinates are very large (subtracts the rounded centroid); ordinary local clouds are left in place.
- None — do not shift at all; import at the file's true coordinates.
- Manual — subtract a Manual Shift X/Y/Z you enter (e.g. your own false origin) instead of the automatic value. The value is in scene metres (after Source Units/Scale), so for a cloud already in metres it is just the source offset. It is stored on the object like the auto shift, so coordinates still round-trip.
- Import progress (file read, point count, mesh build) prints to the system console — opened automatically on Windows, or the launching terminal elsewhere.
- PLY, PTX, uncompressed LAS, and ASCII/binary PCD are read natively. E57 needs the
pye57 package and LAZ needs laspy[lazrs] — both install automatically the first time such a file is opened, or via the Install E57 / LAZ Support Now button. Compressed PCD uses Open3D.
Filter Point Cloud
Cleans a cloud before surfacing. Filtering always creates a *new* cloud object — the original is never modified. The same filters also run automatically when creating a surface, and textures always bake from the full, unfiltered cloud.
- Subsample (Voxel) — on/off. Thins the cloud to one averaged point per occupied voxel — the single biggest speed-up for huge scans.
- Voxel Size (0.1 m) — the voxel edge length. Larger keeps fewer points (coarser, faster surfacing); smaller keeps more detail but thins less. Set it near your target surface resolution.
- Remove Outliers (SOR) — on/off. Statistical Outlier Removal drops points whose average distance to their neighbours is unusually large (floating noise, stray returns). Runs after subsampling.
- SOR Neighbors (k) (16) — how many nearest neighbours are averaged when judging each point. Higher gives a smoother, more forgiving estimate (fewer points flagged); lower is more local and more sensitive to noise.
- SOR Std Ratio (2.0) — keeps points whose mean neighbour distance is within *mean + ratio × std*. Lower removes more (aggressive); higher removes fewer.
- Filter → Create New Point Cloud — runs the enabled filters and adds the result as a new cloud (the original is untouched).
Shared controls (Filter / Ground / 3D)
- Point Cloud — the source mesh whose vertices are the point cloud. Leave empty to use the active object.
- Clip To Object — only surface points inside a boundary object. Bounding Box (fast) uses the object's oriented box: a box/cube clips a true 3D volume, a flat plane clips just its XY footprint. Mesh Volume (exact) ray-casts against the actual, possibly concave, closed mesh — slower on very large clouds.
Create Ground Surface
Drapes a regular grid over the cloud to build a drivable ground surface. Distance controls are given in metres (1 unit = 1 m).
- Resolution (Cell Size) (0.3 m ≈ 1 ft) — spacing of the surface grid. Smaller means finer detail, more polygons, slower; larger is coarser and faster. Set it to the smallest real feature you need to keep. A single surface is capped at 8 million grid vertices; if your cell size and scan extent would exceed that, a dialog appears pre-filled with the smallest cell size that fits. You can accept it, type your own cell size (the dialog shows the resulting grid live as you change it), or Cancel and clip to a smaller area to keep the finer resolution. If a value you enter is still too dense it is raised automatically to fit.
- Ground Percentile (10) — the height percentile taken as "ground" within each cell. Lower samples from below, hugging the lowest returns and rejecting overhead noise (trees, wires, vehicles); raise it only if the true ground is sparse and stray low outliers are dragging cells down.
- Below-Grade Reject (0.5 m) — blanks any cell sitting more than this far below its neighbours (a stray below-ground return) and refills it from the surrounding ground. Lower rejects more aggressively; 0 disables.
- Spike Reject (Above) (1 m) — removes upward spikes where trees, poles, or walls leave a cell with no ground returns (so even the low percentile lands high). Any cell rising more than this above the local ground level is refilled from the surrounding ground. Lower removes shorter bumps too (may cut real curbs); 0 disables.
- Spike Width (Max) (6 m) — the widest above-ground object Spike Reject may remove; anything broader is kept as real grade (hills, embankments). Raise to clear wider vegetation strips; lower to protect narrower real rises.
- Fill Holes (on) — interpolate empty grid cells from their neighbours so sparse spots don't leave gaps.
- Max Fill Distance (2 m) — how far filling reaches across a gap. Larger bridges bigger holes (but can invent surface over true voids); 0 = unlimited within a connected region.
- Color Height Tolerance (0.25 m) — only points within this height of the sampled ground contribute colour to the surface and its texture, so vehicles and foliage above the road can't tint it. Raise to admit more (risks pulling in above-ground colour); 0 uses all points.
- Texture Resolution (4096) — longest side, in pixels, of the baked colour texture, sampled directly from the cloud so it can be sharper than the surface grid. Higher is sharper, larger, slower; 0 matches the grid resolution. The JPG is saved next to the
.blend — save the .blend first.
- Texture Color Source (optional) — sample the texture's colour from a different object (e.g. the original full-resolution cloud) instead of the surface's point cloud. Use it when the geometry cloud is a filtered copy but you still want a full-detail texture.
- Texture Tiles (1) — with N > 1, the ground surface is split into up to N×N tiles, each with its own baked texture, for more total resolution than one big image. It is *up to* N×N because tiles that fall on empty area (holes, or corners the scan doesn't reach) are skipped — so a 4×4 split of an irregular scan may yield fewer than 16 tiles.
- Join Tiles Automatically (on) — after tiling, the tiles are merged into a single object, each tile keeping its own texture as a material slot, so you get the tiled resolution with one object to manage. The shared tile borders are welded (coincident vertices merged), so the joined surface is continuous and a Decimate modifier won't tear gaps along the seams. Turn it off to leave the tiles as separate objects. (Blender's Separate → By Material splits a joined surface back into its tiles.)
- Join Tiles Into One Object — a manual button that appears when two or more separate surface tiles are selected; it performs the same merge (including welding the shared borders), for when Join Tiles Automatically was off or you split a surface yourself.
- Create Ground Surface — builds the surface, bakes the texture, and assigns UVs and an image-texture material. Grid cells with no data (holes the fill couldn't reach) leave no stray points: vertices that aren't part of any face are removed automatically, so you get only the surfaced geometry.
- Rebake Texture (Selected Surface) — shown when a created surface is selected; re-bakes at the current Texture Resolution without rebuilding the mesh.
- Decimate Mode (Un-Subdivide) + Add Decimate Modifier — shown when a mesh is selected; adds a live Decimate modifier to every selected surface to cut polygon count. Un-Subdivide (default) reverses subdivision, removing edge loops a set Un-Subdivide Iterations number of times (each pass roughly quarters the face count) — ideal for the regular ground grid. Collapse merges edges until only a fraction of faces remain, set by Decimate Ratio (0.5 = keep half) — better for the irregular 3D reconstruction. Once added, the panel shows the modifier's Resulting faces count; the modifier stays live so you can adjust or remove it, and Blender's modifier Apply bakes it in.
Aerial image (replace the point-cloud colour)
You can drape one or more aligned aerials / orthophotos over a created surface instead of the colour baked from the point cloud — useful when a recent aerial reads better than the scan colours. Both textures are kept, so you can switch back at any time. This works on ground and 3D surfaces.
- For each aerial, add a reference and align it over the surface in top view: the simplest is a Plane (Add → Mesh → Plane) given the aerial as an image-texture material, scaled and positioned to cover that aerial's area. (An Empty → Image reference also works.)
- Select every aerial plane, then the surface last so it is active. (For a single aerial you can instead set Aerial Reference to the one plane, and optionally Aerial Image to override the image.)
- Click Apply Aerial Image. Each surface face is textured by the aerial whose footprint covers it, with top-down planar UVs computed from that plane's world extent, so every orthophoto lands by geographic position. Because these are real textures (their own UV layer and one material per aerial), they export cleanly.
- Overlaps: where two aerials cover the same spot, the one with the smaller footprint wins (usually the more zoomed-in / higher-detail image).
- Gaps: faces that no aerial covers keep their point-cloud texture, so partial coverage just works — aerial where you have it, scan colour elsewhere.
- Show Point-Cloud Texture / Show Aerial Image toggles the whole surface between the two — the original point-cloud texture (and, for a joined surface, each tile's own texture) is preserved.
If the cloud was recentered on import, aligning the aerials visually over the surface already puts them in the right (shifted) space — no coordinate math needed. Tip: if your aerials are just tiles of one orthomosaic, merging them into a single image first (e.g. QGIS / gdal_merge) lets you use one plane instead.
Tuning & troubleshooting (ground surface)
Adjust one setting at a time and re-create the surface to see its effect.
| If you see… |
Try |
| Too many low points / the surface dips into potholes or drops below the roadway | Lower Below-Grade Reject (e.g. 0.5 → 0.2 m) so stray below-ground returns are cut and refilled; if whole areas sag, raise Ground Percentile a little (e.g. 10 → 20) so it samples higher. |
| Spikes or bumps sticking up from trees, poles, walls, or parked cars | Lower Spike Reject (Above) (e.g. 1.0 → 0.5 m) so shorter spikes are caught; if wide vegetation strips remain, raise Spike Width (Max). |
| Real curbs, embankments, or hills being flattened | Raise Spike Reject (Above) (less aggressive) and/or lower Spike Width (Max) so only narrow objects are removed. |
| The road colour is tinted by vehicles or foliage | Lower Color Height Tolerance (e.g. 0.25 → 0.1 m) so only near-ground points contribute colour. |
| Gaps or holes in the surface | Enable Fill Holes and raise Max Fill Distance to bridge farther. |
| Surface invented over a true void (e.g. across a ditch or off the road edge) | Lower Max Fill Distance, or set Clip To Object to the area of interest. |
| Surface is too heavy / slow to work with | Raise Resolution (Cell Size), enable Subsample (Voxel), or add a Decimate modifier. |
| Blurry texture | Raise Texture Resolution, or use Texture Tiles for more total pixels. |
Create 3D Surface
Full 3D reconstruction via Open3D (installed automatically on first run) for vertical and overhanging geometry — walls, embankments, vehicles, structures. For drivable ground, Create Ground Surface remains the better tool. Distance controls are given in metres (1 unit = 1 m).
- Method — Poisson (the all-rounder; smooth and watertight, but invents geometry past the data — pair it with Density Trim / Trim Bulges), Ball Pivoting (interpolating; keeps the original points as vertices, good for evenly dense clouds), or Alpha Shape (Delaunay concave hull; simple and fast). The controls below change with the method.
- Poisson Depth (9) — octree depth. Higher captures finer detail but is slower and can amplify noise; lower is smoother and coarser.
- Density Trim (0.05) — fraction of the lowest-density (invented) Poisson vertices to cut away. Higher trims more of the ballooned surface (but can eat thin real areas); 0 keeps everything.
- Alpha (0 m = auto) — Alpha Shape wrap radius, in metres. Larger is smoother and bridges gaps; smaller wraps tighter with more holes; 0 auto-picks from the average point spacing.
- BPA Radius Multiplier (1.0) — scales the Ball Pivoting ball radii (derived from point spacing). Raise it to span wider gaps and close holes in sparse areas; too large bridges fine detail.
- Use Existing Normals (on) — when the imported cloud already carries per-point normals (many terrestrial-scanner PLY / E57 / PCD exports do), reconstruct with them and skip estimation and orientation — usually the slowest phase on large clouds. The checkbox is greyed out when the selected cloud has no stored normals, or when voxel subsampling is on (averaging invalidates them); in those cases normals are estimated as usual. Turn it off to always re-estimate.
- Normal Neighbors (k) (30) — neighbours used to estimate normals (only when estimating). Higher gives smoother normals; lower is more local and noise-sensitive.
- Normal Orientation — Consistent (accurate but single-threaded, so slow on big clouds) or Up (near-instant, great for terrain but can misorient steep walls/overhangs). Only applies when estimating.
- Normals are cached automatically. When the toolkit estimates and orients normals (the slowest phase, especially with Consistent orientation), it keeps the result. Reconstructing the same cloud again reuses it and skips that phase — so tweaking Method, Poisson Depth, Density Trim, alpha, Texture Tiles, UV, or texture size and rebuilding is fast. The cache is keyed by the exact points fed to estimation plus Normal Neighbors (k) and Normal Orientation, so it is reused as long as none of those change; editing the cloud, changing a filter (subsample / outlier removal) or clip, or changing k or the orientation recomputes it. The reuse works within a Blender session for any cloud (including subsampled/clipped ones); for a whole-cloud run it is also saved in the
.blend (a pct_computed_normal attribute on the cloud) so it survives save and reload. The system console prints whether a run reused the cache or recomputed.
- Texture Resolution (4096) — longest side of the baked colour texture, sampled from the cloud. Higher is sharper, larger, slower; 0 matches the grid.
- Texture UV — Smart UV (default; handles arbitrary 3D shapes, each surface getting its own texture area) or Planar (top-down projection; zero packing waste, best for pure terrain seen from above).
- Texture Tiles (1) — with N > 1, split the surface into N×N tiles, each with its own texture, for more total resolution.
- Join Tiles Automatically (on) — after tiling, merge the tiles into a single object, each keeping its texture as a material slot. Turn off to keep separate tile objects.
Post-build tools (shown when a reconstructed surface is selected)
- Trim Bulges (To Cloud) — deletes surface farther than the Trim Distance (0 m = auto, from point spacing) from the source cloud, removing Poisson's invented geometry. Larger distance keeps more (trims less); smaller trims more aggressively.
- Rebake Texture (Selected 3D Surface) — re-bakes at a new resolution, sampling the cloud directly.
- Split & Bake Tiles — re-splits the selected surface into Texture Tiles.
- Join Tiles Into One Object — with two or more surface tiles selected, merges them into a single object that keeps each tile's texture as its own material slot. Separate → By Material reverses it.
- Decimate Mode + Add Decimate Modifier — adds a live Decimate modifier to the selected surface(s) to reduce polygon count. Choose Un-Subdivide (set the iterations) or Collapse (set the ratio); the panel then shows the resulting face count. Adjust or Apply it in the modifier stack.
Tuning & troubleshooting (3D reconstruction)
Poisson is the usual starting point; change one control at a time and rebuild.
| If you see… |
Try |
| Surface balloons out past the scan (Poisson invents geometry in empty areas) | Raise Density Trim (e.g. 0.05 → 0.2), or run Trim Bulges (To Cloud) after the build; lowering Poisson Depth also helps. |
| Holes or gaps in the surface | Ball Pivoting: raise BPA Radius Multiplier to span wider gaps. Alpha Shape: raise Alpha. Poisson: lower the depth. |
| Surface is too smooth / fine detail lost | Raise Poisson Depth (e.g. 9 → 10–11). |
| Surface is noisy or lumpy | Lower Poisson Depth, or raise Normal Neighbors (k) for smoother normals. |
| Walls or overhangs look inside-out or patchy | Set Normal Orientation to Consistent (the Up option can misorient vertical faces). |
| Reconstruction is very slow | Turn on Use Existing Normals (if the cloud has them), use the Up orientation, and/or Subsample (Voxel) first. The first run also caches its normals, so later rebuilds skip the slow step. |
| Blurry texture | Raise Texture Resolution or use Texture Tiles; for flat, top-down terrain, Planar UV is the sharpest. |
Documentation & provenance report
The Documentation panel has an Open User Guide button (this guide) and a Provenance Report (Active) button. The report writes a self-contained HTML document for the active cloud or surface — the source file and its SHA-256 hash, point/geometry counts, coordinate extents in both Blender and original (georeferenced) space, the import scale and global shift, and the tool/Blender versions — for documentation and chain-of-custody. It's saved next to the .blend (or a temp folder if unsaved) and opened in your browser. The "Prepared by" field is left blank for you to fill in; it is not taken from the OS login.
Optional dependencies
Optional Python packages install themselves into Blender's Python when first needed — no manual pip work is required. An internet connection is needed the first time each feature is used.
| Package |
Needed for |
When it installs |
open3d | 3D reconstruction, compressed PCD | First Reconstruct 3D Surface (large download; may need a Blender restart) |
pye57 | E57 import | First E57 file opened, or the install button in the panel |
laspy[lazrs] | LAZ import | First LAZ file opened, or the install button in the panel |
Tips & troubleshooting
- Texture stayed inside the .blend? The JPG is written next to the saved
.blend. If the file isn't saved yet, the texture is packed into the .blend instead — save the .blend and rebake (or re-create the surface) to write the JPG to disk.
- Huge cloud is slow? Lower Points Visible % for display, and enable Subsample (Voxel) before surfacing. Textures still bake from the full cloud.
- Grid too large to build a ground surface? A single surface is capped at 8 million vertices. Accept the auto-fit dialog to raise the cell size, type your own cell size there, or clip to a smaller area with Clip To Object.
- Poisson surface balloons past the scan? That's Poisson inventing geometry where there are no points — raise the density trim, or run Trim Bulges (To Cloud) after the build.
- Progress seems stuck? Long operations print progress to the system console (the terminal Blender was launched from, or Window → Toggle System Console on Windows).
- Install of Open3D / pye57 / laspy fails? Check the internet connection and that Blender can write to its own Python; as a fallback, run
pip install <package> with Blender's Python and restart Blender.
- E57 import reports a Visual C++ runtime error? The E57 reader's system libraries need a newer Microsoft Visual C++ runtime than some Blender installs ship. Install the latest Microsoft Visual C++ Redistributable (x64), restart Blender, and retry. Converting the file to PLY or LAS also works.
License & support
Point Cloud Toolkit is © Engineering Dynamics Company, written by Anthony Cornetto, and is free software licensed under the GNU General Public License, version 2 or later — see the bundled LICENSE file. Official builds, updates, and support are provided by Engineering Dynamics Company; visit edccorp.com or contact EDC support.