// 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
}