/*
=============================================================
  ALIAS MODELS
=============================================================
*/

#include "quakedef.h"

#define NUMVERTEXNORMALS	162

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

extern model_t *player_models[NUM_CLASSES];

static qboolean AlwaysDrawModel;

vec3_t	lightcolor; // LordHavoc: used by model rendering
vec3_t	shadevector;
float	shadelight, ambientlight;
float	shadelightcolor[4];
float	ambient[4], diffuse[4];
float	model_constant_alpha; 

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

float	*shadedots = r_avertexnormal_dots[0];
// light lerping - pox@planetquake.com
float   *shadedots2 = r_avertexnormal_dots[0];
float   lightlerpoffset;

int	lastposenum;
int lastposenum0;

extern  float   lerp_mody;

//aliaslerp: lerp data
typedef struct {
	short pose1;
	short pose2;
	float blend;
	vec3_t origin;
	vec3_t angles;
} lerpdata_t;

//cvar_t  r_nolerp_list = {"r_nolerp_list", "progs/flame.mdl,progs/flame2.mdl"};

//==========================================================================
//
// R_RotateForEntity
//
//==========================================================================

void R_RotateForEntity (entity_t *e)
{
    glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);

    glRotatef (e->angles[1],  0, 0, 1);
    glRotatef (-e->angles[0],  0, 1, 0);
    glRotatef (-e->angles[2],  1, 0, 0);
}

//==========================================================================
// R_RotateForEntity2
// Same as R_RotateForEntity(), but checks for EF_ROTATE and modifies
// yaw appropriately.
//==========================================================================

static void R_RotateForEntity2(entity_t *e)
{
	float	forward;
	float	yaw, pitch;
	vec3_t			angles;

	glTranslatef(e->origin[0], e->origin[1], e->origin[2]);

	if (e->model->flags & EF_FACE_VIEW)
	{
		VectorSubtract(e->origin,r_origin,angles);
		VectorSubtract(r_origin,e->origin,angles);
		VectorNormalize(angles);

		if (angles[1] == 0 && angles[0] == 0)
		{
			yaw = 0;
			if (angles[2] > 0)
				pitch = 90;
			else
				pitch = 270;
		}
		else
		{
			yaw = (int) (atan2(angles[1], angles[0]) * 180 / M_PI);
			if (yaw < 0)
				yaw += 360;

			forward = sqrt (angles[0]*angles[0] + angles[1]*angles[1]);
			pitch = (int) (atan2(angles[2], forward) * 180 / M_PI);
			if (pitch < 0)
				pitch += 360;
		}

		angles[0] = pitch;
		angles[1] = yaw;
		angles[2] = 0;

		glRotatef(-angles[0], 0, 1, 0);
		glRotatef(angles[1], 0, 0, 1);
//		glRotatef(-angles[2], 1, 0, 0);
		glRotatef(-e->angles[2], 1, 0, 0);
	}
	else 
	{
		if (e->model->flags & EF_ROTATE)
		{
			glRotatef(anglemod((e->origin[0]+e->origin[1])*0.8
				+(108*cl.time)), 0, 0, 1);
		}
		else
		{
			glRotatef(e->angles[1], 0, 0, 1);
		}
		glRotatef(-e->angles[0], 0, 1, 0);
		glRotatef(-e->angles[2], 1, 0, 0);
	}
}

static void R_RotateForLerpEntity(entity_t *e, lerpdata_t *lerpdata)
{
	float   forward;
	float   yaw, pitch;
	vec3_t	angles;

	glTranslatef(lerpdata->origin[0], lerpdata->origin[1], lerpdata->origin[2]);

	if (e->model->flags & EF_FACE_VIEW)
	{
		VectorSubtract(lerpdata->origin,r_origin,angles);
		VectorSubtract(r_origin,lerpdata->origin,angles);
		VectorNormalize(angles);

		if (angles[1] == 0 && angles[0] == 0)
		{
			yaw = 0;
			if (angles[2] > 0)
				pitch = 90;
			else
				pitch = 270;
		}
		else
		{
			yaw = (int) (atan2(angles[1], angles[0]) * 180 / M_PI);
			if (yaw < 0)
				yaw += 360;

			forward = sqrt (angles[0]*angles[0] + angles[1]*angles[1]);
			pitch = (int) (atan2(angles[2], forward) * 180 / M_PI);
			if (pitch < 0)
				pitch += 360;
		}

		angles[0] = pitch;
		angles[1] = yaw;
		angles[2] = 0;

		glRotatef(-angles[0], 0, 1, 0);
		glRotatef(angles[1], 0, 0, 1);
//              glRotatef(-angles[2], 1, 0, 0);
		glRotatef(-e->angles[2], 1, 0, 0);
	}
	else 
	{
		if (e->model->flags & EF_ROTATE)
		{
			glRotatef(anglemod((lerpdata->origin[0]+lerpdata->origin[1])*0.8+(108*cl.time)), 0, 0, 1);
		}
		else
		{
			glRotatef(lerpdata->angles[1], 0, 0, 1);
		}
		glRotatef(-lerpdata->angles[0], 0, 1, 0);
		glRotatef(-lerpdata->angles[2], 1, 0, 0);
	}
}

/*
=============
R_BlendedRotateForEntity
fenix@io.com: model transform interpolation
=============
*/

/*
void R_BlendedRotateForEntity (entity_t *e, int shadow)
{
    float timepassed;
    float blend;
    vec3_t d;
    int i;

    // positional interpolation
    timepassed = (realtime - e->translate_start_time) * lerp_mody;

    if (e->translate_start_time == 0 || timepassed > 1)
    {
        e->translate_start_time = realtime;
        VectorCopy (e->origin, e->origin1);
        VectorCopy (e->origin, e->origin2);
    }

    if (!VectorCompare (e->origin, e->origin2))
    {
        e->translate_start_time = realtime;
        VectorCopy (e->origin2, e->origin1);
        VectorCopy (e->origin,  e->origin2);
        blend = 0;
    }
    else
    {
        blend =  timepassed / 0.1;

        if (cl.paused || blend > 1) blend = 1;
    }

    VectorSubtract (e->origin2, e->origin1, d);

    glTranslatef (e->origin1[0] + (blend * d[0]),
        e->origin1[1] + (blend * d[1]),
        e->origin1[2] + (blend * d[2]));

    // orientation interpolation (Euler angles, yuck!)
    timepassed = (realtime - e->rotate_start_time) * lerp_mody;

    if (e->rotate_start_time == 0 || timepassed > 1)
    {
        e->rotate_start_time = realtime;
        VectorCopy (e->angles, e->angles1);
        VectorCopy (e->angles, e->angles2);
    }

    if (!VectorCompare (e->angles, e->angles2))
    {
        e->rotate_start_time = realtime;
        VectorCopy (e->angles2, e->angles1);
        VectorCopy (e->angles,  e->angles2);
        blend = 0;
    }
    else
    {
        blend = timepassed / 0.1;
 
        if (cl.paused || blend > 1) blend = 1;
    }

    VectorSubtract (e->angles2, e->angles1, d);

    // always interpolate along the shortest path
    for (i = 0; i < 3; i++) 
    {
        if (d[i] > 180) 
            d[i] -= 360;
        else if (d[i] < -180) d[i] += 360;
    }

    glRotatef (e->angles1[1] + ( blend * d[1]),  0, 0, 1);

    if (!shadow)
    {
        glRotatef (-e->angles1[0] + (-blend * d[0]),  0, 1, 0);
        glRotatef ( e->angles1[2] + ( blend * d[2]),  1, 0, 0);
    }
}
*/

