/* * Interpolates between two frames and origins */ void R_DrawAliasFrameLerp ( dmdl_t *paliashdr, float backlerp ) { #if defined(VERTEX_ARRAYS) uint16_t total; GLenum type; #endif 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; frame = (daliasframe_t *) ( (byte *) paliashdr + paliashdr->ofs_frames + currententity->frame * paliashdr->framesize ); verts = v = frame->verts; oldframe = (daliasframe_t *) ( (byte *) paliashdr + paliashdr->ofs_frames + currententity->oldframe * paliashdr->framesize ); ov = oldframe->verts; order = (int *) ( (byte *) paliashdr + paliashdr->ofs_glcmds ); if ( currententity->flags & RF_TRANSLUCENT ) { alpha = currententity->alpha; } else { alpha = 1.0; } if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { 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 ]; } for ( i = 0; i < 3; i++ ) { frontv [ i ] = frontlerp * frame->scale [ i ]; backv [ i ] = backlerp * oldframe->scale [ i ]; } lerp = s_lerped [ 0 ]; R_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv ); if ( gl_vertex_arrays->value ) { float colorArray [ MAX_VERTS * 4 ]; qglEnableClientState( GL_VERTEX_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 16, s_lerped ); if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { qglColor4f( shadelight [ 0 ], shadelight [ 1 ], shadelight [ 2 ], alpha ); } else { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 3, GL_FLOAT, 0, colorArray ); /* pre light everything */ for ( i = 0; i < paliashdr->num_xyz; i++ ) { float l = shadedots [ verts [ i ].lightnormalindex ]; colorArray [ i * 3 + 0 ] = l * shadelight [ 0 ]; colorArray [ i * 3 + 1 ] = l * shadelight [ 1 ]; colorArray [ i * 3 + 2 ] = l * shadelight [ 2 ]; } } #if !defined(VERTEX_ARRAYS) if ( qglLockArraysEXT != 0 ) { qglLockArraysEXT( 0, paliashdr->num_xyz ); } #endif while ( 1 ) { /* get the vertex count and primitive type */ count = *order++; if ( !count ) { break; /* done */ } if ( count < 0 ) { count = -count; #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_FAN; #else qglBegin( GL_TRIANGLE_FAN ); #endif } else { #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_STRIP; #else qglBegin( GL_TRIANGLE_STRIP ); #endif } #if defined(VERTEX_ARRAYS) total = count; GLfloat vtx[3*total]; GLfloat tex[2*total]; uint32_t index_vtx = 0; uint32_t index_tex = 0; #endif if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { do { index_xyz = order [ 2 ]; order += 3; #if defined(VERTEX_ARRAYS) vtx[index_vtx++] = s_lerped [ index_xyz ][0]; vtx[index_vtx++] = s_lerped [ index_xyz ][1]; vtx[index_vtx++] = s_lerped [ index_xyz ][2]; #else qglVertex3fv( s_lerped [ index_xyz ] ); #endif } while ( --count ); } else { do { #if defined(VERTEX_ARRAYS) tex[index_tex++] = ( (float *) order ) [ 0 ]; tex[index_tex++] = ( (float *) order ) [ 1 ]; index_xyz = order [ 2 ]; order += 3; #else /* texture coordinates come from the draw list */ qglTexCoord2f( ( (float *) order ) [ 0 ], ( (float *) order ) [ 1 ] ); index_xyz = order [ 2 ]; order += 3; qglArrayElement( index_xyz ); #endif } while ( --count ); } #if defined(VERTEX_ARRAYS) qglEnableClientState( GL_VERTEX_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 0, vtx ); qglDrawArrays( type, 0, total ); qglDisableClientState( GL_VERTEX_ARRAY ); #else qglEnd(); #endif } #if !defined(VERTEX_ARRAYS) if ( qglUnlockArraysEXT != 0 ) { qglUnlockArraysEXT(); } #endif } else { while ( 1 ) { /* get the vertex count and primitive type */ count = *order++; if ( !count ) { break; /* done */ } if ( count < 0 ) { count = -count; #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_FAN; #else qglBegin( GL_TRIANGLE_FAN ); #endif } else { #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_STRIP; #else qglBegin( GL_TRIANGLE_STRIP ); #endif } #if defined(VERTEX_ARRAYS) total = count; GLfloat vtx[3*total]; GLfloat tex[2*total]; GLfloat clr[4*total]; uint32_t index_vtx = 0; uint32_t index_tex = 0; uint32_t index_clr = 0; #endif if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) ) { do { index_xyz = order [ 2 ]; order += 3; #if defined(VERTEX_ARRAYS) clr[index_clr++] = shadelight [ 0 ]; clr[index_clr++] = shadelight [ 1 ]; clr[index_clr++] = shadelight [ 2 ]; clr[index_clr++] = alpha; vtx[index_vtx++] = s_lerped [ index_xyz ][ 0 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 1 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 2 ]; #else qglColor4f( shadelight [ 0 ], shadelight [ 1 ], shadelight [ 2 ], alpha ); qglVertex3fv( s_lerped [ index_xyz ] ); #endif } while ( --count ); } else { do { /* texture coordinates come from the draw list */ #if defined(VERTEX_ARRAYS) tex[index_tex++] = ( (float *) order ) [ 0 ]; tex[index_tex++] = ( (float *) order ) [ 1 ]; #else qglTexCoord2f( ( (float *) order ) [ 0 ], ( (float *) order ) [ 1 ] ); #endif index_xyz = order [ 2 ]; order += 3; /* normals and vertexes come from the frame list */ l = shadedots [ verts [ index_xyz ].lightnormalindex ]; #if defined(VERTEX_ARRAYS) clr[index_clr++] = l * shadelight [ 0 ]; clr[index_clr++] = l * shadelight [ 1 ]; clr[index_clr++] = l * shadelight [ 2 ]; clr[index_clr++] = alpha; vtx[index_vtx++] = s_lerped [ index_xyz ][ 0 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 1 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 2 ]; #else qglColor4f( l * shadelight [ 0 ], l * shadelight [ 1 ], l * shadelight [ 2 ], alpha ); qglVertex3fv( s_lerped [ index_xyz ] ); #endif } while ( --count ); } #if defined(VERTEX_ARRAYS) qglEnableClientState( GL_VERTEX_ARRAY ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglEnableClientState( GL_COLOR_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 0, vtx ); qglTexCoordPointer( 2, GL_FLOAT, 0, tex ); qglColorPointer( 4, GL_FLOAT, 0, clr ); qglDrawArrays( type, 0, total ); qglDisableClientState( GL_VERTEX_ARRAY ); qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); qglDisableClientState( GL_COLOR_ARRAY ); #else qglEnd(); #endif } } if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { qglEnable( GL_TEXTURE_2D ); } }
/* ============= 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; frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames + currententity->frame * paliashdr->framesize); verts = v = frame->verts; oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames + currententity->oldframe * paliashdr->framesize); ov = oldframe->verts; order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds); // glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]); // glScalef (frame->scale[0], frame->scale[1], frame->scale[2]); if (currententity->flags & RF_TRANSLUCENT) alpha = currententity->alpha; else alpha = 1.0; // PMM - added double shell if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) ) 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]; } for (i=0 ; i<3 ; i++) { frontv[i] = frontlerp*frame->scale[i]; backv[i] = backlerp*oldframe->scale[i]; } lerp = s_lerped[0]; GL_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv ); if ( gl_vertex_arrays->value ) { float colorArray[MAX_VERTS*4]; qglEnableClientState( GL_VERTEX_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 16, s_lerped ); // padded for SIMD // if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) ) // PMM - added double damage shell if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) ) { qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha ); } else { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 3, GL_FLOAT, 0, colorArray ); // // pre light everything // for ( i = 0; i < paliashdr->num_xyz; i++ ) { float l = shadedots[verts[i].lightnormalindex]; colorArray[i*3+0] = l * shadelight[0]; colorArray[i*3+1] = l * shadelight[1]; colorArray[i*3+2] = l * shadelight[2]; } } if ( qglLockArraysEXT != 0 ) qglLockArraysEXT( 0, paliashdr->num_xyz ); while (1) { // get the vertex count and primitive type count = *order++; if (!count) break; // done if (count < 0) { count = -count; qglBegin (GL_TRIANGLE_FAN); } else { qglBegin (GL_TRIANGLE_STRIP); } // PMM - added double damage shell if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) ) { do { index_xyz = order[2]; order += 3; qglVertex3fv( s_lerped[index_xyz] ); } while (--count); } else { do { // texture coordinates come from the draw list qglTexCoord2f (((float *)order)[0], ((float *)order)[1]); index_xyz = order[2]; order += 3; // 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); qglArrayElement( index_xyz ); } while (--count); } qglEnd (); } if ( qglUnlockArraysEXT != 0 ) qglUnlockArraysEXT(); } else { while (1) { // get the vertex count and primitive type count = *order++; if (!count) break; // done if (count < 0) { count = -count; qglBegin (GL_TRIANGLE_FAN); } else { qglBegin (GL_TRIANGLE_STRIP); } if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) ) { do { index_xyz = order[2]; order += 3; qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha); qglVertex3fv (s_lerped[index_xyz]); } while (--count); } else { do { // texture coordinates come from the draw list qglTexCoord2f (((float *)order)[0], ((float *)order)[1]); index_xyz = order[2]; order += 3; // 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 (s_lerped[index_xyz]); } while (--count); } qglEnd (); } } // if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) ) // PMM - added double damage shell if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) ) qglEnable( GL_TEXTURE_2D ); }
/* ================ R_ArrayElement This is just because of the GLEW and Windows idiocy. Straight call to glArrayElement brakes the build on function type mismatch. ================ */ static void GLAPIENTRY R_ArrayElement(GLint index) { qglArrayElement(index); }