
/************************************************
 **
 **		Surface.cpp
 **     functions for graphics surfaces
 **
 ************************************************/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "include/glut.h"
#include "core.h"
#include "wrapglut.h"
#include "surface.h"


///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////              constructors             ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////


CSurface::CSurface()
	{
		data=NULL;
		xdim=0; ydim=0; size=0; depth=0; channels=0;
		transparency=1;
		GLIndex=0;
	}


CSurface::CSurface(int width,int height,int cdepth)
	{
		depth=cdepth;
		xdim=width;
		ydim=height;
		channels=cdepth/8;
		size=(xdim)*(ydim)*channels;
		data=(char*)malloc(size);
		transparency=1;
		if (GLIndex!=0)
			glDeleteTextures(1,&GLIndex);
	}

CSurface::~CSurface()
{
	if (data!=NULL) free(data);
}


///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////                  draw                 ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////


void CSurface::Draw(float x,float y,float r,float g,float b)
{
	float xsiz=xdim;
	float ysiz=ydim;
	xsiz=(xsiz*2)/640;
	ysiz=(ysiz*2)/480;

	glEnable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
		glLoadIdentity();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
			glLoadIdentity();
			glBegin (GL_QUADS);
				glColor3f(1,1,1);
				glTexCoord2i(0,1);
				glVertex3f (x, y, -1);
				glTexCoord2i(1,1);
				glVertex3f (x+xsiz, y, -1);
				glTexCoord2i(1,0);
				glVertex3f (x+xsiz, y+ysiz, -1);
				glTexCoord2i(0,0);
				glVertex3f (x, y+ysiz, -1);
			glEnd ();
		glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
}


void CSurface::drawRect(float x1,float x2,float y1,float y2,float r,float g,float b,float a)
{
	glEnable(GL_TEXTURE_2D);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
		glLoadIdentity();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
			glLoadIdentity();
			glBegin (GL_QUADS);
				glColor4f(r,g,b,a);

				glTexCoord2i(0,0);
				glVertex3f (x1,y1, -1);

				glTexCoord2i(1,0);
				glVertex3f (x2,y1, -1);

				glTexCoord2i(1,1);
				glVertex3f (x2,y2, -1);

				glTexCoord2i(0,1);
				glVertex3f (x1,y2, -1);
			glEnd ();
		glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	glDisable(GL_TEXTURE_2D);
}

void CSurface::DrawAsBackground()
{
	glBindTexture(GL_TEXTURE_2D,GLIndex);
	glEnable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
		glLoadIdentity();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
			glLoadIdentity();
			glBegin (GL_QUADS);
				glColor4f(1,1,1,transparency);
				glTexCoord2i(0,1);
				glVertex3i (-1, -1, -1);
				glTexCoord2i(1,1);
				glVertex3i (1, -1, -1);
				glTexCoord2i(1,0);
				glVertex3i (1, 1, -1);
				glTexCoord2i(0,0);
				glVertex3i (-1, 1, -1);
			glEnd ();
		glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	//glDisable(GL_TEXTURE_2D);
}


void CSurface::Draw(float x,float y,float z,float r,float g,float b)
{
	float xsiz=xdim;
	float ysiz=ydim;
	xsiz=(xsiz*2)/640;
	ysiz=(ysiz*2)/480;

	glEnable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	glMatrixMode(GL_MODELVIEW);
	//glPushMatrix();
		glLoadIdentity();
		/*glMatrixMode(GL_PROJECTION);
		glPushMatrix();
			glLoadIdentity();*/
			glBegin (GL_QUADS);
				glColor4f(1,1,1,0.4);
				glTexCoord2i(0,1);
				glVertex3f (x-xsiz/2, y-ysiz/2, z);
				glTexCoord2i(1,1);
				glVertex3f (x+xsiz/2, y-ysiz/2, z);
				glTexCoord2i(1,0);
				glVertex3f (x+xsiz/2, y+ysiz/2, z);
				glTexCoord2i(0,0);
				glVertex3f (x-xsiz/2, y+ysiz/2, z);
			glEnd ();
		/*glPopMatrix();
	glMatrixMode(GL_MODELVIEW);*/
	//glPopMatrix();
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
}

