/*
	This TreeLib example application is based on sample code retrieved from http://nehe.gamedev.net
*/


#include <windows.h>
#include <gl/gl.h>
#include <gl/glut.h>


#include "treelib/interface.h"	//This will include both the treelib.h header as well as provide some automated access functionality


TreeLib::Tree	my_tree=NULL;

float angle = 0;


void init ( GLvoid )
{

  glShadeModel(GL_SMOOTH);
	glClearColor(0.7f, 0.7f, 0.7f, 0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
   glEnable ( GL_COLOR_MATERIAL );
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

void display ( void )   // Create The Display Function
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
  
	glLoadIdentity();									// Reset The Current Modelview Matrix
	glTranslatef(0,-5,-10);								// Move camera away from point of origin and a little up
	glRotatef(angle,0,1,0);								// Rotate camera around point of origin
	glEnable(GL_DEPTH_TEST);
	
	float	position[3] = {0,0,0},						// Use point of origin as position for the tree
			up[3] = {0,1,0},							// Use clean Y-axis as up axis
			right[3] = {1,0,0};							// and X as right axis. Make sure that both axes are of length 1 and orthogonal to each other
	
	/*
		The following will put your tree into the scenery at the specified position and orientation. The called function is lightweight and should perform adequate even if called several ten thousand times per frame.
		No opengl context is required at this point.
		You can put as many trees as you like each as often as you like into the scenery. Be sure to call TreeLib::renderComposition() when you're done though.
	*/
	TreeLib::putTree(my_tree,position,up,right);
	
	/*
		Once you finished putting all your trees into the scenery you can initiate a full scene rendering using the renderComposition() function. It handles texture loading, imposter rendering, leaf, and bark rendering,
		and automatically flushes the list of put trees when done.
		Execution time needed by this function heavily depends on how many trees you put into the scenery and what extensions the current system provides. Also the specified level of detail and imposter range
		affect rendering speed when rendering larger amounts of trees.
	*/
	if (!TreeLib::renderComposition())
	{
		//Handle tree rendering exception. This would be rare but can happen if textures are unavailable.
	}
	

  glutSwapBuffers ( );
  // Swap The Buffers To Not Be Left With A Clear Screen
}

void reshape ( int w, int h )   // Create The Reshape Function (the viewport)
{
  glViewport     ( 0, 0, w, h );
  glMatrixMode   ( GL_PROJECTION );  // Select The Projection Matrix
  glLoadIdentity ( );                // Reset The Projection Matrix
  if ( h==0 )  // Calculate The Aspect Ratio Of The Window
     gluPerspective ( 80, ( float ) w, 0.1, 5000.0 );
  else
     gluPerspective ( 80, ( float ) w / ( float ) h, 0.1, 5000.0 );
  glMatrixMode   ( GL_MODELVIEW );  // Select The Model View Matrix
  glLoadIdentity ( );    // Reset The Model View Matrix
}

void keyboard ( unsigned char key, int x, int y )  // Create Keyboard Function
{
  switch ( key ) {
    case 27:        // When Escape Is Pressed...
      exit ( 0 );   // Exit The Program
      break;        // Ready For Next Case
    default:        // Now Wrap It Up
      break;
  }
}

void arrow_keys ( int a_keys, int x, int y )  // Create Special Function (required for arrow keys)
{
  switch ( a_keys ) {
    case GLUT_KEY_UP:     // When Up Arrow Is Pressed...
      glutFullScreen ( ); // Go Into Full Screen Mode
      break;
    case GLUT_KEY_DOWN:               // When Down Arrow Is Pressed...
      glutReshapeWindow ( 800, 600 ); // Go Into A 800 By 600 Window
      break;
	case GLUT_KEY_LEFT:	//simple camera rotation around the tree
		angle += 5;
	break;
	case GLUT_KEY_RIGHT:
		angle -= 5;
	break;
    default:
      break;
  }
}

int main ( int argc, char** argv )   // Create Main Function For Bringing It All Together
{
  glutInit            ( &argc, argv ); // Erm Just Write It =)
  init ();
  glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE ); // Display Mode
  glutInitWindowSize  ( 800, 600 ); // If glutFullScreen wasn't called this is the window size
  glutCreateWindow    ( "TreeLib example application" );
  //glutFullScreen      ( );          // Put Into Full Screen
  glutDisplayFunc     ( display );  // Matching Earlier Functions To Their Counterparts
  glutReshapeFunc     ( reshape );
  glutKeyboardFunc    ( keyboard );
  glutSpecialFunc     ( arrow_keys );
  
  if (!TreeLib::load("treelib/treelib.dll"))	//load the library and automatically execute the init function. This function can be executed anywhere even without a valid OpenGL context
  {
	//oops, loading failed
	//handle treelib exception here. use TreeLib::error() to retrieve an error description
  }
  my_tree = TreeLib::createTree();				//create a new random tree. At this point the library has to be loaded and initialized or tree creation will fail.
  //my_tree = TreeLib::createTreeTreeFromSeed(1024);			//or create a new tree from a fixed seed. if all attributes are the same then the same seed will create the exact same tree
  
  if (!my_tree)	//Technically the only possible reason for the newly created tree to be NULL would be that the library has not been initialized. You might want to check anyway
  {
	//oops, tree creation failed
	//handle treelib exception here. use TreeLib::error() to retrieve an error description
  }
  
  glutMainLoop        ( );          // Initialize The Main Loop
  return 0;
}

