/* 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; iorigin[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