#include <../source/TAL/objbase.h>
#include <../source/PAL/dataman.h>

/*
 *	Wrappers for OpenGL 1.1 texturing stuff
 */

/*
 *	Loads image and binds it to new texture object with given parameters.
 */
GLuint	V_GLOBAL
vglLoadTexture(char *file_name,GLenum filter,GLenum clamp,GLenum env)
{
	u32_t width,height;
	GLuint id;
	u8_t *texels;
	GLenum magf;
	int level;
	texels = rgbaLoad(file_name,&width,&height);
	if(!texels)
		return 0;
	if(!IS_POWER_TWO(width) || !IS_POWER_TWO(height))
	{
#ifdef	CHECKED_BUILD
		conlPrintf(LOG_ERROR,
			"vglLoadTexture(): wrong texture dimensions %dX%d.\n",
			width,height);
#endif	/* CHECKED_BUILD */
		memFree(texels);
		return 0;
	}
	switch(filter)
	{
		case GL_LINEAR_MIPMAP_NEAREST:
		case GL_LINEAR_MIPMAP_LINEAR:
		case GL_LINEAR:
			magf=GL_LINEAR;
			break;
		case GL_NEAREST_MIPMAP_LINEAR:
		case GL_NEAREST_MIPMAP_NEAREST:
		case GL_NEAREST:
			magf=GL_NEAREST;
			break;
		default:
			magf=filter;
			break;
	}
	/* Generate texture and bind it to target */
	glGenTextures(1,&id);
	glBindTexture(GL_TEXTURE_2D,id);
	/* Download image data to renderer */
	level=0;
	if(magf!=filter)	/* generate all except last mipmap levels */
		for(;width>1 && height>1;level++)
		{
			glTexImage2D(GL_TEXTURE_2D,level,GL_RGBA,width,height,0,GL_RGBA,
				GL_UNSIGNED_BYTE,texels);
			texels=rgbaScale(texels,width,height,width >> 1,height >> 1,false);
			width>>=1;
			height>>=1;
		}
	glTexImage2D(GL_TEXTURE_2D,level,GL_RGBA,width,height,0,GL_RGBA,
		GL_UNSIGNED_BYTE,texels);
	memFree(texels);
	/* Set texture parameters */
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,filter);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,magf);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,clamp);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,clamp);
	glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,env);
	/* Clear current texture object */
	glBindTexture(GL_TEXTURE_2D,0);
	return id;
}

/*
 *	Loads six textures for cube map (QuakeII-style sky)
 */
vboolean	V_GLOBAL
vglLoadSkyBoxTextures(GLuint quake_sky[6],char *path,char *sky_name,char *file_ext)
{
	int i;
	static char suffixes[6][3]={"up","ft","lf","bk","rt","dn"};
	char name[_MAX_FNAME];
	char file_name[_MAX_PATH];
	if(!quake_sky || !sky_name || !sky_name[0]
    	|| !file_ext || !file_ext[0])
	{
#ifdef	CHECKED_BUILD
		conlPrintf(LOG_ERROR,
			"vglLoadSky(%X,'%s','%s','%s'): incorrect parameter(s).\n",
			quake_sky,strSafe(path),strSafe(sky_name),strSafe(file_ext));
#endif	/* CHECKED_BUILD */
		return false;	
	}
	/* Load images */
	/* TODO: determine presence of HW renderer by ctx->accelerated */
	for(i=0;i<6;i++)
	{
		sprintf(name,"%s%s",sky_name,suffixes[i]);
		fsMakePath(file_name,path,name,file_ext);
		quake_sky[i]=vglLoadTexture(file_name,
        	GL_LINEAR,GL_CLAMP,GL_MODULATE);
	}
	return true;
}

