/*============================================================================
	Title: HDR.h
	Module: Pi/Engine
	Author: Ignacio Castaņo
	Date: 04/10/2003
============================================================================*/

#ifndef _PI_HDR_H_
#define _PI_HDR_H_

/*----------------------------------------------------------------------------
	Doc
----------------------------------------------------------------------------*/

/** @file HDR.h
 * @brief Hight Dynamic Range environment maps.
**/



/*----------------------------------------------------------------------------
	Headers
----------------------------------------------------------------------------*/

// Core
#include "FileSystem.h"

// Engine
#include "Engine.h"
#include "Texture.h"


/*----------------------------------------------------------------------------
	Forward decls
----------------------------------------------------------------------------*/

class SphericHarm;



/*----------------------------------------------------------------------------
	Functions
----------------------------------------------------------------------------*/

/* Sample a cubemap from a spherical function. */
ENGINE_API PiTexture SampleCubeMap( const ISphericFunction & f, int size, float exposure );



/*----------------------------------------------------------------------------
	Classes
----------------------------------------------------------------------------*/

struct PiRGBE {
	uint8 r, g, b, e;

	/** Cast operator, return a pointer to uint8. */
	operator uint8 * () const { return (uint8 *) this; }

	/** Convert to real vector. */
	void ToVec( FColor & c ) const {
		REAL d = pow(2, (e - 128));
		c.r = float(r) / 255.0f * d;
		c.g = float(g) / 255.0f * d;
		c.b = float(b) / 255.0f * d;
	}
};


/** High dynamic range map. */
class PiHDRMap {
public:

	/** Ctor. */
	PiHDRMap() : width(0), height(0), map(NULL) {
	}

	/** Dtor. */
	~PiHDRMap() {
		piCheck( map == NULL );
	}


	/* Open an HDR map. */
	ENGINE_API bool Open( const char * fname );

	/* Close map. */
	ENGINE_API void Close();

	/* Sample the map. */
	ENGINE_API void Sample( FColor * out, int x, int y ) const;

	inline uint GetWidth() const { return width; }
	inline uint GetHeight() const { return height; }

private:

	bool ReadColors( PiRGBE * scanline, int len, PiVirtualFile * vfile );
	bool OldReadColors( PiRGBE * scanline, int len, PiVirtualFile * vfile );


private:

	uint width;
	uint height;
	FColor * map;

};



/** High dynamic range light probe. */
class PiLightProbe : public ISphericFunction {
public:

	enum mode_t {
		UNKNOWN,
		CROSS,
		PROBE
	};

	/** Ctor. */
	PiLightProbe() : mode(UNKNOWN) {
	}

	/** Virtual dtor. */
	virtual ~PiLightProbe() {
		Close();
	}

	/* Open an HDR light prove. */
	ENGINE_API bool Open( const char * fname, mode_t mode = UNKNOWN );

	/* Close the light prove. */
	ENGINE_API void Close();

	/* Sample the light prove. */
	ENGINE_API void Sample( FColor * out, const Vec3 & dir ) const;

	/**Filter the map and output a spherical harmonic using the given exposure. */
	ENGINE_API bool PreFilter( SphericHarm * out, float exposure );

	/* Convert to cube map using the given exposure. */
	ENGINE_API PiTexture CubeMap( int size, float exposure );


private:

	mode_t mode;
	PiHDRMap map;

};



#endif	// _PI_HDR_H_
