/*
   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:
      Table generated by a surface of revolution module.
*/

#include "global.h"

// BS:
#define TABLE_TEXTURE1 "c:/DiscoStu/gfx/wood.tga"
#define NUM_POINTS 8
#define NUM_SLICES 20

// BS: silohette data pts
vec3_t dataPts[] =
{{0, 10, 0},
{10, 10, 0},
{10, 9, 0},
{1, 9, 0},
{1, 1, 0},
{4, 1, 0},
{4, 0, 0},
{0, 0, 0}};

vec3_t rgb = {1, 1, 1};

vec3_t **surface;
text_coord_t **text_coords;
int axis = YAXIS;
/*
   BS:
   Render A TAble
*/
void TableRender(edict_t *self)
{
	int i, j;

   if (last_texture != self->skin_index)
   {
      glBindTexture (GL_TEXTURE_2D, self->skin_index); 
      last_texture = self->skin_index;
   }  

   /* Use a triangle fan to draw the top and triangle strips to draw the body */
   glEnable(GL_DEPTH_TEST);
	glBegin(GL_TRIANGLE_FAN);
		glTexCoord2f(1, 1);
		glVertex3f(surface[0][0][0], surface[0][0][1], surface[0][0][2]);
		for(i = 0; i < NUM_SLICES; i++)
		{
			glTexCoord2f(text_coords[1][i].s, text_coords[1][i].t);
			glVertex3f(surface[1][i][0], surface[1][i][1], surface[1][i][2]);
		}
		glTexCoord2f(text_coords[1][0].s, text_coords[1][0].t);
		glVertex3f(surface[1][0][0], surface[1][0][1], surface[1][0][2]);

	glEnd();

	glBegin(GL_TRIANGLE_STRIP);
		for(i = 1; i < 3; i++)
		{
			for(j = 0; j < NUM_SLICES; j++)
			{
				glTexCoord2f(text_coords[i][j].s,text_coords[i][j].t);
				glVertex3f(surface[i][j][0],
						   surface[i][j][1],
						   surface[i][j][2]);

				glTexCoord2f(text_coords[i + 1][j].s,text_coords[i][j].t);
				glVertex3f(surface[i + 1][j][0],
						   surface[i + 1][j][1],
						   surface[i + 1][j][2]);
			}

			glTexCoord2f(text_coords[i][0].s,text_coords[i][0].t);
			glVertex3f(surface[i][0][0],
					   surface[i][0][1],
					   surface[i][0][2]);

			glTexCoord2f(text_coords[i + 1][0].s,text_coords[i + 1][0].t);
			glVertex3f(surface[i + 1][0][0],
					   surface[i + 1][0][1],
					   surface[i + 1][0][2]);
		}

		/* The middle column is tricky to texture */
		i = 3;
		for(j = 0; j < NUM_SLICES; j++)
		{
			glTexCoord2f(text_coords[i][j].s,text_coords[i][j].t);
			glVertex3f(surface[i][j][0],
					   surface[i][j][1],
					   surface[i][j][2]);

			glTexCoord2f(text_coords[i][j].s, text_coords[i][j].t + 0.5);
			glVertex3f(surface[i + 1][j][0],
					   surface[i + 1][j][1],
					   surface[i + 1][j][2]);
		}
		glTexCoord2f(text_coords[i][0].s,text_coords[i][0].t);
		glVertex3f(surface[i][0][0],
				   surface[i][0][1],
				   surface[i][0][2]);

		glTexCoord2f(text_coords[i][0].s,text_coords[i][0].t + 0.5);
		glVertex3f(surface[i + 1][0][0],
				   surface[i + 1][0][1],
				   surface[i + 1][0][2]);

		for(i = 4; i < NUM_POINTS - 1; i++)
		{
			for(j = 0; j < NUM_SLICES; j++)
			{
				glTexCoord2f(text_coords[i][j].s,text_coords[i][j].t);
				glVertex3f(surface[i][j][0],
						   surface[i][j][1],
						   surface[i][j][2]);

				glTexCoord2f(text_coords[i + 1][j].s,text_coords[i + 1][j].t);
				glVertex3f(surface[i + 1][j][0],
						   surface[i + 1][j][1],
						   surface[i + 1][j][2]);
			}
			glTexCoord2f(text_coords[i][0].s,text_coords[i][0].t);
			glVertex3f(surface[i][0][0],
					   surface[i][0][1],
					   surface[i][0][2]);

			glTexCoord2f(text_coords[i + 1][0].s,text_coords[i + 1][0].t);
			glVertex3f(surface[i + 1][0][0],
					   surface[i + 1][0][1],
					   surface[i + 1][0][2]);
		}	

		for(j = 0; j < NUM_SLICES; j++)
		{
			glTexCoord2f(text_coords[NUM_POINTS - 1][j].s,text_coords[NUM_POINTS - 1][j].t);
			glVertex3f(surface[NUM_POINTS - 1][j][0],
					   surface[NUM_POINTS - 1][j][1],
					   surface[NUM_POINTS - 1][j][2]);

			glTexCoord2f(text_coords[0][j].s,text_coords[0][j].t);
			glVertex3f(surface[0][j][0],
					   surface[0][j][1],
					   surface[0][j][2]);
		}
		glTexCoord2f(text_coords[NUM_POINTS - 1][0].s,text_coords[NUM_POINTS - 1][0].t);	
		glVertex3f(surface[NUM_POINTS - 1][0][0],
				   surface[NUM_POINTS - 1][0][1],
				   surface[NUM_POINTS - 1][0][2]);


		glTexCoord2f(text_coords[0][0].s,text_coords[0][0].t);
		glVertex3f(surface[0][0][0],
				   surface[0][0][1],
				   surface[0][0][2]);

	glEnd();

   glDisable(GL_DEPTH_TEST);
}


