// macros to create a dandelion clock 

#include "transforms.inc"

#declare dGeneralRand = seed(71282);   

// Macro to return a random number

#macro dr(num)
        rand(dGeneralRand)*num
#end


#macro mkDLPetal()                   

#local gTop = <-0.025+dr(0.05), 1.0+dr(0.1), (0.25+dr(0.1))>; 
#local gMiddle = <-0.025+dr(0.05), 0.5+dr(0.1), (dr(0.1)-dr(0.1))>;
#local gWidth1 = 0.07+dr(0.02);
#local gWidth2 = 0.1+dr(0.02);
#local gDepth=0.05+dr(0.025); 

#local  petalSpline = spline {
         natural_spline
         0.00, <0, 0.0, 0>
         0.5, gMiddle 
         1.0, gTop
       };   

#local  petalSplineLeft = spline {
         natural_spline
         0.00, <-gWidth1, 0.0, -(gDepth/2)>
         0.5, gMiddle-<gWidth2, 0, -gDepth> 
         1.0, gTop 
       };   

#local  petalSplineRight = spline {
         natural_spline
         0.00, <gWidth1, 0.0, -(gDepth/2)>
         0.5, gMiddle+<gWidth2, 0, -gDepth> 
         1.0, gTop 
       };   

        mesh {
    #local gpDetail=0.1;
    #local gp = 0;
    #while(gp < 1)
            triangle { petalSpline(gp), petalSplineLeft(gp), petalSpline(gp+gpDetail) }
            triangle { petalSpline(gp+gpDetail), petalSplineLeft(gp), petalSplineLeft(gp+gpDetail) }
    
            #local gp=gp+gpDetail;
    #end
    #local gp = 0;
    #while(gp < 1)
            triangle { petalSpline(gp), petalSplineRight(gp), petalSpline(gp+gpDetail) }
            triangle { petalSpline(gp+gpDetail), petalSplineRight(gp), petalSplineRight(gp+gpDetail) }
    
            #local gp=gp+gpDetail;
    #end

}
#end

#macro mkHair(hairSpline, hThickness)                   
    #local gpDetail=0.01;
    #local gp = 0;
    #while(gp < 1)
            triangle { hairSpline(gp), hairSpline(gp)-<hThickness, hThickness, hThickness>, hairSpline(gp+gpDetail) }
            triangle { hairSpline(gp+gpDetail), hairSpline(gp)-<hThickness, hThickness, hThickness>, hairSpline(gp+gpDetail)-<hThickness, hThickness, hThickness> }
    
            #local gp=gp+gpDetail;
    #end
#end

// dandelion  

#macro mkSeedHairs(numHairs, hThickness, seedTexture)
    #local hRotStep = 360/numHairs;
    #local hRot = 0;
    union {
    mesh {
    #while(hRot < 360)
    #local  hZRot= -10+dr(60);
    #local seedHairSpline  = spline {
         natural_spline
         0, <0, 0, 0>,
         0.45+dr(0.1), vrotate(vrotate(<1.4+dr(0.3), -(0.2+dr(0.2)), -0.1+dr(0.1)>, <0, 0, hZRot>), <0, hRot, 0>),
         1.0, vrotate(vrotate(<3+dr(0.5), 0, 0>, <0, 0, hZRot>), <0, hRot, 0>)
    }  
    mkHair(seedHairSpline, hThickness)
    
    #local hRot=hRot+(hRotStep-(hRotStep/10)+dr(hRotStep/5));
    #end

    }
    torus { 0.05, 0.05 texture { seedTexture } }  
    }
#end       