void CSurface::draw(float x,float y,float z)
{
		float xsiz=xdim;
		float ysiz=ydim;
		xsiz=(xsiz*2)/640;
		ysiz=(ysiz*2)/480;
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity ();
		glTranslatef(-xsiz/2,-ysiz/2,-2);
		glBegin (GL_QUADS);
			glColor4f(1,1,1,1);
			glTexCoord2i(0,1);
			glVertex3f (x, y, z);
			glTexCoord2i(1,1);
			glVertex3f (x+xsiz, y, z);
			glTexCoord2i(1,0);
			glVertex3f (x+xsiz, y+ysiz, z);
			glTexCoord2i(0,0);
			glVertex3f (x, y+ysiz, z);
		glEnd ();
}


void CSurface::draw(float x,float y,float z,float rx,float ry,float rz,float sx,float sy,float sz)
{
		float xsiz=xdim;
		float ysiz=ydim;
		xsiz=(xsiz*2)/640;
		ysiz=(ysiz*2)/480;
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity ();
		glScalef(sx,sy,sz);
		glTranslatef(-xsiz/2,-ysiz/2,-2);
		glRotatef(rx,1,0,0);
		glRotatef(ry,0,1,0);
		glRotatef(rz,0,0,1);
		glBegin (GL_QUADS);
			glColor4f(1,1,1,1);
			glTexCoord2i(0,1);
			glVertex3f (x, y, z);
			glTexCoord2i(1,1);
			glVertex3f (x+xsiz, y, z);
			glTexCoord2i(1,0);
			glVertex3f (x+xsiz, y+ysiz, z);
			glTexCoord2i(0,0);
			glVertex3f (x, y+ysiz, z);
		glEnd ();
}

void CSurface::draw(float x,float y,float z,float alpha)
{
		float xsiz=xdim;
		float ysiz=ydim;
		xsiz=(xsiz*2)/640;
		ysiz=(ysiz*2)/480;

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity ();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();

		glBegin (GL_QUADS);
			glColor4f(alpha,alpha,alpha,alpha);
			glTexCoord2i(0,1);
			glVertex3f (x, y, z);
			glTexCoord2i(1,1);
			glVertex3f (x+xsiz, y, z);
			glTexCoord2i(1,0);
			glVertex3f (x+xsiz, y+ysiz, z);
			glTexCoord2i(0,0);
			glVertex3f (x, y+ysiz, z);
		glEnd ();

		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
}

void CSurface::drawflat(float x,float y,float z,float xsiz,float ysiz,float alpha)
{
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity ();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();

	glBegin (GL_QUADS);
		glColor4f(alpha,alpha,alpha,alpha);
		glTexCoord2i(0,1);
		glVertex3f (x, y, z);
		glTexCoord2i(1,1);
		glVertex3f (x+xsiz,y, z);
		glTexCoord2i(1,0);
		glVertex3f (x+xsiz,y+ysiz, z);
		glTexCoord2i(0,0);
		glVertex3f (x, y+ysiz, z);
	glEnd ();

	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
}

///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////                 loadTGA               ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////


