// Christmas tree #include "metals.inc" // branch texture #ifndef ( branch_texture ) #declare branch_texture = texture { pigment{ rgb < .5, .4, .2 > } normal { bumps.9 turbulence .7 scale .025 } } #end // needle texture #ifndef ( needle_texture ) #declare needle_texture = texture { pigment{ rgb < .2, .5, .5 > } } #end // ornament finish #ifndef ( ball_finish ) #declare ball_finish = finish { F_MetalB } #end // tree height #ifndef ( tree_height ) #declare tree_height = 30; #end // branch spacing #ifndef ( branch_increment ) #declare branch_increment = 0.2; #end // needle spacing #ifndef ( needle_increment ) #declare needle_increment = 2.0; #end // needle is elongated sphere #declare needle = sphere { < 0, 0, 0 >, 1 scale < .75, .1, .1> } // random number seed #declare r = seed( 777 ); #declare xtree = union { // trunk is cone with base at origin cone { < 0, 0, 0 >, tree_height / 50, < 0, tree_height, 0 >, tree_height / 200 texture{ branch_texture } } // top of trunk hides top of cone sphere { < 0, tree_height, 0 >, tree_height / 175 texture{ branch_texture } } // branch height starts 10% off ground #declare branch_offset = tree_height / 10; // add branches #while ( branch_offset < tree_height ) union { #declare needle_offset = 0; #declare branch_length = ( tree_height - branch_offset ) / 2.5; #while( needle_offset < branch_length ) union { // mini-branch (only one segment) #if ( needle_offset > 0 ) sphere { < 0, 0, 0 >, 0.2 scale < 1, needle_increment * 5, 1 > texture{ branch_texture } } #end // needles at end of segment #declare j = 60 * rand( r ); #while ( j < 360 ) object { needle translate -x rotate z * -15 - needle_offset * 45 / branch_length rotate y * j + 30 * rand(r) texture { needle_texture } } #if ( needle_offset < ( branch_length / 2 ) ) #declare j = j + 360 * rand(r); #else #declare j = j + 60 * rand(r); #end #end // branches get thinner near the tip scale 1 - 0.25 * ( needle_offset / branch_length ) // move segment into location translate y * needle_offset } // increase needle position (next segment) #declare needle_offset = needle_offset + needle_increment; #end // decoration at the end of each branch #if ( ( rand(r) * branch_length ) > 2 ) sphere { < 0, 0, 0 > 0.6 - ( ( branch_offset / tree_height ) / 3 ) translate x translate y * ( branch_length * 0.9 ) #declare choice = rand(r); #if ( choice < 0.40 ) pigment { color Red } #else #if ( choice < 0.70 ) pigment { color Green } #else #if ( choice < 0.85 ) pigment { color Blue } #else pigment { color Yellow } #end #end #end finish { ball_finish } } #end // longer branches get a decoration about half way #if ( ( rand(r) * branch_length ) > ( tree_height / 10 ) ) sphere { < 0, 0, 0 > 0.6 - ( ( branch_offset / tree_height ) / 3 ) translate x translate y * ( branch_length * 0.6 ) #declare choice = rand(r); #if ( choice < 0.40 ) pigment { color Red } #else #if ( choice < 0.70 ) pigment { color Green } #else #if ( choice < 0.85 ) pigment { color Blue } #else pigment { color Yellow } #end #end #end finish { ball_finish } } #end // angle branch up rotate z * ( -75 + branch_offset / 2 ) // orientation around trunk rotate y * 360 * rand(r) // move to height above ground translate y * branch_offset } // next branch height (further from ground) #declare branch_offset = branch_offset + branch_increment; #end }