#macro dLeaf(minBend, maxBend, leafTex, detailLevel)
    
    #local midHeight=minBend+dr(maxBend-minBend);//.2 .3
    
    #local  TestSpline = spline {
                 natural_spline           
    
    #local spointDiff=dr(0.1);
    #local spoint=0.1+dr(0.1);
                 0.0, <-0.025, 0.05, 0>, 
    #while(spoint < 0.71)   
        #local spos=spoint*0.35+spointDiff;
            (spoint-(0.02+dr(0.01))), <-(spos+dr(0.01)), 0.05+(sin(spoint*4)*midHeight), (spoint-0.0125)*2>,
            spoint, <-(spos+0.02+dr(0.015)), 0.05+(sin(spoint*4)*midHeight), (spoint*2)>,        
            (spoint+(0.02+dr(0.01))), <-(spos+dr(0.01)), 0.05+(sin(spoint*4)*midHeight), (spoint+0.0125)*2>,

        #local spointDiff=dr(0.1);
        #local spoint=spoint+0.1;
        #end
                 0.75, <-0.3, 0.05+(sin(3)*midHeight), 1.5>
                 1.0, <0, 0.05+(sin(4)*midHeight), 2>
                };

        #local  TestSpline3 = spline {
                 natural_spline           

    #local spoint=0.1+dr(0.1);
                 0.0, <0.025, 0.05, 0>, 
    #while(spoint < 0.71)   
        #local spos=spoint*0.35+spointDiff;
            (spoint-(0.02+dr(0.01))), <spos+dr(0.01), 0.05+(sin(spoint*4)*midHeight), (spoint-0.0125)*2>,
            spoint, <(spos+0.02+dr(0.015)), 0.05+(sin(spoint*4)*midHeight), (spoint*2)>,        
            (spoint+(0.02+dr(0.01))), <spos+dr(0.01), 0.05+(sin(spoint*4)*midHeight), (spoint+0.0125)*2>,

        #local spoint=spoint+0.1;
        #end
                 0.75, <0.3, 0.05+(sin(3)*midHeight), 1.5>
                 1.0, <0, 0.05+(sin(4)*midHeight), 2>
                };

                                 
        #local  TestSpline2 = spline {
                 natural_spline
                 0.0, <0, 0.05, 0> 
                 0.3, <0, (sin(1.2)*midHeight), 0.6>
                 0.5, <0, (sin(2)*midHeight), 1.05>
                 0.7, <0, (sin(2.8)*midHeight), 1.4>
                 1.0, <0, 0.1+(sin(4.0)*midHeight), 2>
                };
  
union{ 
union {
sphere { <0, 0.0, 0> 0.025 scale <1, 3, 1> }
cylinder { <0, 0.0, 0> <0, -0.5, 0> 0.025 }   
scale <1, 1, 0.25>
rotate <80-(midHeight*40), 0, 0> translate <0, 0.05, 0> 

}
 #local lastHeight=0.01;
 
 #local meshStep=detailLevel;

mesh {
    #local mCount=0;
    #while(mCount < 1)   
     
        #local currentHeight=0.01+dr(0.001)-dr(0.002);  
        
        #local msp1 = spline {
            natural_spline
            0.0 TestSpline(mCount),
            0.5 ((TestSpline(mCount)+TestSpline2(mCount))/2)+<0, lastHeight, 0>,
            1.0 TestSpline2(mCount)
        }                          
        
