// File: Weeds.inc
// Vers: 3.5
// Desc: Weeds/tall-grass macros (WIP)
// Date: 02/15/2003
// Auth: Jeremy Praay
// Modified from "Example of use of the Makegrass macro by Gilles Tran - March 1999"
// Modified by Jeremy Praay
// requires Gilles Tran's mgrass.inc (available from www.oyonale.com)
// --------------------------------------
// Uses two textures to generate variable grass colors (half have one texture, half the other).
// This could be expanded to use more textures, or a texture map or something.
// The makeWeedPatch generates weeds that are (no more than) roughly 1 unit tall.  This can 
// be confusing, I suppose, but otherwise the stem size gets goofy.  So, a 10x10 patch, with a height
// of 50, would produce a patch that was 0.2x0.2 with a height of 1.  
// A patch starts at <0,0,0> and extends in the positive x and z directions.
// -------------------------------------
// How does it do it?
// Pretty simple really.  makeWeed uses the makeBlade macro from mgrass.inc, and simply sticks the 
// blades onto a cone (the stem), alternating from side to side, creeping up the stem.  It adds in 
// some controlled variance in the placement, so that not every blade is exactly 180 degrees from the 
// previous blade.
// makeWeedPatch just makes lots of weeds, with other parameters for adding variance.
// --------------------------------------
// What doesn't it do?
// It doesn't parse quickly.  It may not be a good idea to have more than a few hundred, or perhaps a 
// couple thousand weeds in a scene, but feel free to experiment.
// It only produces one type of weed (type 1).  I plan to add more weed types, and maybe even some 
// with flowers, or other weedy things.
// It doesn't "make a prairie".  If you want to fill up a whole field, you'll be parsing for the rest
// of your life.  I may add that capability at some point, though.
//---------------------------------------
#include "colors.inc"
#include "mgrass.inc"

// --------------------------------------
// Green Grass texture
// --------------------------------------
#declare Green1=rgb<0.65,0.7,0.4>*1;
#declare Green2=rgb<1.4,1.60,0.8>*0.25;

#declare pigSpotted =pigment {
spotted
    color_map {
        [0.0, 0.2   color Tan*0.1 color Tan*0.6]
        [0.2, 0.3   color Tan*0.2 color Green1]
        [0.3, 1.01   color Green1 color Green1*1.2]
    }
}

#declare pigEarth =pigment {
    spotted
    color_map {
        [0 color Tan*0.15]
        [0.6 color Tan*0.15]
        [0.6 color Green1*0.4]
        [1   color Green1*0.4]
    }
}
#declare pigGreen=pigment{Green2*1.3}
#declare txtGreenGrass=texture {                  
  pigment {
    gradient y
    turbulence 0.2
      pigment_map {                                
        [0.0 pigEarth]
        [0.3 pigSpotted]
        [0.8 pigGreen]
        [1.00 pigGreen]
      }
    }
  finish{diffuse 0.7 specular 0.3 roughness 0.03}
  scale <0.001,1,0.001>
} 

// --------------------------------------
// Brown Dead Grass texture
// --------------------------------------
//
#declare Green1=rgb<0.85,0.55,0.25>*0.65;
#declare Green2=rgb<1,0.9,0.7>*0.65;
#declare pigSpotted =pigment {
spotted
    color_map {
        [0.0, 0.2   color Tan*0.1 color Tan*0.2]
        [0.2, 0.3   color Tan*0.2 color Green1]
        [0.3, 1.01   color Green1 color Green1*1.2]
    }
}

#declare pigEarth =pigment {
    spotted
    color_map {
        [0 color Tan*0.15]
        [0.6 color Tan*0.15]
        [0.6 color Green1*0.4]
        [1   color Green1*0.4]
    }
}
#declare pigGreen=pigment{Green2}
#declare txtBrownGrass=texture {                  
  pigment {
    gradient y
    turbulence 0.2
      pigment_map {                                
        [0.0 pigEarth]
        [0.3 pigSpotted]
        [0.8 pigGreen]
        [1.00 pigGreen]
      }
    }
  finish{diffuse 0.7 specular 0.15 roughness 0.05}
  scale <0.001,1,0.001>
} 


