#include "skybox.h"
#include "renderer.h"
#include "camera.h"
#include "math.h"

extern rRenderer *g_Renderer;
extern CCamera g_Camera;
extern float runtime;

void rSkyBox::Create(rSBHeader *sbh)
{
	rotSpeed = sbh->rotSpeed;
	rotX = sbh->rotX;
	rotY = sbh->rotY;
	rotZ = sbh->rotZ;

	cloudSpeed = sbh->cloudSpeed;
	cX = sbh->cX;
	cY = sbh->cY;
	cZ = sbh->cZ;
	bHasClouds = sbh->bHasClouds;

	if(rotSpeed > 0.0f)
		bRotating = true;
	else
		bRotating = false;

	g_Renderer->CreateTexture(textures[Left], sbh->textures[Left],0);
	g_Renderer->CreateTexture(textures[Right], sbh->textures[Right],0);
	g_Renderer->CreateTexture(textures[Front], sbh->textures[Front],0);
	g_Renderer->CreateTexture(textures[Back], sbh->textures[Back],0);
	g_Renderer->CreateTexture(textures[Top], sbh->textures[Top],0);
	g_Renderer->CreateTexture(textures[Bottom], sbh->textures[Bottom],0);

	if(sbh->bHasClouds)
	{
		g_Renderer->CreateTexture(textures[Clouds], sbh->textures[Clouds],0);
		g_Renderer->CreateTexture(textures[CloudsA], sbh->textures[CloudsA],0);
	}

	listIndex = glGenLists(1);
	glNewList(listIndex, GL_COMPILE);
	
	glPushAttrib(GL_DEPTH_BUFFER_BIT);
	glDepthRange(1.0f, 1.0f);
	glDepthFunc(GL_EQUAL);

	glEnable(GL_TEXTURE_2D);

	glActiveTexture(GL_TEXTURE0);
	glEnable(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, textures[Left]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBegin(GL_QUADS);
		glTexCoord2f(0,0); glVertex3f(-1,-1,1);
		glTexCoord2f(1,0); glVertex3f(-1,-1,-1);
		glTexCoord2f(1,1); glVertex3f(-1,1,-1);
		glTexCoord2f(0,1); glVertex3f(-1,1,1);
	glEnd();

	glBindTexture(GL_TEXTURE_2D, textures[Right]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBegin(GL_QUADS);
		glTexCoord2f(0,0); glVertex3f(1,-1,-1);
		glTexCoord2f(1,0); glVertex3f(1,-1,1);
		glTexCoord2f(1,1); glVertex3f(1,1,1);
		glTexCoord2f(0,1); glVertex3f(1,1,-1);
	glEnd();

	glBindTexture(GL_TEXTURE_2D, textures[Front]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBegin(GL_QUADS);
		glTexCoord2f(0,0); glVertex3f(-1,-1,-1);
		glTexCoord2f(1,0); glVertex3f(1,-1,-1);
		glTexCoord2f(1,1); glVertex3f(1,1,-1);
		glTexCoord2f(0,1); glVertex3f(-1,1,-1);
	glEnd();

	glBindTexture(GL_TEXTURE_2D, textures[Back]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBegin(GL_QUADS);
		glTexCoord2f(0,0); glVertex3f(1,-1,1);
		glTexCoord2f(1,0); glVertex3f(-1,-1,1);
		glTexCoord2f(1,1); glVertex3f(-1,1,1);
		glTexCoord2f(0,1); glVertex3f(1,1,1);
	glEnd();

	glBindTexture(GL_TEXTURE_2D, textures[Top]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBegin(GL_QUADS);
		glTexCoord2f(0,1); glVertex3f(-1,1,1);
		glTexCoord2f(0,0); glVertex3f(-1,1,-1);
		glTexCoord2f(1,0); glVertex3f(1,1,-1);
		glTexCoord2f(1,1); glVertex3f(1,1,1);
	glEnd();

	glBindTexture(GL_TEXTURE_2D, textures[Bottom]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBegin(GL_QUADS);
		glTexCoord2f(0,0); glVertex3f(-1,-1,1);
		glTexCoord2f(1,0); glVertex3f(1,-1,1);
		glTexCoord2f(1,1); glVertex3f(1,-1,-1);
		glTexCoord2f(0,1); glVertex3f(-1,-1,-1);
	glEnd();

	glDepthRange(0,1);
	glPopAttrib();
	glEndList();

}

void rSkyBox::DrawClouds()
{
	float offset = cloudSpeed * runtime * 60.0f;
	float x = cX * offset;
	float z = cZ * offset;

	glPushAttrib(GL_DEPTH_BUFFER_BIT);
	glDepthRange(1.0f, 1.0f);
	glDepthFunc(GL_EQUAL);


	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_COLOR, GL_ONE);

	glActiveTexture(GL_TEXTURE0);
	glEnable(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, textures[Clouds]);
	
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glTranslatef(x, z, 0);
	glMatrixMode(GL_MODELVIEW);

	glActiveTexture(GL_TEXTURE1);
	glEnable(GL_TEXTURE_2D);


	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glBindTexture(GL_TEXTURE_2D, textures[CloudsA]);

	glBegin(GL_QUADS);
		glMultiTexCoord2f(GL_TEXTURE0,0,1);
		glMultiTexCoord2f(GL_TEXTURE1,0,1);
		glVertex3f(-1,cY,1);

		glMultiTexCoord2f(GL_TEXTURE0,0,0);
		glMultiTexCoord2f(GL_TEXTURE1,0,0); 
		glVertex3f(-1,cY,-1);

		glMultiTexCoord2f(GL_TEXTURE0,1,0);
		glMultiTexCoord2f(GL_TEXTURE1,1,0);
		glVertex3f(1,cY,-1);

		glMultiTexCoord2f(GL_TEXTURE0,1,1);
		glMultiTexCoord2f(GL_TEXTURE1,1,1);
		glVertex3f(1,cY,1);
	glEnd();

	glActiveTextureARB(GL_TEXTURE1_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE0_ARB);		
	glDisable(GL_TEXTURE_2D);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	glDisable(GL_BLEND);

	glDepthRange(0,1);
	glPopAttrib();
}

void rSkyBox::Draw()
{
	static float rotA = 0;
	vector3 cPos = g_Camera.Position();
	glPushMatrix();
	glTranslatef(cPos.x, cPos.y, cPos.z);
	if(bRotating)
	{
		glRotatef(rotA, rotX, rotY, rotZ);
		rotA += rotSpeed;
	}
	glCallList(listIndex);	//Draw the sky box

	if(bHasClouds)
	{
			DrawClouds();
	}
	glPopMatrix();
}

rSkyBox::~rSkyBox()
{
	g_Renderer->DeleteTextures(8, textures);
	glDeleteLists(listIndex, 1);
}