        #local msp2 = spline {
            natural_spline
            0.0 TestSpline(mCount+meshStep),
            0.5 ((TestSpline(mCount+meshStep)+TestSpline2(mCount+meshStep))/2)+<0, currentHeight, 0>,
            1.0 TestSpline2(mCount+meshStep)
        }                          
        
        #local mCount2=0;
        #local meshStep2 = detailLevel*5;
        
        #while(mCount2 < 1)
            triangle {     msp1(mCount2),             msp2(mCount2),             msp1(mCount2+meshStep2) 
               uv_vectors <msp1(mCount2).x, mCount>,<msp2(mCount2).x, mCount>,<msp1(mCount2+meshStep2).x,  mCount+meshStep2>
            }
            triangle { msp2(mCount2),                msp2(mCount2+meshStep2),                       msp1(mCount2+meshStep2) 
              uv_vectors <msp2(mCount2).x, mCount>,<msp2(mCount2+meshStep2).x, mCount+meshStep2>,<msp1(mCount2+meshStep2).x,  mCount+meshStep2>            
            }
            #local mCount2=mCount2+meshStep2;
        #end
        #local mCount = mCount+meshStep;
        #local lastHeight=currentHeight;
    #end  


    #local mCount=0;
    #while(mCount < 1)   
     
        #local currentHeight=0.01+dr(0.001)-dr(0.002);  
        
        #local msp1 = spline {
            natural_spline
            0.0 TestSpline3(mCount),
            0.5 ((TestSpline3(mCount)+TestSpline2(mCount))/2)+<0, lastHeight, 0>,
            1.0 TestSpline2(mCount)
        }                          
        
        #local msp2 = spline {
            natural_spline
            0.0 TestSpline3(mCount+meshStep),
            0.5 ((TestSpline3(mCount+meshStep)+TestSpline2(mCount+meshStep))/2)+<0, currentHeight, 0>,
            1.0 TestSpline2(mCount+meshStep)
        }                          
        
        #local mCount2=0;
        #local meshStep2 = detailLevel*5;
        
        #while(mCount2 < 1)
            triangle {     msp1(mCount2),             msp2(mCount2),             msp1(mCount2+meshStep2)
               uv_vectors <msp1(mCount2).x, mCount>,<msp2(mCount2).x, mCount>,<msp1(mCount2+meshStep2).x,  mCount+meshStep2>            
             }
            triangle {    msp2(mCount2),             msp2(mCount2+meshStep2),                       msp1(mCount2+meshStep2) 
              uv_vectors <msp2(mCount2).x, mCount>,<msp2(mCount2+meshStep2).x, mCount+meshStep2>,<msp1(mCount2+meshStep2).x,  mCount+meshStep2>                        
            }
            #local mCount2=mCount2+meshStep2;
        #end
        #local mCount = mCount+meshStep;
        #local lastHeight=currentHeight;
    #end  


}   
      
}
#end


#macro mkDandelion(totalRows, lowMemory, min_stem_bends, max_stem_bends, stem_bend_min, stem_bend_max, stemStep, hairs, stemTex, headTex)
union {
// stem 
#local numStemBends=min_stem_bends+(dr(max_stem_bends-min_stem_bends));
#local stemBendCount=0;
#local stemBendSteps=1/numStemBends;   
#local stemHeight=130+dr(40);
#local stemSpline = spline { natural_spline
#local stemBendDir=1;
                     0, < 0, 0, 0.0>,
    #while(stemBendCount < numStemBends)
        #if(numStemBends = 1) // only 1 bend so randomise the position  
            #local stemBendPos=0.3+dr(0.5);
        #else
            #local stemBendPos=(1/(numStemBends+1))*(stemBendCount+1);
        #end
                     #if(stemBendDir)  
                            #local stemBendAmount=stem_bend_min+dr((stem_bend_max-stem_bend_min));
                            #local stemBendDir=stemBendDir*-1;
                        stemBendPos, <(stemBendAmount*stemBendDir), -(stemHeight*stemBendPos),(stemBendAmount*stemBendDir*0.2)>,
                     #end
        #local stemBendCount=stemBendCount+1;
    #end                    
                     1.0, <0, -stemHeight, 0>
} 
#local stemNormal = stemSpline(0.02)-stemSpline(0.0);

