#ifndef MYATMOSPHERE_HXX
#define MYATMOSPHERE_HXX

#include "../Atmosphere/AbstractAtmosphere.hxx"

#include "../../Shared/Fractals/fractal.h"


/**
   Defines the atmosphere that is used for the Rendering Competition.
*/
class MyAtmosphere : public AbstractAtmosphere
{
 public:
    MyAtmosphere()
    {
	deltaT = 1; // step size of the volume tracing
	maxT = 500; // upper bound for the volume tracing
	min = Vec3f( 0, 50, 35 ); // min point of the volume
	max = Vec3f( 500, 400, 200 ); // max point of the volume
	
	initParticles(); // initialize the particles in the atmosphere

	// add a primary rainbow
	rainbows.push_back(new Rainbow(Vec3f(-20,10,-10),0.733,0.04,200,150,0.95,false));
	// add a secondary rainbow
	rainbows.push_back(new Rainbow(Vec3f(-20,10,-10),0.89,0.04,200,150,0.99,true));
    }

     
 protected:
    /** Initializes the particles in the atmosphere. */
    virtual void initParticles() {
	Init_Noise(); // used by the fractal function

	// determine min and max values of the fractal function
	float min = +1000000;
	float max = -1000000;
	for (int x=0; x<=resX; x++)
	    for (int y=0; y<=resY; y++)
		for (int z=0; z<=resZ; z++) {
		    float value = fractal(Vec3f(x,y,z));
		    min = std::min(min, value);
		    max = std::max(max, value);
		}
	
	// create the particles
	for (int x=0; x<=resX; x++)
	    for (int y=0; y<=resY; y++)
		for (int z=0; z<=resZ; z++) {
		    float value = fractal(Vec3f(x,y,z));
		    // normalized value of the fractal function
		    float normalized = (value - min) / (max - min);
		    if (y-x>-40) {
			// fog (for points behind the diagonal y = x-40)
			particles[x][y][z] =
			    new SimpleParticle(0.986, // transparency
					       // color (depends on fractal function)
					       Vec3f(1,1,1) * (normalized/1.5) + Vec3f(0.33,0.33,0.33));
		    }
		    else {
			if (y-x>-50) {
			    // more transparent fog (for points between y = x-50 and y = x-40)
			    particles[x][y][z] =
				new SimpleParticle(0.995,
						   Vec3f(1,1,1) * (normalized/1.5) + Vec3f(0.33,0.33,0.33));
			}
			else {
			    // no fog (for points in the foreground up to the diagonal y = x-50)
			    particles[x][y][z] = new SimpleParticle(1,Vec3f(1,1,1));
			}
		    }
		    
		}
    }

    /** fractal function */
    float fractal(Vec3f point) const {
	return fBm(point/Vec3f(resX,resY,resZ),0.5,2,8);
    }
};


#endif // MYATMOSPHERE_HXX
