Mesh processor

To aid my freelance work and speed up art asset creation I created a mesh processor for Houdini: It takes almost any kind of mesh and prepares it for texturing in Substance Painter and ingame use. The system takes care of simplification, UV layout, the duplication of repeating elements and baking. Both poly reduction and UV generation is influenced by importance settings to keep details where they matter the most.


This tool is not meant for hero objects which are probably better off with human love and care. Rather, it’s aimed at cases where we need a “good enough” result quickly, like rapid prototyping or background assets.


I’m standing on the shoulders of giants as I’m using many nodes from the excellent SideFX Labs. Many thanks to SideFX, and especially to Luiz Kruel and Paul Ambrosiussen for their support.


Mesh Processor v1.3 (5.19 Mb) – Requires Houdini 18 and up.

Licensed under GNU GPLv3.

Made using Houdini’s “Limited commercial” license.


Extract the zip file to the “Documents\HoudiniXX\otls” folder.

— Changes in v1.3 —

– Added visibility based importance.
– Removed distance from ground, direction facing and imported vertex color based methods from importance calculations.


– Vertex colors from the high poly mesh are now baked.
– Vertex colors from the high poly mesh can be used as ID color.
– Normalized position map is baked.
– High poly UV map is baked.
– Output textures are in EXR format.


– Added scaling to LoadMesh node.
– Added UCX collider support.
– Added small hole filling.
– Curvature step now shows value clipping preview.
– Fixed deleting polys with zero importance.

art assets for games Mesh processor MeshProcessor17 231x300

The workflow uses 3 HDAs:


Load Mesh: Loads a file and transforms it so it’s oriented and scaled properly. Optionally it can pre-process high poly UVs. (See bellow.)


Process Mesh Part: Takes a named part of the imported geometry and turns it into a game ready asset. More than one can be used.


Finalize Mesh: Gathers all the processed mesh parts, properly arranges their UVs, bakes the textures and exports the model.

Now let’s go through the whole workflow in greater detail.


When modeling the high poly mesh there are very few limitations: aside of degenerate polygons, anything goes: any polycount, intersecting polygons, etc. (Subdivision surfaces have to be frozen at this time as I yet to find a way to reproduce the Modo’s pSDS results from the cage.) However it is recommended to keep the geometry as watertight as possible. Small, flat holes are fine but bigger ones with complicated boundaries might produce unexpected results.

The LoadMesh node

The source geometry is referenced in the LoadMesh node, along with a second, optional mesh which will be exported as a collider, using Unreal’s naming convention.


The scaling value is for cases when the incoming mesh is so small or so big that the curvature calculations (which use absolute distances) don’t produce usable results.

When ProcessUVs is enabled then UV coordinates on the incoming high poly mesh are prepared, to be baked into a texture at the end. (The process can take a long time.) That texture (*_hpuv1.exr) can be used as a basis for projection in Substance Painter.


Creating high poly UVs is often fairly easy, especially when working with subdivision surfaces. Now they will survive the decimation and low poly UV generation so they can help in cases when the stock Painter projection modes are not sufficient. (The low poly UV layout is volatile and automatic and that makes Painter’s default projection method useless here.)

art assets for games Mesh processor MeshProcessor20 300x300
art assets for games Mesh processor MeshProcessor19 300x226

It’s enough to unwrap only the required polygons as long as the rest of the vertices are in 0,0. The laid out poly islands will get a distance field calculated for them which can be used as a mask in Painter later on. That mask’s transition to black is controlled by the UV Fade distance slider.

The final texture storing the UV information is quite simple: The red and green channels store the coordinates while the blue is for the distance field mask.

art assets for games Mesh processor MeshProcessor22
art assets for games Mesh processor MeshProcessor21

In Substance Painter use my ImageBasedProjection filter on top of the layers needing to be reprojected. The hpuv1 texture should be used as the image input.

Extracting the blue channel of that texture with the ColorMask filter makes creating masks simpler.

The ProcessMeshPart node
art assets for games Mesh processor MeshProcessor02

The bulk of the work is done in the Process Mesh Part. Its parameters panel guides the setup process by showing all steps but only revealing the params for the current one. It also indicates when the data is going to be cached.


The “Active?” flag allows us to temporally disable this node: the node’s color becomes gray and the Finalize Mesh node skips its output.


The “Part name” is the value of the “name” attribute we are interested in. This corresponds to the item name in Modo.


The “Mode” dropdown let’s us choose the steps, one after the other. When the last one is reach the node turns green indicating that it’s ready. Only then will the Finalize Mesh node use its data.


Both caching and node color changes are handled by the Python Module in the Scripts tab of the Type Properties panel.

art assets for games Mesh processor MeshProcessor03 273x300

The ID Coloring step is about assigning a distinct color to each material, to be baked and used as an ID map in Substance Painter. For now it’s totally random so we just change the random seed until the colors are distinct enough.