/*
=============
GL_DrawAliasFrame
=============
*/
extern float RTint[256],GTint[256],BTint[256];

void GL_DrawAliasFrame (aliashdr_t *paliashdr, lerpdata_t lerpdata)
{
	float 	l;
	trivertx_t	*verts1, *verts2;
	int		*order;
	int		count;
	float	r,g,b;
	qboolean lerping;
	float	blend, iblend;

	if (lerpdata.pose1 != lerpdata.pose2)
	{
		lerping = true;
		verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
		verts2  = verts1;
		verts1 += lerpdata.pose1 * paliashdr->poseverts;
		verts2 += lerpdata.pose2 * paliashdr->poseverts;
		blend = lerpdata.blend;
		iblend = 1.0f - blend;
	}
	else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled
	{
		lerping = false;
		verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
		verts1 += lerpdata.pose1 * paliashdr->poseverts;
	}

	order = (int *)((byte *)paliashdr + paliashdr->commands);

	if (currententity->colorshade)
	{
		r = RTint[currententity->colorshade];
		g = GTint[currententity->colorshade];
		b = BTint[currententity->colorshade];
	}
	else
		r = g = b = 1;

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

		do
		{
        	// texture coordinates come from the draw list
			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
			order += 2;

			// normals and vertexes come from the frame list
            if (gl_lightmap_format == GL_RGBA)
                {
                if (r_lerp_alias.value == 1)
                    {
                    // light lerping - pox@planetquake.com
                    float l1, l2, diff;

					if (lerping)
					{
						l1 = shadedots[verts1->lightnormalindex]*iblend+shadedots[verts2->lightnormalindex]*blend;
						l2 = shadedots2[verts1->lightnormalindex]*iblend+shadedots2[verts2->lightnormalindex]*blend;
					}
					else
					{
						l1 = shadedots[verts1->lightnormalindex];
						l2 = shadedots2[verts1->lightnormalindex];
					}

                    if (l1 != l2)
                        {
                        if (l1 > l2) 
                            {
                             diff = l1 - l2;
                             diff *= lightlerpoffset;
                             l = l1 - diff;
                            } 
                        else {
                             diff = l2 - l1;
                             diff *= lightlerpoffset;
                             l = l1 + diff;
                            }

                        }
                    else
                        l = l1;
                    // light contrast - pox@planetquake.com
                    l *= l;
                    }
                else 
				{
					if (lerping)
					{
						l = shadedots[verts1->lightnormalindex]*iblend+shadedots[verts2->lightnormalindex]*blend;
					}
					else
						l = shadedots[verts1->lightnormalindex];
				}

                glColor4f (l * shadelightcolor[0], l * shadelightcolor[1], l * shadelightcolor[2], model_constant_alpha);
            }
            else
            {
                if (r_lerp_alias.value == 1)
                    {
                    // light lerping - pox@planetquake.com
                    float l1, l2, diff;

					if (lerping)
					{
						l1 = (shadedots[verts1->lightnormalindex]*iblend+shadedots[verts2->lightnormalindex]*blend) * shadelight;
						l2 = (shadedots2[verts1->lightnormalindex]*iblend+shadedots2[verts2->lightnormalindex]*blend) * shadelight;
					}
					else
					{
						l1 = shadedots[verts1->lightnormalindex] * shadelight;
						l2 = shadedots2[verts1->lightnormalindex] * shadelight;
					}

                    if (l1 != l2)
                        {
                        if (l1 > l2) 
                            {
                             diff = l1 - l2;
                             diff *= lightlerpoffset;
                             l = l1 - diff;
                            } 
                        else {
                             diff = l2 - l1;
                             diff *= lightlerpoffset;
                             l = l1 + diff;
                            }

                        }
                    else
                        l = l1;
                    // light contrast - pox@planetquake.com
                    l *= l;
                    }
                else 
				{
					if (lerping)
					{
						l = (shadedots[verts1->lightnormalindex]*iblend+shadedots[verts2->lightnormalindex]*blend) * shadelight;
					}
					else
						l = shadedots[verts1->lightnormalindex] * shadelight;
				}
                
                glColor4f (r*l, g*l, b*l, model_constant_alpha);
            }

			if (lerping)
			{
				glVertex3f (verts1->v[0]*iblend + verts2->v[0]*blend,
				verts1->v[1]*iblend + verts2->v[1]*blend,
				verts1->v[2]*iblend + verts2->v[2]*blend);
				verts1++;
				verts2++;
			}
			else
			{
				glVertex3f (verts1->v[0], verts1->v[1], verts1->v[2]);
				verts1++;
			}

		} while (--count);

		glEnd ();
	}
}



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

// muff@yakko.globalnet.co.uk - 17 Mar 2000
trace_t        steptrace, downtrace;
vec3_t         dest,stop, downmove;

