////////////////////////////////////////////////////////////
//                                                        //
//  PC MAGAZIN - PC Underground                           //
//  P-Buffer Beispielprogramm: einfache Shadow Maps       //
//  (w)(c)2002 Carsten Dachsbacher                        //
//                                                        //
////////////////////////////////////////////////////////////

#include	<windows.h>			
#include	<math.h>
#include	<gl\gl.h>			
#include	<gl\glu.h>			
#include	"glext.h"
#include	"texture.h"
#include	"oglExtension.h"
#include	"hprender.h"

PCUTexture *texSpot;

#include "keys.h"

static GLfloat lightPosition[] = { 2.0f, 3.0f, 2.0f, 1.0f };
static GLfloat lightDirection[] = { 2.0f, -4.0f, 2.0f, 1.0f };

// Prototypes
void	renderPlane();
void	renderScene();

void	init3DEngine()
{
    glShadeModel( GL_SMOOTH );

	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

	glDisable( GL_POLYGON_SMOOTH );

	glEnable( GL_DEPTH_TEST );
	glFrontFace( GL_CCW );
	glEnable( GL_CULL_FACE );

	// Lichtquelle zur Beleuchtung der 3D Modelle
	glEnable( GL_LIGHT0 );

	GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };

	glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );
	glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
	glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );

	glLightf( GL_LIGHT0, GL_SPOT_EXPONENT, 18 );

	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

	setMaterial();

	glEnable( GL_TEXTURE_2D );
	glDisable( GL_BLEND );

	loadKeyTexture();

	// benötigte Extensions initialisieren
	getOpenGLExtensions();

	texSpot = new PCUTexture();
	texSpot->loadBMP( "./data/spot.bmp" );

	init3DModel( "./data/bunny" );
}



//
// Render Callback
//
void	draw3DEngine()
{
	float time = GetTickCount() * 0.001f;
	lightPosition[ 0 ] = (float)cos( time ) * 2.0f;
	lightPosition[ 1 ] = (float)sin( time * 0.123f ) * 1.0f + 3.0f;
	lightPosition[ 2 ] = (float)sin( time ) * 2.0f;

	lightDirection[ 0 ] = -lightPosition[ 0 ];
	lightDirection[ 1 ] = -lightPosition[ 1 ];
	lightDirection[ 2 ] = -lightPosition[ 2 ];

	glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
	glLightfv( GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection );

	extern bool keys[ 256 ];

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	extern int windowX, windowY;
	gluPerspective( 45.0f, (float)windowX / (float)max( 1, windowY ), 0.1f, 500.0f );

	glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
	glTranslatef( 0, 0, -5 );
	glRotatef( 20, 1, 0, 0 );
	glRotatef( GetTickCount() * 0.02f, 0, 1, 0 );

	// Objekt zeichnen

	renderScene();


	
	
	

	glEnable( GL_TEXTURE_2D );
	glDisable( GL_LIGHTING );
	drawKeys();

	glFlush();
}

void	quit3DEngine()
{
}


void renderScene()
{
	glEnable( GL_LIGHTING );
	glEnable( GL_DEPTH_TEST );

	glDisable( GL_BLEND );
	glDisable( GL_TEXTURE_2D );

	glPushMatrix();

	glEnable( GL_NORMALIZE );

	glRotatef( -(float)GetTickCount() * 0.01f, 0, 1, 0 );
	glScalef( 4.0f, 4.0f, 4.0f );

	render3DModel();

	glPopMatrix();

	renderPlane();
}

void renderPlane()
{
	glDisable( GL_CULL_FACE );

	glBegin( GL_QUADS );
	const float height = -1.0f;
	glNormal3f( 0.0f, 1.0f, 0.0f );
	glVertex3f( -10.0f, height, -10.0f );
	glVertex3f( -10.0f, height, 10.0f );
	glVertex3f( 10.0f, height, 10.0f );
	glVertex3f( 10.0f, height, -10.0f );
	glEnd();
}