//*****************************************************************************************
// Disclaimer, Authorship and License
/*
	This code has been written to serve as a learning tool for the course MAE 410-574, 
	Virtual Reality Applications and Research, Spring 2007.
	
	Large parts of the code has been adapted from the examples given in the OpenGL 
	Programming Guide by Woo et. al and also from Computer Graphics Using OpenGL by FS Hill
	Some parts of the code has also been adapted from various resources available through 
	out the internet.I thank all those whose code and resources I have used to write these 
	examples. You may use this code for any non-commerical purpose. Feel free to include 
	and use parts of this code for your own application, but remember that this code is not
	entirely bug free, use it at your own risk..If you plan on using the code for your any 
	academic purpose please drop me an email. I would like to attach a link to your course 
	from my home page.

	The Author of this code is Govindarajan Srimathveeravalli, Dept. of Mech and Aero Eng. ,
	University at Buffalo.
*/
//******************************************************************************************
// This code demonstrates the reading and adding textures from TGA files.
// Try the following
// 1. Note that lighting has been disabled and yet the scene renders correctly, notice
//    that texture mode has been set to DECAL
// 2. Play with parameters in CLAMP and REPEAT and see what happens in the first case.
// 3. How would you put a texture such that image appears only once (in reduced size)
//    and at exactly the center of the polygon?

#include <iostream>
#include <algorithm>
#include <fstream>
#include <vector>
#include <string>
#include <stdlib.h>
#include <glut.h>
#include <math.h>

#include "CTgaImg.h"

float xVal = 10.;
float yVal = 0.;
float zVal = 0.;

// create a checkerboard image.
CTgaImg *img1 = new CTgaImg;

bool one, two = false;

GLuint texName1;

// White directional light
GLfloat white_light[] = { 1., 1., 1., 1. };
GLfloat light_posn[] = { 0., 0., 500., 0. }; 

// Silvery material for the object
GLfloat mat_ambient[] = { 0.19, 0.19, 0.19, 1. };
GLfloat mat_diffuse[] = { 0.7, 0.2, 0.2, 1. };
GLfloat mat_specular[] = { 0.51, 0.51, 0.51, 1. };
GLfloat low_shininess[] = { 51.2 };

void drawAxis()
{
	// draw the axis

	glPushAttrib( GL_CURRENT_BIT );
	glBegin( GL_LINES );
		glColor3f( 1., 0., 0. );
		glVertex3f( -200., 0., 0. );
		glVertex3f( 200., 0., 0. );
	glEnd();

	glBegin( GL_LINES );
		glColor3f( 0., 1., 0. );
		glVertex3f( 0., -200., 0. );
		glVertex3f( 0., 200., 0. );
	glEnd();

	glBegin( GL_LINES );
		glColor3f( 0., 0., 1. );
		glVertex3f( 0., 0., -200. );
		glVertex3f( 0., 0., 200. );
	glEnd();

	glPopAttrib( );
}

void keys( unsigned char key, int x, int y )
{

	switch( key )
	{
	case '1':
		{
			xVal += 1.;
		}break;
	
	case '2':
		{
			yVal += 1.;
		}break;
	
	case '3':
		{
			zVal += 1.;
		}break;

	case 'a':
		{
			one = true;
			two = false;
		}break;

	case 'A':
		{
			one = false;
		}break;

	case 's':
		{
			one = false;
			two = true;
		}break;

	case 'S':
		{
			two = false;
		}break;

	}
	
	glutPostRedisplay();
}

void reshape( int w, int h )
{
	glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
	
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glFrustum( -.4, .4, -.3, .3, 1., 1300. );
	
	glMatrixMode( GL_MODELVIEW );
	
	glutPostRedisplay();
}

void draw( )
{
	// Prelims
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glLoadIdentity();
 
	gluLookAt( 0., 0., 150., 0., 0., 0., 0., 1., 0. );
	
	glDisable( GL_LIGHTING );
	drawAxis();
	//glEnable( GL_LIGHTING );

	// set material
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, low_shininess);
	
	// do the drawing
	glRotatef( xVal, 1., 0., 0. );
	glRotatef( yVal, 0., 1., 0. );
	glRotatef( zVal, 0., 0., 1. );

	// repeat the texture over the entire surface
	if( one )
	{
		glEnable( GL_TEXTURE_2D );
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
		glBegin( GL_QUADS );
			glNormal3f( 0., 0., 1. );
			glTexCoord2f(10, 0.0);  glVertex3f( -50, -50, 0. );
			glTexCoord2f(0.0, 0.0);  glVertex3f( 50, -50, 0. );
			glTexCoord2f(0.0, 10);  glVertex3f( 50, 50, 0. );
			glTexCoord2f(10, 10);  glVertex3f( -50, 50, 0. );
		glEnd();
	}

	// put the texture full size
	if( two )
	{
		glEnable( GL_TEXTURE_2D );
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );

		glBegin( GL_QUADS );
			glNormal3f( 0., 0., 1. );
			glTexCoord2f(1, 0.0);  glVertex3f( -50, -50, 0. );
			glTexCoord2f(0.0, 0.0);  glVertex3f( 50, -50, 0. );
			glTexCoord2f(0.0, 1);  glVertex3f( 50, 50, 0. );
			glTexCoord2f(1, 1);  glVertex3f( -50, 50, 0. );
		glEnd();
	}

	glDisable( GL_TEXTURE_2D );

	glutSwapBuffers();
}

void init( )
{
	glClearColor( .46, .53, .6, 0. );

	// We keep our light within the display func so that we can influence its properties
	// Create the first white light
	glLightfv( GL_LIGHT0, GL_POSITION, light_posn );
	glLightfv( GL_LIGHT0, GL_AMBIENT, white_light );
	glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light );
	glLightfv( GL_LIGHT0, GL_SPECULAR, white_light );	
	glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );

	glEnable( GL_LIGHTING );
	glEnable( GL_LIGHT0 );

	// Enable depth testing
	glEnable( GL_DEPTH_TEST );
	// Set up a shading model
	glShadeModel( GL_SMOOTH );

	// Read in info from the TGA image now
	std::cout << img1->loadTGAImg("wall.tga") << "\n";
	
	glGenTextures(1, &texName1);
	glBindTexture(GL_TEXTURE_2D, texName1);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img1->getImgWidth(), img1->getImgHeight(), 
                0, GL_RGB, GL_UNSIGNED_BYTE , img1->getImgPixelData() );

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
	
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	one = true;
	
}

int main(int argc, char* argv[])
{
	glutInit( &argc, argv );
	glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
	glutInitWindowPosition( 50, 50 );
	glutInitWindowSize( 640, 480 );
	glutCreateWindow( "Texture - image from file" );

	glutDisplayFunc( draw );
	glutReshapeFunc( reshape );
	glutKeyboardFunc( keys );

	init( );

	glutMainLoop();

	return 0;
}

