#macro Crevice(base_obj,samp_loc,samp_res,ctrl_ang,ctrl_dep,surf_off,adap_min,adap_max,adap_cnf) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // Crevice Finder Pattern // // Trevor G. Quayle, 2011 // // For POV-Ray 3.7 // // // // PASSED VARIABLES: // // // // base_obj = Base object: should be declared and postioned before passing. // // // // samp_loc = Origin of sampling rays: usually camera location, but other location may be used for other effects // // // // samp_res = Resolution of sampling grid: sampling grid size = diagonal of object bounding box // // // // ctrl_ang = Sampling control angle: angle of trace samples from surface tangent (0=tangent, 90=normal), affects // // influence of crevice depth, smaller values will capture shallower crevices // // // // ctrl_dep = Sampling control depth: control depth for trace samples, affects influence of crevice size, larger // // values will capture larger crevices and open areas // // // // surf_off = Surface offset for traces: sample traces start offset from object surface, should be used for mesh // // objects and for edge-finding // // // // adap_min = Minimum adaptive sampling level (2^value): 2 (4 samples) recommended, but may be less, non-positive // // values automatically reset to 2 // // // // adap_max = Maximum adaptive sampling level (2^value): values less than adap_min automatically reset to adap_min // // // // adap_cnf = Confidence value for adaptive sampling: adaptive sampling stopped when new value reaches confidence // // level of old value // // // // NOTES: // // - Macro returns directly as a function with values 0-1 which can be used for pigment, normal or texture mapping // // - To use as crevice finder, ctrl_ang and surf_off should be positive // // - To use as edge finder, ctrl_ang and surf_off should be negative // // - to avoid artifacts, surface offset should be set (non zero) for meshes and for edge finder // // - crevice data is only determined for surface points directly visible from sample_location: // // - samp_loc should be equal to scene camera location (perspective cameras) // // - object should have all transforms applied before being passed // // - reflections of object may not display the crevice data properly // // - CSG objects should be merged (not unioned) for edge finder to work properly, otherwise, interior surfaces may // // interfere with proper detection // // - temporary "CreviceData.df3" file will be created with each run of the macro // // - "arrays.inc" must be included (uses ARRAYS_WriteDF3()) // // - Warning! increasing samp_res exponentially increases parse time! // // // // USAGE: // // texture{ // // function{Crevice(base_obj,samp_loc,samp_res,ctrl_ang,ctrl_dep,surf_off,adap_min,adap_max,adap_cnf)} // // texture_map{...} // // } // // // // pigment{ // // function{Crevice(base_obj,samp_loc,samp_res,ctrl_ang,ctrl_dep,surf_off,adap_min,adap_max,adap_cnf)} // // colour_map{...} // // } // // // // normal{ // // function{Crevice(base_obj,samp_loc,samp_res,ctrl_ang,ctrl_dep,surf_off,adap_min,adap_max,adap_cnf)} // // normal_map{...} // // } // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #local obj_ctr=(min_extent(base_obj)+max_extent(base_obj))/2; #local obj_ctr_x=obj_ctr.x;#local obj_ctr_y=obj_ctr.y;#local obj_ctr_z=obj_ctr.z; #local obj_siz=vlength(max_extent(base_obj)-min_extent(base_obj)); #local samp_vec=samp_loc-obj_ctr; #local samp_os_x=vnormalize(); #local samp_os_y=vnormalize(vcross(samp_vec,samp_os_x)); #local ang_xz=(acos(samp_vec.x/vlength(samp_vec*<1,0,1>)))*select(samp_vec.z,-1,1); #local ang_xy=(asin(samp_vec.y/vlength(samp_vec))); #local obj_norm=<0,0,0>; #local trace_norm=<0,0,0>; #local pix_val=array[samp_res+1][samp_res+1]; #for (i,0,samp_res,1) #for (j,0,samp_res,1) #local trace_len=0; #local pix_val[j][i]=0; #local pix_cur=obj_ctr+obj_siz*((i/samp_res-0.5)*samp_os_y+(j/samp_res-0.5)*samp_os_x); #local obj_int=trace(base_obj,samp_loc,pix_cur-samp_loc,obj_norm); #if (vlength(obj_norm)!=0) #for (p,0,adap_max,1) #local adap_cur=p; #local PTLen=trace_len; #for (k,0,max(pow(2,adap_cur-1)-1,0),1) #local trace_ang=(k*2+1)*360/pow(2,adap_cur); #local trace_vec=vaxis_rotate(vaxis_rotate(obj_norm,<-obj_norm.z,0,obj_norm.x>,90-ctrl_ang),obj_norm,trace_ang); #local trace_int=trace(base_obj,obj_int+obj_norm*surf_off,trace_vec,trace_norm); #if (vlength(trace_norm)!=0) #local trace_len=trace_len+ctrl_dep/vlength(trace_int-obj_int); #end #end #if (adap_cur=adap_min) #if (trace_len=0) #local p=adap_max; #end #elseif (adap_cur>adap_min) #if ((1-abs(1-(trace_len/PTLen)/2))>=adap_max) #local p=adap_max; #end #end #end #end #if (trace_len=0) #local trace_len=1; #else #local trace_len=min(pow(2,adap_cur)/trace_len,1); #end #local pix_val[j][i]=trace_len; #local pix_siz=obj_siz/(2*samp_res); #end #end ARRAYS_WriteDF3(pix_val, "CreviceData.df3", 16) #ifdef(FUNK1) #undef FUNK1 #end #ifdef(FUNK2) #undef FUNK2 #end #local FUNK1= function{pattern { density_file df3 "CreviceData.df3" interpolate 1 //use interpolate 0 or 1 only, for interpolate 1 enable pixel shift below translate -0.5 scale obj_siz+pix_siz*2 translate +pix_siz //enable pixel shift for interpolate 1, disable for interpolate 0 } } #local vec_len=vlength(samp_vec); #local FUNK2= //Perspective warp function{FUNK1(-z/(1-x/vec_len),y/(1-x/vec_len),0)} FUNK2(//rotate and translate alignment - output function (cos(-ang_xz)*(x-obj_ctr_x)-sin(-ang_xz)*(z-obj_ctr_z))*cos(-ang_xy)-(y-obj_ctr_y)*sin(-ang_xy), (cos(-ang_xz)*(x-obj_ctr_x)-sin(-ang_xz)*(z-obj_ctr_z))*sin(-ang_xy)+(y-obj_ctr_y)*cos(-ang_xy), (sin(-ang_xz)*(x-obj_ctr_x)+cos(-ang_xz)*(z-obj_ctr_z)) ) #end