void GL_DrawAliasShadow (aliashdr_t *paliashdr, lerpdata_t lerpdata)
{
	trivertx_t	*verts1, *verts2;
	int		*order;
	vec3_t	point;
	float	height, lheight;
	int		count;
        
	qboolean lerping;
	float   blend, iblend;

    float        s1,c1; //this will store the sin and cos values as they are used so heavily
    //end of muff

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

	if (lerpdata.pose1 != lerpdata.pose2)
	{
		lerping = true;
		verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
		verts2  = verts1;
		verts1 += lerpdata.pose1 * paliashdr->poseverts;
		verts2 += lerpdata.pose2 * paliashdr->poseverts;
		blend = lerpdata.blend;
		iblend = 1.0f - blend;
	}
	else
	{
		lerping = false;
		verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
		verts1 += lerpdata.pose1 * paliashdr->poseverts;
	}
	order = (int *)((byte *)paliashdr + paliashdr->commands);

	//height = -lheight + 1.0;
    height = -lheight + 0.1f;	// lowered shadows to ground more - MrG
    
    // better shadowing, now takes angle of ground into account    
    VectorCopy (currententity->origin, downmove);
    downmove[2] = downmove[2] - 4096;
    memset (&downtrace, 0, sizeof(downtrace));
    SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, currententity->origin, downmove, &downtrace);

    // calculate the all important angles to keep speed up
    s1 = sin( currententity->angles[1] / 180*M_PI);
    c1 = cos( currententity->angles[1] / 180*M_PI);
    // end of muff

    // Stencil shadows - MrG
    if (have_stencil == true && gl_stencilshadow.value != 0) {
	    glEnable(GL_STENCIL_TEST);
	    glStencilFunc(GL_EQUAL,1,2);
	    glStencilOp(GL_KEEP,GL_KEEP,GL_INCR);
        }
    // End Stencil shadows - MrG
    glDepthMask(0);

	while (1)
	{

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

		do
		{
			// texture coordinates come from the draw list
			// (skipped for shadows) glTexCoord2fv ((float *)order);
			order += 2;

			if (lerping)
			{
				// normals and vertexes come from the frame list
				point[0] = (verts1->v[0]*iblend + verts2->v[0]*blend) * paliashdr->scale[0] + paliashdr->scale_origin[0];
				point[1] = (verts1->v[1]*iblend + verts2->v[1]*blend) * paliashdr->scale[1] + paliashdr->scale_origin[1];
				point[2] = (verts1->v[1]*iblend + verts2->v[1]*blend) * paliashdr->scale[2] + paliashdr->scale_origin[2];

				point[0] -= shadevector[0]*(point[0]); 
				point[1] -= shadevector[1]*(point[1]);
				point[2] -= shadevector[2]*(point[2]);

				//drop it down to floor
				point[2] = point[2] - (currententity->origin[2] - downtrace.endpos[2]) ;
				// now adjust the point with respect to all the normals of the tracepoint
				// I'm probably missing an easy piece of maths to do this
				// it reads messy, but works ;)
            
				point[2] +=		((point[1] * (s1 * downtrace.plane.normal[0])) - (point[0] * (c1 * downtrace.plane.normal[0])) - 
								(point[0] * (s1 * downtrace.plane.normal[1])) - (point[1] * (c1 * downtrace.plane.normal[1]))) +
								((1.0 - downtrace.plane.normal[2])*20) + 0.2 ;
				//end of muff
                                
				glVertex3fv (point);
				verts1++;
				verts2++;
			}
			else
			{
				// normals and vertexes come from the frame list
				point[0] = verts1->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
				point[1] = verts1->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
				point[2] = verts1->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];

				point[0] -= shadevector[0]*(point[0]); 
				point[1] -= shadevector[1]*(point[1]);
				point[2] -= shadevector[2]*(point[2]);

				//drop it down to floor
				point[2] = point[2] - (currententity->origin[2] - downtrace.endpos[2]) ;
				// now adjust the point with respect to all the normals of the tracepoint
				// I'm probably missing an easy piece of maths to do this
				// it reads messy, but works ;)

				point[2] +=		((point[1] * (s1 * downtrace.plane.normal[0])) - (point[0] * (c1 * downtrace.plane.normal[0])) - 
								(point[0] * (s1 * downtrace.plane.normal[1])) - (point[1] * (c1 * downtrace.plane.normal[1]))) +
								((1.0 - downtrace.plane.normal[2])*20) + 0.2 ;
				//end of muff

				glVertex3fv (point);
				verts1++;
			}

		} while (--count);

		glEnd ();
	}	
    glDepthMask(1);


    if (have_stencil == true && gl_stencilshadow.value != 0) 
        glDisable(GL_STENCIL_TEST); // Stencil shadows - MrG

}

/*
=================
R_SetupAliasFrame

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

void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
{
	int				pose, numposes;
	entity_t		*e = currententity;

	if ((frame >= paliashdr->numframes) || (frame < 0))
	{
		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
		frame = 0;
	}

	pose = paliashdr->frames[frame].firstpose;
	numposes = paliashdr->frames[frame].numposes;

	if (numposes > 1)
	{
		e->lerptime = paliashdr->frames[frame].interval;
		pose += (int)(cl.time / e->lerptime) % numposes;
	}
	else
		e->lerptime = (float) r_interpolate_time.value;

	if (e->lerpflags & LERP_RESETANIM) //kill any lerp in progress
	{
		e->lerpstart = 0;
		e->previouspose = pose;
		e->currentpose = pose;
		e->lerpflags -= LERP_RESETANIM;
	}
	else if (e->currentpose != pose) // pose changed, start new lerp
	{
		if (e->lerpflags & LERP_RESETANIM2) //defer lerping one more time
		{
			e->lerpstart = 0;
			e->previouspose = pose;
			e->currentpose = pose;
			e->lerpflags -= LERP_RESETANIM2;
		}
		else
		{
			e->lerpstart = cl.time;
			e->previouspose = e->currentpose;
			e->currentpose = pose;
		}
	}

	//set up values
	if (r_interpolate_alias.value && !(e->model->flags & MOD_NOLERP))
	{
		if (e->lerpflags & LERP_FINISH && numposes == 1)
			lerpdata->blend = CLAMP (0, (cl.time - e->lerpstart) / (e->lerpfinish - e->lerpstart), 1);
		else
			lerpdata->blend = CLAMP (0, (cl.time - e->lerpstart) / e->lerptime, 1);
                
		lerpdata->pose1 = e->previouspose;
		lerpdata->pose2 = e->currentpose;
	}
	else //don't lerp
	{
		lerpdata->blend = 1;
		lerpdata->pose1 = pose;
		lerpdata->pose2 = pose;
	}

	//GL_DrawAliasFrame (paliashdr, lerpdata);
}


/*
=============================
		Alias chrome
=============================
*/