#local dPC = 0;
union {
#while(dPC < 360)
    object { mkDLPetal() scale <2, 8+dr(1), 4> rotate <-(180+dr(5)), dr(10)-dr(20), 0> translate <0, 0, -1.7> rotate <0, dPC, 0> material { stemTex } }
    #local dPC = dPC+25+dr(2);
#end
    Reorient_Trans(-y, stemNormal)  
}   
blob {
    threshold 0.6 
    #local stemC = 0;
    #while(stemC < 1-(stemStep*0.9))       
         cylinder { stemSpline(stemC), stemSpline(stemC+stemStep), 2, 1 }
         sphere { stemSpline(stemC), 2, -1 }
    
        #local stemC=stemC+stemStep;
    #end
    
    material { stemTex }
} 

 
// head
union {
sphere { <0, 0, 0> 2 
material { headTex }
rotate <0, 0, -40>  
}        

#local numRows=0;
#while(numRows < totalRows)
    #local numSeeds=0;
    #while (numSeeds < (numRows*totalRows))
        union {
        
        blob {  threshold 0.6
        #local seedr = 0;
        
            #while(seedr < 360)
                #local seedSpline1  = spline {
                     natural_spline
                      0, < 0, 0, 0.0>,
                     0.1+dr(0.2), < 0, 0.25+dr(0.1), -0.075+dr(0.025)>,
                     0.45+dr(0.1), < 0, 0.8+dr(0.1), -0.15+dr(0.025)>,
                     0.7+dr(0.2), < 0, 1.2+dr(0.1), -0.1+dr(0.025)>,
                     1.0, < 0, 1.5, 0>
                 }   
        
                #local tp = 0;
                #while(tp < 1)
                     sphere { 0, 0.15+dr(0.02), 1 translate seedSpline1(tp) translate <0, 0, -0.05> rotate <0, seedr, 0> }
                        #if(tp < 0.3)
                            #local tp=tp+0.2+dr(0.035);
                        #elseif (tp < 0.7)
                            #local tp=tp+0.15+dr(0.01);
                        #else
                            #local tp=tp+0.2+dr(0.035);
                        #end                
                     
                #end 
        
            #local seedr=seedr+23+dr(5);
        
            #end                                                              
            texture { seedTex }
            } 
            #local seedSpline2  = spline {
                     natural_spline
                      0, <0, 0, 0>,
                     0.45+dr(0.1), <-0.25+dr(0.5), 4.05+dr(0.1), -0.25+dr(0.5)>,
                     1.0, < 0, 8+dr(0.2), 0>
                 }   
        #if(lowMemory)  
            blob {
                threshold 0.6
               
                
             
            #local tp = 0.3;
                cylinder { seedSpline2(0), seedSpline2(0.1), 0.175, 1 translate <0, 1, 0> }
                sphere { seedSpline2(0.1), 0.175, -1 translate <0, 1, 0>  }
                cylinder { seedSpline2(0.1), seedSpline2(0.2), 0.13, 1 translate <0, 1, 0>  }
                sphere { seedSpline2(0.2), 0.13, -1 translate <0, 1, 0>   }
                cylinder { seedSpline2(0.2), seedSpline2(0.3), 0.1, 1 translate <0, 1, 0>  } 
                texture { seedTex }
            } 
            blob {
                threshold 0.6
            #while(tp < 0.91)
                cylinder { seedSpline2(tp), seedSpline2(tp+0.1), 0.1, 1 translate <0, 1, 0>  }
                sphere { seedSpline2(tp), 0.1, -1 translate <0, 1, 0>  }
                
                #local tp=tp+0.1;
            #end
        } 

            #else    
            blob {
                threshold 0.6
                sphere { <0, 0, 0> 0.15, 1 scale <1, 5, 1> translate <0, 0.75, 0> texture { seedTex }  }
               
                
             
            #local tp = 0.3;
                cylinder { seedSpline2(0), seedSpline2(0.1), 0.175, 1 translate <0, 1, 0> texture { seedTex }  }
                sphere { seedSpline2(0.1), 0.175, -1 translate <0, 1, 0> texture { seedTex }  }
                cylinder { seedSpline2(0.1), seedSpline2(0.2), 0.13, 1 translate <0, 1, 0> texture { seedTex }  }
                sphere { seedSpline2(0.2), 0.13, -1 translate <0, 1, 0> texture { seedTex }  }
                cylinder { seedSpline2(0.2), seedSpline2(0.3), 0.1, 1 translate <0, 1, 0>  }
                
                
        
            #while(tp < 0.91)
                cylinder { seedSpline2(tp), seedSpline2(tp+0.1), 0.1, 1 translate <0, 1, 0>  }
                sphere { seedSpline2(tp), 0.1, -1 translate <0, 1, 0>  }
                
                #local tp=tp+0.1;
            #end
        } 
        #end 
        // hairs     
            object { hairs scale 1+dr(0.1) translate seedSpline2(1)+<0, 1, 0>  }
          // object { mkSeedHairs(48, 0.01) scale 1+dr(0.1) translate seedSpline2(1)+<0, 1, 0> }   
          material { hairTex }
            scale 1   
            translate <0, 2, 0> 
            rotate <0, 0, -((numRows*(130/totalRows))+dr((130/totalRows)/3))>
            rotate <0, numSeeds*((360/(numRows*totalRows))+dr((numRows*totalRows)/4)), 0>
        }
        #local numSeeds=numSeeds+1;
    #end 
    #local numRows=numRows+1;
