//Fur generator by Margus Ramst //Macro parameters: //Object - #declared object to be made furry //DivIn - sampling rate along each axis (float or vector) //PosJ - randomness in the position of hairs; // PosJ=1 => max_displacement=object_size/DivIn/2 //NumSegm - number of segments (cones) in each hair //Len - length of hairs //LenJ - randomness in hair length (fraction of total length) //RadIn - radius of hair at the base //Wind - direcion of wind (or any directional force), // longer vector => stronger force //BendExp - how the hair is bent by Wind: // 1 bends uniformly from start to end; // >1 bends more towards end; // <1 bends more towards start; //DirJ - randomness in initial direction (fraction of 90 degrees rotation) //TwistIn - random twisting of hair (fraction of 90 degrees rotation); // it is independent of NumSegm: // twist per segment is calculated as TwistIn/NumSegm //Seed - random number seed to be used //FileO - if true, outputs cones to FileName, // declaring a CSG union object Hairs //FileName - name of the output file (in double quotes, e.g. "filename.inc") // You need to put something here even if FileO=false //NB! I have added manual bounding to the hairs to save memory; //this generates warnings. You should either disable the warning //stream with -GW or comment out the bounded_by statement in worm.inc #include "admacros.inc" #include "worm.inc" #macro Fur(Object, DivIn, PosJ, NumSegm, Len, LenJ, RadIn, Wind, BendExp, DirJ, TwistIn, Seed, FileO, FileName) #local Seed=seed(Seed); #local Divisions = DivIn+<0,0,0>; #local Jitter = PosJ+<0,0,0>; #local LenJ = LenJ*Len; #local Twist=TwistIn*90/NumSegm; #local PosMin = min_extent(Object); #local PosMax = max_extent(Object); #local Dim = PosMax-PosMin; #local JumpInit = Dim/Divisions; #local Start=PosMin; #local XYZ=1; #if(FileO!=0) #fopen OFile FileName write #write(OFile,"#declare Fur=union{\n") #end #debug "Calculating points...\n" #while (XYZ<=3) #local Count1=1; #local Count2=1; #switch(XYZ) #case(1) #local PosC=; #local NDir=z; #local CountDim1=Divisions.x; #local CountDim2=Divisions.y; #local Jump1=JumpInit*x; #local Jump2=JumpInit*y; #break #case(2) #local PosC=; #local NDir=x; #local CountDim1=Divisions.z; #local CountDim1=Divisions.y; #local Jump1=JumpInit*z; #local Jump2=JumpInit*y; #break #case(3) #local PosC=; #local NDir=y; #local CountDim1=Divisions.x; #local CountDim2=Divisions.z; #local Jump1=JumpInit*x; #local Jump2=JumpInit*z; #break #end #local Pos=PosC; #while(Count2<=CountDim2) #local SeedC=Count1+Count2; #local Flag=1; #local PosT=Pos+(1-NDir)*v_rand_ext(0,JumpInit/2*Jitter,Seed); #while(Flag=1) #local Rad=RadIn; #local N = <0,0,0>; #local Start = trace(Object, PosT, NDir, N); #if (N.x!=0 | N.y!=0 | N.z!=0) Worm(NumSegm,rand_ext(Len,LenJ,Seed),Rad, Start,vrotate(N,v_rand_ext(0,90*DirJ,Seed)), Wind,BendExp, Twist,Seed, FileO) #local PosT=Pos+NDir*(Start-Pos)+(1-NDir)*v_rand_ext(0,JumpInit/2*Jitter,Seed); #else #local Flag=0; #end #end #if(Count1>=CountDim1) #local Pos=PosC+Count2*Jump2; #local Count1=1; #debug concat("Dim ",str(XYZ,0,0)," Count2=",str(Count2,0,0),"\n") #local Count2=Count2+1; #else #local Pos=PosC+Count1*Jump1+(Count2-1)*Jump2; #local Count1=Count1+1; #end #end #local XYZ=XYZ+1; #end #if(FileO!=0) #write (OFile,"}") #fclose OFile #end #end