Tiling a surface with geometry

   1730   2   0
User Avatar
Member
139 posts
Joined: March 2018
Offline
Hi, quite new to Houdini so this is a newbie question.

Anyway, I'm doing some procedural architecture as an exercise and I want to tile the surface with geometric tiles like bricks of different sizes and planks for the floor. I want to be able to base this on assets that I create separately where the scale will not change(e.g. photogrammetry or existing kits).

This should be randomized so that different tilings can be tested. It is not just about optimal packing.

I have tried the new UV layout SOP but can not get an aesthetic tiling.

Being a programmer I might be able to solve this using a lot of vex but I was thinking that maybe there was an easy way out and that it might be a common problem.
Any help or pointers are greatly appriciated!
/Filip
User Avatar
Member
139 posts
Joined: March 2018
Offline
Ok, I made a flakey solution that tiles a flat surface with known objects of specified width but different lengths.
Most was written in a details VEX wrangle + a for loop network. It solves my need but it feels very ugly/inelegant combining nodes, snippets of codes, expressions etc…. If anyone could suggest improvements I would gladly hear them.

/F
Edited by filipw - Nov. 19, 2018 09:08:11

Attachments:
vex_tile_floor_v2.hipnc (148.8 KB)
Screenshot 2018-11-19 at 14.59.22.png (1.5 MB)

User Avatar
Member
139 posts
Joined: March 2018
Offline
the core of my approach is to run a detail attribute wrangle that does this:
vector areaBoundsIn = getbbox_size(2);
areaBounds.x = areaBoundsIn.x;
areaBounds.y = areaBoundsIn.y;
vector2 tiles[];
int placedTileType[];
vector2 placedTilePositions[];
vector2 placedTileSizes[];

//i@num_items = chi("../object_merge1/numobj");


s[]@groups  = detailintrinsic(1, 'primitivegroups');
int numItems = len(@groups)-1 ;
for(int i=0;i< numItems;i++)
{
    vector groupSize = getbbox_size(1, @groups[i+1]);
    //@maxy = groupSize.y;
    tiles[i].x = groupSize.x;
    tiles[i].y = groupSize.y;
}


int seed = chi("seed"); 
float yOffset = ch("yoffset");
float currentX = 0;
float currentY = 0;
int currentTile = 0; 
int withinBounds = 1;
int lastType = 0;
float startY = 0;
//@some = @opinput1_max_height;
while(withinBounds)
{
        vector2 tilePosition = set(currentX, currentY);
        int tileTypeIndex = floor(rand(491+seed+currentTile)*(numItems));
        if(lastType == tileTypeIndex) {
            tileTypeIndex = (tileTypeIndex+1)%numItems;
            
        }
        lastType = tileTypeIndex;
        vector2 tileSize = tiles[tileTypeIndex];
        
        
        placedTilePositions[currentTile] = tilePosition;
        placedTileType[currentTile] = tileTypeIndex;
        placedTileSizes[currentTile] = tileSize ;


        float nextY = currentY + tileSize.y;
        float nextXIfWrap = currentX + tileSize.x;
        if (nextY > areaBounds.y){
        
                startY = -rand(currentTile+seed+667)*yOffset;
                currentY = startY;
                currentX = nextXIfWrap;
                if(currentX > areaBounds.x+tileSize.x){
                        withinBounds = 0;
                }
        }else
        {
            currentY = nextY;
        }
        currentTile++;
}
i@numTiles = currentTile;
int i=0;

foreach(vector2 pos; placedTilePositions)
{
    int pt = addpoint(0, set(pos.x, pos.y, 0.0));
    setpointattrib(0, "tile_type", pt, placedTileType[i], "set");
    i++;
}

Is this an approach a more experienced houdnini user also would chose? Or are there better/easier ways?
  • Quick Links