/*
   CMSC 427 - Term Project Candidate
   ---------------------------------

   Beth Weinstein - bweinste@wam.umd.edu
   Ben Stewart - stewartb@wam.umd.edu
   Nawfel Tricha - Topaz@endorproductions.com

   Minimal OpenGL project using Microsoft Visual C++.
   This project is a premilinary candidate for the term 
   project required by CMSC 427.

   ABSTRACT:
      In this project, we will develop several fast 
      rendering and collision routines which would 
      require C/C++ speed and accuracy and then 
      implement a VisualJ++ interface.

   MODULE:
      Beth Engine module.
*/

#include "Global.h"

static skin_t r_floor_skin;
skin_t r_wall_skin;
skin_t r_chrome_skin;
static skin_t r_discolight_skin;
static edict_t *speaker[4], *sub[4], *jupiter;
#define SPEAKER_CORNER 21.213f
#define SQUARE_BOUND          400
#define SCALED_SQUARE_BOUND    400 *.4f


#define BETH_STZ_SHOW_JUPITER			3
#define JUPITER_STANZA_LENGTH			15


/*
   Initialization of Beth engine:
*/
void BethInit()
{
   skin_t *skin;
   char *filename;
   int ix, iy;

   jupiter = JupiterSpawn();
   // Load floor texture:
   skin = &r_floor_skin;
   filename = "c:/DiscoStu/gfx/floor7.tga";
   if (!LoadTGA(filename, &r_floor_skin.tga, r_floor_skin.width, r_floor_skin.height))
      EngineError("TGA LOAD: Floor '%s' could not be loaded.\n", filename);

   
   //glGenTextures (1, &skin->index);
   skin->index = eng.skin_index++;
   glBindTexture (GL_TEXTURE_2D, skin->index);
   TGA2GLTexture (skin, 0, 0, ix, iy);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexImage2D (GL_TEXTURE_2D, 0, 4, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin->glTexture);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);	


   skin = &r_wall_skin;
   filename = "c:/DiscoStu/gfx/wall.tga";
   if (!LoadTGA(filename, &r_wall_skin.tga, r_wall_skin.width, r_wall_skin.height))
      EngineError("TGA LOAD: Wall '%s' could not be loaded.\n", filename);

   //glGenTextures (1, &skin->index);
   skin->index = eng.skin_index++;
   glBindTexture (GL_TEXTURE_2D, skin->index);
   TGA2GLTexture (skin, 0, 0, ix, iy);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexImage2D (GL_TEXTURE_2D, 0, 4, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin->glTexture);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);	

   skin = &r_chrome_skin;
   filename = "c:/DiscoStu/gfx/wall.tga";
   //filename = "c:/DiscoStu/gfx/chrome0.tga";
   if (!LoadTGA(filename, &r_chrome_skin.tga, r_chrome_skin.width, r_chrome_skin.height))
      EngineError("TGA LOAD: Chrome '%s' could not be loaded.\n", filename);

   //glGenTextures (1, &skin->index);
   skin->index = eng.skin_index++;
   glBindTexture (GL_TEXTURE_2D, skin->index);
   TGA2GLTexture (skin, 0, 0, ix, iy);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexImage2D (GL_TEXTURE_2D, 0, 4, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin->glTexture);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);	

   skin = &r_discolight_skin;
   filename = "c:/DiscoStu/gfx/discolight.tga";
   if (!LoadTGA(filename, &r_discolight_skin.tga, r_discolight_skin.width, r_discolight_skin.height))
      EngineError("TGA LOAD: DiscoLight '%s' could not be loaded.\n", filename);

   //glGenTextures (1, &skin->index);
   skin->index = eng.skin_index++;
   glBindTexture (GL_TEXTURE_2D, skin->index);
   TGA2GLTexture (skin, 0, TGA_ABSOLUTE_BLEND, ix, iy);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexImage2D (GL_TEXTURE_2D, 0, 4, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin->glTexture);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);	

   // Only one listen function is needed to feed all other speakers:
   speaker[0] = SpeakerSpawn();
   VectorSet(speaker[0]->origin, -408 * .4f + SPEAKER_CORNER, 0, -400  * .4f+ SPEAKER_CORNER);
   speaker[0]->angle[YAW] = -45 + 90;
   speaker[1] = SpeakerSpawn();
   speaker[1]->listen = NULL;
   VectorSet(speaker[1]->origin, -408  * .4f + SPEAKER_CORNER, 0, 400  * .4f - SPEAKER_CORNER);
   speaker[1]->angle[YAW] = 45 + 90;
   speaker[2] = SpeakerSpawn();
   speaker[2]->listen = NULL;
   VectorSet(speaker[2]->origin, 408  * .4f - SPEAKER_CORNER, 0, -400  * .4f + SPEAKER_CORNER);
   speaker[2]->angle[YAW] = 225 + 90;
   speaker[3] = SpeakerSpawn();
   speaker[3]->listen = NULL;
   VectorSet(speaker[3]->origin, 408  * .4f - SPEAKER_CORNER, 0, 400  * .4f - SPEAKER_CORNER);
   speaker[3]->angle[YAW] = 135 + 90;

}