void	V_GLOBAL
vglDrawSkyBox(GLuint quake_sky[6],vec_t sky_intensity,vec_t sky_opacity)
{
	int i;
	GLfloat	mat[16];
	/* Skybox geometry, topology and texture coordinates */
	vec_t	cube_vertices[8][3]={
		{	1,	1,	1},
		{	-1,	1,	1},
		{	-1,	-1,	1},
		{	1,	-1,	1},
		{	1,	1,	-1},
		{	-1,	1,	-1},
		{	-1,	-1,	-1},
		{	1,	-1,	-1}};
	int		cube_faces[6][4]={
		{	0,	1,	2,	3	},		/* up */
		{	0,	3,	7,	4	},		/* forward */
		{	1,	0,	4,	5	},		/* left */
		{	2,	1,	5,	6	},		/* back */
		{	3,	2,	6,	7	},		/* right */
		{	4,	7,	6,	5	}};		/* down */
	vec_t	cube_bottom[4][2]=
	{
		{1,0},
		{1,1},
		{0,1},
		{0,0}
	};
	vec_t	cube_top[4][2]=
	{
		{1,1},
		{0,1},
		{0,0},
		{1,0}
	};
	vec_t	cube_wall[4][2]=
	{
		{0,0},
		{1,0},
		{1,1},
		{0,1}
	};
	/* setup state */
	glDisable(GL_CULL_FACE);
	glEnable(GL_TEXTURE_2D);
	/*
     *	Move cube to the origin of the world
     *	(reset current translation & scale transform)
     */
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glGetFloatv(GL_MODELVIEW_MATRIX,mat);
	mat[3]=mat[7]=mat[11]=mat[12]=mat[13]=mat[14]=0;
	mat[15]=1;
	glLoadMatrixf(mat);
    /* Make cube large enought */
	glScalef(10,10,10);
	/* Draw textured cube */
	glColor4f((GLfloat)sky_intensity,(GLfloat)sky_intensity,
		(GLfloat)sky_intensity,(GLfloat)sky_opacity);
	if(IsZero(sky_opacity-1))
	{
		glDisable(GL_BLEND);
	}
	else
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	}
	/* top */
	glBindTexture(GL_TEXTURE_2D,quake_sky[0]);
	glBegin(GL_QUADS);
	for(i=0;i<4;i++)
	{
		VGL_TEXCOORD2V(cube_top[i]);
		VGL_VERTEX3V(cube_vertices[cube_faces[0][i]]);
	}
	glEnd();
	/* forward */
	glBindTexture(GL_TEXTURE_2D,quake_sky[1]);
	glBegin(GL_QUADS);
	for(i=0;i<4;i++)
	{
		VGL_TEXCOORD2V(cube_wall[i]);
		VGL_VERTEX3V(cube_vertices[cube_faces[1][i]]);
	}
	glEnd();
	/* left */
	glBindTexture(GL_TEXTURE_2D,quake_sky[4]);
	glBegin(GL_QUADS);
	for(i=0;i<4;i++)
	{
		VGL_TEXCOORD2V(cube_wall[i]);
		VGL_VERTEX3V(cube_vertices[cube_faces[2][i]]);
	}
	glEnd();
	/* back */
	glBindTexture(GL_TEXTURE_2D,quake_sky[3]);
	glBegin(GL_QUADS);
	for(i=0;i<4;i++)
	{
		VGL_TEXCOORD2V(cube_wall[i]);;
		VGL_VERTEX3V(cube_vertices[cube_faces[3][i]]);
	}
	glEnd();
	/* right */
	glBindTexture(GL_TEXTURE_2D,quake_sky[2]);
	glBegin(GL_QUADS);
	for(i=0;i<4;i++)
	{
		VGL_TEXCOORD2V(cube_wall[i]);;
		VGL_VERTEX3V(cube_vertices[cube_faces[4][i]]);
	}
	glEnd();
	/* bottom */
	glBindTexture(GL_TEXTURE_2D,quake_sky[5]);
	glBegin(GL_QUADS);
	for(i=0;i<4;i++)
	{
		VGL_TEXCOORD2V(cube_bottom[i]);
		VGL_VERTEX3V(cube_vertices[cube_faces[5][i]]);
	}
	glEnd();
	glPopMatrix();
	glDisable(GL_TEXTURE_2D);
}
