Jump to content

Poisson Disk Sampling Help


miccetro

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

Link to comment
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

Link to comment
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;
    
}

to read
https://www.jasondavies.com/poisson-disc/

http://devmag.org.za/2009/05/03/poisson-disk-sampling/

Link to comment
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

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...