Jump to content

## Recommended Posts

Hi guys and girls, I have this condensation on bottle shot I'm working and would love to create a poisson disk distribution with a uniform sample of points based on the area of the triangles in the mesh. I've been looking at the papers written about this but its a liittle bit technical for me at this time. I'm hoping some could maybe look at my file and point me in the right direction to use vex to create this algorithm. Thanks much in advance.

poisson_on_bottle_setup.hip

#### Share this post

##### Share on other sites

as said, I've never used it so this could be a disaster...just try fiddle around with Mean/Max

poisson_on_bottle_setup_mod.hipnc

#### Share this post

##### Share on other sites

Hi Noobini, thanks for the tip, didn’t know about that function. I’m however looking to create something more like the algorithm in the paper attached! the parts about grouping points by cell ID and the hashtables parts go over my head, but I know with some technical assistance I can implement this algorithm!

c95-f95_199-a16-paperfinal-v5.pdf

#### Share this post

##### Share on other sites
```//detail
float r =1;
int k = 30;
int dim = 2;
int width = 200;
int height = 100;
// fill grid with -1
int grid[];        // -1 is no sample
vector grid_pts[]; // -1 is default set(0,0,0)

int active[];    // an array of sample indices
vector active_pts[];

vector process_pts[];

// cell size of per voxel
float w = r / sqrt(dim);

int cols = floor(width  / w);
int rows = floor(height / w);

for(int i= 0;i<cols * rows ; i++){
push(grid, -1);
push(grid_pts, set(0,0,0));
}
printf("cellsize: %d, cols: %d, rows: %d\n",w, cols, rows);

// step1
// Select the initial sample,x0, randomly chosen uniformlyfrom the domain
float init_x = width / 2.0f;
float init_y = height / 2.0f;
vector init_pos = set(init_x, init_y, 0 ); // init point from center!
int init_i = floor(init_x / w);
int init_j = floor(init_y / w);

grid_pts[init_i + init_j *cols] = init_pos;
grid[ init_i + init_j *cols] = 1;

push(active_pts, init_pos); // Insert it into the background grid
push(active, 0); // push the first point=0 is active!

// ---------------------  step2
int sel_active_seed = 1237;
int push_active_index = 0;

while(len(active)!=0 ){
// choose a random index from it (say i) from active list
//printf("length active:%d\n", len(active) );
int rand_index =  floor(rand(sel_active_seed) * float(len(active) ) );

//printf("sel rand active index: %d\n", rand_index);
vector pos = active_pts[rand_index];

int found = false;
//Generate up to k points chosen uniformly from thespherical annulus between radius r and 2r) aroundxi.
for(int ns = 0; ns < k; ns++){
float genkseed = rand( (sel_active_seed + ns )*564  ) * 2 * PI;
vector genkpos;
genkpos.x = sin(genkseed);
genkpos.y = cos(genkseed);
genkpos.z = 0;

float vlen = rand(ns*135 + sel_active_seed *54);
vlen = fit(vlen, 0, 1, r, 2*r);

genkpos *= vlen;
genkpos += pos; // generate our k points

//printf("%f %f \n", genkpos.x, genkpos.y);
//
int col = floor(genkpos.x / w);
int row = floor(genkpos.y / w);
//printf("col:%d, row:%d\n",col,row);

int cond_0 = col >-1 && col < cols;
int cond_1 = row >-1 && row < rows;
int cond_2 = grid[col + row * cols] == 1;

if(cond_0 && cond_1 && !cond_2){
// query neibours
int should_insert = 1;

for(int i= -1; i<=1; i++ ){
for(int j =-1; j<=1; j++){
int neibour_index = (col+i) + (row+j) * cols;
int neibour_grid_data = grid[neibour_index];

vector neibour_pos = grid_pts[neibour_index];
if(neibour_grid_data == 1){
float dist = distance(genkpos, neibour_pos);
if(dist < r) should_insert = 0;
}
}
}// end of query near points

if(should_insert) {
//printf("insert a point\n");
found = 1;

// update the grid
grid[col + row * cols] = 1;
grid_pts[col + row * cols] = genkpos;

// update active
push(active_pts, genkpos);
push_active_index +=1;
push(active, push_active_index);
push(process_pts, genkpos);
break;
}

}

}

if(!found){
/*
printf("{\n");
for(int i: active){
printf("now active list value: %d\n", i);
}
printf("}\n");
printf("---now remove id:%d\n", rand_index);
if(removevalue(active,rand_index) ){
printf("---after remove active, now has length:%d \n", len(active));
}
else{
printf("****remove id:%d faild\n", rand_index);
}*/

pop(active, rand_index);
pop(active_pts, rand_index);
}

sel_active_seed += 135;
}

int i=0;
for(vector p: process_pts){
int pt = addpoint(geoself(), p);
vector c0 = set(1,0,1);
vector c1 = set(0,1,1);
float bias = (sin( float(i*0.002) ) + 1.0) / 2.0f;
setpointattrib(geoself(), "Cd" , pt , lerp(c0,c1, bias)   );
++i;

}```

#### Share this post

##### Share on other sites

You can also use scatter with relax iteration to get quite equidistant sampling. It is a bit slow but you can also use density attribute.

poisson_on_bottle_setup_scattering.hipnc

#### Share this post

##### Share on other sites

Not sure i will make it more complicated at it as to myself. Another totally different approach, would be to remesh with high value iteration, place a point at each prim center, compute the area to define the pscale of each point so they will not be colliding.

There are multiple desintersect method too off course, Matt from houdini wiki show some for example...

________________________________________________________________

Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts

http://fr.linkedin.com/in/vincentthomas

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

## Sign in

Already have an account? Sign in here.

Sign In Now

×
• Donations

• Leaderboard