// gl_mesh.c: triangle model functions

#include	"gl_local.h"
#include	"gl_protex.h"

//	prototype.  defined in gl_rmain.c
int	R_GetProjectedVert (vec3_t org, int *x, int *y);

/*
=============================================================

  ALIAS MODELS


=============================================================
*/

#define NUMVERTEXNORMALS	162

float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};

static	vec3_t	lerped[MAX_VERTS];

vec3_t	shadevector;
float	shadelight[3];
float	oldshadelight[3];
qboolean	shademodified = false;

dmdl_t			*s_pmdl;
dsurface_t		*s_psurface;

// precalculated dot products for quantized angles
#define SHADEDOT_QUANT 16
float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
#include "anormtab.h"
;

float	*shadedots = r_avertexnormal_dots[0];

void GL_LerpVerts( int nverts, dtrivertx_t *v, dtrivertx_t *ov, dtrivertx_t *verts, float *lerp, float move[3], float frontv[3], float backv[3] )
{
	int i;

	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
	{
		for (i=0 ; i < nverts; i++, v++, ov++, lerp+=3)
		{
			float *normal = r_avertexnormals[verts[i].lightnormalindex];

			lerp[0] = move[0] + ov->v[0]*backv[0] + v->v[0]*frontv[0] + normal[0] * POWERSUIT_SCALE;
			lerp[1] = move[1] + ov->v[1]*backv[1] + v->v[1]*frontv[1] + normal[1] * POWERSUIT_SCALE;
			lerp[2] = move[2] + ov->v[2]*backv[2] + v->v[2]*frontv[2] + normal[2] * POWERSUIT_SCALE; 
		}
	}
	else
	{
		for (i=0 ; i < nverts; i++, v++, ov++, lerp+=3)
		{
			lerp[0] = move[0] + ov->v[0]*backv[0] + v->v[0]*frontv[0];
			lerp[1] = move[1] + ov->v[1]*backv[1] + v->v[1]*frontv[1];
			lerp[2] = move[2] + ov->v[2]*backv[2] + v->v[2]*frontv[2];
		}
	}

}

/*
=============
GL_AddAliasGlow
=============
*/
void GL_AddAliasGlow (void)
{
	int		i;
	float	scale;
	float	min;

	oldshadelight[0] = shadelight[0];
	oldshadelight[1] = shadelight[1];
	oldshadelight[2] = shadelight[2];

	scale = 0.1 * sin(r_newrefdef.time*7);
	for (i=0 ; i<3 ; i++)
	{
		min = shadelight[i] * 0.8;
		shadelight[i] += scale;
		if (shadelight[i] < min)
			shadelight[i] = min;
	}
	shademodified = true;
}

#define SURFANIM_LOOP	0x01

/*
===============
R_AliasAnimateSurface
===============
*/
int R_AliasAnimateSurface (int surface)
{
	int			i;
	uvaentity_t	*entity;

	return (int)(r_newrefdef.time) % s_psurface[surface].num_uvframes;

	// find the entity
	for (i = 0; i < r_newrefdef.num_uvaentities; i++, r_newrefdef.uvaentities++)
	{
		if (r_newrefdef.uvaentities->key == (int)(currententity))
			entity = r_newrefdef.uvaentities;
	}
		
	// return frame 0 if the entity could not be found
	if (!entity)
		return 0;

	// return 0 if the entity is not animating
	if (entity->current_frame[surface] == -1)
		return 0;

	// increment the frame
	entity->current_frame[surface]++;

	// bounds checking
	if (entity->current_frame[surface] >= s_psurface[surface].num_uvframes)
	{
		if (entity->flags[surface] & SURFANIM_LOOP)
			entity->current_frame[surface] = 0;
		else
			entity->current_frame[surface] = -1;
	}

	// return the frame
	return entity->current_frame[surface];
}

