//greebles //take a polygon, subdivide and displace. #macro quad(a,b,c,d,e,f,g,h) triangle { a,b,c uv_vectors e,f,g } triangle { a,c,d uv_vectors e,g,h } #end //greeble macro /* set these variables before calling: #declare rs=seed(17); #declare greebleResX = 54; #declare greebleResY = 18; #declare greebleSize = 12; //units of res #declare numGreebles = 20; #declare greebleHeight = .5; or #declare f_greebleHeight = function(u,v,h){ ... }; function defined for [-1,1] range on each parameter, u,v is position of top of the "tower", h is the base height optional variables: #declare greebleDebug=off; */ //input: //points - an array 4 of points, should be coplanar, defining a face in clockwise order (as viewed from outside the object) #macro greeblequad(points) //preserve the edge, since we don't know the normal of adjacent greebled polys. #ifdef(greebleDebug) //debug: draw just the poly quad( #local i=0; #while ( i < 4 ) points[i], #local i = i+1; #end 0,u,u+v,v ) #else // you must define either greebleHeight or f_greebleHeight // function must obey: f_greebleHeight(-1) <= f_greebleHeight(x) <= f_greebleHeight(1) for all x in [-1,1] #ifndef (f_greebleHeight) #declare f_greebleHeight = function(u,v,h){ h*greebleHeight } #end /* subdiv & loft. perhaps using axis-aligned squares regardless of shape, or align to nearest feature. greebles that overlap should trash each other (always go to greater displacement) avoid specific features for now. so: div up into grid, then raise randomly placed rectangles to random heights, using a param to control how many to do. inter connecting polys: simply double up points on edge of grid, i.e. fill grid(array) with values, then read back dropping polys for faces, and more polys for any changes in val. */ #local greebleMap = array[greebleResX][greebleResY]; //set to 0 #local iy = 0; #while ( iy < greebleResY ) #local ix = 0; #while ( ix < greebleResX ) #local greebleMap[ix][iy] = 0; #local ix=ix+1; #end #local iy=iy+1; #end //---place greebles!--- #local i=0; #while ( i < numGreebles ) #local D = rand(rs)*2-1; #local up_down = (rand(rs)>0.5); #local W = int(1+rand(rs)*(greebleSize-0.0001)); #local X = int(rand(rs)*(greebleResX - W + 0.999)); #local H = int(1+rand(rs)*(greebleSize-0.0001)); #local Y = int(rand(rs)*(greebleResY - H + 0.999)); #local D = f_greebleHeight(-1+2*(X+W/2)/greebleResX,-1+2*(Y+H/2)/greebleResY,D); #local iy = Y; #while ( iy < Y+H ) #local ix = X; #while ( ix < X+W ) #if (up_down) #local greebleMap[ix][iy] = max(greebleMap[ix][iy],D); //only overwrite if taller #else #local greebleMap[ix][iy] = min(greebleMap[ix][iy],D); //only overwrite if taller #end #local ix=ix+1; #end #local iy=iy+1; #end #local i=i+1; #end //simple version, draw grid of polys evenly spread over this poly (assume it's 4 sided) //all inter-connected by perpendicular polys #local J = vnormalize(vcross(points[1]+points[2]-points[0]-points[3],points[3]+points[2]-points[0]-points[1])); //cross product of average horiz & vert vectors, i.e. normal at center #local iy = 0; #while ( iy <= greebleResY ) #local ix = 0; #while ( ix <= greebleResX ) #local i00=/; #local i01=/; #local i10=/; #local i11=/; //bilinear blend #local P00 = i00.x*i00.y*points[0] + i00.x*(1-i00.y)*points[1] + (1-i00.x)*i00.y*points[3] + (1-i00.x)*(1-i00.y)*points[2]; #local P01 = i01.x*i01.y*points[0] + i01.x*(1-i01.y)*points[1] + (1-i01.x)*i01.y*points[3] + (1-i01.x)*(1-i01.y)*points[2]; #local P10 = i10.x*i10.y*points[0] + i10.x*(1-i10.y)*points[1] + (1-i10.x)*i10.y*points[3] + (1-i10.x)*(1-i10.y)*points[2]; #local P11 = i11.x*i11.y*points[0] + i11.x*(1-i11.y)*points[1] + (1-i11.x)*i11.y*points[3] + (1-i11.x)*(1-i11.y)*points[2]; //left edge #if ((ix>0 & iy 0.001 ) //avoid pov error on degenerates quad ( P00 + A, P00 + B, P10 + B, P10 + A, //abba! i00, i00, i10, i10 ) #end //bottom edge #if ((ix0)) #local A = J*greebleMap[ix][iy-1]; #else #local A=0; #end #if ((ix 0.001 ) quad ( P00 + A, P00 + B, P01 + B, P01 + A //abba! i00, i00, i01, i01 ) #end //middle #if ( ix < greebleResX & iy < greebleResY ) quad ( P00 + J*greebleMap[ix][iy], P01 + J*greebleMap[ix][iy], P11 + J*greebleMap[ix][iy], P10 + J*greebleMap[ix][iy], i00, i01, i11, i10 ) #end #local ix=ix+1; #end #local iy=iy+1; #end #end #end #macro greebles(points) mesh { greeblequad(points) } //mesh #end #macro greeblestrip(points) //for points abcdefgh make clockwise quads: abdc, cdfe, efhg #local i=0; #while ( i < dimension_size(points,1)-2 ) greeblequad(array[4]{points[i],points[i+1],points[i+3],points[i+2]}) #local i=i+2; #end #end