// --------------------------------------
// makeWeed macro parameter descriptions
// weedType: [1..3] type of weed-grass
// devBladeRot: [0..1] deviation of blade rotation position on the stalk (0=blades alternate 180 degrees apart, 1=blades anywhere)
// numBlade: the number of grass blades on the stalk
// stalkHeight: the y height of the stalk (with the blades sticking up, it will be taller)
//---------------------------------------
#macro makeWeed(weedType,devBladeRot,numBlades,stalkHeight) 
  #local segBlade= 15;            // number of blade segments
  #local lBlade = stalkHeight*0.7;// length of blade
  #local wBlade = 0.2;            // width of blade at start
  #local wBladeEnd = 0;           // width of blade at the end
  #local wStalk = 0.3;            // width of stalk at start
  #local wStalkEnd = 0.16;        // width of stalk at end
  #local doSmooth=true;          // true makes smooth triangles
  #local pwBend = 3;              // bending power (how slowly the curve bends)
  #local dofold = false;          // true creates a central fold in the blade (twice more triangles)
  #local dofile=false;
  #local startBend = <0,1,0.1>;   // bending of blade at start (<0,1,0>=no bending)
  #local scBlade=1;
  #local xBladeStart=wBlade*scBlade;
  #local xBladeEnd=wBladeEnd*scBlade;
  #local zBladeStart=xBladeStart*1;
  #local lSeed=seed(23);
  
  #local i=0;
  
  union {
    object {
      cone { 0, wStalk/2, y*stalkHeight, wStalkEnd/2
        open
      }
      texture { txtGrass scale stalkHeight}
    }
    mesh {
      #switch (weedType)
        #case (1)
          #while (i < numBlades)
            #local i = i + 1;
            #local lvBend = <0,i-4,2>;       // force bending the blade (<0,1,1> = 45°)
            #local lBladeRot = 180*(1-devBladeRot*rand(lSeed)); // add randomness to rotation
            #local lBladeRot = lBladeRot+mod(i,2)*180; // figure out which side it's on (each one 180° from the last)
            MakeBlade(doSmooth,y*(stalkHeight*(i-1)/numBlades),lBladeRot,segBlade,lBlade*((numBlades-i/2)/numBlades),xBladeStart,xBladeEnd,zBladeStart,startBend,lvBend,pwBend,dofold,dofile)
          #end
          #break
        #case (2)
          #break
        #case (3)
          #break
      #end
      texture { txtGrass scale stalkHeight*1.1}
    }
  }
#end

// --------------------------------------
// makeWeedPatch macro parameter descriptions
// patchLength: the length size of the patch (x)
// patchWidth: the width size of the patch (z)
// numWeeds: the number of weeds in the patch
// devBend: [0..1] deviation of stalk bend (0=all straight up, 1=some horizontal)
// numBladeRangeStart: each weed has at LEAST this many blades
// numBladeRangeEnd: each weed has at MOST this many blades
// stalkHeight: the y height of the stalk (with the blades sticking up, it will be taller)
// devStalkHeight: [0..1] the deviation of the stalk height 
// devBladeRot: [0..1] deviation of blade rotation position on the stalk (0=blades alternate 180 degrees apart, 1=blades anywhere)
//---------------------------------------
#macro makeWeedPatch(patchLength,patchWidth,numWeeds,devBend,numBladeRangeStart,numBladeRangeEnd,stalkHeight,devStalkHeight,devBladeRot, randSeed)
  union {  
    #local i=0;
    #while (i < numWeeds)
      #local lPosWeed=<patchLength*rand(randSeed), 0, patchWidth*rand(randSeed)>;
      #local lBendX=devBend*rand(randSeed)*90;
      #local lBendZ=devBend*rand(randSeed)*90;
      #local lNumBlades = (numBladeRangeEnd-numBladeRangeStart)*rand(randSeed)+numBladeRangeStart;
      #local lStalkHeight = stalkHeight - stalkHeight*(devStalkHeight*rand(randSeed));
     
      #if (rand(randSeed) < 0.5)
        #declare txtGrass = txtGreenGrass 
      #else
        #declare txtGrass = txtBrownGrass
      #end 
      object { makeWeed(1,devBladeRot,lNumBlades,lStalkHeight)
        rotate <lBendX,360*rand(randSeed),lBendZ>
        translate lPosWeed
      }
      
      #local i = i + 1;
    #end // while
  }

  scale 1/stalkHeight // make it roughly unit tall
#end

