/****************************************************************
** glDataStructure.h                                           **
** -----------------                                           **
**                                                             **
** Most beginner OpenGL programmers (and beginner C developers **
**    generally) end up with a lot of global variables.  This  **
**    leads to really ugly and hard to read source files, as   **
**    you have to wade through an arbitrary number of globals  **
**    at the top of each file.  Furthermore, each one needs to **
**    be included at the top of each source when used within.  **
** Instead, a simple way to simplify this is to create a super **
**    data structure (or class) that contains all variables    **
**    that would have been globally defined.  Then you have    **
**    just one global variable, which keeps source files clean **
**    and reduces the number of externs at the top of each.    **
** It also allows you to group globals logically by having sub **
**    groups to keep variables organized and easy to find (esp **
**    when using an IDE like Visual Studio with autocomplete   **
**    variable/function).                                      **
**                                                             **
** As with other includes, this is included automatically by   **
**    the project header 'projectIncludes.h'                   **
**                                                             **
** Chris Wyman (04/06/2012)                                    **
****************************************************************/

#ifndef GL_DATA_STRUCTURE_H
#define GL_DATA_STRUCTURE_H

// These are the types of logical groupings I'll use within
//    the global data structure for this program.  You're welcome
//    to create a different sort of organization & clustering.
class FrameBufferData;
class MatrixData;
class VertexArrayData;
class TextureData;
class UserInterfaceData;
class ShaderData;
class ModelData;
class SceneParameterData;


// This defines our global data structure
class RenderingData
{
public:
	FrameBufferData    *fbo;     // Will contain all shared framebuffer objects
	MatrixData         *mat;     // Will contain all shared matrices
	ModelData          *geom;    // Will contain all shared OBJ geometry (and other models)
	SceneParameterData *param;   // Will contain internal parameter data not modifiable (directly) by user
	ShaderData         *glsl;    // Will contain all shared shaders
	TextureData        *tex;     // Will contain all shared textures
	UserInterfaceData  *ui;      // Will contain all shared UI elements
	VertexArrayData    *vao;     // Will contain all shared vertex arrays 

	// Also, store a pointer to our window here, for easy access.
	IGLUMultiDisplayWindow::Ptr  win;
};


class FrameBufferData
{
public:
	// Framebuffer for storing a paraboloid shadow map
	IGLUFramebuffer::Ptr  paraboloidShadowMap;

	// Framebuffer storing the epipolar voxelization/rectification
	IGLUFramebuffer::Ptr  epipolarVoxels;

	// Framebuffer for doing ping-ponging during the scan to create a VSV
	IGLUFramebuffer::Ptr voxelMipScan[12];
};

class MatrixData
{
public:
	IGLUMatrix4x4  eyeProj, eyeView;
	IGLUMatrix4x4  cowPosition;

};

class ShaderData
{
public:
	// Shaders for creating, displaying, and (basic) querying of paraboloid shadow maps
	IGLUShaderProgram::Ptr parabSMapCreate, parabSMapQuery, parabSMapDisplay;

	// Rectify the shadow map into epipolar space
	IGLUShaderProgram::Ptr rectifySMap;
	IGLUShaderProgram::Ptr countVoxels;

	// Create a voxelized shadow volume
	IGLUShaderProgram::Ptr upScan, downScan;

	// Visualize voxels in eye space
	IGLUShaderProgram::Ptr combineDrawVoxelViz;
};

class VertexArrayData
{
public:
	// An array filled with garbage for drawing points that compute their own location.
	IGLUVertexArray::Ptr garbagePoints;
	IGLUVertexArray::Ptr textureScreenQuad;
};

class SceneParameterData
{
public:
	vec3 lightPos, eyePos;
};

class ModelData
{
public:
	IGLUOBJReader::Ptr cow, cornellBox;
};

class TextureData
{
public:	

};

class UserInterfaceData
{
public:
	IGLUTrackball::Ptr	ball;    // Our trackball UI class

	// Values storing the current VSV resolution (in pixels)
	IGLUInt    vsvWidth, vsvHeight;
	int        vsvPadWidth, vsvPadHeight; // w & h padded to power of 2.
	vec2       vsvPadCoef;

	// Variables used inside Mode_ParaboloidShadowMaps.cpp
	IGLUBool   visualizeShadowmap, useLambertian;
	IGLUInt    smapRes, visualizeLayer;
	IGLUFloat  zBias, lightMovement, lightNear, lightFar;
	IGLUFloat  eyeFOV, eyeNear, eyeFar, eyeAspect;

	// Variables used inside Mode_SampleVoxelsFromShadowMaps
	IGLUFloat  heatMapIntensity;
	IGLUBool   visLayer[4];

	// Variables used inside Mode_VisualizeVoxelizedShadowVolumes
	IGLUBool   visVoxelsOnly, useVSVForSurface;
	IGLUFloat  vsvSurfBias;
};



#endif