void CSurface::LoadTGA(char *filename)
{

	FILE *tgafile=NULL;
	//if (!filename) return;

	//printf("Loading TGA - %s - ",filename);
	//tgafile=fopen(filename,"rb");
	//if (!tgafile) { printf("file not found\n"); return; }
	
	tgafile=FileOpen(filename);
	if (tgafile==NULL) return;
	fseek(tgafile,12,SEEK_CUR);
	fread(&xdim,2,1,tgafile);
	fread(&ydim,2,1,tgafile);
	fread(&depth,1,1,tgafile);
	channels=depth/8;
	//printf("%ix%ix%i\n",xdim,ydim,depth);
	fseek(tgafile,2,SEEK_CUR);
	if (data!=NULL) free(data);
	size=(xdim)*(ydim)*channels;
	data=(char*)malloc(size);
	fread(data,size,1,tgafile);

	for (int x=0; x<size; x+=channels)
	{
		int color,r,g,b,a;
		memcpy(&color,data+x,channels);
		g=color&255;
		b=(color>>8)&255;
		a=(color>>16)&255;
		r=(color>>24)&255;
		color=b+(g<<8)+(r<<16)+(a<<24);
		memcpy(data+x,&color,channels);
	}
	for (int y=0; y<ydim/2; y++)
	for (x=0; x<xdim; x++)
	{
		int color1,color2;
		memcpy(&color1,data+(x*channels)+(y*xdim*channels),channels);
		memcpy(&color2,data+(x*channels)+(((ydim-1)-y)*xdim*channels),channels);
		
		memcpy(data+(x*channels)+(y*xdim*channels),&color2,channels);
		memcpy(data+(x*channels)+(((ydim-1)-y)*xdim*channels),&color1,channels);
	}
	FileClose(tgafile);
}


void CSurface::LoadTGARAR(char *filename)
{
	//printf("Loading TGA - %s - ",filename);

	char *tgabuf;
	unsigned long tgasize;
	tgabuf=NULL;

	urarlib_get(&tgabuf,&tgasize,filename,"demo.moo\0",NULL);
	if (!tgabuf) return;
	if (!tgasize) return;

	tgabuf+=12;
	memcpy(&xdim,tgabuf,2); tgabuf+=2;
	memcpy(&ydim,tgabuf,2); tgabuf+=2;
	memcpy(&depth,tgabuf,2); tgabuf+=1;
	channels=depth/8;
	//printf("%ix%ix%i\n",xdim,ydim,depth);
	tgabuf+=2;
	if (data!=NULL) free(data);
	size=(xdim)*(ydim)*channels;
	data=(char*)malloc(size);
	memcpy(data,tgabuf,size);

	for (int x=0; x<size; x+=channels)
	{
		int color,r,g,b,a;
		memcpy(&color,data+x,channels);
		g=color&255;
		b=(color>>8)&255;
		a=(color>>16)&255;
		r=(color>>24)&255;
		color=b+(g<<8)+(r<<16)+(a<<24);
		memcpy(data+x,&color,channels);
	}
	for (int y=0; y<ydim/2; y++)
	for (x=0; x<xdim; x++)
	{
		int color1,color2;
		memcpy(&color1,data+(x*channels)+(y*xdim*channels),channels);
		memcpy(&color2,data+(x*channels)+(((ydim-1)-y)*xdim*channels),channels);
		
		memcpy(data+(x*channels)+(y*xdim*channels),&color2,channels);
		memcpy(data+(x*channels)+(((ydim-1)-y)*xdim*channels),&color1,channels);
	}

	//printf("\nRARsays: mem%i size:%i\n",tgabuf,tgasize);
	flushall();
	if (tgabuf) delete tgabuf;
}

void CSurface::Bind(unsigned int index)
{
	GLIndex=index;
	MapTexture(index,this);
}

void CSurface::BindToUse()
{
	glBindTexture(GL_TEXTURE_2D,GLIndex);

}

void CSurface::Update(int index)
{
	glBindTexture(GL_TEXTURE_2D,index);
	if (channels==4)
		glTexSubImage2D(GL_TEXTURE_2D,0,0,0,xdim,ydim,GL_RGBA,GL_UNSIGNED_BYTE,data);
	if (channels==3)
		glTexSubImage2D(GL_TEXTURE_2D,0,0,0,xdim,ydim,GL_RGB,GL_UNSIGNED_BYTE,data);
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////