void GL_DrawAliasChrome (aliashdr_t *paliashdr, lerpdata_t lerpdata)
{
	//jeank
	trivertx_t	*verts1, *verts2;
	int			*order;
	int			count;
   	vec3_t		nv, lerpvert;
	vec3_t		viewer, reflected, normal;
	float		d;
	vec3_t		playerorg, angles, origin;
	qboolean	lerping;
	float		blend, iblend;

	//jeank	
	float Xdeform=0, Ydeform=0, XdeformMul=1, YdeformMul=1;
	//chrome tunes
	float chromealpha;

	if (!currententity->model->chromeflag)
		return;

	if (!modelchrometexture && !modelchrometexture2)
		return;

	glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); 
	if(modelchrometexture)
		GL_Bind (modelchrometexture);
	else
		GL_Bind (modelchrometexture2);

	//=====================================
	//Presets for different kinds of entity
	//=====================================
	if	(currententity->model->chromeflag & CR_POWERUPROTATED)	//Power book, boots, ect.
	{
		if (!gl_power_chrome.value)
			return;
		chromealpha = gl_power_chrome.value;
		XdeformMul = gl_powerup_chromescale.value;
		YdeformMul = gl_powerup_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_WEAPONROTATED)
	{
		if (!gl_weapon_chrome.value)
			return;
		chromealpha = gl_weapon_chrome.value;
		XdeformMul = gl_weapon_chromescale.value;
		YdeformMul = gl_weapon_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_HEALTS)
	{
		if (!gl_bonus_chrome.value)
			return;
		if (modelchrometexture2)
				GL_Bind(modelchrometexture2);
		chromealpha = gl_bonus_chrome.value;
		XdeformMul = gl_health_chromescale.value;
		YdeformMul = gl_health_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_BLUMANA)
	{
		if (!gl_bonus_chrome.value)
			return;
		chromealpha = gl_bonus_chrome.value;
		XdeformMul = gl_blumana_chromescale.value;
		YdeformMul = gl_blumana_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_GRNMANA)
	{
		if (!gl_bonus_chrome.value)
			return;
		if (modelchrometexture2)
				GL_Bind(modelchrometexture2);
		chromealpha = gl_bonus_chrome.value;
		XdeformMul = gl_grnmana_chromescale.value;
		YdeformMul = gl_grnmana_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_REDMANA)
	{
		if (!gl_bonus_chrome.value)
			return;
		chromealpha = gl_bonus_chrome.value;
		XdeformMul = gl_redmana_chromescale.value;
		YdeformMul = gl_redmana_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_BONUSROTATED)
	{
		if (!gl_bonus_chrome.value)
			return;
		chromealpha = gl_bonus_chrome.value;
		XdeformMul = gl_bonus_chromescale.value;
		YdeformMul = gl_bonus_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_MONSTER)
	{
		if (!gl_monster_chrome.value)
			return;
		chromealpha = gl_monster_chrome.value;
		XdeformMul = gl_monster_chromescale.value;
		YdeformMul = gl_monster_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_MONSTERTOXIC)
	{
		if (!gl_monster_chrome.value)
			return;
		chromealpha = gl_monster_chrome.value;
		if (modelchrometexture2)
				GL_Bind(modelchrometexture2);
		Xdeform = 0.5+0.5*sin(realtime*0.1);
		Ydeform = 0.5+0.5*cos(realtime*0.1);	
		XdeformMul = gl_monstertoxic_chromescale.value;
		YdeformMul = gl_monstertoxic_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_MONSTERSHINED)
	{
		if (!gl_monster_chrome.value)
			return;
		glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); 
		chromealpha = gl_monster_chrome.value;
		XdeformMul = gl_monstershined_chromescale.value;
		YdeformMul = gl_monstershined_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_MONSTERWATER)
	{
		if (!gl_monster_chrome.value)
			return;
		chromealpha = gl_monster_chrome.value;
		if (modelchrometexture2)
				GL_Bind(modelchrometexture2);
		Xdeform = 0.5+0.5*sin(realtime*0.2);
		Ydeform = 0.5+0.5*cos(realtime*0.2);	
		XdeformMul = gl_monsterwater_chromescale.value;
		YdeformMul = gl_monsterwater_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_STATUE)
	{
		if (!gl_interior_chrome.value)
			return;
		chromealpha = gl_interior_chrome.value;
		XdeformMul = gl_statue_chromescale.value;
		YdeformMul = gl_statue_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_ARCYELLOW)
	{
		if (!gl_interior_chrome.value)
			return;
		chromealpha = gl_interior_chrome.value;
		XdeformMul = gl_arcyellow_chromescale.value;
		YdeformMul = gl_arcyellow_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_INTERIOR)
	{
		if (!gl_interior_chrome.value)
			return;
		chromealpha = gl_interior_chrome.value;
		XdeformMul = gl_interior_chromescale.value;
		YdeformMul = gl_interior_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_WEAPON)
	{
		if (!gl_player_chrome.value)
			return;
		chromealpha = gl_player_chrome.value;
		XdeformMul = gl_playerwpn_chromescale.value;
		YdeformMul = gl_playerwpn_chromescale.value;
	}
	else if	(currententity->model->chromeflag & CR_PAZZLES)
	{
		if (!gl_power_chrome.value)
			return;
		chromealpha = gl_power_chrome.value;
		XdeformMul = gl_pazzles_chromescale.value;
		YdeformMul = gl_pazzles_chromescale.value;	
	}

	if (lerpdata.pose1 != lerpdata.pose2)
	{
		lerping = true;
		verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
		verts2  = verts1;
		verts1 += lerpdata.pose1 * paliashdr->poseverts;
		verts2 += lerpdata.pose2 * paliashdr->poseverts;
		blend = lerpdata.blend;
		iblend = 1.0f - blend;
	}
	else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled
	{
		lerping = false;
		verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
		verts1 += lerpdata.pose1 * paliashdr->poseverts;
	}

	order = (int *)((byte *)paliashdr + paliashdr->commands);

	//Set active entity angles and origins
	angles[PITCH] = currententity->angles[PITCH];
	angles[ROLL] = currententity->angles[ROLL];
	origin[0]=currententity->origin[0];
	origin[1]=currententity->origin[1];
	if(currententity->model->flags & EF_ROTATE)
	{
		//rotate
		angles[YAW] = anglemod((currententity->origin[0]+currententity->origin[1])*0.8+(108*cl.time));
		//floating effect
		origin[2]=currententity->origin[2]+sin(currententity->origin[0]+currententity->origin[1]+(cl.time*3))*5.5;
	}
	else
	{
		angles[YAW] = currententity->angles[YAW];
		origin[2]=currententity->origin[2];
	}

	//Modify player org
	//============================
	//VectorCopy(r_refdef.vieworg, playerorg); 
	VectorCopy(r_origin, playerorg); 

	//if	(!(currententity->model->chromeflag & CR_WEAPON || currententity->model->flags & EF_ROTATE))
	if	(!(currententity->model->chromeflag & CR_WEAPON || currententity->model->chromeflag & CR_HEALTS || currententity->model->chromeflag & CR_REDMANA))
		VectorSubtract (playerorg, origin, playerorg);


	if (angles[PITCH] || angles[YAW] || angles[ROLL])
	{
		vec3_t	temp;
		vec3_t	forward, right, up;

		AngleVectors (angles, forward, right, up);
		VectorCopy (playerorg, temp);
		playerorg[PITCH] = DotProduct (temp, forward);
		playerorg[YAW] = -DotProduct (temp, right);
		playerorg[ROLL] = DotProduct (temp, up);
	}

	glColor4f( chromealpha, chromealpha, chromealpha, chromealpha);
	glEnable (GL_BLEND);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, 0.5);

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

		do
		{
			//Normal
			if (lerping)
			{
				normal[0]=r_avertexnormals[verts1->lightnormalindex][0]*iblend+r_avertexnormals[verts2->lightnormalindex][0]*blend;
				normal[1]=r_avertexnormals[verts1->lightnormalindex][1]*iblend+r_avertexnormals[verts2->lightnormalindex][1]*blend;
				normal[2]=r_avertexnormals[verts1->lightnormalindex][2]*iblend+r_avertexnormals[verts2->lightnormalindex][2]*blend;
				lerpvert[0] = verts1->v[0]*iblend+verts2->v[0]*blend;
				lerpvert[1] = verts1->v[1]*iblend+verts2->v[1]*blend;
				lerpvert[2] = verts1->v[2]*iblend+verts2->v[2]*blend;
				//VectorNormalize (normal);
				VectorSubtract (playerorg, lerpvert, viewer);
			}
			else
			{
				normal[0]=r_avertexnormals[verts1->lightnormalindex][0];
				normal[1]=r_avertexnormals[verts1->lightnormalindex][1];
				normal[2]=r_avertexnormals[verts1->lightnormalindex][2];
				//VectorNormalize (normal);
				VectorSubtract (playerorg, verts1->v, viewer);
			}

			VectorNormalize (viewer); 
			d = DotProduct (normal, viewer);
			
			reflected[0] = normal[0]*2*d - viewer[0]*0.2;
			reflected[1] = normal[1]*2*d - viewer[1]*0.2;
			reflected[2] = normal[2]*2*d - viewer[2]*0.2;
			//VectorNormalize (reflected);

			nv[0] = (0.5 + reflected[1] * 0.5)*XdeformMul+Xdeform;
			nv[1] = (0.5 - reflected[2] * 0.5)*YdeformMul+Ydeform;

			//nv[0] = (0.5 + 0.5*(reflected[1]*normal[2] + reflected[0]*normal[1] + reflected[2]*normal[0]))*XdeformMul+Xdeform;
			//nv[1] = (0.5 - 0.5*(reflected[0]*abs(normal[2]) + reflected[2]*abs(normal[1]) + reflected[1]*abs(normal[0])))*YdeformMul+Ydeform;
			glTexCoord2f (nv[0], nv[1]);
			
			order += 2;

			if (lerping)
			{
				glVertex3f (verts1->v[0]*iblend + verts2->v[0]*blend,
							verts1->v[1]*iblend + verts2->v[1]*blend,
							verts1->v[2]*iblend + verts2->v[2]*blend);
				verts1++;
				verts2++;
			}
			else
			{
				glVertex3f (verts1->v[0], verts1->v[1], verts1->v[2]);
				verts1++;
			}

		} while (--count);
		glEnd ();
	}

	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable (GL_BLEND);
	/*
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	*/

	GL_Bind ( paliashdr->gl_texturenum[currententity->skinnum]);
}


