// MIT License (MIT) // Copyright (c) 2020 Patrick Seeber // // xs_begin // author : '@rubikow' // arg : { id = '0' name = 'Max Volume' value = '4' range = '0 100' step = '1' decimal = '0' } // arg : { id = '1' name = 'Random Seed' value = '123' range = '0 10000' step = '1' decimal = '2' } // arg : { id = '2' name = 'Growth Density' value = '0.3' range = '0 1' step = '0.01' decimal = '2' } // arg : { id = '3' name = 'Additional Colors' value = '0' range = '-255 255' step = '1' decimal = '0' } // xs_end float thickness = float(iArgs[0]); float seed = float(iArgs[1]); float density = float(iArgs[2]); float colorRange = float(iArgs[3]); bool isGrowColor(vec3 v){ return voxel(v) >= min(i_color_index, i_color_index + colorRange) && voxel(v) <= max(i_color_index, i_color_index + colorRange); } float random(vec3 v, float seed){ float n = v.x*v.y*v.z + seed; return abs(fract(sin(1./tan(n) + seed * 1235.342))); } float minDistanceToWall(vec3 v, float distance){ float minDistance = distance+1.; for(float x=-distance; x<=distance;x+=1.){ for(float y=-distance; y<=distance;y+=1.){ for(float z=-distance; z<=distance;z+=1.){ if(voxel(vec3(v.x+x,v.y+y,v.z+z)) != 0. && !isGrowColor(vec3(v.x+x,v.y+y,v.z+z))){ float d = sqrt(pow(x,2.) + pow(y,2.) + pow(z,2.)); if(minDistance > d){ minDistance = d; } } } } } return minDistance; } float getCrowColor(vec3 v){ float distance = minDistanceToWall(v, thickness); return i_color_index + colorRange * (distance/sqrt(pow(thickness,2.)*3.)); } bool hasWallNextToIt(vec3 v, float distance){ for(float x=-distance; x<=distance;x+=1.){ for(float y=-distance; y<=distance;y+=1.){ for(float z=-distance; z<=distance;z+=1.){ if(voxel(vec3(v.x+x,v.y+y,v.z+z)) != 0. && !isGrowColor(vec3(v.x+x,v.y+y,v.z+z)) ){ return true; } } } } return false; } int getFlatNeighbors(vec3 v){ int neighbors = 0; if(isGrowColor(vec3(v.x+1.,v.y+1.,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x+1.,v.y-1.,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x-1.,v.y+1.,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x-1.,v.y-1.,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x+1.,v.y,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x-1.,v.y,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x,v.y-1.,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x,v.y+1.,v.z))){ neighbors++; } return neighbors; } int getNeighbors(vec3 v){ int neighbors = 0; if(isGrowColor(vec3(v.x,v.y,v.z+1.))){ neighbors++; } if(isGrowColor(vec3(v.x,v.y,v.z-1.))){ neighbors++; } if(isGrowColor(vec3(v.x+1.,v.y,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x-1.,v.y,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x,v.y-1.,v.z))){ neighbors++; } if(isGrowColor(vec3(v.x,v.y+1.,v.z))){ neighbors++; } return neighbors; } bool growsDown(vec3 v){ if(isGrowColor(vec3(v.x,v.y,v.z+1.))){ return true; } if(isGrowColor(vec3(v.x+1.,v.y,v.z))){ return true; } if(isGrowColor(vec3(v.x-1.,v.y,v.z))){ return true; } if(isGrowColor(vec3(v.x,v.y-1.,v.z))){ return true; } if(isGrowColor(vec3(v.x,v.y+1.,v.z))){ return true; } return false; } bool grows(vec3 v){ int n = getNeighbors(v); float r = random(v, seed+float(n)); if(voxel(v) == 0.){ if(hasWallNextToIt(v, 1.) && isGrowColor(v+vec3(0,0,-1.)) && mod(v.x+v.y,13.) == 0.){ return true; } if(hasWallNextToIt(v, 1.) && isGrowColor(v+vec3(0,0,1.)) && mod(v.x+v.y,27.) == 0.){ return true; } if(hasWallNextToIt(v, 1.) && isGrowColor(v+vec3(0,0,-2.)) && mod(v.x+v.y,13.) == 0.){ return true; } if(hasWallNextToIt(v, 1.) && isGrowColor(v+vec3(0,0,2.)) && mod(v.x+v.y,27.) == 0.){ return true; } if(hasWallNextToIt(v, 1.) && getFlatNeighbors(v) > 3){ return true; } else if(r < (density) - (minDistanceToWall(v,thickness)/thickness)*(density/2.) && hasWallNextToIt(v, thickness) && n > 0 && (growsDown(v) || random(v, seed+5.567) < 0.3)) { return true; } } return false; } float grow(vec3 v, float seed){ if( grows(v)){ return getCrowColor(v); }else if(isGrowColor(v) && minDistanceToWall(v, thickness) > 1.){ int n = getNeighbors(v); float r = random(v, seed+float(n)); if(r < density + float(n)/100. + (pow(minDistanceToWall(v, thickness),2.)/pow(thickness,2.)) * 0.5){ return 0.; } } return voxel(v); } float map(vec3 v) { return grow(v, seed); }