PaintBlocks is a real-time geometry scattering brush tool for Rhino. Whether you’re placing vegetation, populating urban environments, or detailing architectural facades, PaintBlocks makes the process incredibly fast, precise, and interactive.
Real-Time Scatter Brush: Paint meshes, breps, curves, or blocks on any target geometry.
3-Axis Rotation (X, Y, Z): Complete control with independent random rotation ranges for pitch, roll, and yaw.
Smart Alignment: Instantly toggle between standing straight up (World Z-Axis) or aligning perfectly to the surface normals.
Brush Erase: Simply sweep the brush in Erase Mode to clean up populated blocks.
Live UI Synchronization: Change random seeds, scales, rotation ranges, or alignment toggles, and watch the placed objects update in the viewport in real-time under a single Undo history step.
This is awesome! I have been waiting for something like this (lightweight, fast, easy to use…) for a long time. I would love it if you could add some features to it which would make it even better for vegetation distribution:
Ability to distribute multiple objects and defining the Density of them e.g. block01 = 10%, block02= 30%, block03=60%
(this might be a bit of a stretch…) to be able to edit the distribution at a later point by changing the percentual values of the individual objects.
Personally I would be happy to pay for the development of such a tool, I think some users used Patreon or similar websites.
Thanks
Added Percentage and Count fields. Once you stop painting, you can double-click any percentage to change its value, or use the Lock checkbox to lock specific percentages in place.
Manual Redistribution: When painting is stopped, double-clicking the percentage allows you to adjust and redistribute block instances in the viewport.
Smart Locking: Check the ‘Lock’ box to protect specific block percentages from changing while the remaining unlocked blocks automatically recalculate to total 100%.
I think another useful addition might be, to introduce besides the random rotation and scale, a random translation dialog.
With this you could add randomness to the insertion point of the blocks. This way there would be more height variety for a more natural look.
What about a fill option for surfaces? This could be combined with an option for clustering, maybe based on a parametric noise pattern like e.g. perlin, for a natural looking distribution.
What we need now is proxy system to substitute The mesh blocks with display friendly object.
For example, a block of a tree which will right now have a very hard impact on the display pipeline having hundred thousands of polygons especially if we are talking about hundreds or thousands of them…so the meshes should be substituted by a low polygon representative or pointcloud to be gentle on the display engine.
I’m trying to convince McNeel for 10 years now to implement such a thing which would enable us to have manageable scenes with best vegetation consisting of millions of polygons. I will dig out my old thread about this.
We could replace the blocks with a simple vertical line or bounding box for display, but that only solves half the problem the render engine also needs to know, automatically, that this simplified stand-in represents real geometry.
This needs to be a native RhinoCommon feature: a lightweight proxy object (a point, curve, or bounding box) that carries a reference to the actual mesh, so Cycles - or any external render engine - can resolve it back to full geometry at render time, the same way V-Ray Proxy or Arnold Standins work, without every plugin having to build its own integration.
For an even faster path, all the block base points could be collapsed into a single point cloud for display, one lightweight object instead of thousands of individual proxies, and at render time each point gets swapped back out for its original block. But this has the same requirement: it only works if RhinoCommon exposes it natively, so external render engines know how to resolve the point cloud back into real geometry.
I can add a toggle in my plugin to show all blocks as simple curves, boxes, or a single point cloud, but that only fixes the viewport. When you actually render - with Rhino Render or a third-party engine - the real, full-detail blocks still need to appear, and a plugin-side toggle can’t make an external render engine understand that substitution. Only a native SDK-level proxy system can.
Yes, I completely agree with your conclusion. That is essentially the point I’m trying to make in the other thread.
However, it might be worth taking a closer look at RhinoNature, as it demonstrates that this kind of proxy representation can already be implemented using the SDK currently available.
I also agree that this is functionality Rhino should support natively. Nevertheless, given the current situation, RhinoNature may provide a useful example of what is already technically possible within the existing SDK.
I’ve got a few ideas for PaintBlocks but it might take a while to implement.
The ability to paint across multiple meshes and polysurfaces in one command.
It would be great to be able to edit a painted cluster after it has been created, to tweak the % allocation and add or erase from the cluster. I thought the best way to do it would be to add a serialised string of information to the block instance user data. The user would select a block in the relevant cluster and then press a button on the PaintBlocks panel to load/edit a previous session.
It would also be great to have the option to automatically group the painted cluster of blocks (as a checkbox on the tool panel).
I also want to ask why PaintBlocks currently creates a new block type rather than using the original block type/name?