POV-Ray : Newsgroups : povray.binaries.images : Greenfingers : Re: Greenfingers Server Time
8 Aug 2024 04:11:28 EDT (-0400)
  Re: Greenfingers  
From: Bill Pragnell
Date: 5 Oct 2005 07:25:00
Message: <web.4343b6f2c3fd9719731f01d10@news.povray.org>
Rick Measham <rickm*at%isite.net.au> wrote:
> This grass looks spectacular .. I love the clump idea rather than the
> individual blade .. any chance of freeing the source?
No problem at all. I almost included it on the original post, but couldn't
be bothered to prune it! Naturally, it could probably do with some
refining, and it should be simple to play with the precise blade geometry
if you want it to more closely resemble real grass. Note that GrassBlade()
or GrassClump() calls must be inside a mesh { } definition.

Also note that this grass isn't really suitable for modelling e.g.
spider-plants, where the leaves can hang down - these blades only grow
upwards.
Enjoy!

#declare r1 = seed(1);

// pos = position vector of blade base
// dir = direction vector of central axis
// hgt = max blade height
// wid = max blade "radius"
// thick = width of blade base
// segments = number of straight lines ni curve
#macro GrassBlade(pos, dir, hgt, wid, thick, segments)
  #local seg = 1;
  #local ri = wid / segments;
  #local r = ri;
  #local yi = dir * hgt / segments;
  #local yp = yi;
  #local ux = vnormalize(vcross(<rand(r1),rand(r1),rand(r1)>, dir));
  #local uy = vnormalize(vcross(ux, dir));
  #local ang = rand(r1)*360;
  #local opos = pos;
  #local npos = pos + ux*r*sin(radians(ang)) + yp + uy*r*cos(radians(ang));
  #local opvec = vnormalize(vcross(npos-pos, dir))*thick;
  #local npvec = opvec * (segments-1) / segments;
  #while (seg <= segments)
    triangle { opos+opvec, opos-opvec, npos-npvec }
    triangle { opos+opvec, npos-npvec, npos+npvec }
    #local r = r + ri;
    #local ri = ri * 1.25;
    #local yp = yp + yi;
    #local opos = npos;
    #local npos = pos + ux*r*sin(radians(ang)) + yp +
uy*r*cos(radians(ang));
    #local opvec = npvec;
    #local npvec = npvec * (segments-seg) / segments;
    #local seg = seg + 1;
  #end
#end

// p, d, mh, mw, thick, segments as above
// blade = no of blades
#macro GrassClump(p, d, mh, mw, thick, segments, blades)
  #local n = 0;
  #while (n < blades)
    GrassBlade(p, d, rand(r1)*mh+mh*0.2, rand(r1)*mw+mw*0.2, thick,
segments)
    #local n = n + 1;
  #end
#end

#declare Clump = mesh {
  GrassClump(<0,0,0>, <0,1,0>, 0.08, 0.08, 0.005, 5, 10)
  pigment { color rgb <0.7,1,0.5> }
  finish { ambient 0 phong 0.75 phong_size 10 } }

// gradient-dependent grass
// TestThing = some landscape, i.e. isosurface
// tweak the line commented 'coverage angle' below for different gradients:
// currently no grass is laid if the slope is < 70 degrees from the vertical
// (i.e., > 30 degrees from the horizontal)
#declare n = 0;
#while (n < 150000)
  #declare direct = <0,0,0>;
  #declare raypos = <rand(r1)*9.95-5, 0, rand(r1)*9.95-5>;
  #declare position = trace(TestThing, <raypos.x,1,raypos.z>, <0,-1,0>,
direct);
  #declare a = 90;
  #if (vlength(<direct.x,0,direct.z>) > 0.001)
    #declare a = degrees(acos(vdot(direct,<direct.x,0,direct.z>)
/(vlength(direct)*vlength(<direct.x,0,direct.z>))));
  #end
  #if ((a > 70) & (position.y > 0)) // coverage angle
    #declare rotz = -degrees(atan2(vlength(<direct.x,0,direct.z>),
direct.y));
    #if ((direct.x=0) & (direct.z=0))
      #declare roty = 0;
    #else
      #declare roty = -degrees(atan2(direct.z,direct.x));
    #end
    object { Clump rotate <0, rand(r1)*360, 0>
                   rotate <0, 0, rotz>
                   rotate <0, roty, 0>
                   translate position }
  #end
  #declare n = n + 1;
#end
object { TestThing }

// mini-planet grass
// LittlePlanet = some closed convex surface, i.e. sphere, isosurface
#declare n = 0;
#while (n < 10000)
  #declare direct = <0,0,0>;
  #declare position = trace(LittlePlanet, <0,0,0>, <rand(r1)-0.5,
rand(r1)-0.5, rand(r1)-0.5>, direct);
  #declare rotz = -degrees(atan2(vlength(<direct.x,0,direct.z>), direct.y));
  #if ((direct.x=0) & (direct.z=0))
    #declare roty = 0;
  #else
    #declare roty = -degrees(atan2(direct.z,direct.x));
  #end
  object { Clump rotate <0, rand(r1)*360, 0>
                 rotate <0, 0, rotz>
                 rotate <0, roty, 0>
                 translate position }
  #declare n = n + 1;
#end
object { LittlePlanet }

--Bill


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.