/******************************************************************/
/* A very crude, inefficient program that draws the Cornell Box.  */
/*                                                                */
/* -> Demonstrates how to create very simple geometry in vertex   */
/*    arrays.  Note that this is probably not truly extendable to */
/*    seriously complex geometry.  See other examples for how to  */
/*    much more efficiently create this geometry!                 */
/* -> Demonstrates how to use the IGLUWidgetWindow to give simple */
/*    options for the user to manipulate the program.             */
/* -> Demonstrates the use of IGLUVariable (bool,int,float) for   */
/*    dynamically modifying variables used during the rendering   */
/*    process.  These variables are modified automatically by the */
/*    user interface (here, the Widget Window) and when using     */
/*    during rendering, they have the last value set by the UI.   */
/*                                                                */
/* Chris Wyman (02/23/2012)                                       */
/******************************************************************/

#include <GL/glew.h>
#include <stdio.h>

// Include IGLU and set it up to avoid the iglu:: prefix on types
#include "iglu.h"
using namespace iglu;

// IGLU shaders this program uses
IGLUShaderProgram::Ptr  shaders[2] = { 0, 0 };  


// Vertex arrays to store our geometry!
IGLUVertexArray::Ptr    floorArray    = 0;  
IGLUVertexArray::Ptr    ceilArray     = 0; 
IGLUVertexArray::Ptr    backArray     = 0; 
IGLUVertexArray::Ptr    leftArray     = 0; 
IGLUVertexArray::Ptr    rightArray    = 0; 
IGLUVertexArray::Ptr    small1Array   = 0; 
IGLUVertexArray::Ptr    small2Array   = 0; 
IGLUVertexArray::Ptr    small3Array   = 0; 
IGLUVertexArray::Ptr    small4Array   = 0; 
IGLUVertexArray::Ptr    small5Array   = 0; 
IGLUVertexArray::Ptr    large1Array   = 0; 
IGLUVertexArray::Ptr    large2Array   = 0; 
IGLUVertexArray::Ptr    large3Array   = 0; 
IGLUVertexArray::Ptr    large4Array   = 0; 
IGLUVertexArray::Ptr    large5Array   = 0; 

// Setup 3D projection and default viewing matrix
IGLUMatrix4x4           proj = IGLUMatrix4x4::Perspective( 38.5, 1.0, 5, 20 );
IGLUMatrix4x4           view = IGLUMatrix4x4::LookAt( vec3(2.78, 2.73, -8.00), 
													  vec3(2.78, 2.73, 2.795), 
													  vec3(0.0, 1.0, 0.0) );
IGLUMatrix4x4           smallRotation = IGLUMatrix4x4::Identity();
IGLUMatrix4x4           largeRotation = IGLUMatrix4x4::Identity();

// IGLU variables that can be changed via a FLTK-window user-interface.
IGLUBool                displayFPS ( true,                                  "Display framerate" );
IGLUBool                simpleShade( true,                                  "Use simple shader" );
IGLUBool                enableCull ( false,                                 "Enable back-face culling?" );
IGLUBool                drawSmall  ( true,                                  "Draw small box?" );
IGLUBool                drawLarge  ( true,                                  "Draw large box?" );
IGLUBool                rotateSmall( false,                                 "Rotate small box?" );
IGLUBool                rotateLarge( false,                                 "Rotate large box?" );

// Stores the current rotation angles for our boxes
float angleSmall = 0;
float angleLarge = 0;

// These are handles to the two windows, should you need to modify their
//   behavior after window creation.
IGLUWindow::Ptr         myWin = 0;
IGLUWidgetWindow::Ptr   uiWin = 0;

// Data for the Cornell Box floor quad
float cboxFloorData[32] = { 
	0, 1,  0, 1, 0,  0.000, 0.000, 0.000, 
	0, 0,  0, 1, 0,  0.000, 0.000, 5.592,
	1, 1,  0, 1, 0,  5.560, 0.000, 0.000,
	1, 0,  0, 1, 0,  5.560, 0.000, 5.592, 
};

// Data for the Cornell Box ceiling quad
float cboxCeilingData[32] = { 
	0, 1,  0, -1, 0,  0.000, 5.488, 5.592, 
	0, 0,  0, -1, 0,  0.000, 5.488, 0.000,
	1, 1,  0, -1, 0,  5.560, 5.488, 5.592, 
	1, 0,  0, -1, 0,  5.560, 5.488, 0.000,
};

// Data for the Cornell Box back wall quad
float cboxBackData[32] = { 
	0, 1,  0, 0, -1,  0.000, 0.000, 5.592, 
	0, 0,  0, 0, -1,  0.000, 5.488, 5.592,
	1, 1,  0, 0, -1,  5.560, 0.000, 5.592, 
	1, 0,  0, 0, -1,  5.560, 5.488, 5.592,
};