/*
=============
GL_DrawAliasFrameLerp

interpolates between two frames and origins
FIXME: batch lerp all vertexes
=============
*/
void GL_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp)
{
	float 	l;
	daliasframe_t	*frame, *oldframe;
	dtrivertx_t	*v, *ov, *verts;
	int		*order;
	int		count;
	float	frontlerp;
	float	alpha;
	vec3_t	move, delta, vectors[3];
	vec3_t	frontv, backv;
	int		i;
	int		index_xyz;
	float	*lerp;
	
	image_t		*skin;
	GLenum		primtype;
	dtriangle_t	*ptri;
	int			surface, uvframe;

	frame = (daliasframe_t *)((byte *)s_pmdl + s_pmdl->ofs_frames 
		+ currententity->frame * s_pmdl->framesize);
	verts = v = frame->verts;

	oldframe = (daliasframe_t *)((byte *)s_pmdl + s_pmdl->ofs_frames 
		+ currententity->oldframe * s_pmdl->framesize);
	ov = oldframe->verts;

	order = (int *)((byte *)s_pmdl + s_pmdl->ofs_glcmds);
	ptri = (dtriangle_t *) ((byte *) s_pmdl + s_pmdl->ofs_tris);

//	glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]);
//	glScalef (frame->scale[0], frame->scale[1], frame->scale[2]);

	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
		qglDisable( GL_TEXTURE_2D );

	frontlerp = 1.0 - backlerp;

	// move should be the delta back to the previous frame * backlerp
	VectorSubtract (currententity->oldorigin, currententity->origin, delta);
	AngleVectors (currententity->angles, 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

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

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

//		move[i] /= oldframe->scale[i];
//		move[i] *= backlerp;
	}

	for (i=0 ; i<3 ; i++)
	{
		frontv[i] = frontlerp*frame->scale[i];
		backv[i] = backlerp*oldframe->scale[i];
	}

	lerp = lerped[0];

	GL_LerpVerts( s_pmdl->num_xyz, v, ov, verts, lerp, move, frontv, backv );

	while (1)
	{
		// get the vertex count and primitive type
		count = *order++;
		if (!count)
			break;		// done
		if (count < 0)
		{
			count = -count;
			primtype = GL_TRIANGLE_FAN;
		}
		else
			primtype = GL_TRIANGLE_STRIP;

		if (currententity->flags & RF_TRANSLUCENT)
		{
			alpha = currententity->alpha;
			qglEnable (GL_BLEND);
		}
		else
			alpha = 1.0;

		if (currententity->skin)
			skin = currententity->skin;	// custom player skin
		else
		{
			if (currententity->skinnum >= MAX_MD2SKINS)
				skin = currentmodel->skins[0];
			else
			{
				skin = currentmodel->skins[*order];
				if (!skin)
					skin = currentmodel->skins[0];
			}
		}

		order++;
		surface = *order++;

		// dont draw this surface
		if (s_psurface[surface].flags & SRF_NODRAW)
		{	
			do 
			{
				order += (s_psurface[surface].num_uvframes * 2) + 1;
			} while (--count);
			continue;
		}
		// 33% translucent surface
		if (s_psurface[surface].flags & SRF_TRANS33)
		{
			qglEnable (GL_BLEND);
			alpha = 0.33;
		}
		// 66% translucent surface
		else if (s_psurface[surface].flags & SRF_TRANS66)
		{
			qglEnable (GL_BLEND);
			alpha = 0.66;
		}
		// glowing surface
		if (s_psurface[surface].flags & SRF_GLOW)
			GL_AddAliasGlow ();

		if (!skin)
			skin = r_notexture;	// fallback...
		GL_Bind(skin->texnum);

		qglBegin (primtype);

		if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
		{
			do
			{
				index_xyz = *order++;
				order += s_psurface[surface].num_uvframes * 2;

				qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha);
				qglVertex3fv (lerped[index_xyz]);

			} while (--count);
		}
		else
		{
			do
			{
				index_xyz = *order++;

				// get the current frame
				uvframe = R_AliasAnimateSurface (surface) * 2;

				// texture coordinates come from the draw list
				qglTexCoord2f (((float *)order)[uvframe], ((float *)order)[uvframe + 1]);
				order += s_psurface[surface].num_uvframes * 2;

				// normals and vertexes come from the frame list
				l = shadedots[verts[index_xyz].lightnormalindex];
				
				qglColor4f (l*shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
				qglVertex3fv (lerped[index_xyz]);
			} while (--count);

		}
		qglEnd ();
		qglDisable (GL_BLEND);

		if (shademodified)
		{
			shadelight[0] = oldshadelight[0];
			shadelight[1] = oldshadelight[1];
			shadelight[2] = oldshadelight[2];
			shademodified = false;
		}
	}

	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
		qglEnable( GL_TEXTURE_2D );

	qglDisable (GL_BLEND);
}

/*
=============
GL_DrawAliasShadow
=============
*/
extern	vec3_t			lightspot;