/*
=================
R_SetupEntityTransform -- johnfitz -- set up transform part of lerpdata
=================
*/
void R_SetupEntityTransform (entity_t *e, lerpdata_t *lerpdata)
{
	float blend;
	vec3_t d;
	int i;

	// if LERP_RESETMOVE, kill any lerps in progress
	if (e->lerpflags & LERP_RESETMOVE)
	{
		e->movelerpstart = 0;
		VectorCopy (e->origin, e->previousorigin);
		VectorCopy (e->origin, e->currentorigin);
		VectorCopy (e->angles, e->previousangles);
		VectorCopy (e->angles, e->currentangles);
		e->lerpflags -= LERP_RESETMOVE;
	}
	else if (!VectorCompare (e->origin, e->currentorigin) || !VectorCompare (e->angles, e->currentangles)) // origin/angles changed, start new lerp
	{
		e->movelerpstart = cl.time;
		VectorCopy (e->currentorigin, e->previousorigin);
		VectorCopy (e->origin,  e->currentorigin);
		VectorCopy (e->currentangles, e->previousangles);
		VectorCopy (e->angles,  e->currentangles);
	}

	//set up values
	if (r_interpolate_alias.value && e != &cl.viewent && e->lerpflags & LERP_MOVESTEP)
	{
		if (e->lerpflags & LERP_FINISH)
			blend = CLAMP (0, (cl.time - e->movelerpstart) / (e->lerpfinish - e->movelerpstart), 1);
		else
			blend = CLAMP (0, (cl.time - e->movelerpstart) / 0.1, 1);

		//translation
		VectorSubtract (e->currentorigin, e->previousorigin, d);
		lerpdata->origin[0] = e->previousorigin[0] + d[0] * blend;
		lerpdata->origin[1] = e->previousorigin[1] + d[1] * blend;
		lerpdata->origin[2] = e->previousorigin[2] + d[2] * blend;

		//rotation
		VectorSubtract (e->currentangles, e->previousangles, d);
		for (i = 0; i < 3; i++)
		{
			if (d[i] > 180)  d[i] -= 360;
			if (d[i] < -180) d[i] += 360;
		}
		lerpdata->angles[0] = e->previousangles[0] + d[0] * blend;
		lerpdata->angles[1] = e->previousangles[1] + d[1] * blend;
		lerpdata->angles[2] = e->previousangles[2] + d[2] * blend;
	}
	else //don't lerp
	{
		VectorCopy (e->origin, lerpdata->origin);
		VectorCopy (e->angles, lerpdata->angles);
	}
}

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

