Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
268 lines (239 sloc) 4.99 KB
// bubble sort. fast enough
// for small collections
void sort(int np, output point p[], output float f[]){
int n=np;
for(int j=0; j<np; j++){
for(int i=1; i < n; i++){
if( f[i-1] > f[i] ){
float tf=f[i-1];
f[i-1]=f[i];
f[i]=tf;
point tp=p[i-1];
p[i-1]=p[i];
p[i]=tp;
}
}
n--;
}
}
void voronoip9d(
point q,
float T,
output point vp[9],
output float vd[9])
{
point p = point(q[0],q[1],0);
float xx, yy, xi, yi;
xi = floor(p[0]);
yi = floor(p[1]);
int i=-1;
for(xx=xi-1; xx<=xi+1; xx++){
for(yy=yi-1; yy<=yi+1; yy++){
i++;
vector ip =
vector(xx, yy, 0);
vector np = cellnoise(ip);
vp[i]=ip + np*T +
vector((1-T)/2,(1-T)/2,0);
vp[i][2] = 0;
vector dp = vp[i] - p;
vd[i] = dp[0]*dp[0] +
dp[1]*dp[1];
}
}
sort(9,vp,vd);
}
// given a point p which is a voronoi sample point,
// return 8 other sample points distributed around p
// in clockwise sorted order
void voronoip8a(
point q,
float T,
output point vp[8],
output float angles[8])
{
point p = point(q[0],q[1],0);
float xx, yy, xi, yi;
xi = floor(p[0]);
yi = floor(p[1]);
int i=-1;
for(xx=xi-1; xx<=xi+1; xx++){
for(yy=yi-1; yy<=yi+1; yy++){
vector ip =
vector(xx, yy, 0);
vector np = cellnoise(ip);
np[2] = 0;
vector vvp = ip + np*T +
vector((1-T)/2,(1-T)/2,0);
vector d = vvp-p;
if( dot(d,d)>1e-7 ){
float angle =
atan2(d[1],d[0]);
i++;
vp[i]=vvp;
angles[i]=angle;
}
}
}
sort(8,vp,angles);
}
int point_inside_polygon(
point p,
point verts[],
int nverts,
output float sumangle
){
int i;
sumangle=0;
vector ref=
normalize(verts[0]-p);
vector ref2;
float amod;
for(i=1; i<nverts; i++){
ref2 = normalize(verts[i]-p);
sumangle += acos(dot(ref, ref2));
ref = ref2;
}
ref2=normalize(verts[0]-p);
sumangle+=acos(dot(ref, ref2));
amod=abs(mod(sumangle,M_2PI));
return (amod < 1e-2)
|| (M_2PI - amod < 1e-2) ;
}
int closest_convex_polygon(
point c0,
point vp[8],
output point mp[8])
{
int imp[8] = { 0, 1};
int nmp = 2;
int delauney(int b,int c,int d)
{
float alpha = acos(
dot(vp[b]-vp[c],vp[b]-c0));
float gamma = acos(
dot(vp[d]-vp[c],vp[d]-c0));
return (alpha+gamma) <= M_PI;
}
for(int i=2; i<8; i++){
if( delauney( imp[nmp-2], imp[nmp-1],
i) )
{
imp[nmp]=i;
nmp++;
}else{
imp[nmp-1]=i;
}
}
while( (nmp > 3) &&
! delauney(imp[nmp-2], imp[nmp-1],
imp[0]) )
{
nmp--;
}
#if 0
int deleted=1;
while( (nmp>3) && deleted ){
deleted = 0;
for(int i=0; i<nmp; i++){
if( !delauney(
imp[i],
imp[(i+1)%nmp],
imp[(i+2)%nmp]) )
{
for(int j=i+1;
j<(nmp-1);
j++)
{
imp[j] = imp[j+1];
}
deleted = 1;
nmp--;
break;
}
}
}
#endif
for(int i=0; i<nmp; i++){
mp[i] = vp[imp[i]];
}
return nmp;
}
shader leopard(
point Pos = P,
float Scale = 1,
color Blob = 0,
color Inside = 0.5,
color Outside = 1,
color Center = 0,
float R = 184,
float Radius = 2.4,
float S = 1.4,
float E = -2,
float Shape = 0.5,
float F = 0.01,
float G = 11.0,
float Cp = 0.2,
float Cr = 0.005,
output color Color = Blob,
output float D = 0,
output float Edge = 0
){
color colors[8]={color(1,0,0),
color(0,1,0),
color(0,0,1),
color(.6,0,0),
color(0,.6,0),
color(0,0,.6),
color(.3,0,0),
color(0,.3,0)
};
point p = Pos * Scale;
p[2]=0;
point vp[9];
float dp[9];
voronoip9d(p,Shape,vp,dp);
point nvp[8];
float angles[8];
voronoip8a(vp[0],
Shape,nvp,angles);
point mp[8];
int m = closest_convex_polygon(
vp[0], nvp, mp);
float sump = 0;
float mind = 1e7;
point mmp[8];
for(int i=0; i<m; i++){
mmp[i]=mix(vp[0], mp[i],
Radius/10);
float d = distance(mmp[i],p);
sump += S * pow(d, E);
d= distance(vp[0],mp[i]);
if( d < mind ){ mind = d; }
}
if( noise("cell",p) < Cp
&& dp[0] < Cr )
{
Color = Center;
}else if( sump < R ){
float sumangle;
if(point_inside_polygon(
p+noise("snoise",G*p)*F,
mmp,m,sumangle) )
{
Color = Inside;
}else{
Color = Outside;
}
}
// the distance from the
// center of the rosette
D = dp[0];
// for debugging, highlight
// the edge of a cell
if ( mod(p[0],1.0)<0.02
|| mod(p[1],1.0)<0.02)
{
Edge=1;
}
}
You can’t perform that action at this time.