#end
    Reorient_Trans(-y, stemNormal)  

} // end of head
    translate <0, stemHeight, 0>   
}

#end



#macro mkDandelionCluster(numDandelions, minSeeds, maxSeeds, numSeedHairs, hairThickness, useLowMem, min_stem_bends, max_stem_bends, min_bend_amount, max_bend_amount, stemStep, numLeaves, minLeafRotation, maxLeafRotation, minLeafBend, maxLeafBend, leafDetail, leafTex, stemTex, hairTex, headTex)   
union {
#local hairs = object { mkSeedHairs(numSeedHairs, hairThickness, seedTex) }

#local dlCount=0;             
#local dRot=dr(360);
#local dRotStep=360/numDandelions;


//#macro mkDandelion(totalRows, lowMemory, min_stem_bends, max_stem_bends, stem_bend_min, stem_bend_max)

#while(dlCount < numDandelions)                                                                                                                                                  
    #local dRot=dRot+(dRotStep*0.9)+dr(dRotStep*0.15);
//    object { dl1  scale 0.03+dr(0.0025) rotate <0, 180, -(6+dr(8))> translate <(0.015+dr(0.01)), 0, 0> rotate <0, dRot, 0> }
    #local dlCount=dlCount+1;
//    object { dl1  scale 0.03+dr(0.0025) rotate <0, 180, -(6+dr(8))> translate <(0.015+dr(0.01)), 0, 0> rotate <0, dRot, 0> }
    object { mkDandelion(
            minSeeds+(dr(maxSeeds-minSeeds)), 
            useLowMem, // low memory use (don't use blobs)  
            min_stem_bends, // min_stem_bends 
            max_stem_bends, // max_stem_bends
            min_bend_amount, // minimum amount of bend 
            max_bend_amount,  // maximum amount of bend
            stemStep, // stemStep distance between cylinders in the stem decrease if you can see the straight edges  
            hairs,   // reuse for memory benefits   
            stemTex,
            headTex
            ) 
    
     scale 0.03 rotate <-(10+dr(10)), 0, 0> translate <0.05, 0, 0> rotate <0, dRot, 0> }   

#end
union {
#local dCount=0; 
#local dR=0;
#local dRStep=180/numLeaves;
#local dROff=360/numLeaves;
#while(dCount <numLeaves)  
#local dR=dR+dRStep+dr(dROff);
object { dLeaf(minLeafBend,maxLeafBend, leafTex, leafDetail)  translate <0, 0, 0.5> rotate <-(minLeafRotation+dr(maxLeafRotation-minLeafRotation)), dR, 0> }// object { lp scale <-1, 1, 1> } 
#local dCount=dCount+1;
#end                   
material { leafTex }
}

}
#end

       