/*

	Copyright (C) 2004 Michael Liebscher
	Copyright (C) 2000-2002 by DarkOne the Hacker
	Copyright (C) 1997-2001 Id Software, Inc.

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

/*
 *	wolf_opengl.c:  Wolfenstein3-D OpenGL renderer.
 *	
 *	Author:	Michael Liebscher <johnnycanuck@users.sourceforge.net>
 *	Date:	2004 
 *
 *	Acknowledgement:
 *	Portion of this code was derived from NewWolf, and was originally
 *	written by DarkOne the Hacker.
 *
 *	Portion of this code was derived from Quake II, and was originally
 *	written by Id Software, Inc.
 *
 */
 
#include "../wolfiphone.h"

// width and height in 2D
#define WIDTH_2D		640
#define HEIGHT_2D		480




/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void GL_SetDefaultState( void )
{
	pfglClearColor( 1,0, 0.5 , 0.5 );
	pfglCullFace( GL_FRONT );
	pfglEnable( GL_TEXTURE_2D );
	pfglDisable( GL_DEPTH_TEST );
	pfglDisable( GL_CULL_FACE );
	pfglDisable( GL_BLEND );
	pfglColor4f( 1, 1, 1, 1 );
	pfglShadeModel( GL_FLAT );
	pfglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}



/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void R_DrawBox( int x, int y, int w, int h, W32 color )
{
	pfglDisable( GL_TEXTURE_2D );

//	pfglEnable( GL_BLEND );
//	pfglBlendFunc( GL_SRC_COLOR, GL_DST_COLOR );

	pfglColor4ubv( (GLubyte *) & color );

	pfglBegin( GL_QUADS );

	pfglVertex2i( x, y );
	pfglVertex2i( x, y + h);
	pfglVertex2i( x + w, y + h );
	pfglVertex2i( x + w, y );
	
	pfglEnd();

	pfglColor3f( 1, 1, 1 );
//	pfglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//	pfglDisable( GL_BLEND );
	pfglEnable( GL_TEXTURE_2D );
}


/*
 ====================
 LoadWallTexture
 
 Returns with the texture bound and glColor set to the right intensity.
 Loads an image from the filesystem if necessary.
 Used both during gameplay and for preloading during level parse.
 
 Wolfenstein was very wasteful with texture usage, making almost half of
 the textures just dim versions to provide "lighting" on the different
 wall sides.  With only a few exceptions for things like the elevator tiles
 and outdoor tiles that could only be used in particular orientations
 ====================
*/ 
float	wallBrightness[1000];
void LoadWallTexture( int wallPicNum ) {
	assert( wallPicNum >= 0 && wallPicNum < 1000 );
	texture_t *twall = wallTextures[wallPicNum];
	if ( !twall ) {
		if ( ( wallPicNum & 1 ) &&  
			wallPicNum != 31 &&
			wallPicNum != 41 &&
			wallPicNum != 43 &&
			wallPicNum != 133 ) {
			// this wallPicNum is just a dim version of another image
			
			// load the brighter version
			LoadWallTexture( wallPicNum - 1 );
			// use the same texture
			twall = wallTextures[wallPicNum] = wallTextures[wallPicNum - 1];
			// at a dimmer intensity
			wallBrightness[wallPicNum] = 0.7f;
		} else {
			// this wallPicNum has a real image associated with it
			char	name[1024];
			my_snprintf( name, sizeof( name ), "walls/%.3d.tga", wallPicNum );
			twall = wallTextures[wallPicNum] = TM_FindTexture( name, TT_Wall );
			wallBrightness[wallPicNum] = 1.0f;
		}
	}

    R_Bind( twall->texnum );
	
	// almost half of the walls are just slightly dimmer versions of
	// the "bright side", and are not stored as separate textures
	float f = wallBrightness[wallPicNum];
	pfglColor3f( f, f, f );
}

/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

           north (y)
          __________
          |        |
 west (x) |        | east (x)
          |________|
           south (y)