/*
   BS:
   Spawn A Table
*/
edict_t *TableSpawn()
{
   static unsigned int skinned = NOT_FOUND, modeled = NOT_GENERATED;
   int i, j;
   edict_t *ent;
   skin_t *skin;
   ent = EdictSpawn();

   if (modeled == NOT_GENERATED)
   {

	   surface = (vec3_t **) malloc(sizeof(vec3_t *) * NUM_POINTS);
	   text_coords = (text_coord_t **) malloc(sizeof(text_coord_t *) * NUM_POINTS);
	   for(i = 0; i < NUM_POINTS; i++)
	   {
		   surface[i] = (vec3_t *) malloc(sizeof(vec3_t) * NUM_SLICES);
		   text_coords[i] = (text_coord_t *) malloc(sizeof(text_coord_t) * NUM_SLICES);
	   }

	   GenerateSurface(dataPts, NUM_POINTS, NUM_SLICES, YAXIS, surface);

	   /* These are hard coded more or less, they should be stored in a file */
	   for(j =  0; j < NUM_SLICES; j++)
	   {
		   text_coords[0][j].s = 1;
		   text_coords[0][j].t = 1;
	   }

	   for(j =  0; j < NUM_SLICES; j++)
	   {
		   text_coords[1][j].s = ((surface[1][j][0] + 10.0f) / 10.0f);
		   text_coords[1][j].t = ((surface[1][j][2] + 10.0f) / 10.0f);
	   }
	   for(j = 0; j < NUM_SLICES; j++)
	   {
			text_coords[2][j].s = text_coords[1][j].s;
			text_coords[2][j].t = text_coords[1][j].t + 0.05;
	   }

   	   for(j = 0; j < NUM_SLICES; j++)
	   {
		   text_coords[3][j].s = ((surface[3][j][0] + 10.0f) / 10.0f);
		   text_coords[3][j].t = ((surface[3][j][2] + 10.0f) / 10.0f);
	   }

   	   for(j = 0; j < NUM_SLICES; j++)
	   {
		   text_coords[4][j].s = ((surface[4][j][0] + 10.0f) / 10.0f);
		   text_coords[4][j].t = ((surface[4][j][2] + 10.0f) / 10.0f);
	   }

   	   for(j = 0; j < NUM_SLICES; j++)
	   {
		   text_coords[5][j].s = ((surface[5][j][0] + 10.0f) / 10.0f);
		   text_coords[5][j].t = ((surface[5][j][2] + 10.0f) / 10.0f);
	   }

   	   for(j = 0; j < NUM_SLICES; j++)
	   {
			text_coords[6][j].s = text_coords[5][j].s;
			text_coords[6][j].t = text_coords[5][j].t + 0.05;
	   }

   	   for(j = 0; j < NUM_SLICES; j++)
	   {
			text_coords[NUM_POINTS - 1][j].s = 1;
			text_coords[NUM_POINTS - 1][j].t = 1;
	   }

	   modeled = GENERATED;
   }
 
   // BS: Only load skins if they are not allocated already:
   if (skinned == NOT_FOUND)
      {
      // BS: Does skin exist in library?
      if ((ent->skin_num = SkinIndex(TABLE_TEXTURE1)) == NOT_FOUND)
         {
         int ix, iy;
         skin = new skin_t;
         memset(skin, 0, sizeof(*skin));
         ent->skin_num = SkinSpawn(TABLE_TEXTURE1, skin);
         if (!LoadTGA(TABLE_TEXTURE1, &skin->tga, skin->width, skin->height))
            EngineError("TGA LOAD: Skin '%s' could not be loaded.\n", TABLE_TEXTURE1);
         ent->skin_index = eng.skin_index++;
         glBindTexture (GL_TEXTURE_2D, ent->skin_index);
         TGA2GLTexture (skin, 0, 255, 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->index = ent->skin_index;
         skinned = ent->skin_index;
         InitGL();      
         }
      else // Just use skin from already loaded list:
         ent->skin_index = g_skins[ent->skin_num]->skin->index;
      }
   else
      ent->skin_index = skinned;

   // State of entity:
   ent->state = ENT_ST_USED | ENT_ST_VISIBLE;

   ent->origin[0] = 0;
   ent->origin[1] = 0;
   ent->origin[2] = 0;
   ent->rgba[0] = rgb[0];
   ent->rgba[1] = rgb[1];
   ent->rgba[2] = rgb[2];
   ent->rgba[3] = 1;
   ent->scale = 0.5f;
   ent->render = TableRender;
   ent->listen = NULL;
   ent->think = NULL;
   ent->camera = NULL;

   return ent;
}