// Data for the Cornell Box left wall quad
float cboxLeftData[32] = { 
	0, 1,  -1, 0, 0,  5.560, 0.000, 0.000, 
	1, 1,  -1, 0, 0,  5.560, 0.000, 5.592, 
	0, 0,  -1, 0, 0,  5.560, 5.488, 0.000,
	1, 0,  -1, 0, 0,  5.560, 5.488, 5.592,
};

// Data for the Cornell Box right wall quad
float cboxRightData[32] = { 
	0, 1,  1, 0, 0,  0.000, 0.000, 5.592, 
	1, 1,  1, 0, 0,  0.000, 0.000, 0.000,
	0, 0,  1, 0, 0,  0.000, 5.488, 5.592,
	1, 0,  1, 0, 0,  0.000, 5.488, 0.000,
};

// Data for the Cornell Box small box quads
float cboxSmall1Data[32] = { 
	0, 1,  0, 1, 0,  1.30, 1.65, 0.65,
	1, 1,  0, 1, 0,  0.82, 1.65, 2.25,
	0, 0,  0, 1, 0,  2.90, 1.65, 1.14,
	1, 0,  0, 1, 0,  2.40, 1.65, 2.72,
};
float cboxSmall2Data[32] = { 
	0, 1,  0.953, 0.000, 0.302,    2.90, 0, 1.14,
	1, 1,  0.953, 0.000, 0.302,    2.90, 1.65, 1.14,
	0, 0,  0.953, 0.000, 0.302,    2.40, 0, 2.72,
	1, 0,  0.953, 0.000, 0.302,    2.40, 1.65, 2.72,
};
float cboxSmall3Data[32] = { 
	0, 1,  0.293, 0.000, -0.956,    1.30, 0, 0.65,
	1, 1,  0.293, 0.000, -0.956,    1.30, 1.65, 0.65,
	0, 0,  0.293, 0.000, -0.956,    2.90, 0, 1.14,
	1, 0,  0.293, 0.000, -0.956,    2.90, 1.65, 1.14,
};
float cboxSmall4Data[32] = { 
	0, 1,  -0.958, 0.000, -0.287,    0.82, 0, 2.25,
	1, 1,  -0.958, 0.000, -0.287,    0.82, 1.65, 2.25,
	0, 0,  -0.958, 0.000, -0.287,    1.30, 0, 0.65,
	1, 0,  -0.958, 0.000, -0.287,    1.30, 1.65, 0.65,
};
float cboxSmall5Data[32] = { 
	0, 1,  -0.285, 0.000, 0.958,    2.40, 0, 2.72,
	1, 1,  -0.285, 0.000, 0.958,    2.40, 1.65, 2.72,
	0, 0,  -0.285, 0.000, 0.958,    0.82, 0, 2.25,
	1, 0,  -0.285, 0.000, 0.958,    0.82, 1.65, 2.25,
};

// Data for the Cornell Box large box quads
float cboxLarge1Data[32] = { 
	0, 1,  0, 1, 0,  4.23, 3.30, 2.47,
	1, 1,  0, 1, 0,  2.65, 3.30, 2.96,
	0, 0,  0, 1, 0,  4.72, 3.30, 4.06,
	1, 0,  0, 1, 0,  3.14, 3.30, 4.56,
};
float cboxLarge2Data[32] = { 
	0, 1,  0.956, 0.000, -0.295,    4.23, 0, 2.47,
	1, 1,  0.956, 0.000, -0.295,    4.23, 3.30, 2.47,
	0, 0,  0.956, 0.000, -0.295,    4.72, 0, 4.06,
	1, 0,  0.956, 0.000, -0.295,    4.72, 3.30, 4.06,
};
float cboxLarge3Data[32] = { 
	0, 1,  0.302, 0.000, 0.953,    4.72, 0, 4.06,
	1, 1,  0.302, 0.000, 0.953,    4.72, 3.30, 4.06,
	0, 0,  0.302, 0.000, 0.953,    3.14, 0, 4.56,
	1, 0,  0.302, 0.000, 0.953,    3.14, 3.30, 4.56,
};
float cboxLarge4Data[32] = { 
	0, 1,  -0.956, 0.000, 0.293,    3.14, 0, 4.56,
	1, 1,  -0.956, 0.000, 0.293,    3.14, 3.30, 4.56,
	0, 0,  -0.956, 0.000, 0.293,    2.65, 0, 2.96,
	1, 0,  -0.956, 0.000, 0.293,    2.65, 3.30, 2.96,
};
float cboxLarge5Data[32] = { 
	0, 1,  -0.296, 0.000, -0.955,    2.65, 0, 2.96,
	1, 1,  -0.296, 0.000, -0.955,    2.65, 3.30, 2.96,
	0, 0,  -0.296, 0.000, -0.955,    4.23, 0, 2.47,
	1, 0,  -0.296, 0.000, -0.955,    4.23, 3.30, 2.47,
};