-----------------------------------------------------------------------------
*/
PUBLIC void R_Draw_Wall( float x, float y, float z1, float z2, int type, int tex )
{
	float x1, x2, y1, y2;

	switch( type )
	{
	// X wall
		case dir4_east:
			x1 = x2 = x + 1;
			y1 = -1 - y;
			y2 = -y;
			break;

		case dir4_west:
			x1 = x2 = x;
			y1 = -y;
			y2 = -1 - y;
			break;

	// Y wall
		case dir4_north:
			y1 = y2 = -y - 1;
			x1 = x;
			x2 = x + 1;
			break;

		case dir4_south:
			y1 = y2 = -y;
			x1 = x + 1;
			x2 = x;
			break;
	}

	LoadWallTexture( tex );
	
	pfglBegin( GL_QUADS );

	pfglTexCoord2f( 1.0, 0.0 ); pfglVertex3f( x1, z2, y1 );
	pfglTexCoord2f( 0.0, 0.0 ); pfglVertex3f( x2, z2, y2 );
	pfglTexCoord2f( 0.0, 1.0 ); pfglVertex3f( x2, z1, y2 );
	pfglTexCoord2f( 1.0, 1.0 ); pfglVertex3f( x1, z1, y1 );
	
	pfglEnd();
}

/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void R_Draw_Door( int x, int y, float z1, float z2, _boolean vertical, _boolean backside, int tex, int amount )
{
	float x1, x2, y1, y2, amt;

	if( amount == DOOR_FULLOPEN )
	{
		return;
	}	
	
	amt = (float)amount / DOOR_FULLOPEN;


	if( vertical )
	{
		x1 = x2 = (float)x + 0.5f;
		y1 = -((float)y - amt);
		y2 = -((float)y - amt); // -1
		if( backside )
		{
			y1 -= 1;
		}
		else
		{
			y2 -= 1;
		}
	}
	else
	{
		y1 = y2 = -(float)y - 0.5f;
		x1 = (float)x + amt; // +1
		x2 = (float)x + amt;
		if( backside )
		{
			x2 += 1;
		}
		else
		{
			x1 += 1;
		}
	}

	LoadWallTexture( tex );

	pfglBegin( GL_QUADS );

	pfglTexCoord2f( backside ? 0.0f : 1.0f, 0.0 ); pfglVertex3f( x1, z2, y1 );
	pfglTexCoord2f( backside ? 1.0f : 0.0f, 0.0 ); pfglVertex3f( x2, z2, y2 );
	pfglTexCoord2f( backside ? 1.0f : 0.0f, 1.0 ); pfglVertex3f( x2, z1, y2 );
	pfglTexCoord2f( backside ? 0.0f : 1.0f, 1.0 ); pfglVertex3f( x1, z1, y1 );
	
	pfglEnd();
}


