/*
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.

*/
// r_md3mesh.c: MD3 triangle model functions

#include "r_local.h"

vec3_t	tempVertexArray[MD3_MAX_MESHES][MD3_MAX_VERTS];
vec3_t	shadevector_md3; // Knightmare added
float	shadelight_md3[3];
int	meshnum;

#define MAX_MODEL_DLIGHTS 128
m_dlight_t model_dlights_md3[MAX_MODEL_DLIGHTS];
int model_dlights_num_md3;

void R_ShadowLight (vec3_t pos, vec3_t lightAdd); // Knightmare added
void SetShellBlend (qboolean toggle); //Knightmare added
qboolean FlowingShell (void); //Knightmare added

void light_md3_model(vec3_t normal, vec3_t color)
{
	int	i;
	vec3_t	colo[8];
	float s1,s2,s3,angle;//, dif;

	VectorClear(color);
	for (i=0; i<model_dlights_num_md3; i++)
	{
		s1 = model_dlights_md3[i].direction[0]*normal[0] + model_dlights_md3[i].direction[1]*normal[1] + model_dlights_md3[i].direction[2]*normal[2];
		s2 = sqrt(model_dlights_md3[i].direction[0]*model_dlights_md3[i].direction[0] + model_dlights_md3[i].direction[1]*model_dlights_md3[i].direction[1] + model_dlights_md3[i].direction[2]*model_dlights_md3[i].direction[2]);
		s3 = sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]);

		angle = s1/(s2*s3);
		colo[i][0] = model_dlights_md3[i].color[0]*(angle*100);
		colo[i][1] = model_dlights_md3[i].color[1]*(angle*100);
		colo[i][2] = model_dlights_md3[i].color[2]*(angle*100);
		colo[i][0] /= 100;
		colo[i][1] /= 100;
		colo[i][2] /= 100;
		color[0] += colo[i][0];
		color[1] += colo[i][1];
		color[2] += colo[i][2];
	}
	color[0] /= model_dlights_num_md3;
	color[1] /= model_dlights_num_md3;
	color[2] /= model_dlights_num_md3;
	if (color[0] < 0 || color[1] < 0 || color[2] < 0)
		color[0] = color[1] = color[2] = 0;
}

extern	vec3_t			lightspot;

void R_DrawAliasMD3Shadow (maliasmesh_t mesh)
{
	float	height, lheight;
	int	i;

	lheight = currententity->origin[2] - lightspot[2];
	height = -lheight + 1.0;

	qglBegin (GL_TRIANGLES);
	for(i=0; i < mesh.num_tris; i++)
	{
		tempVertexArray[meshnum][mesh.indexes[3*i+0]][0] -= shadevector_md3[0]*(tempVertexArray[meshnum][mesh.indexes[3*i+0]][2]+lheight);
		tempVertexArray[meshnum][mesh.indexes[3*i+0]][1] -= shadevector_md3[1]*(tempVertexArray[meshnum][mesh.indexes[3*i+0]][2]+lheight);
		tempVertexArray[meshnum][mesh.indexes[3*i+0]][2] = height;

		qglVertex3fv (tempVertexArray[meshnum][mesh.indexes[3*i+0]]);

		tempVertexArray[meshnum][mesh.indexes[3*i+1]][0] -= shadevector_md3[0]*(tempVertexArray[meshnum][mesh.indexes[3*i+1]][2]+lheight);
		tempVertexArray[meshnum][mesh.indexes[3*i+1]][1] -= shadevector_md3[1]*(tempVertexArray[meshnum][mesh.indexes[3*i+1]][2]+lheight);
		tempVertexArray[meshnum][mesh.indexes[3*i+1]][2] = height;

		qglVertex3fv (tempVertexArray[meshnum][mesh.indexes[3*i+1]]);

		tempVertexArray[meshnum][mesh.indexes[3*i+2]][0] -= shadevector_md3[0]*(tempVertexArray[meshnum][mesh.indexes[3*i+2]][2]+lheight);
		tempVertexArray[meshnum][mesh.indexes[3*i+2]][1] -= shadevector_md3[1]*(tempVertexArray[meshnum][mesh.indexes[3*i+2]][2]+lheight);
		tempVertexArray[meshnum][mesh.indexes[3*i+2]][2] = height;

		qglVertex3fv (tempVertexArray[meshnum][mesh.indexes[3*i+2]]);
	}
	qglEnd ();

}