// The display callback that is invoked by our IGLUWindow with the screen is redrawn
void display ( void )
{
	// Select which shader to use this pass
	int curShader = simpleShade ? 0 : 1;

	// Does the user want back-face culling enabled?
	if (enableCull) 
		glEnable( GL_CULL_FACE );
	else
		glDisable( GL_CULL_FACE );
	
	// Clear the screen
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	// Draw our geometry with an appropriate shader
	shaders[curShader]->Enable();
	shaders[curShader]["model"] = IGLUMatrix4x4::Identity();
		floorArray->DrawArrays ( GL_TRIANGLE_STRIP, 0, 4 );
		ceilArray->DrawArrays  ( GL_TRIANGLE_STRIP, 0, 4 );
		backArray->DrawArrays  ( GL_TRIANGLE_STRIP, 0, 4 );
		leftArray->DrawArrays  ( GL_TRIANGLE_STRIP, 0, 4 );
		rightArray->DrawArrays ( GL_TRIANGLE_STRIP, 0, 4 );
		if (drawSmall)
		{
			shaders[curShader]["model"] = smallRotation;
			small1Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			small2Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			small3Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			small4Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			small5Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
		}
		if (drawLarge)
		{
			shaders[curShader]["model"] = largeRotation;
			large1Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			large2Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			large3Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			large4Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
			large5Array->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
		}
	shaders[curShader]->Disable();

	// Draw text with some instructions
	IGLUDraw::DrawText( IGLU_FONT_VARIABLE, 5, 738, 
		"A simple Cornell Box display program....  Click the (+) button for options." );
}

void idle( void )
{
	// Does the user want to rotate the blocks
	if (rotateSmall) angleSmall += 0.02;
	if (rotateLarge) angleLarge += 0.02;

	// Update the rotational transforms.
	smallRotation = IGLUMatrix4x4::Translate(1.855,0.0,1.69) * 
		            IGLUMatrix4x4::Rotate( angleSmall, vec3(0,1,0) ) *
					IGLUMatrix4x4::Translate(-1.855,0.0,-1.69);
	largeRotation = IGLUMatrix4x4::Translate(3.685,0.0,3.5125) *
		            IGLUMatrix4x4::Rotate( angleLarge, vec3(0,1,0) ) *
					IGLUMatrix4x4::Translate(-3.685,0.0,-3.5125);
}