void GL_DrawAliasShadow (dmdl_t *paliashdr, int posenum)
{
	dtrivertx_t	*verts;
	int		*order;
	vec3_t	point;
	float	height, lheight;
	int		count;
	daliasframe_t	*frame;
	GLenum		primtype;
	int			surface;
	int		index_xyz;

	lheight = currententity->origin[2] - lightspot[2];

	frame = (daliasframe_t *)((byte *)s_pmdl + s_pmdl->ofs_frames 
		+ currententity->frame * s_pmdl->framesize);
	verts = frame->verts;

	height = 0;

	order = (int *)((byte *)s_pmdl + s_pmdl->ofs_glcmds);

	height = -lheight + 1.0;

	while (1)
	{
		// get the vertex count and primitive type
		count = *order++;
		if (!count)
			break;		// done
		if (count < 0)
		{
			count = -count;
			primtype = GL_TRIANGLE_FAN;
		}
		else
			primtype = GL_TRIANGLE_STRIP;

		order++;
		surface = *order++;

		// dont draw this surface
		if (s_psurface[surface].flags & SRF_NODRAW)
		{	
			do 
			{
				order += (s_psurface[surface].num_uvframes * 2) + 1;
			} while (--count);
			continue;
		}

		qglBegin (primtype);

		do
		{
			index_xyz = *order++;
			// normals and vertexes come from the frame list
			point[0] = verts[index_xyz].v[0] * frame->scale[0] + frame->translate[0];
			point[1] = verts[index_xyz].v[1] * frame->scale[1] + frame->translate[1];
			point[2] = verts[index_xyz].v[2] * frame->scale[2] + frame->translate[2];

			memcpy( point, lerped[index_xyz], sizeof( point )  );

			point[0] -= shadevector[0]*(point[2]+lheight);
			point[1] -= shadevector[1]*(point[2]+lheight);
			point[2] = height;
//			height -= 0.001;
			qglVertex3fv (point);

			order += s_psurface[surface].num_uvframes * 2;

//			verts++;

		} while (--count);

		qglEnd ();
	}	
}

/*
** R_CullAliasModel
*/
static qboolean R_CullAliasModel( vec3_t bbox[8], entity_t *e )
{
	int i;
	vec3_t		mins, maxs;
	vec3_t		vectors[3];
	vec3_t		thismins, oldmins, thismaxs, oldmaxs;
	daliasframe_t *pframe, *poldframe;
	vec3_t		angles;
	vec3_t		scaled_org;

	if ( ( e->frame >= s_pmdl->num_frames ) || ( e->frame < 0 ) )
	{
		ri.Con_Printf (PRINT_ALL, "R_CullAliasModel: no such frame %d\n", e->frame);
		e->frame = 0;
	}
	if ( ( e->oldframe >= s_pmdl->num_frames ) || ( e->oldframe < 0 ) )
	{
		ri.Con_Printf (PRINT_ALL, "R_CullAliasModel: no such oldframe %d\n", e->oldframe);
		e->oldframe = 0;
	}

	pframe = ( daliasframe_t * ) ( ( byte * ) s_pmdl + 
		                              s_pmdl->ofs_frames +
									  e->frame * s_pmdl->framesize);

	poldframe = ( daliasframe_t * ) ( ( byte * ) s_pmdl + 
		                              s_pmdl->ofs_frames +
									  e->oldframe * s_pmdl->framesize);

	/*
	** compute axially aligned mins and maxs
	*/
	if ( pframe == poldframe )
	{
		for ( i = 0; i < 3; i++ )
		{
			mins[i] = pframe->translate[i];
			maxs[i] = mins[i] + pframe->scale[i]*255;
		}
	}
	else
	{
		for ( i = 0; i < 3; i++ )
		{
			thismins[i] = pframe->translate[i];
			thismaxs[i] = thismins[i] + pframe->scale[i]*255;

			oldmins[i]  = poldframe->translate[i];
			oldmaxs[i]  = oldmins[i] + poldframe->scale[i]*255;

			if ( thismins[i] < oldmins[i] )
				mins[i] = thismins[i];
			else
				mins[i] = oldmins[i];

			if ( thismaxs[i] > oldmaxs[i] )
				maxs[i] = thismaxs[i];
			else
				maxs[i] = oldmaxs[i];
		}
	}

	//	Nelno:	scale bounding box
	for (i = 0; i < 3; i++)
	{
		mins [i] *= e->render_scale [i];
		maxs [i] *= e->render_scale [i];
		
		//	Nelno:	compute scaled center of model
		scaled_org [i] = e->origin [i] - ((e->render_scale [i] * s_pmdl->org [i]) - s_pmdl->org [i]);
	}

	/*
	** compute a full bounding box
	*/
	for ( i = 0; i < 8; i++ )
	{
		vec3_t   tmp;

		if ( i & 1 )
			tmp[0] = mins[0];
		else
			tmp[0] = maxs[0];

		if ( i & 2 )
			tmp[1] = mins[1];
		else
			tmp[1] = maxs[1];

		if ( i & 4 )
			tmp[2] = mins[2];
		else
			tmp[2] = maxs[2];

		VectorCopy( tmp, bbox[i] );
	}

	/*
	** rotate the bounding box
	*/
	VectorCopy( e->angles, angles );
	angles[YAW] = -angles[YAW];
	AngleVectors( angles, vectors[0], vectors[1], vectors[2] );

	for ( i = 0; i < 8; i++ )
	{
		vec3_t tmp;

		VectorCopy( bbox[i], tmp );

		bbox[i][0] = DotProduct( vectors[0], tmp );
		bbox[i][1] = -DotProduct( vectors[1], tmp );
		bbox[i][2] = DotProduct( vectors[2], tmp );

	//	VectorAdd( e->origin, bbox[i], bbox[i] );
		VectorAdd( scaled_org, bbox[i], bbox[i] );
	}

	{
		int p, f, aggregatemask = ~0;

		for ( p = 0; p < 8; p++ )
		{
			int mask = 0;

			for ( f = 0; f < 4; f++ )
			{
				float dp = DotProduct( frustum[f].normal, bbox[p] );

				if ( ( dp - frustum[f].dist ) < 0 )
				{
					mask |= ( 1 << f );
				}
			}

			aggregatemask &= mask;
		}

		if ( aggregatemask )
		{
			return true;
		}

		return false;
	}
}

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