/*
   Stanza change for Beth engine:
*/
void BethStanza(int stanza)
{
	switch (stanza) {
	case BETH_STZ_SHOW_JUPITER:
		cam.target = jupiter;
		eng.next_stanza = eng.time + (JUPITER_STANZA_LENGTH*1000);
		break;
	}
}

/*
   Display a static ground at Y = 0:
*/
static inline void DisplayGround()
{
   static float xrotate = 0;
   float dspkick2 = dsp.kick/2;
   glColor3f(1, 1, 1);
   glEnable(GL_DEPTH_TEST);
   glBindTexture (GL_TEXTURE_2D, r_floor_skin.index);

   glPushMatrix();
   glScalef(.4, .4, .4);

   // FLOOR:
   // UPPER STRIP:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 4.5);
      glVertex3f(-SQUARE_BOUND, 0, -20);
      glTexCoord2f(10, 4.5);
      glVertex3f(SQUARE_BOUND, 0, -20);
      glTexCoord2f(0, 0);
      glVertex3f(-SQUARE_BOUND, 0, -SQUARE_BOUND);
      glTexCoord2f(10, 0);
      glVertex3f(SQUARE_BOUND, 0, -SQUARE_BOUND);
   glEnd();
   // LOWER STRIP:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 10);
      glVertex3f(-SQUARE_BOUND, 0, SQUARE_BOUND);
      glTexCoord2f(10, 10);
      glVertex3f(SQUARE_BOUND, 0, SQUARE_BOUND);
      glTexCoord2f(0, 5.5);
      glVertex3f(-SQUARE_BOUND, 0, 20);
      glTexCoord2f(10, 5.5);
      glVertex3f(SQUARE_BOUND, 0, 20);
   glEnd();
   // MIDDLE STRIP LEFT:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 5.5);
      glVertex3f(-SQUARE_BOUND, 0, 20);
      glTexCoord2f(4.5, 5.5);
      glVertex3f(-20, 0, 20);
      glTexCoord2f(0, 4.5);
      glVertex3f(-SQUARE_BOUND, 0, -20);
      glTexCoord2f(4.5, 4.5);
      glVertex3f(-20, 0, -20);
   glEnd();
   // MIDDLE STRIP RIGHT:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(5.5, 5.5);
      glVertex3f(20, 0, 20);
      glTexCoord2f(10, 5.5);
      glVertex3f(SQUARE_BOUND, 0, 20);
      glTexCoord2f(5.5, 4.5);
      glVertex3f(20, 0, -20);
      glTexCoord2f(10, 4.5);
      glVertex3f(SQUARE_BOUND, 0, -20);
   glEnd();


   glBindTexture (GL_TEXTURE_2D, r_wall_skin.index);
   // RIGHT WALL:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 1);
      glVertex3f(SQUARE_BOUND, 120, -SQUARE_BOUND);
      glTexCoord2f(0, 0);
      glVertex3f(SQUARE_BOUND, 0, -SQUARE_BOUND);
      glTexCoord2f(1, 1);
      glVertex3f(SQUARE_BOUND, 120, SQUARE_BOUND);
      glTexCoord2f(1, 0);
      glVertex3f(SQUARE_BOUND, 0, SQUARE_BOUND);
   glEnd();

   // LEFT WALL:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(1, 1);
      glVertex3f(-SQUARE_BOUND, 120, SQUARE_BOUND);
      glTexCoord2f(1, 0);
      glVertex3f(-SQUARE_BOUND, 0, SQUARE_BOUND);
      glTexCoord2f(0, 1);
      glVertex3f(-SQUARE_BOUND, 120, -SQUARE_BOUND);
      glTexCoord2f(0, 0);
      glVertex3f(-SQUARE_BOUND, 0, -SQUARE_BOUND);
   glEnd();

   // FRONT WALL:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 1);
      glVertex3f(SQUARE_BOUND, 120, SQUARE_BOUND);
      glTexCoord2f(0, 0);
      glVertex3f(SQUARE_BOUND, 0, SQUARE_BOUND);
      glTexCoord2f(1, 1);
      glVertex3f(-SQUARE_BOUND, 120, SQUARE_BOUND);
      glTexCoord2f(1, 0);
      glVertex3f(-SQUARE_BOUND, 0, SQUARE_BOUND);
   glEnd();

   // BACK WALL:
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(1, 1);
      glVertex3f(-SQUARE_BOUND, 120, -SQUARE_BOUND);
      glTexCoord2f(1, 0);
      glVertex3f(-SQUARE_BOUND, 0, -SQUARE_BOUND);
      glTexCoord2f(0, 1);
      glVertex3f(SQUARE_BOUND, 120, -SQUARE_BOUND);
      glTexCoord2f(0, 0);
      glVertex3f(SQUARE_BOUND, 0, -SQUARE_BOUND);
   glEnd();


   glDisable(GL_DEPTH_TEST);

   glPushMatrix();
   glRotatef(xrotate, 0, 1, 0);
   glScalef(.8, .8, .8);
   glColor4f(cam.RGB_filter[0], cam.RGB_filter[1], cam.RGB_filter[2], dsp.kick);
   glBindTexture (GL_TEXTURE_2D, r_discolight_skin.index);
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 1);
      glVertex3f(-SQUARE_BOUND, 0, SQUARE_BOUND);
      glTexCoord2f(1, 1);
      glVertex3f(SQUARE_BOUND, 0, SQUARE_BOUND);
      glTexCoord2f(0, 0);
      glVertex3f(-SQUARE_BOUND, 0, -SQUARE_BOUND);
      glTexCoord2f(1, 0);
      glVertex3f(SQUARE_BOUND, 0, -SQUARE_BOUND);
   glEnd();
   glPopMatrix();
/*
   glPushMatrix();
   glRotatef(90 - xrotate, 0, 1, 0);
   glColor4f(1 - cam.RGB_filter[0], 1 - cam.RGB_filter[1], 1 - cam.RGB_filter[2], dsp.kick);
   glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2f(0, 1);
      glVertex3f(-408, 0, 400);
      glTexCoord2f(1, 1);
      glVertex3f(408, 0, 400);
      glTexCoord2f(0, 0);
      glVertex3f(-408, 0, -400);
      glTexCoord2f(1, 0);
      glVertex3f(408, 0, -400);
   glEnd();
   glPopMatrix();
*/
   xrotate += 2;
   glPopMatrix();

}

/*
   Main function, called from RenderFrame every frame:
*/
void BethMain(struct winampVisModule *this_mod)
{
   DisplayGround();
}