// Code that initializes our OpenGL state.  This is guaranteed (by IGLUWindow) to be 
//    called after the OpenGL context & all extensions have been initialized
void OpenGLInitialization( void )
{            
	// Set up our Cornell Box geometry.
	floorArray = new IGLUVertexArray();
	floorArray->SetVertexArray( sizeof( cboxFloorData ), cboxFloorData, IGLU_STATIC|IGLU_DRAW );
	floorArray->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	floorArray->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	floorArray->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	ceilArray = new IGLUVertexArray();
	ceilArray->SetVertexArray( sizeof( cboxCeilingData ), cboxCeilingData, IGLU_STATIC|IGLU_DRAW );
	ceilArray->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	ceilArray->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	ceilArray->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	backArray = new IGLUVertexArray();
	backArray->SetVertexArray( sizeof( cboxBackData ), cboxBackData, IGLU_STATIC|IGLU_DRAW );
	backArray->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	backArray->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	backArray->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	leftArray = new IGLUVertexArray();
	leftArray->SetVertexArray( sizeof( cboxLeftData ), cboxLeftData, IGLU_STATIC|IGLU_DRAW );
	leftArray->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	leftArray->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	leftArray->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	rightArray = new IGLUVertexArray();
	rightArray->SetVertexArray( sizeof( cboxRightData ), cboxRightData, IGLU_STATIC|IGLU_DRAW );
	rightArray->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	rightArray->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	rightArray->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	small1Array = new IGLUVertexArray();
	small1Array->SetVertexArray( sizeof( cboxSmall1Data ), cboxSmall1Data, IGLU_STATIC|IGLU_DRAW );
	small1Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	small1Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	small1Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	small2Array = new IGLUVertexArray();
	small2Array->SetVertexArray( sizeof( cboxSmall2Data ), cboxSmall2Data, IGLU_STATIC|IGLU_DRAW );
	small2Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	small2Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	small2Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	small3Array = new IGLUVertexArray();
	small3Array->SetVertexArray( sizeof( cboxSmall3Data ), cboxSmall3Data, IGLU_STATIC|IGLU_DRAW );
	small3Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	small3Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	small3Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	small4Array = new IGLUVertexArray();
	small4Array->SetVertexArray( sizeof( cboxSmall4Data ), cboxSmall4Data, IGLU_STATIC|IGLU_DRAW );
	small4Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	small4Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	small4Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	small5Array = new IGLUVertexArray();
	small5Array->SetVertexArray( sizeof( cboxSmall5Data ), cboxSmall5Data, IGLU_STATIC|IGLU_DRAW );
	small5Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	small5Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	small5Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	large1Array = new IGLUVertexArray();
	large1Array->SetVertexArray( sizeof( cboxLarge1Data ), cboxLarge1Data, IGLU_STATIC|IGLU_DRAW );
	large1Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	large1Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	large1Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	large2Array = new IGLUVertexArray();
	large2Array->SetVertexArray( sizeof( cboxLarge2Data ), cboxLarge2Data, IGLU_STATIC|IGLU_DRAW );
	large2Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	large2Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	large2Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	large3Array = new IGLUVertexArray();
	large3Array->SetVertexArray( sizeof( cboxLarge3Data ), cboxLarge3Data, IGLU_STATIC|IGLU_DRAW );
	large3Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	large3Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	large3Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	large4Array = new IGLUVertexArray();
	large4Array->SetVertexArray( sizeof( cboxLarge4Data ), cboxLarge4Data, IGLU_STATIC|IGLU_DRAW );
	large4Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	large4Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	large4Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	large5Array = new IGLUVertexArray();
	large5Array->SetVertexArray( sizeof( cboxLarge5Data ), cboxLarge5Data, IGLU_STATIC|IGLU_DRAW );
	large5Array->EnableAttribute( IGLU_ATTRIB_VERTEX,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(5*sizeof(float)) );
	large5Array->EnableAttribute( IGLU_ATTRIB_NORMAL,   3, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(2*sizeof(float)) );
	large5Array->EnableAttribute( IGLU_ATTRIB_TEXCOORD, 2, GL_FLOAT, 8 * sizeof(float), BUFFER_OFFSET(0) );

	// Load the shader that performs the wavelet transform
	shaders[0] = new IGLUShaderProgram( "test.vert.glsl", "test.frag.glsl" );
	shaders[0]->SetProgramEnables( IGLU_GLSL_DEPTH_TEST ); 
	shaders[0]->SetProgramDisables( IGLU_GLSL_BLEND ); 
	shaders[0]["project"]   = proj;
	shaders[0]["model"]     = IGLUMatrix4x4::Identity();
	shaders[0]["view"]      = view;

	shaders[1] = new IGLUShaderProgram( "test.vert.glsl", "test2.frag.glsl" );
	shaders[1]->SetProgramEnables( IGLU_GLSL_DEPTH_TEST ); 
	shaders[1]->SetProgramDisables( IGLU_GLSL_BLEND ); 
	shaders[1]["project"]   = proj;
	shaders[1]["model"]     = IGLUMatrix4x4::Identity();
	shaders[1]["view"]      = view;
}

void ToggleFramerate( void *uiBool )
{
	myWin->DisplayFramerate( ((IGLUBool *)uiBool)->GetValue() );
}

// Our main entry point
int main(int argc, char** argv)
{
	// Put together our main window
	myWin = new IGLUWindow( 768, 768, "Simple IGLU Example:  Draw a Cornell Box" );
	myWin->SetWindowProperties( IGLU_WINDOW_NO_RESIZE |	
								IGLU_WINDOW_DOUBLE |
								IGLU_WINDOW_REDRAW_ON_IDLE |
								IGLU_WINDOW_W_FRAMERATE ); 
	myWin->SetDisplayCallback( display );  
	myWin->SetIdleCallback( idle );
	myWin->SetPreprocessOnGLInit( OpenGLInitialization );
	myWin->CreateWindow( argc, argv );     

	// Create a widget window to allow us to interact/change our IGLUVariables
	uiWin = new IGLUWidgetWindow( 300, 300, "UI Widget Window" );
	uiWin->AddWidget( &simpleShade );
	uiWin->AddWidget( &enableCull );
	uiWin->AddWidgetSpacer();
	uiWin->AddWidget( &drawSmall );
	uiWin->AddWidget( &rotateSmall );
	uiWin->AddWidgetSpacer();
	uiWin->AddWidget( &drawLarge );
	uiWin->AddWidget( &rotateLarge );
	uiWin->AddWidgetSpacer();
	uiWin->AddWidget( &displayFPS );

	// Tell our main window about the widget window... 
	myWin->SetWidgetWindow( uiWin );

	// Turning off the framerate display is more complex and actually
	//    needs a callback, so we know when the variable changes
	displayFPS.SetCallback( ToggleFramerate );

	// Start the FLTK interaction loop
	IGLUWindow::Run();
	return 0;
}