=================
*/
void R_DrawAliasModel (entity_t *e)
{
	int			i;
	int			lnum;
	vec3_t		dist;
	float		add;
	model_t		*clmodel;
	vec3_t		mins, maxs;
	aliashdr_t	*paliashdr;
	float		an;
	static float	tmatrix[3][4];
	float entScale;
	float xyfact;
	float zfact;
	qpic_t		*stonepic;
	glpic_t			*gl;
	char temp[40];
	int mls;
    int* lpc;
	vec3_t		adjust_origin;
    float       shadowalpha;
	lerpdata_t      lerpdata;

	clmodel = currententity->model;

	VectorAdd (currententity->origin, clmodel->mins, mins);
	VectorAdd (currententity->origin, clmodel->maxs, maxs);

	if (!AlwaysDrawModel && R_CullBox (mins, maxs))
		return;

    if(!AlwaysDrawModel)
    {
	VectorCopy (currententity->origin, r_entorigin);
	VectorSubtract (r_origin, r_entorigin, modelorg);

	VectorCopy(currententity->origin, adjust_origin);
	adjust_origin[2] += (currententity->model->mins[2] + currententity->model->maxs[2]) / 2;
	ambientlight = shadelight = R_LightPoint (adjust_origin);

    if (gl_lightmap_format == GL_RGBA)
        {
        // get lighting information
        lpc = R_LightPointColour (adjust_origin);
        shadelightcolor[0] = (float) lpc[0];
        shadelightcolor[1] = (float) lpc[1];
        shadelightcolor[2] = (float) lpc[2];
        shadelightcolor[3] = (float) lpc[3];
        ambientlight = shadelightcolor[3];
        }
    else 
        ambientlight = shadelight = R_LightPoint (adjust_origin);

    }
    
	//
	// get lighting information
	//
        
	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
	{
		if (cl_dlights[lnum].die >= cl.time)
		{
			VectorSubtract (currententity->origin, cl_dlights[lnum].origin, dist);
			add = cl_dlights[lnum].radius - Length(dist);

			if (add > 0)
				ambientlight += add;

            if (add > 0)
			{
	            shadelightcolor[0] += (cl_dlights[lnum].color[0] * add);
                shadelightcolor[1] += (cl_dlights[lnum].color[1] * add);
                shadelightcolor[2] += (cl_dlights[lnum].color[2] * add);
                shadelightcolor[3] += add;
			}

		}
	}

	// clamp lighting so it doesn't overbright as much
	if (ambientlight > 128)
		ambientlight = 128;
	if (ambientlight + shadelight > 192)
		shadelight = 192 - ambientlight;

    if (clmodel->ex_flags & XF_FULLBRIGHT)
            shadelightcolor[0] = shadelightcolor[1] = shadelightcolor[2] = 256;	

	mls = currententity->drawflags&MLS_MASKIN;
	if(currententity->model->flags&EF_ROTATE)
	{
		shadelightcolor[0] = shadelightcolor[1] = shadelightcolor[2] =ambientlight = shadelight =
			60+34+sin(currententity->origin[0]+currententity->origin[1]
				+(cl.time*3.8))*34;
	}
	else if (mls == MLS_ABSLIGHT)
	{
		shadelightcolor[0] = shadelightcolor[1] = shadelightcolor[2] = ambientlight = shadelight = currententity->abslight;
	}
	else if (mls != MLS_NONE)
	{ // Use a model light style (25-30)
		shadelightcolor[0] = shadelightcolor[1] = shadelightcolor[2] = ambientlight = shadelight = d_lightstylevalue[24+mls]/2;
	}

    if (r_lerp_alias.value == 1)
       {
       // light lerping - pox@planetquake.com
       float ang_ceil, ang_floor;

        // add pitch angle so lighting changes when looking up/down (mainly for viewmodel)
       lightlerpoffset = (e->angles[1]+e->angles[0]) * (SHADEDOT_QUANT / 360.0);

       ang_ceil = ceil(lightlerpoffset);
       ang_floor = floor(lightlerpoffset);

       lightlerpoffset = ang_ceil - lightlerpoffset;

       shadedots = r_avertexnormal_dots[(int)ang_ceil & (SHADEDOT_QUANT - 1)];
       shadedots2 = r_avertexnormal_dots[(int)ang_floor & (SHADEDOT_QUANT - 1)];
       } 
	else 
        shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
	
    shadelight = shadelight / 200.0;
	VectorScale(lightcolor, 1.0f / 200.0f, lightcolor);
    VectorScale(shadelightcolor, 1.0f / 200.0f, shadelightcolor);

    
    if (r_lerp_alias.value == 1)
        {
        // light lerping - pox@planetquake.com
        shadelight = (shadelight + currententity->last_shadelight)/2;
        currententity->last_shadelight = shadelight;
        
        if ( gl_lightmap_format == GL_RGBA)
            {
            shadelightcolor[0] = (shadelightcolor[0]+currententity->last_shadelightcolor[0])/2;
            shadelightcolor[1] = (shadelightcolor[1]+currententity->last_shadelightcolor[1])/2;
            shadelightcolor[2] = (shadelightcolor[2]+currententity->last_shadelightcolor[2])/2;
            shadelightcolor[3] = (shadelightcolor[3]+currententity->last_shadelightcolor[3])/2;
            
            currententity->last_shadelightcolor[0] = shadelightcolor[0];       
            currententity->last_shadelightcolor[1] = shadelightcolor[1];       
            currententity->last_shadelightcolor[2] = shadelightcolor[2];       
            currententity->last_shadelightcolor[3] = shadelightcolor[3];       
            }   
        }
   
   
	
    an = e->angles[1]/180*M_PI;
	shadevector[0] = cos(-an);
	shadevector[1] = sin(-an);
	shadevector[2] = 1;
	VectorNormalize (shadevector);

	//
	// locate the proper data
	//
	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);

	c_alias_polys += paliashdr->numtris;

	//
	// draw all the triangles
	//

	//jeanklerp
	R_SetupAliasFrame (paliashdr, currententity->frame, &lerpdata);
	R_SetupEntityTransform (e, &lerpdata);

    glPushMatrix ();
	R_RotateForLerpEntity(e, &lerpdata);

	if(currententity->scale != 0 && currententity->scale != 100)
	{
		entScale = (float)currententity->scale/100.0;
		switch(currententity->drawflags&SCALE_TYPE_MASKIN)
		{
		case SCALE_TYPE_UNIFORM:
			tmatrix[0][0] = paliashdr->scale[0]*entScale;
			tmatrix[1][1] = paliashdr->scale[1]*entScale;
			tmatrix[2][2] = paliashdr->scale[2]*entScale;
			xyfact = zfact = (entScale-1.0)*127.95;
			break;
		case SCALE_TYPE_XYONLY:
			tmatrix[0][0] = paliashdr->scale[0]*entScale;
			tmatrix[1][1] = paliashdr->scale[1]*entScale;
			tmatrix[2][2] = paliashdr->scale[2];
			xyfact = (entScale-1.0)*127.95;
			zfact = 1.0;
			break;
		case SCALE_TYPE_ZONLY:
			tmatrix[0][0] = paliashdr->scale[0];
			tmatrix[1][1] = paliashdr->scale[1];
			tmatrix[2][2] = paliashdr->scale[2]*entScale;
			xyfact = 1.0;
			zfact = (entScale-1.0)*127.95;
			break;
		}
		switch(currententity->drawflags&SCALE_ORIGIN_MASKIN)
		{
		case SCALE_ORIGIN_CENTER:
			tmatrix[0][3] = paliashdr->scale_origin[0]-paliashdr->scale[0]*xyfact;
			tmatrix[1][3] = paliashdr->scale_origin[1]-paliashdr->scale[1]*xyfact;
			tmatrix[2][3] = paliashdr->scale_origin[2]-paliashdr->scale[2]*zfact;
			break;
		case SCALE_ORIGIN_BOTTOM:
			tmatrix[0][3] = paliashdr->scale_origin[0]-paliashdr->scale[0]*xyfact;
			tmatrix[1][3] = paliashdr->scale_origin[1]-paliashdr->scale[1]*xyfact;
			tmatrix[2][3] = paliashdr->scale_origin[2];
			break;
		case SCALE_ORIGIN_TOP:
			tmatrix[0][3] = paliashdr->scale_origin[0]-paliashdr->scale[0]*xyfact;
			tmatrix[1][3] = paliashdr->scale_origin[1]-paliashdr->scale[1]*xyfact;
			tmatrix[2][3] = paliashdr->scale_origin[2]-paliashdr->scale[2]*zfact*2.0;
			break;
		}
	}
	else
	{
		tmatrix[0][0] = paliashdr->scale[0];
		tmatrix[1][1] = paliashdr->scale[1];
		tmatrix[2][2] = paliashdr->scale[2];
		tmatrix[0][3] = paliashdr->scale_origin[0];
		tmatrix[1][3] = paliashdr->scale_origin[1];
		tmatrix[2][3] = paliashdr->scale_origin[2];
	}

	if(clmodel->flags&EF_ROTATE)
	{ // Floating motion
		tmatrix[2][3] += sin(currententity->origin[0]
			+currententity->origin[1]+(cl.time*3))*5.5;
	}

