// Persistence of Vision Ray Tracer Scene Description File
// File: rose.inc
// Vers: 3.5
// Desc: CreateRose macro
// Date: 2003/05/20
// Auth: Maurizio Tomasi
//

#ifndef (__ROSE_INC__)
#declare __ROSE_INC__ = 1;

#version 3.5;

#include "rand.inc"

/* Create a rose.  It is bounded by box {<-1, 0, -1>, <1, 1, 1> }
 * and has a semi-spherical outline.  
 *
 * Parameters:
 *   MaxGradient    : used to render the isosurface (see
 *                    the "Hint" section below).
 *   RndSeed        : a value returned by the "seed" function.
 *   NumOfLayers    : number of layers of petals
 *   Color1, Color2 : colors to be used for the object
 *
 * Example:
 *
 *     object
 *     {
 *         #local Color1 = color rgb <1, 0, 0>;
 *         #local Color2 = color rgb 1.2;
 *         CreateRose (80, seed (16), 60, Color1, Color2)
 *         rotate -40*x
 *         rotate 30*y
 *     }
 *
 * Hint: Set MaxGradient to 50 and render the image; use the value 
 *       output by POV-Ray to change 50 into something more suitable,
 *       then render again.*/

#macro CreateRose (MaxGradient, RndSeed, NumOfLayers, Color1, COlor2)

    // "Turbulence" function
    #local AgateFn =
    function
    {
        pigment
        {
            agate
            warp { turbulence 0.15 }
        }
    }
    
    // The "rose" function (in quasi-spherical coordinates)
    #local RoseFn = 
    function (r, theta, phi, Rotation)
    {
        // This is the "core" of the object
        r - 0.85 + 0.15 * sin (4 * phi + Rotation * pi * sin (theta)) 
                          // This defines the layers of petals
                        * cos (NumOfLayers * theta)
                          // This redistributes the layers on the y direction
                        * pow (theta, 0.1)
    }
    
    // The "rose" function (in cartesian coordinates)
    #local RoseFnXYZ = 
    function(x, y, z, Rotation) 
    {
        // This is a quasi-spherical transform
        RoseFn (sqrt (x*x + y*y + z*z),
                // In a *true* spherical transform there would be y*y / sqrt (...)
                acos (y / sqrt (x*x + y*y + z*z)),
                atan2 (z, x), 
                Rotation)
    }
    
    #local RndDir1 = VRand_In_Sphere (RndSeed);
    #local RndDir2 = VRand_In_Sphere (RndSeed);
    #local Rotation = int (RRand (6, 12, RndSeed));
    
    #local RndX1 = RndDir1.x;
    #local RndY1 = RndDir1.y;
    #local RndZ1 = RndDir1.z;

    #local RndX2 = RndDir2.x;
    #local RndY2 = RndDir2.y;
    #local RndZ2 = RndDir2.z;

    intersection
    {
        isosurface
        {
            function
            { 
                RoseFnXYZ (x, y, z, Rotation) 
                    + 0.2 * AgateFn (2 * (x + RndX1), y + RndY1, 2 * (z + RndZ1)).gray 
            }
                               
            contained_by { sphere { 0, 1 } }
            
            accuracy 0.005
            max_gradient MaxGradient
        }
        
        box
        {
            <-1, 0, -1>, <1, 1, 1>
        }
    
        pigment 
        { 
            function { 
                AgateFn (2*(RndX2 + x), 3*(RndY2 + y), 2*(RndZ2 + z)).gray 
                * (x*x + y*y + z*z) * 0.99
            }
            
            color_map
            {
                [0.0 color Color1]
                [1.0 color Color2]
            }
        }
        
    }

#end

#end // ! __ROSE_INC__