//void R_DrawAliasMD3FrameLerp (maliasmodel_t *paliashdr, maliasmesh_t mesh, float backlerp)
void R_DrawAliasMD3FrameLerp (maliasmodel_t *paliashdr, entity_t *e)
{
	int i,j,k;
	maliasframe_t	*frame, *oldframe;
	vec3_t	move, delta, vectors[3];
	maliasvertex_t	*v, *ov;
	vec3_t	tempNormalsArray[4096];
	vec3_t	color1,color2,color3;
	float	alpha;
	//vec3_t	coss, forward1, forward2, norm;
	//float	diff1, diff2, diff3, diff;
	//vec3_t	lightpoint;
	float	frontlerp;
	vec3_t	tempangle;
	// Knighmare added
	image_t		*skin;
	float		backlerp = e->backlerp;
	maliasmesh_t	mesh;
	int		va;
	float	mode;
	float	tempSkinArray[3][2];

	color1[0] = color1[1] = color1[2] = 0;
	color2[0] = color2[1] = color2[2] = 0;
	color3[0] = color3[1] = color3[2] = 0;

	frontlerp = 1.0 - backlerp;

	if (currententity->flags & RF_TRANSLUCENT)
		alpha = currententity->alpha;
	else
		alpha = 1.0;

	SetShellBlend (true);

	frame = paliashdr->frames + currententity->frame;
	oldframe = paliashdr->frames + currententity->oldframe;

	VectorSubtract ( currententity->oldorigin, currententity->origin, delta );
	VectorCopy(currententity->angles, tempangle);
	tempangle[YAW] = tempangle[YAW] - 90;
	AngleVectors (tempangle, vectors[0], vectors[1], vectors[2]);

	move[0] = DotProduct (delta, vectors[0]);	// forward
	move[1] = -DotProduct (delta, vectors[1]);	// left
	move[2] = DotProduct (delta, vectors[2]);	// up

	SetVertexOverbrights(true); // added

	VectorAdd (move, oldframe->translate, move);

	for (i=0 ; i<3 ; i++)
	{
		move[i] = backlerp*move[i] + frontlerp*frame->translate[i];
	}

	// Knightmare- new outer loop for whole model
	for (k=0; k < paliashdr->num_meshes; k++)
	{
		// select skin
		if (currententity->skin)
			skin = currententity->skin;	// custom player skin
		else
			skin = currentmodel->skins[k][e->skinnum];
		if (!skin)
			skin = r_notexture;
		if ( !(currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM)) )
			GL_Bind(skin->texnum);
		else if (FlowingShell())
			alpha = 0.7;
		mesh = paliashdr->meshes[k];

		v = mesh.vertexes + currententity->frame*mesh.num_verts;
		ov = mesh.vertexes + currententity->oldframe*mesh.num_verts;
		for ( i = 0; i < mesh.num_verts; i++, v++, ov++ )
		{
			VectorSet ( tempNormalsArray[i],
					v->normal[0] + (ov->normal[0] - v->normal[0])*backlerp,
					v->normal[1] + (ov->normal[1] - v->normal[1])*backlerp,
					v->normal[2] + (ov->normal[2] - v->normal[2])*backlerp );

			if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
			{
				if (currententity->flags & RF_WEAPONMODEL)
					VectorSet ( tempVertexArray[meshnum][i], 
							move[0] + ov->point[0]*backlerp + v->point[0]*frontlerp+tempNormalsArray[i][0]*WEAPON_SHELL_SCALE,
							move[1] + ov->point[1]*backlerp + v->point[1]*frontlerp+tempNormalsArray[i][1]*WEAPON_SHELL_SCALE,
							move[2] + ov->point[2]*backlerp + v->point[2]*frontlerp+tempNormalsArray[i][2]*WEAPON_SHELL_SCALE);
				else
					VectorSet ( tempVertexArray[meshnum][i], 
							move[0] + ov->point[0]*backlerp + v->point[0]*frontlerp+tempNormalsArray[i][0]*POWERSUIT_SCALE,
							move[1] + ov->point[1]*backlerp + v->point[1]*frontlerp+tempNormalsArray[i][1]*POWERSUIT_SCALE,
							move[2] + ov->point[2]*backlerp + v->point[2]*frontlerp+tempNormalsArray[i][2]*POWERSUIT_SCALE);
			}
			else
				VectorSet ( tempVertexArray[meshnum][i], 
						move[0] + ov->point[0]*backlerp + v->point[0]*frontlerp,
						move[1] + ov->point[1]*backlerp + v->point[1]*frontlerp,
						move[2] + ov->point[2]*backlerp + v->point[2]*frontlerp);
		}
#if 1
		va = 0;
		mode = GL_TRIANGLES;

		qglEnableClientState(GL_COLOR_ARRAY);
		for (j=0; j < mesh.num_tris; j++)
		{
			if ( (currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
					&& FlowingShell())
			{				
				tempSkinArray[0][0] = (tempVertexArray[meshnum][mesh.indexes[3*j+0]][0] + tempVertexArray[meshnum][mesh.indexes[3*j+0]][1]) / 40.0;
				tempSkinArray[0][1] = tempVertexArray[meshnum][mesh.indexes[3*j+0]][2] / 40.0 - r_newrefdef.time / 2.0;
				tempSkinArray[1][0] = (tempVertexArray[meshnum][mesh.indexes[3*j+1]][0] + tempVertexArray[meshnum][mesh.indexes[3*j+1]][1]) / 40.0;
				tempSkinArray[1][1] = tempVertexArray[meshnum][mesh.indexes[3*j+1]][2] / 40.0 - r_newrefdef.time / 2.0;
				tempSkinArray[2][0] = (tempVertexArray[meshnum][mesh.indexes[3*j+2]][0] + tempVertexArray[meshnum][mesh.indexes[3*j+2]][1]) / 40.0;
				tempSkinArray[2][1] = tempVertexArray[meshnum][mesh.indexes[3*j+2]][2] / 40.0 - r_newrefdef.time / 2.0;
			} else {
				tempSkinArray[0][0] = mesh.stcoords[mesh.indexes[3*j+0]].st[0];
				tempSkinArray[0][1] = mesh.stcoords[mesh.indexes[3*j+0]].st[1];
				tempSkinArray[1][0] = mesh.stcoords[mesh.indexes[3*j+1]].st[0];
				tempSkinArray[1][1] = mesh.stcoords[mesh.indexes[3*j+1]].st[1];
				tempSkinArray[2][0] = mesh.stcoords[mesh.indexes[3*j+2]].st[0];
				tempSkinArray[2][1] = mesh.stcoords[mesh.indexes[3*j+2]].st[1];
			}
			
			VA_SetElem2(tex_array[va], tempSkinArray[0][0], tempSkinArray[0][1]);
			VA_SetElem3(vert_array[va], tempVertexArray[meshnum][mesh.indexes[3*j+0]][0], tempVertexArray[meshnum][mesh.indexes[3*j+0]][1], tempVertexArray[meshnum][mesh.indexes[3*j+0]][2]);
			VA_SetElem4(col_array[va], shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
			va++;
			
			VA_SetElem2(tex_array[va], tempSkinArray[1][0], tempSkinArray[1][1]);
			VA_SetElem3(vert_array[va], tempVertexArray[meshnum][mesh.indexes[3*j+1]][0], tempVertexArray[meshnum][mesh.indexes[3*j+1]][1], tempVertexArray[meshnum][mesh.indexes[3*j+1]][2]);
			VA_SetElem4(col_array[va], shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
			va++;
			
			VA_SetElem2(tex_array[va], tempSkinArray[2][0], tempSkinArray[2][1]);
			VA_SetElem3(vert_array[va], tempVertexArray[meshnum][mesh.indexes[3*j+2]][0], tempVertexArray[meshnum][mesh.indexes[3*j+2]][1], tempVertexArray[meshnum][mesh.indexes[3*j+2]][2]);
			VA_SetElem4(col_array[va], shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
			va++;
		}
		qglDrawArrays(mode,0,va);
		qglDisableClientState( GL_COLOR_ARRAY );
#else
		qglBegin (GL_TRIANGLES);
		for (j=0; j < mesh.num_tris; j++)
		{
			// use color instead of shadelight_md3... maybe
			/*if (r_model_shading->value)
			{
				light_md3_model(tempNormalsArray[mesh.indexes[3*j+0]], color1);
				light_md3_model(tempNormalsArray[mesh.indexes[3*j+1]], color2);
				light_md3_model(tempNormalsArray[mesh.indexes[3*j+2]], color3);
			}*/

			if ( (currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
				&& FlowingShell())
			{				
				qglColor4f (shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
				qglTexCoord2f ((tempVertexArray[meshnum][mesh.indexes[3*j+0]][0] + tempVertexArray[meshnum][mesh.indexes[3*j+0]][1]) / 40.0, tempVertexArray[meshnum][mesh.indexes[3*j+0]][2] / 40.0 - r_newrefdef.time / 2.0);
				qglVertex3fv(tempVertexArray[meshnum][mesh.indexes[3*j+0]]);
				
				qglColor4f (shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
				qglTexCoord2f ((tempVertexArray[meshnum][mesh.indexes[3*j+1]][0] + tempVertexArray[meshnum][mesh.indexes[3*j+1]][1]) / 40.0, tempVertexArray[meshnum][mesh.indexes[3*j+1]][2] / 40.0 - r_newrefdef.time / 2.0);
				qglVertex3fv(tempVertexArray[meshnum][mesh.indexes[3*j+1]]);
				
				qglColor4f (shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
				qglTexCoord2f ((tempVertexArray[meshnum][mesh.indexes[3*j+2]][0] + tempVertexArray[meshnum][mesh.indexes[3*j+2]][1]) / 40.0, tempVertexArray[meshnum][mesh.indexes[3*j+2]][2] / 40.0 - r_newrefdef.time / 2.0);
				qglVertex3fv(tempVertexArray[meshnum][mesh.indexes[3*j+2]]);
			}
			else
			{
				//if (r_model_shading->value)
				//	qglColor4f (color1[0], color1[1], color1[2], alpha);
				//else
				qglColor4f (shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
				qglTexCoord2f (mesh.stcoords[mesh.indexes[3*j+0]].st[0], mesh.stcoords[mesh.indexes[3*j+0]].st[1]);
				qglVertex3fv(tempVertexArray[meshnum][mesh.indexes[3*j+0]]);
				
				//if (r_model_shading->value)
				//	qglColor4f (color2[0], color2[1], color2[2], alpha);
				//else
				qglColor4f (shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
				qglTexCoord2f (mesh.stcoords[mesh.indexes[3*j+1]].st[0], mesh.stcoords[mesh.indexes[3*j+1]].st[1]);
				qglVertex3fv(tempVertexArray[meshnum][mesh.indexes[3*j+1]]);
				
				//if (r_model_shading->value)
				//	qglColor4f (color3[0], color3[1], color3[2], alpha);
				//else
				qglColor4f (shadelight_md3[0], shadelight_md3[1], shadelight_md3[2], alpha);
				qglTexCoord2f (mesh.stcoords[mesh.indexes[3*j+2]].st[0], mesh.stcoords[mesh.indexes[3*j+2]].st[1]);
				qglVertex3fv(tempVertexArray[meshnum][mesh.indexes[3*j+2]]);
			}
		}
		qglEnd ();
#endif
		meshnum++;
	} // end new outer loop
	
	SetShellBlend (false);

	SetVertexOverbrights(false); // added
}

// Add shadow code (R_DrawAliasMD3ShadowVolume) here

void R_LightPointDynamics (vec3_t p, vec3_t color, m_dlight_t *list, int *amount, int max);
void R_FlipModel (qboolean on);

void R_DrawAliasMD3Model (entity_t *e)
{
	maliasmodel_t	*paliashdr;
	//image_t		*skin;
	qboolean	mirrormodel = false;
	int	i;
	float		an;

	meshnum = 0;
	memset (tempVertexArray, 0, sizeof(tempVertexArray));

	// Knightmare- mirroring support
	if (e->flags & RF_WEAPONMODEL)
	{
		if (r_lefthand->value == 2)
			return;
		else if (r_lefthand->value == 1)
			mirrormodel = true;
	}
	else if (e->renderfx & RF2_CAMERAMODEL)
	{
		if (r_lefthand->value==1)
			mirrormodel = true;
	}
	else if (currententity->flags & RF_MIRRORMODEL)
		mirrormodel = true;
	// end mirroring support

	paliashdr = (maliasmodel_t *)currentmodel->extradata;


	if ( e->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
	{
		VectorClear (shadelight_md3);
		if (e->flags & RF_SHELL_HALF_DAM)
		{
				shadelight_md3[0] = 0.56;
				shadelight_md3[1] = 0.59;
				shadelight_md3[2] = 0.45;
		}
		if ( e->flags & RF_SHELL_DOUBLE )
		{
			shadelight_md3[0] = 0.9;
			shadelight_md3[1] = 0.7;
		}
		if ( e->flags & RF_SHELL_RED )
			shadelight_md3[0] = 1.0;
		if ( e->flags & RF_SHELL_GREEN )
			shadelight_md3[1] = 1.0;
		if ( e->flags & RF_SHELL_BLUE )
			shadelight_md3[2] = 1.0;
	}
	else if ( e->flags & RF_FULLBRIGHT )
	{
		for (i=0 ; i<3 ; i++)
			shadelight_md3[i] = 1.0;
	}
	else
	{
		//if (r_model_shading->value)
		//	R_LightPointDynamics (e->origin, shadelight_md3, model_dlights_md3, &model_dlights_num_md3, 8);
		//else
			R_LightPoint (e->origin, shadelight_md3, true);

		// player lighting hack for communication back to server
		// big hack!
		if ( e->flags & RF_WEAPONMODEL )
		{
			// pick the greatest component, which should be the same
			// as the mono value returned by software
			if (shadelight_md3[0] > shadelight_md3[1])
			{
				if (shadelight_md3[0] > shadelight_md3[2])
					r_lightlevel->value = 150*shadelight_md3[0];
				else
					r_lightlevel->value = 150*shadelight_md3[2];
			}
			else
			{
				if (shadelight_md3[1] > shadelight_md3[2])
					r_lightlevel->value = 150*shadelight_md3[1];
				else
					r_lightlevel->value = 150*shadelight_md3[2];
			}

		}
		if ( gl_monolightmap->string[0] != '0' )
		{
			float s = shadelight_md3[0];

			if ( s < shadelight_md3[1] )
				s = shadelight_md3[1];
			if ( s < shadelight_md3[2] )
				s = shadelight_md3[2];

			shadelight_md3[0] = s;
			shadelight_md3[1] = s;
			shadelight_md3[2] = s;
		}
	}
	if ( e->flags & RF_MINLIGHT )
	{
		for (i=0 ; i<3 ; i++)
			if (shadelight_md3[i] > 0.1)
				break;
		if (i == 3)
		{
			shadelight_md3[0] = 0.1;
			shadelight_md3[1] = 0.1;
			shadelight_md3[2] = 0.1;
		}
	}

	if ( e->flags & RF_GLOW )
	{	// bonus items will pulse with time
		float	scale;
		float	min;

		scale = 0.1 * sin(r_newrefdef.time*7);
		for (i=0 ; i<3 ; i++)
		{
			min = shadelight_md3[i] * 0.8;
			shadelight_md3[i] += scale;
			if (shadelight_md3[i] < min)
				shadelight_md3[i] = min;
		}
	}
	// Knightmare- IR goggles support
	if (r_newrefdef.rdflags & RDF_IRGOGGLES)
	{
		if (currententity->flags & RF_IR_VISIBLE)
		{
			shadelight_md3[0] = 1.0;
			shadelight_md3[1] = 0.0;
			shadelight_md3[2] = 0.0;
		}
	}

	if (e->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
	{
		if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
			qglDepthRange (gldepthmin, gldepthmin + 0.01*(gldepthmax-gldepthmin));
		else
			qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
	}

	// Knightmare- mirroring support
	if (mirrormodel)
		R_FlipModel(true);

	for(i=0; i < paliashdr->num_meshes; i++)
	{
		c_alias_polys += paliashdr->meshes[i].num_tris;
	}

	qglPushMatrix ();
	e->angles[PITCH] = -e->angles[PITCH];	// sigh.
	//e->angles[YAW] = e->angles[YAW] - 90;
	R_RotateForEntity (e, true);
	e->angles[PITCH] = -e->angles[PITCH];	// sigh.
	//e->angles[YAW] = e->angles[YAW] + 90;

	GL_ShadeModel (GL_SMOOTH);

	GL_TexEnv( GL_MODULATE );
	if ( e->flags & RF_TRANSLUCENT )
	{
		qglEnable (GL_BLEND);
	}

	if ( (e->frame >= paliashdr->num_frames) || (e->frame < 0) )
	{
		VID_Printf (PRINT_ALL, "R_DrawAliasMD3Model %s: no such frame %d\n", currentmodel->name, e->frame);
		e->frame = 0;
		e->oldframe = 0;
	}

	if ( (e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
	{
		VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
			currentmodel->name, e->oldframe);
		e->frame = 0;
		e->oldframe = 0;
	}

	if ( !r_lerpmodels->value )
		e->backlerp = 0;

	// Knightmare- moved this inside the function, possible speedup
	/*for (i=0; i < paliashdr->num_meshes; i++)
	{
		skin = currentmodel->skins[i][e->skinnum];
		if (!skin)
			skin = r_notexture;
		GL_Bind(skin->texnum);
		R_DrawAliasMD3FrameLerp (paliashdr, paliashdr->meshes[i], e->backlerp);
		meshnum++;
	}*/
	R_DrawAliasMD3FrameLerp (paliashdr, e);

	// Knightmare- mirroring support
	if (mirrormodel)
		R_FlipModel(false);

	if ( e->flags & RF_TRANSLUCENT )
	{
		qglDisable (GL_BLEND);
	}

	if (e->flags & RF_DEPTHHACK)
		qglDepthRange (gldepthmin, gldepthmax);

	GL_TexEnv( GL_REPLACE );
	GL_ShadeModel (GL_FLAT);

	qglPopMatrix ();

#if 1
	// Knightmare- added noshadow flag
	if (!(currententity->flags & (RF_WEAPONMODEL | RF_NOSHADOW))
		// no shadows from shells
		&& !( (currententity->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
		&& (currententity->flags & RF_TRANSLUCENT) ) )
	{
		meshnum = 0;
		an = currententity->angles[1]/180*M_PI;
		shadevector_md3[0] = cos(-an);
		shadevector_md3[1] = sin(-an);
		shadevector_md3[2] = 1;
		VectorNormalize (shadevector_md3);
		switch ((int)(gl_shadows->value))
		{
		case 0:
			break;
		case 2:
		case 3:
			//dynamic lighted shadows - psychospaz
			R_ShadowLight (currententity->origin, shadevector_md3);
		default:
			{
 				qglPushMatrix ();
				//Knightmare- 12/24/2001- don't rotate shadows on bad axis
				//R_RotateForEntity (e);
				qglTranslatef	(e->origin[0], e->origin[1], e->origin[2]);
				qglRotatef (e->angles[1], 0, 0, 1);
				//end Knightmare
				qglDisable (GL_TEXTURE_2D);
				qglEnable (GL_BLEND);

				if (currententity->flags & RF_TRANSLUCENT)
					qglColor4f (0,0,0,gl_shadowalpha->value * currententity->alpha); //Knightmare- variable alpha
				else
					qglColor4f (0,0,0,gl_shadowalpha->value);

				GL_Stencil(true, false);
				GL_BlendFunction (GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA);
				for (i=0; i < paliashdr->num_meshes; i++)
				{
					R_DrawAliasMD3Shadow (paliashdr->meshes[i]);
					meshnum++;
				}
				GL_Stencil(false, false);

				qglEnable (GL_TEXTURE_2D);
				qglDisable (GL_BLEND);
				qglPopMatrix ();
			}
			break;
		}
	}
#endif
	qglColor4f (1,1,1,1);
}

#if 0
/*
=================
R_DrawAliasMD3ModelShadow
Just draws the shadow for an MD3 model.
=================
*/
void R_DrawAliasMD3ModelShadow (entity_t *e)
{
	maliasmodel_t	*paliashdr;
	qboolean	mirrormodel = false;
	int			i;
	float		an;

	meshnum = 0;
	memset (tempVertexArray, 0, sizeof(tempVertexArray));

	if (currententity->flags & (RF_WEAPONMODEL | RF_NOSHADOW))
		return;
	// no shadows from shells
	if ( (currententity->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
		&& (currententity->flags & RF_TRANSLUCENT) )
		return;

	if (e->renderfx & RF2_CAMERAMODEL)
	{
		if (r_lefthand->value==1)
			mirrormodel = true;
	}
	else if (currententity->flags & RF_MIRRORMODEL)
		mirrormodel = true;

	paliashdr = (maliasmodel_t *)currentmodel->extradata;

	// Knightmare- mirroring support
//	if (mirrormodel)
//		R_FlipModel(true);

	if ( (e->frame >= paliashdr->num_frames) || (e->frame < 0) )
	{
		e->frame = 0;
		e->oldframe = 0;
	}

	if ( (e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
	{
		e->frame = 0;
		e->oldframe = 0;
	}

	//if ( !r_lerpmodels->value )
	//	e->backlerp = 0;
	
	meshnum = 0;
	an = currententity->angles[1]/180*M_PI;
	shadevector_md3[0] = cos(-an);
	shadevector_md3[1] = sin(-an);
	shadevector_md3[2] = 1;
	VectorNormalize (shadevector_md3);
	
	switch ((int)(gl_shadows->value))
	{
	case 0:
		break;
	case 2:
	case 3:
		//dynamic lighted shadows - psychospaz
		R_ShadowLight (currententity->origin, shadevector_md3);
	default:
		{
			qglPushMatrix ();
			//Knightmare- 12/24/2001- don't rotate shadows on bad axis
			//R_RotateForEntity (e);
			qglTranslatef	(e->origin[0], e->origin[1], e->origin[2]);
			qglRotatef (e->angles[1], 0, 0, 1);
			//end Knightmare
			qglDisable (GL_TEXTURE_2D);
			qglEnable (GL_BLEND);
			
			if (currententity->flags & RF_TRANSLUCENT)
				qglColor4f (0,0,0,gl_shadowalpha->value * currententity->alpha); //Knightmare- variable alpha
			else
				qglColor4f (0,0,0,gl_shadowalpha->value);
			
			GL_Stencil(true, false);
			GL_BlendFunction (GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA);
			for (i=0; i < paliashdr->num_meshes; i++)
			{
				R_DrawAliasMD3Shadow (paliashdr->meshes[i]);
				meshnum++;
			}
			GL_Stencil(false, false);
			
			qglEnable (GL_TEXTURE_2D);
			qglDisable (GL_BLEND);
			qglPopMatrix ();
		}
		break;
	}

	// Knightmare- mirroring support
//	if (mirrormodel)
//		R_FlipModel(false);

	qglColor4f (1,1,1,1);
}
#endif