Alternatively the vertex colors on the high poly mesh could be used as IDs.

art assets for games Mesh processor MeshProcessor04 300x218

The voxelization step is simply an interface to the SideFX Labs Voxel Mesh node. Hole filling also happens here, which can be skipped, if we are sure all the bits are watertight and thus voxelization friendly, to speed up the processing.


The AttribTransfer node proved to be very unprecise so vertex attributes are copied over to the voxelized mesh using the xyzdist function in a wrangler node.


This step can take a lot time and memory, slowing down iteration so, if possible, we should split the mesh into multiple parts and process them one by one using multiple Process Mesh nodes.

Next comes curvature calculation. An ambient occlusion based method is used and values are calculated for 5 different scales. That process takes some time but when it’s done the contribution of each value can be mixed realtime. I tweak these values based on how I intend to texture the mesh part later on: I might want to emphasize mid size curvature for chipped paint but finer details for moss on a rock.

When moving from Curvature to Importance setup, the results are cached and saved into the .hip file so next time the scene is loaded the high definition mesh is readily available.

art assets for games Mesh processor MeshProcessor23 197x300
art assets for games Mesh processor MeshProcessor24 300x196

Next up is calculating importance for poly reduction. The values are visualized and range from 0 (dark red) to 1 (white). The Delete zero importance bits flag will delete unimportant polygons, leaving holes in the mesh. Those can be filled in the next step.

The following factors can contribute to the final value:


— Visibility —

When its Weight is greater than 0 then visibility from the points in Point cloud source is used to determine importance. (It’s the 3 point curve being edited on the image to the left.)


Ray length is how far the points can see while Edge fade distance is how long the importance decreases nearing the max ray length.


Contour strength controls how much extra importance to assign to surfaces at glancing angles. Helps to maintain contours when the point cloud is unevenly distributed around the high polygon mesh.


Blur spreads the importance values which is often required to avoid sudden changes in polycount during poly reduction.


Fast mode is required for complex voxelized geometry where tweaking the point cloud or the values above is not fast enough to be interactive. Ironically enabling this will need a length calculation once but after that’s done fine tuning visibility should be much smoother.


— Occlusion —

Occlusion, helps to decrease importance in hard to see places. For more on the parameters watch the official tutorial.

Then comes the actual decimation using the PolyReduce node with the Importance attribute used to retain density by.

art assets for games Mesh processor MeshProcessor25 300x130
art assets for games Mesh processor MeshProcessor26 300x203

Sometimes there are triangles folded onto each other, almost overlapping but not quite, those are left intact until I can figure out a way to detect and fix them. In the mean time if that happens I keep adjusting the parameters until it goes away fully or at least to a less visible part of the mesh… ಠ_ಠ

With the Hole filling tolerance parameter it is possible to fill many or all holes in the mesh. Mostly used with Delete zero importance bits in the Importance step. The slider goes from 0 to 1: from no filling any holes to filling even the biggest hole. In between values correspond to holes arranged by circumference.

art assets for games Mesh processor MeshProcessor10 300x216

With the topology ready we can set up the preliminary UVs. Only the shape of the UV islands are important in this step because their size and place in the UV space will be finalized later.

The parameters are mirroring that of the AutoUV SOP. The following logic takes care of the UV overlaps often produced: UV coordinates are used as point locations so the polys a laid out in 3D space. The PolyDoctor node then marks overlaps, the marks are copied over to the original geometry by primitive index and finally the overlapping primitives are unwrapped again. This fix increases the number of UV islands but that’s a much smaller problem than overlaps.

art assets for games Mesh processor MeshProcessor27 300x202

The next step is calculating importance for UVs, used during the final UV layout (which contains all the mesh parts in the scene). The importance parameters are the same as before but the values are quantized to 4 distinct steps, from dark purple to white in the visualization.

art assets for games Mesh processor MeshProcessor12 300x141

The Duplication phase works from the second, low poly cache. This is an optimization step because the copies are stacked in the final UV, saving texture space on repeating elements.

At this time only mirroring and cloning is supported but I’d like to have a more generic solution in the future based on incoming points carrying transforms.

art assets for games Mesh processor MeshProcessor13 300x195
art assets for games Mesh processor MeshProcessor14 300x294
The FinalizeMesh node

After all the mesh parts are fully set up the Finalize Mesh node can finish the job.

The parameters UI works similarly to the Process Mesh node:


First the UVs of all the mesh parts are laid out and the UV islands are scaled based on their UV importance value. Enabling the “Visualize variable UV scale” tickbox helps to see the relative texel densities.
Internally, after the UVLayout node the UV stacking is restored and the result is cached.


The Bake step sets up and runs the baking process. All textures are saved as EXR files so position and uv textures don’t lose precision.


The Export mode is for exporting the finished model into two files: one without collision (for texturing in Substance Painter) and one with (for Unreal).