void R_RotateAndScaleEntity (entity_t *e)
{
	vec3_t		scale_ofs;

	if (e->render_scale [0] == 0.0 && e->render_scale [1] == 0.0 && e->render_scale [2] == 0.0)
		ri.Sys_Error (ERR_FATAL, "Entity with model %s has 0, 0, 0 render_scale.\n", currentmodel->name);

	//	Nelno:	add x, y and z origin offsets here.
	scale_ofs [0] = (e->render_scale [0] * s_pmdl->org [0]) - s_pmdl->org [0];
	scale_ofs [1] = (e->render_scale [1] * s_pmdl->org [1]) - s_pmdl->org [1];
	scale_ofs [2] = (e->render_scale [2] * s_pmdl->org [2]) - s_pmdl->org [2];

	qglTranslatef (e->origin[0] - scale_ofs [0],  e->origin[1] - scale_ofs [1],  e->origin[2] - scale_ofs [2]);
	
    qglRotatef (e->angles[1],  0, 0, 1);
    qglRotatef (-e->angles[0],  0, 1, 0);
    qglRotatef (-e->angles[2],  1, 0, 0);

	qglScalef (e->render_scale [0], e->render_scale [1], e->render_scale [2]);
}

/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
	int			i;
	float		an;
	vec3_t		bbox[8];

	float		blend_colors [4] = {0.5, 0.5, 0.5, 0.5};

	s_pmdl = (dmdl_t *)currentmodel->extradata;
	s_psurface = (dsurface_t *) ((byte *) s_pmdl + s_pmdl->ofs_surfaces);

	if (e->flags & RF_NODRAW)
		return;

	if ( !( e->flags & RF_WEAPONMODEL ) )
	{
		if ( R_CullAliasModel( bbox, e ) )
			return;
	}

	ent_draw_count++;

	if ( e->flags & RF_WEAPONMODEL )
	{
		if ( r_lefthand->value == 2 || r_drawweapon->value == 0)
			return;
	}

	//
	// get lighting information
	//
	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
	{
		VectorClear (shadelight);
		if ( currententity->flags & RF_SHELL_RED )
			shadelight[0] = 1.0;
		if ( currententity->flags & RF_SHELL_GREEN )
			shadelight[1] = 1.0;
		if ( currententity->flags & RF_SHELL_BLUE )
			shadelight[2] = 1.0;
	}
	else if ( currententity->flags & RF_FULLBRIGHT )
	{
		for (i=0 ; i<3 ; i++)
			shadelight[i] = 1.0;
	}
	else
	{
		R_LightPoint (currententity->origin, shadelight);

		// player lighting hack for communication back to server
		// big hack!

		if ( currententity->flags & RF_WEAPONMODEL )
		{
			// pick the greatest component, which should be the same
			// as the mono value returned by software
			if (shadelight[0] > shadelight[1])
			{
				if (shadelight[0] > shadelight[2])
					r_lightlevel->value = 150*shadelight[0];
				else
					r_lightlevel->value = 150*shadelight[2];
			}
			else
			{
				if (shadelight[1] > shadelight[2])
					r_lightlevel->value = 150*shadelight[1];
				else
					r_lightlevel->value = 150*shadelight[2];
			}

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

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

			shadelight[0] = s;
			shadelight[1] = s;
			shadelight[2] = s;
		}
	}

	if ( currententity->flags & RF_MINLIGHT )
	{
		//	Nelno:	changed from 0.1 for testing
		for (i=0 ; i<3 ; i++)
			if (shadelight[i] > 0.3)
				break;
		if (i == 3)
		{
			shadelight[0] = 0.3;
			shadelight[1] = 0.3;
			shadelight[2] = 0.3;
		}
	}

	if ( currententity->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[i] * 0.8;
			shadelight[i] += scale;
			if (shadelight[i] < min)
				shadelight[i] = min;
		}
	}

	shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
	
	an = currententity->angles[1]/180*M_PI;
	shadevector[0] = cos(-an);
	shadevector[1] = sin(-an);
	shadevector[2] = 1;
	VectorNormalize (shadevector);

	//
	// locate the proper data
	//

	c_alias_polys += s_pmdl->num_tris;

	//
	// draw all the triangles
	//

	if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
		qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));

	///////////////////////////////////////////////////////////////////////////
	//	flip left-handed weapon models
	///////////////////////////////////////////////////////////////////////////

	if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
	{
		extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );

		qglMatrixMode( GL_PROJECTION );
		qglPushMatrix();
		qglLoadIdentity();

		qglScalef (-1, 1, 1);

	    MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height,  4,  8192);
		qglMatrixMode( GL_MODELVIEW );

		qglCullFace( GL_BACK );
	}

    qglPushMatrix ();
	e->angles[PITCH] = -e->angles[PITCH];	// sigh.

	R_RotateAndScaleEntity (e);

	e->angles[PITCH] = -e->angles[PITCH];	// sigh.

	//	show name of model for testing
