// scottGrass.inc #declare MAX_BLADES = 10; // number of unique blade shapes #declare oBlade = array[MAX_BLADES]; #macro NormalDistribution( s , mean , sd ) mean + sd * sqrt( -2 * ln( rand(s) ) ) * cos( 2 * pi * rand(s) ) #end #local seed1 = seed(5); #local blade = 0; #while( blade < MAX_BLADES ) #local SEGMENTS = 10; // could be variable/random? #local BLADE_LENGTH = NormalDistribution( seed1 , 60 , 10 ); #local SEGMENT_LENGTH = BLADE_LENGTH / SEGMENTS; #local BASE_WIDTH = NormalDistribution( seed1 , 2.5 , .6 ); #local FOLD_ANGLE = NormalDistribution( seed1 , radians(25) , radians(10) ); #local CURVATURE = NormalDistribution( seed1 , radians(25) , radians(5) ); // total curvature in radians #declare oBlade[blade] = mesh2 { vertex_vectors { (SEGMENTS+1)*3 #local Y = 0; #local X = 0; #local ROW = 0; #while( ROW <= SEGMENTS ) #local WIDTH = BASE_WIDTH * (SEGMENTS-ROW) / SEGMENTS; , // left , // center , // right #local Y = Y + SEGMENT_LENGTH * cos( CURVATURE * ROW / SEGMENTS ); #local X = X + SEGMENT_LENGTH * sin( CURVATURE * ROW / SEGMENTS ); #local ROW=ROW+1; #end } normal_vectors { (SEGMENTS+1)*3 #local ROW = 0; #while( ROW <= SEGMENTS ) #local Rz = CURVATURE*(ROW-0.5)/SEGMENTS; vnormalize() , // left vnormalize() , // center vnormalize() , // right #local ROW=ROW+1; #end } uv_vectors { (SEGMENTS+1)*3 #local ROW = 0; #while( ROW <= SEGMENTS ) #local WIDTH = BASE_WIDTH * (SEGMENTS-ROW) / SEGMENTS; <0.0,ROW/SEGMENTS> , <0.5,ROW/SEGMENTS> , <1.0,ROW/SEGMENTS> , #local ROW=ROW+1; #end } face_indices { SEGMENTS * 4 #local ROW = 0; #while( ROW < SEGMENTS ) #local BASE = ROW * 3; < BASE + 0 , BASE + 3 , BASE + 4 >, < BASE + 0 , BASE + 4 , BASE + 1 >, < BASE + 1 , BASE + 4 , BASE + 2 >, < BASE + 4 , BASE + 5 , BASE + 2 >, #local ROW = ROW + 1; #end } texture { uv_mapping pigment { gradient x color_map { [0.0 color rgb <0 , 0.6 , 0>] [0.3 color rgb <0 , 0.6 , 0>] [0.5 color rgb <0.4 , 0.6 , 0>] [0.7 color rgb <0 , 0.6 , 0>] [1.0 color rgb <0 , 0.6 , 0>] } } finish{ ambient 0 diffuse NormalDistribution( seed1 , 0.8 , 0.2 ) } } } #local blade=blade+1; #end // use FlattenedGrassPatch to make all the blades tend to face in one direction // ANG is the mean angle (0 is along the X axis), SD is the standard deviation // of angles. #macro FlattenedGrassPatch( W , L , SPACING , ANG , SD ) union{ #local s2 = seed(45); #local X = 0; #while( X < W ) #local Z = 0; #while( Z < L ) object { oBlade[int(rand(s2)*MAX_BLADES)] #if( SD < 180 ) rotate y * NormalDistribution( s2 , ANG , SD ) #else rotate y * rand(s2) * 360 #end translate } #local Z = Z + SPACING; #end #local X = X + SPACING; #end } #end // Use GrassPatch to place blades pointing in totally random directions #macro GrassPatch( W , L , SPACING ) FlattenedGrassPatch( W , L , SPACING , 0 , 360 ) #end