// [0][3] [1][3] [2][3]
//	glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
	glTranslatef (tmatrix[0][3],tmatrix[1][3],tmatrix[2][3]);
// [0][0] [1][1] [2][2]
//	glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
	glScalef (tmatrix[0][0],tmatrix[1][1],tmatrix[2][2]);

    if (clmodel->ex_flags & XF_NOZWRITE)
        glDepthMask (0);
         
	if ((currententity->model->flags & EF_SPECIAL_TRANS))
	{
		// rjr
		glEnable (GL_BLEND);
		glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
		glColor3f( 1,1,1);
		model_constant_alpha = 1.0f;
		glDisable( GL_CULL_FACE );

	}
	else if (currententity->drawflags & DRF_TRANSLUCENT)
	{
		// rjr
		glEnable (GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		//glColor4f( 1,1,1,r_wateralpha.value);
		//model_constant_alpha = r_wateralpha.value;
		glColor4f( 1,1,1,r_model_alpha.value);
		model_constant_alpha = r_model_alpha.value;
    }
	else if ((currententity->model->flags & EF_TRANSPARENT))
	{
		// rjr
		glEnable (GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glColor3f( 1,1,1);
		model_constant_alpha = 1.0f;
    }
	else if ((currententity->model->flags & EF_HOLEY))
	{
		// rjr
		glEnable (GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glColor3f( 1,1,1);
		model_constant_alpha = 1.0f;
	}
	else
	{
		// rjr
		glColor3f( 1,1,1);
		model_constant_alpha = 1.0f;
	}

	if (currententity->skinnum >= 100)
	{
		if (currententity->skinnum > 255) 
		{
			Sys_Error ("skinnum > 255");
		}

		if (gl_extra_textures[currententity->skinnum-100] == -1)  // Need to load it in
		{
			sprintf(temp,"gfx/skin%d.lmp",currententity->skinnum);
			stonepic = Draw_CachePic(temp);
			gl = (glpic_t *)stonepic->data;
			gl_extra_textures[currententity->skinnum-100] = gl->texnum;
		}

		GL_Bind(gl_extra_textures[currententity->skinnum-100]);
	}
	else
	{
		GL_Bind(paliashdr->gl_texturenum[currententity->skinnum]);

		// we can't dynamically colormap textures, so they are cached
		// seperately for the players.  Heads are just uncolored.
	
		if (currententity->colormap != vid.colormap && !gl_nocolors.value)
		{
			if (currententity->model == player_models[0] ||
			    currententity->model == player_models[1] ||
			    currententity->model == player_models[2] ||
			    currententity->model == player_models[3] ||
			    currententity->model == player_models[4])
			{
				i = currententity - cl_entities;
				if (i >= 1 && i<=cl.maxclients)
					GL_Bind(playertextures - 1 + i);
			}
		}
	}

	if (gl_smoothmodels.value)
		glShadeModel (GL_SMOOTH);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

	GL_DrawAliasFrame (paliashdr, lerpdata);
	
    // alias model chrome effect
    if (gl_alias_chrome.value == 1)
			GL_DrawAliasChrome(paliashdr, lerpdata); 

    if ((currententity->drawflags & DRF_TRANSLUCENT) ||
		(currententity->model->flags & EF_SPECIAL_TRANS))
		{
        glDisable (GL_BLEND);
        }
	if ((currententity->model->flags & EF_TRANSPARENT))
		{
        glDisable (GL_BLEND);
        }

	if ((currententity->model->flags & EF_HOLEY))
		{
        glDisable (GL_BLEND);
        }

	if ((currententity->model->flags & EF_SPECIAL_TRANS))
	    {
		// rjr
		glEnable( GL_CULL_FACE );
        }

    if (clmodel->ex_flags & XF_NOZWRITE)
        glDepthMask (1);
	
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glShadeModel (GL_FLAT);
	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glPopMatrix ();

    

	if (r_shadows.value && !(currententity->drawflags & (DRF_TRANSLUCENT | DRF_NOSHADOW)) && !(currententity->model->flags & EF_NOSHADOW))
	{
        // return id lame solution - i realy have to change this
        // move this to model loading section 

        // in first person the engine currently draws the player's weapon, but no player. This means 
        // a weapon shadow is drawn we'll remove weapon shadow until this is fixed
	    int nodraw = 0;
        	
        // Assasin
        
        if (clmodel->ex_flags & XF_NOSHADOW)
            nodraw = 1;
    
    	// end of muff

        if (nodraw == 0)
        {
            glPushMatrix ();

            // muff@yakko.globalnet.co.uk - 05 Mar 00 
		    // this determines the shadow vector relative to origin of entity
		    // changed always be directly below entity for the moment.
		    // will alter later (hopefully) when I got proper light source shadows working
		    shadevector[0] = 0;
		    shadevector[1] = 0;
		    shadevector[2] = 1;
		    VectorNormalize (shadevector);

            //R_RotateForEntity2(e);

            glTranslatef (lerpdata.origin[0],  lerpdata.origin[1],  lerpdata.origin[2]);
   	        glRotatef (lerpdata.angles[1],  0, 0, 1);

            // this is so we can calculate height of the ground accurately
		    VectorCopy (lerpdata.origin, downmove);

		    downmove[2] = downmove[2] - 4096;
		    memset (&downtrace, 0, sizeof(downtrace));
		    SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, lerpdata.origin, downmove, &downtrace);
		    // end of muff


		    glDisable (GL_TEXTURE_2D);
		    glEnable (GL_BLEND);
   		    glBlendFunc(GL_ZERO ,GL_ONE_MINUS_SRC_ALPHA);            
                
        
            if ((currententity->drawflags & DRF_TRANSLUCENT) || 
                (currententity->model->flags & EF_TRANSPARENT) ||
        	    (currententity->model->flags & EF_HOLEY) || r_fullbright.value > 0)
                {
                glBlendFunc(GL_ZERO ,GL_ONE_MINUS_SRC_ALPHA);            
                }
        
		    //glColor4f (0,0,0,0.5);
            shadowalpha = max(min(gl_shadowalpha.value,1),0);
        
            shadowalpha = shadowalpha - max(0,min(shadowalpha,(mins[2]-downtrace.endpos[2])/180));
                      
            if (have_stencil == true && gl_stencilshadow.value != 0) 
                {        
                if (gl_detailtexture.value || gl_caustictexture.value)
                    {    
                    if (gl_lightmap_format == GL_RGBA)
                        // set the shade of the shadow based on height off ground
		                glColor4f (shadowalpha,shadowalpha,shadowalpha,shadowalpha); 
                    else 
                        glColor4f (0.0f, 0.0f, 0.0f, shadowalpha); 
                    }
                else 
                    {
                    if (gl_lightmap_format == GL_RGBA)
                    // set the shade of the shadow based on height off ground
		                glColor4f (shadowalpha,shadowalpha,shadowalpha,shadowalpha);                        
                    else 
                        glColor4f (0.0f, 0.0f, 0.0f, shadowalpha); 
                    }
                }
            else 
                {
                if (gl_lightmap_format == GL_RGBA)
                // set the shade of the shadow based on height off ground
		            glColor4f (shadowalpha, shadowalpha, shadowalpha, shadowalpha); 
                    //glColor4f (0, 0, 0, 0); 
                else         
                    glColor4f (0.0f, 0.0f, 0.0f, shadowalpha); 
                }

		    GL_DrawAliasShadow (paliashdr, lerpdata);

		    if ((currententity->drawflags & DRF_TRANSLUCENT) || 
                (currententity->model->flags & EF_TRANSPARENT) ||
        	    (currententity->model->flags & EF_HOLEY))
                {
  		        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                }

            glEnable (GL_TEXTURE_2D);
		    glDisable (GL_BLEND);
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
                
		    glColor4f (1.0f,1.0f,1.0f,1.0f);
		    glPopMatrix ();
        }
	}

}

/*
=============
R_DrawViewModel
=============
*/

char	activegunname[MOD_GUNNAME];

void R_DrawViewModel (void)
{
	int			j;
	int			lnum;
	vec3_t		dist;
	float		add;
	dlight_t	*dl;
	//float			ambientlight, shadelight;
    //float         shadelightcolor[4];
    int*        lpc;
    
	if (!r_drawviewmodel.value)
		return;

	if (chase_active.value)
		return;

	if (envmap)
		return;

	if (!r_drawentities.value)
		return;

	if (cl.items & IT_INVISIBILITY)
		return;

	if (cl.v.health <= 0)
		return;

	currententity = &cl.viewent;
	if (!currententity->model)
		return;

    
    if (gl_lightmap_format == GL_RGBA)
    {
        lpc = R_LightPointColour (currententity->origin);
	
        // allways give some light on gun
        ambientlight = (float) lpc[3] > 24 ? lpc[3] : 24;
        shadelightcolor[0] = (float) lpc[0] > 24 ? lpc[0] : 24;
        shadelightcolor[1] = (float) lpc[1] > 24 ? lpc[1] : 24;
        shadelightcolor[2] = (float) lpc[2] > 24 ? lpc[2] : 24;
        shadelightcolor[3] = (float) lpc[3] > 24 ? lpc[3] : 24;
    
    }
    else 
    {
        j = R_LightPoint (currententity->origin);

        // allways give some light on gun
        if (j < 24)
            j = 24;

        ambientlight = (float) j;
        shadelight = (float) j;
    }

    
// add dynamic lights		
	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
	{
		dl = &cl_dlights[lnum];
		if (!dl->radius)
			continue;
		if (!dl->radius)
			continue;
		if (dl->die < cl.time)
			continue;

		VectorSubtract (currententity->origin, dl->origin, dist);
		add = dl->radius - Length(dist);
		
        if (add > 0)
            {
            if (gl_lightmap_format == GL_RGBA)
                {
                shadelightcolor[0] += (float) (dl->color[0] * add);
                shadelightcolor[1] += (float) (dl->color[1] * add);
                shadelightcolor[2] += (float) (dl->color[2] * add);
                shadelightcolor[3] += (float) add;
                }
            else shadelight += (float) add;    // id left this out...

            ambientlight += (float) add;
            }
	}

#ifdef QUAKE2RJ
	cl.light_level = ambientlight;
#endif

	ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
	diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;

    if (gl_lightmap_format == GL_RGBA)
        {
        diffuse[0] = (float)shadelightcolor[0] / 128;
        diffuse[1] = (float)shadelightcolor[1] / 128;
        diffuse[2] = (float)shadelightcolor[2] / 128;
        diffuse[3] = (float)shadelightcolor[3] / 128;
        }
    else 
        diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;

	// hack the depth range to prevent view model from poking into walls
	glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
	AlwaysDrawModel = true;

	if (strcmp(activegunname, currententity->model->name))
	{
		currententity->lerpflags |= LERP_RESETMOVE|LERP_RESETANIM;
		sprintf (activegunname, "%s", currententity->model->name);
	}
	R_DrawAliasModel (currententity);


	AlwaysDrawModel = false;
	glDepthRange (gldepthmin, gldepthmax);
}