//	R_GetProjectedVert (currententity->origin, &x, &y);
//	ri.dk_printxy (x, y, currentmodel->name);

	// draw it

	qglShadeModel (GL_SMOOTH);


	GL_TexEnv( GL_MODULATE );
	if ( (currententity->frame >= s_pmdl->num_frames) 
		|| (currententity->frame < 0) )
	{
		ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel: no such frame %d\n",
			currententity->frame);
		currententity->frame = 0;
		currententity->oldframe = 0;
	}

	if ( (currententity->oldframe >= s_pmdl->num_frames)
		|| (currententity->oldframe < 0))
	{
		ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel: no such oldframe %d\n",
			currententity->oldframe);
		currententity->frame = 0;
		currententity->oldframe = 0;
	}

	if ( !r_lerpmodels->value )
		currententity->backlerp = 0;
	GL_DrawAliasFrameLerp (s_pmdl, currententity->backlerp);

	GL_TexEnv( GL_REPLACE );

	qglShadeModel (GL_FLAT);

	qglPopMatrix ();

#if 0
	qglDisable( GL_CULL_FACE );
	qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
	qglDisable( GL_TEXTURE_2D );
	qglBegin( GL_TRIANGLE_STRIP );
	for ( i = 0; i < 8; i++ )
	{
		qglVertex3fv( bbox[i] );
	}
	qglEnd();
	qglEnable( GL_TEXTURE_2D );
	qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	qglEnable( GL_CULL_FACE );
#endif

	if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
	{
		qglMatrixMode( GL_PROJECTION );
		qglPopMatrix();
		qglMatrixMode( GL_MODELVIEW );
		qglCullFace( GL_FRONT );
	}

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

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


	if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL)))
	{
		qglPushMatrix ();
		R_RotateForEntity (e);
		qglDisable (GL_TEXTURE_2D);
		qglEnable (GL_BLEND);
		qglColor4f (0,0,0,0.5);
		GL_DrawAliasShadow (s_pmdl, currententity->frame );
		qglEnable (GL_TEXTURE_2D);
		qglDisable (GL_BLEND);
		qglPopMatrix ();
	}

	qglColor4f (1,1,1,1);
}