Today I needed to enforce certain texel density for my procedurally generated meshes in Houdini. I found this tool, but unfortunately supplied HDA did not work on my Indie license and it was locked, so I had to recreate this myself.
Nothing complicated, but It is actually a very useful tool to have when dealing with procedurally generated meshes.
First for each primitive you measure its area in world space and in UV space.
Then you multiply world space area with target texel density (how many pixels you want per square meter)
Multiply UV space area by texture pixel count ( how many pixels will be in texture = texture_size
Now you have a ratio = target texel density / current texel density
Use it (square root of it, because area increases quadratically) as a scaling factor for your UV islands.
To be more precise, I calculate average scaling ratio per UV island. To do that, you first split geometry along UV seams and then generate class id using Connectivity SOP. This is better than using connectivity of UV attribute directly, because it allows overlapping UV islands to be handled separately.
After that you can do it in two ways – you can use UV Transform SOP to scale each island one by one (using
$CEX, $CEY, $CEZ to get centroid as a pivot). This scales islands in place, possibly generating many overlaps. Another option is to use UVLayout SOP with the “iscale” primitive attribute to scale and re-pack all the islands in one go. I provided both methods in HDA and you can switch between them using checkbox.