In total, the scene I sent to the render farm consisted of approximately 215000 objects. Most of these were instances of houses, trees, the glass roof, windows and other models. I used SideFX Houdini to lay out the points, and then copied the instances to them.

Glass roof

The glass roof was the setting stone for the instances underneath, as it set a proportion of how big the blocks of houses were. Naturally, I laid it out first. I created a tube sop, and rotated every second row of it to create a base point cloud for instancing. These instances were packed in the CopyToPoints SOP.

Houses

There are 21 variants of the houses in four categories – small, medium, wide and large. They were imported from a kitbash in Maya. I used VEX to categorize them and to create a variant attribute, used when copying the houses to an appropriately scaled lot. The lots were created using Chain SOP, which deformed a simple grid on a hexagonal curve. The scale of the houses copied was determined by hand using groups, however I imagine this could have easily been set up procedurally.

These lots were projected on the ground plane using Ray SOP, and cleaned up of pieces that contained less than four points per primitive.

For randomizing which variant of the house from its respective category goes on its lot, I used this VEX snippet:

[email protected] = fit(rand(@ptnum *chf("Seed")),0,1,0,6) ;

on the point groups I created earlier. This randomized the variant number, which the CopyToPoints SOP took as an input when instancing.

CopyToPoints SOP operation
An early render test of house instancing.

After a few iterations I was happy with the result.

Trees

I used a similar approach when loading the trees and categorized them based on their size. The only difference is that I used the AttributePaint SOP to create a mask for instancing.

AttributePaint mask
Instanced trees

A VEX snippet I found myself using repeatedly while instancing:

for (int i = 0; i < @numpt; i++) {
[email protected] = @P.y; vector a = set(0,@posy,0);@N = normalize([email protected]);
}

This orients every point’s normal at X,Z origin.

Leave a comment

Your email address will not be published. Required fields are marked *