/*
-----------------------------------------------------------------------------
 Function: R_DrawSprites -Draws all visible sprites.
 
 Parameters: Nothing.
 
 Returns: Nothing.
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void R_DrawSprites( void )
{
	float sina, cosa;
	float Ex, Ey, Dx, Dy;
	int n_sprt, n, ang;
	texture_t *twall;
	extern cvar_t *cropSprites;
	
// build visible sprites list
	n_sprt = Sprite_CreateVisList();
	if( ! n_sprt )
	{
		return; // nothing to draw
	}

// prepare values for billboarding
	ang = NormalizeAngle( Player.position.angle + ANG_90 );
	sina = (float)(0.5 * SinTable[ ang ]);
	cosa = (float)(0.5 * CosTable[ ang ]);

	pfglEnable( GL_BLEND );
	qglDepthMask( GL_FALSE );
	for( n = 0; n < n_sprt; ++n )
	{
		int	texnum = vislist[ n ].tex;
		if( vislist[ n ].dist < MINDIST / 2 ) 
		{
			continue; // little hack to save speed & z-buffer
		}


	
		assert( texnum >= 0 && texnum < 1000 );
		twall = spriteTextures[texnum];
		if ( !twall ) {	
			char	name[1024];
			my_snprintf( name, sizeof( name ), "%s/%.3d.tga", spritelocation, (vislist[ n ].tex) );
			twall = spriteTextures[texnum] = TM_FindTexture( name, TT_Wall );
		}
		R_Bind( twall->texnum );
		
		pfglBegin( GL_QUADS );

		if ( cropSprites->value && twall->header.numBounds > 0 ) {
			// draw one or two subrects to avoid blending all the empty space
			int	b;
			
			for ( b = 0 ; b < twall->header.numBounds ; b++ ) {
				// include a bit extra for filtering
				float x1 = (float)(twall->header.bounds[b][0][0]-1) / (twall->header.uploadWidth-1);
				float y1 = (float)(twall->header.bounds[b][0][1]-1) / (twall->header.uploadHeight-1);
				float x2 = (float)(twall->header.bounds[b][1][0]+1) / (twall->header.uploadWidth-1);
				float y2 = (float)(twall->header.bounds[b][1][1]+1) / (twall->header.uploadHeight-1);
				if ( x1 < 0 ) {
					x1 = 0;
				} else if ( x2 > 1.0 ) {
					x2 = 1.0;
				}
				if ( y1 < 0 ) {
					y1 = 0;
				} else if ( y2 > 1.0 ) {
					y2 = 1.0;
				}
				Ex = vislist[ n ].x / FLOATTILE + cosa;
				Ey = vislist[ n ].y / FLOATTILE + sina;

				pfglTexCoord2f( x1, y1 );	pfglVertex3f( Ex - x1 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y1), -Ey + x1 * 2*sina );
				pfglTexCoord2f( x1, y2 );	pfglVertex3f( Ex - x1 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y2), -Ey + x1 * 2*sina );				
				pfglTexCoord2f( x2, y2 );	pfglVertex3f( Ex - x2 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y2), -Ey + x2 * 2*sina );
				pfglTexCoord2f( x2, y1 );	pfglVertex3f( Ex - x2 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y1), -Ey + x2 * 2*sina );
			}
		} else {
			Ex = Dx = vislist[ n ].x / FLOATTILE;
			Ey = Dy = vislist[ n ].y / FLOATTILE;
			Ex += cosa; Ey += sina;
			Dx -= cosa; Dy -= sina;

			pfglTexCoord2f( 0.0, 0.0 );	pfglVertex3f( Ex, UPPERZCOORD, -Ey );
			pfglTexCoord2f( 0.0, 1.0 );	pfglVertex3f( Ex, LOWERZCOORD, -Ey );
			pfglTexCoord2f( 1.0, 1.0 );	pfglVertex3f( Dx, LOWERZCOORD, -Dy );
			pfglTexCoord2f( 1.0, 0.0 );	pfglVertex3f( Dx, UPPERZCOORD, -Dy );
		}
		
		pfglEnd();
	}
}


/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void R_DrawNumber( int x, int y, int number )
{
	texture_t *tex;
	int	col; 
	float fcol;
	static float w = 0.1f;	
	int i;
	char string[ 20 ];
	W32 length;


	my_snprintf( string, sizeof( string ), "%d", number );
	length = strlen( string );

	tex = TM_FindTexture( "pics/N_NUMPIC.tga", TT_Pic );


	pfglEnable( GL_TEXTURE_2D );
	
	R_Bind( tex->texnum );

	pfglBegin( GL_QUADS );

	for( i = length-1 ; i >= 0 ; --i )
	{
		col = string[ i ] - 48;

		fcol = col * w;		
		
		pfglTexCoord2f( fcol,	0 );	pfglVertex2i( x, y );
		pfglTexCoord2f( fcol+w, 0 );	pfglVertex2i( x+18, y );
		pfglTexCoord2f( fcol+w, 1 );	pfglVertex2i( x+18, y+32 );
		pfglTexCoord2f( fcol,	1 );	pfglVertex2i( x, y+32 );

		x -= 18;
	}

	pfglEnd();

}


W8 wfont[ ] = {	
			    	32, 15, 32, 32, 32, 32, 32, 12, 32, 32, 32, 32, 32, 32, 32, 32,
			    	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32,
			    	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
			    	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 };

/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void R_put_line( int x, int y, const char *string )
{
	texture_t *tex;
	int mx = x;
	int num;
	float frow, fcol;
	static float	h = 0.25f;	// (32 / 128.0f);
	static float	w = 0.0625f; // (32 / 512.0f);


	tex = TM_FindTexture( "pics/L_FONTPIC.tga", TT_Pic );
	

	R_Bind( tex->texnum );
	
	pfglBegin( GL_QUADS );

	while( *string )
	{
		if( *string == '\n' )
		{
			mx = x;
			y += 32;
			++string;
			continue;
		}

		num = *string;

		num &= 255;
	
		if( (num & 127) == 32 )
		{			
			mx += 32;
			++string;
			continue;		// space	
		}


		frow = ((num >> 4) - 2) * h;
		fcol = (num & 15) * w;

	
		pfglTexCoord2f( fcol, frow );		pfglVertex2i( mx, y );
		pfglTexCoord2f( fcol+w, frow );		pfglVertex2i( mx+32, y );
		pfglTexCoord2f( fcol+w, frow+h );	pfglVertex2i( mx+32, y+32 );
		pfglTexCoord2f( fcol, frow+h );		pfglVertex2i( mx, y+32 );
	
	
			
		mx += wfont[ (num & 127) - 32 ];
		++string;
	}

	pfglEnd();
}

