/*****************************************************************
  multitex1.cpp
  by Dave Pape
  2 April 2003

  This program is a basic demonstration of multitexturing.  It
  creates two textures, and then uses the glActiveTextureARB
  function to bind one of them to "texture unit 0" and the other
  to "texture unit 1".  When the square is rendered, the colors
  from the two textures will be combined (along with the base
  color of the polygon).
  glMultiTexCoord2fARB is used to define the texture coordinates
  for the second texture, so that it can be mapped differently
  than the first one.  In this case, the second texture repeats
  3 times in the S direction and 2 times in the T direction, while
  the first texture is just applied once.

*****************************************************************/
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <dms/dms.h>

using namespace dms;

void createScene(Object& root);
void drawEverything(void);

void key(unsigned char k, int x, int y);
void specialkey(int k, int x, int y);
void idle(void);


PerspCamera camera;

Texture2D texture1("zebra.tif");
Texture2D texture2("macbeth.tif");

bool showTex1=true, showTex2=false;


int main(int argc, char *argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(512,512);
    glutCreateWindow(argv[0]);
    
    glutDisplayFunc(drawEverything);
    glutKeyboardFunc(key);
    glutSpecialFunc(specialkey);
    glutIdleFunc(idle);
    
    camera.setPosition(0, 0, 15);
    
    glutMainLoop();
    return 0;
    }


void drawEverything(void)
    {
    glClearColor(0.5, 0.7, 1.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    
    camera.apply();

    glColor4f(1, 1, 1, 1);
    
/*************** CODE OF INTEREST ******************************/
/* Use glActiveTextureARB to control which texture unit each   */
/* texture object will be bound to.                            */
/*                                                             */
/* Note that the second texture can still be applied even if   */
/* nothing is bound to the first texture unit (GL_TEXTURE0_ARB)*/
/* It will just act like an ordinary single-texture in that    */
/* case.                                                       */
/*                                                             */
    if (showTex1)
        {
        glActiveTextureARB(GL_TEXTURE0_ARB);
        texture1.apply();
        }
    if (showTex2)
        {
        glActiveTextureARB(GL_TEXTURE1_ARB);
        texture2.apply();
        glActiveTextureARB(GL_TEXTURE0_ARB);
        }
    
/*************** CODE OF INTEREST ******************************/
/* Draw the square, using glMultiTexCoord2fARB to define the   */
/* texture coordinates to use for the second texture.          */
/* (Note that calling glTexCoord2f(s,t) is equivalent to       */
/* calling glMultiTexCoord2fARB(GL_TEXTURE0_ARB, s, t) )       */
/*                                                             */
    glBegin(GL_QUADS);
    
     glTexCoord2f(0, 0);
     glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
     glVertex3f(-5, -5, 0);
     
     glTexCoord2f(3, 0);
     glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);
     glVertex3f(5, -5, 0);
     
     glTexCoord2f(3, 2);
     glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
     glVertex3f(5, 5, 0);
     
     glTexCoord2f(0, 2);
     glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);
     glVertex3f(-5, 5, 0);

    glEnd();
    
/*************** CODE OF INTEREST ******************************/
/* Make sure to disable both textures.                         */
/*                                                             */
    if (showTex1)
        {
        glActiveTextureARB(GL_TEXTURE0_ARB);
        texture1.disable();
        }
    if (showTex2)
        {
        glActiveTextureARB(GL_TEXTURE1_ARB);
        texture2.disable();
        glActiveTextureARB(GL_TEXTURE0_ARB);
        }
    
    glutSwapBuffers();

    checkGLError("end-of-frame");
    }


void key(unsigned char k, int x, int y)
    {
    if (k == 27)
        exit(0);
    else if (k == '1')
        showTex1 = !showTex1;
    else if (k == '2')
        showTex2 = !showTex2;
    }


void specialkey(int k, int x, int y)
    {
    if (k == GLUT_KEY_LEFT)
        camera.turn(3);
    else if (k == GLUT_KEY_RIGHT)
        camera.turn(-3);
    else if (k == GLUT_KEY_UP)
        camera.pitch(2);
    else if (k == GLUT_KEY_DOWN)
        camera.pitch(-2);
    else if (k == GLUT_KEY_HOME)
        camera.moveForward(0.25);
    else if (k == GLUT_KEY_END)
        camera.moveForward(-0.25);
    else if (k == GLUT_KEY_PAGE_UP)
        camera.zoom(-1);
    else if (k == GLUT_KEY_PAGE_DOWN)
        camera.zoom(1);
    }


void idle(void)
    {
    glutPostRedisplay();
    }

