/* * Mod_AliasBuildMeshesForFrame0 */ static void Mod_AliasBuildMeshesForFrame0( model_t *mod ) { int i, j, k; size_t size; maliasframe_t *frame; maliasmodel_t *aliasmodel = ( maliasmodel_t * )mod->extradata; frame = &aliasmodel->frames[0]; for( k = 0; k < aliasmodel->nummeshes; k++ ) { maliasmesh_t *mesh = &aliasmodel->meshes[k]; size = sizeof( vec3_t ) + sizeof( vec3_t ); // xyz and normals size += sizeof( vec4_t ); // s-vectors size *= mesh->numverts; mesh->xyzArray = ( vec3_t * )Mod_Malloc( mod, size ); mesh->normalsArray = ( vec3_t * )( ( qbyte * )mesh->xyzArray + mesh->numverts * sizeof( vec3_t ) ); mesh->sVectorsArray = ( vec4_t * )( ( qbyte * )mesh->normalsArray + mesh->numverts * sizeof( vec3_t ) ); for( i = 0; i < mesh->numverts; i++ ) { for( j = 0; j < 3; j++ ) mesh->xyzArray[i][j] = frame->translate[j] + frame->scale[j] * mesh->vertexes[i].point[j]; R_LatLongToNorm( mesh->vertexes[i].latlong, mesh->normalsArray[i] ); } R_BuildTangentVectors( mesh->numverts, mesh->xyzArray, mesh->normalsArray, mesh->stArray, mesh->numtris, mesh->elems, mesh->sVectorsArray ); if( glConfig.ext.vertex_buffer_object ) { // build a static vertex buffer object to be used for rendering simple models, such as items Mod_AliasBuildStaticVBOForMesh( mesh ); } } }
/* * R_LightForOrigin */ void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius ) { int i, j; int k, s; int vi[3], elem[4]; float dot, t[8], scale; vec3_t vf, vf2, tdir; vec3_t ambientLocal, diffuseLocal; vec_t *gridSize, *gridMins; int *gridBounds; static mgridlight_t lightarray[8]; lightstyle_t *lightStyles = rsc.lightStyles; VectorSet( ambientLocal, 0, 0, 0 ); VectorSet( diffuseLocal, 0, 0, 0 ); if( !rsh.worldModel /* || (rn.refdef.rdflags & RDF_NOWORLDMODEL)*/ || !rsh.worldBrushModel->lightgrid || !rsh.worldBrushModel->numlightgridelems ) { VectorSet( dir, 0.1f, 0.2f, 0.7f ); goto dynamic; } gridSize = rsh.worldBrushModel->gridSize; gridMins = rsh.worldBrushModel->gridMins; gridBounds = rsh.worldBrushModel->gridBounds; for( i = 0; i < 3; i++ ) { vf[i] = ( origin[i] - gridMins[i] ) / gridSize[i]; vi[i] = (int)vf[i]; vf[i] = vf[i] - floor( vf[i] ); vf2[i] = 1.0f - vf[i]; } elem[0] = vi[2] * gridBounds[3] + vi[1] * gridBounds[0] + vi[0]; elem[1] = elem[0] + gridBounds[0]; elem[2] = elem[0] + gridBounds[3]; elem[3] = elem[2] + gridBounds[0]; for( i = 0; i < 4; i++ ) { lightarray[i*2+0] = *rsh.worldBrushModel->lightarray[bound( 0, elem[i]+0, (int)rsh.worldBrushModel->numlightarrayelems-1)]; lightarray[i*2+1] = *rsh.worldBrushModel->lightarray[bound( 1, elem[i]+1, (int)rsh.worldBrushModel->numlightarrayelems-1)]; } t[0] = vf2[0] * vf2[1] * vf2[2]; t[1] = vf[0] * vf2[1] * vf2[2]; t[2] = vf2[0] * vf[1] * vf2[2]; t[3] = vf[0] * vf[1] * vf2[2]; t[4] = vf2[0] * vf2[1] * vf[2]; t[5] = vf[0] * vf2[1] * vf[2]; t[6] = vf2[0] * vf[1] * vf[2]; t[7] = vf[0] * vf[1] * vf[2]; VectorClear( dir ); for( i = 0; i < 4; i++ ) { R_LatLongToNorm( lightarray[i*2].direction, tdir ); VectorScale( tdir, t[i*2], tdir ); for( k = 0; k < MAX_LIGHTMAPS && ( s = lightarray[i*2].styles[k] ) != 255; k++ ) { dir[0] += lightStyles[s].rgb[0] * tdir[0]; dir[1] += lightStyles[s].rgb[1] * tdir[1]; dir[2] += lightStyles[s].rgb[2] * tdir[2]; } R_LatLongToNorm( lightarray[i*2+1].direction, tdir ); VectorScale( tdir, t[i*2+1], tdir ); for( k = 0; k < MAX_LIGHTMAPS && ( s = lightarray[i*2+1].styles[k] ) != 255; k++ ) { dir[0] += lightStyles[s].rgb[0] * tdir[0]; dir[1] += lightStyles[s].rgb[1] * tdir[1]; dir[2] += lightStyles[s].rgb[2] * tdir[2]; } } for( j = 0; j < 3; j++ ) { if( ambient ) { for( i = 0; i < 4; i++ ) { for( k = 0; k < MAX_LIGHTMAPS; k++ ) { if( ( s = lightarray[i*2].styles[k] ) != 255 ) ambientLocal[j] += t[i*2] * lightarray[i*2].ambient[k][j] * lightStyles[s].rgb[j]; if( ( s = lightarray[i*2+1].styles[k] ) != 255 ) ambientLocal[j] += t[i*2+1] * lightarray[i*2+1].ambient[k][j] * lightStyles[s].rgb[j]; } } } if( diffuse || radius ) { for( i = 0; i < 4; i++ ) { for( k = 0; k < MAX_LIGHTMAPS; k++ ) { if( ( s = lightarray[i*2].styles[k] ) != 255 ) diffuseLocal[j] += t[i*2] * lightarray[i*2].diffuse[k][j] * lightStyles[s].rgb[j]; if( ( s = lightarray[i*2+1].styles[k] ) != 255 ) diffuseLocal[j] += t[i*2+1] * lightarray[i*2+1].diffuse[k][j] * lightStyles[s].rgb[j]; } } } } // convert to grayscale if( r_lighting_grayscale->integer ) { vec_t grey; if( ambient ) { grey = ColorGrayscale( ambientLocal ); ambientLocal[0] = ambientLocal[1] = ambientLocal[2] = bound( 0, grey, 255 ); } if( diffuse || radius ) { grey = ColorGrayscale( diffuseLocal ); diffuseLocal[0] = diffuseLocal[1] = diffuseLocal[2] = bound( 0, grey, 255 ); } } dynamic: // add dynamic lights if( radius && r_dynamiclight->integer ) { unsigned int lnum; dlight_t *dl; float dist, dist2, add; vec3_t direction; qboolean anyDlights = qfalse; for( lnum = 0; lnum < rsc.numDlights; lnum++ ) { dl = rsc.dlights + lnum; if( Distance( dl->origin, origin ) > dl->intensity + radius ) continue; VectorSubtract( dl->origin, origin, direction ); dist = VectorLength( direction ); if( !dist || dist > dl->intensity + radius ) continue; if( !anyDlights ) { VectorNormalizeFast( dir ); anyDlights = qtrue; } add = 1.0 - (dist / (dl->intensity + radius)); dist2 = add * 0.5 / dist; for( i = 0; i < 3; i++ ) { dot = dl->color[i] * add; diffuseLocal[i] += dot; ambientLocal[i] += dot * 0.05; dir[i] += direction[i] * dist2; } } } VectorNormalizeFast( dir ); scale = mapConfig.mapLightColorScale / 255.0f; if( ambient ) { float scale2 = bound( 0.0f, r_lighting_ambientscale->value, 1.0f ) * scale; for( i = 0; i < 3; i++ ) ambient[i] = ambientLocal[i] * scale2; ambient[3] = 1.0f; } if( diffuse ) { float scale2 = bound( 0.0f, r_lighting_directedscale->value, 1.0f ) * scale; for( i = 0; i < 3; i++ ) diffuse[i] = diffuseLocal[i] * scale2; diffuse[3] = 1.0f; } }
/* ================= R_SetupEntityLightingGrid ================= */ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { vec3_t lightOrigin; //int pos[3]; //byte *gridData; //float frac[3]; //int gridStep[3]; vec3_t direction; //float totalFactor; int i, j; int k, s; int vi[3], elem[4]; float t[8]; vec3_t vf, vf2, tdir; vec_t *gridSize, *gridMins; int *gridBounds; static dgrid_t lightarray[8]; if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) { // seperate lightOrigins are needed so an object that is // sinking into the ground can still be lit, and so // multi-part models can be lit identically VectorCopy( ent->e.lightingOrigin, lightOrigin ); } else { VectorCopy( ent->e.origin, lightOrigin ); } gridSize = tr.world->lightGridSize; gridMins = tr.world->lightGridMins; gridBounds = tr.world->lightGridBounds; for( i = 0; i < 3; i++ ) { vf[i] = ( lightOrigin[i] - gridMins[i] ) / gridSize[i]; vi[i] = (int)vf[i]; vf[i] = vf[i] - floor( vf[i] ); vf2[i] = 1.0f - vf[i]; } elem[0] = vi[2] * gridBounds[3] + vi[1] * gridBounds[0] + vi[0]; elem[1] = elem[0] + gridBounds[0]; elem[2] = elem[0] + gridBounds[3]; elem[3] = elem[2] + gridBounds[0]; for( i = 0; i < 4; i++ ) { lightarray[i*2+0] = *tr.world->lightGridArray[BOUND( 0, elem[i]+0, tr.world->numLightGridArrayItems-1)]; lightarray[i*2+1] = *tr.world->lightGridArray[BOUND( 0, elem[i]+1, tr.world->numLightGridArrayItems-1)]; } t[0] = vf2[0] * vf2[1] * vf2[2]; t[1] = vf[0] * vf2[1] * vf2[2]; t[2] = vf2[0] * vf[1] * vf2[2]; t[3] = vf[0] * vf[1] * vf2[2]; t[4] = vf2[0] * vf2[1] * vf[2]; t[5] = vf[0] * vf2[1] * vf[2]; t[6] = vf2[0] * vf[1] * vf[2]; t[7] = vf[0] * vf[1] * vf[2]; VectorClear( ent->ambientLight ); VectorClear( ent->directedLight ); VectorClear( direction ); for( i = 0; i < 4; i++ ) { R_LatLongToNorm( lightarray[i*2].latLong, tdir ); VectorScale( tdir, t[i*2], tdir ); for( k = 0; k < MAXLIGHTMAPS && ( s = lightarray[i*2].styles[k] ) != 255; k++ ) { direction[0] += tr.lightStyles[s].rgb[0] * tdir[0]; direction[1] += tr.lightStyles[s].rgb[1] * tdir[1]; direction[2] += tr.lightStyles[s].rgb[2] * tdir[2]; } R_LatLongToNorm( lightarray[i*2+1].latLong, tdir ); VectorScale( tdir, t[i*2+1], tdir ); for( k = 0; k < MAXLIGHTMAPS && ( s = lightarray[i*2+1].styles[k] ) != 255; k++ ) { direction[0] += tr.lightStyles[s].rgb[0] * tdir[0]; direction[1] += tr.lightStyles[s].rgb[1] * tdir[1]; direction[2] += tr.lightStyles[s].rgb[2] * tdir[2]; } } for( j = 0; j < 3; j++ ) { //if( ambient ) { for( i = 0; i < 4; i++ ) { for( k = 0; k < MAXLIGHTMAPS; k++ ) { if( ( s = lightarray[i*2].styles[k] ) != 255 ) ent->ambientLight[j] += t[i*2] * lightarray[i*2].ambientLight[k][j] * tr.lightStyles[s].rgb[j]; if( ( s = lightarray[i*2+1].styles[k] ) != 255 ) ent->ambientLight[j] += t[i*2+1] * lightarray[i*2+1].ambientLight[k][j] * tr.lightStyles[s].rgb[j]; } } } //if( diffuse || radius ) { for( i = 0; i < 4; i++ ) { for( k = 0; k < MAXLIGHTMAPS; k++ ) { if( ( s = lightarray[i*2].styles[k] ) != 255 ) ent->directedLight[j] += t[i*2] * lightarray[i*2].directLight[k][j] * tr.lightStyles[s].rgb[j]; if( ( s = lightarray[i*2+1].styles[k] ) != 255 ) ent->directedLight[j] += t[i*2+1] * lightarray[i*2+1].directLight[k][j] * tr.lightStyles[s].rgb[j]; } } } } VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight ); VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight ); VectorNormalize2( direction, ent->lightDir ); #if 0 //VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin ); for ( i = 0 ; i < 3 ; i++ ) { float v; v = lightOrigin[i]*tr.world->lightGridInverseSize[i]; pos[i] = floor( v ); frac[i] = v - pos[i]; if ( pos[i] < 0 ) { pos[i] = 0; } else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) { pos[i] = tr.world->lightGridBounds[i] - 1; } } VectorClear( ent->ambientLight ); VectorClear( ent->directedLight ); VectorClear( direction ); assert( tr.world->lightGridData ); // NULL with -nolight maps // trilerp the light value gridStep[0] = 8; gridStep[1] = 8 * tr.world->lightGridBounds[0]; gridStep[2] = 8 * tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1]; gridData = tr.world->lightGridData + pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2]; totalFactor = 0; for ( i = 0 ; i < 8 ; i++ ) { float factor; byte *data; int lat, lng; vec3_t normal; #if idppc float d0, d1, d2, d3, d4, d5; #endif factor = 1.0; data = gridData; for ( j = 0 ; j < 3 ; j++ ) { if ( i & (1<<j) ) { factor *= frac[j]; data += gridStep[j]; } else { factor *= (1.0f - frac[j]); } } if ( !(data[0]+data[1]+data[2]) ) { continue; // ignore samples in walls } totalFactor += factor; #if idppc d0 = data[0]; d1 = data[1]; d2 = data[2]; d3 = data[3]; d4 = data[4]; d5 = data[5]; ent->ambientLight[0] += factor * d0; ent->ambientLight[1] += factor * d1; ent->ambientLight[2] += factor * d2; ent->directedLight[0] += factor * d3; ent->directedLight[1] += factor * d4; ent->directedLight[2] += factor * d5; #else ent->ambientLight[0] += factor * data[0]; ent->ambientLight[1] += factor * data[1]; ent->ambientLight[2] += factor * data[2]; ent->directedLight[0] += factor * data[3]; ent->directedLight[1] += factor * data[4]; ent->directedLight[2] += factor * data[5]; #endif lat = data[7]; lng = data[6]; lat *= (FUNCTABLE_SIZE/256); lng *= (FUNCTABLE_SIZE/256); // decode X as cos( lat ) * sin( long ) // decode Y as sin( lat ) * sin( long ) // decode Z as cos( long ) normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; normal[1] = tr.sinTable[lat] * tr.sinTable[lng]; normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; VectorMA( direction, factor, normal, direction ); } if ( totalFactor > 0 && totalFactor < 0.99 ) { totalFactor = 1.0f / totalFactor; VectorScale( ent->ambientLight, totalFactor, ent->ambientLight ); VectorScale( ent->directedLight, totalFactor, ent->directedLight ); } VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight ); VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight ); VectorNormalize2( direction, ent->lightDir ); #endif }
/* * R_DrawAliasSurf * * Interpolates between two frames and origins */ qboolean R_DrawAliasSurf( const entity_t *e, const shader_t *shader, const mfog_t *fog, drawSurfaceAlias_t *drawSurf ) { int i; int framenum, oldframenum; float backv[3], frontv[3]; vec3_t normal, oldnormal; qboolean calcVerts, calcNormals, calcSTVectors; vec3_t move; const maliasframe_t *frame, *oldframe; const maliasvertex_t *v, *ov; float backlerp = e->backlerp; const maliasmodel_t *model = ( const maliasmodel_t * )drawSurf->model->extradata; const maliasmesh_t *aliasmesh = drawSurf->mesh; vattribmask_t vattribs; // see what vertex attribs backend needs vattribs = RB_GetVertexAttribs(); framenum = bound( e->frame, 0, model->numframes ); oldframenum = bound( e->oldframe, 0, model->numframes ); frame = model->frames + framenum; oldframe = model->frames + oldframenum; for( i = 0; i < 3; i++ ) move[i] = frame->translate[i] + ( oldframe->translate[i] - frame->translate[i] ) * backlerp; // based on backend's needs calcNormals = calcSTVectors = qfalse; calcNormals = ( ( vattribs & VATTRIB_NORMAL_BIT ) != 0 ) && ( ( framenum != 0 ) || ( oldframenum != 0 ) ); calcSTVectors = ( ( vattribs & VATTRIB_SVECTOR_BIT ) != 0 ) && calcNormals; if( aliasmesh->vbo != NULL && !framenum && !oldframenum ) { RB_BindVBO( aliasmesh->vbo->index, GL_TRIANGLES ); RB_DrawElements( 0, aliasmesh->numverts, 0, aliasmesh->numtris * 3 ); } else { mesh_t *rb_mesh; vec3_t *inVertsArray; vec3_t *inNormalsArray; vec4_t *inSVectorsArray; RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLES ); rb_mesh = RB_MapBatchMesh( aliasmesh->numverts, aliasmesh->numtris * 3 ); if( !rb_mesh ) { ri.Com_DPrintf( S_COLOR_YELLOW "R_DrawAliasSurf: RB_MapBatchMesh returned NULL for (%s)(%s)", drawSurf->model->name, aliasmesh->name ); return qfalse; } inVertsArray = rb_mesh->xyzArray; inNormalsArray = rb_mesh->normalsArray; inSVectorsArray = rb_mesh->sVectorsArray; if( !framenum && !oldframenum ) { calcVerts = qfalse; if( calcNormals ) { v = aliasmesh->vertexes; for( i = 0; i < aliasmesh->numverts; i++, v++ ) R_LatLongToNorm( v->latlong, inNormalsArray[i] ); } } else if( framenum == oldframenum ) { calcVerts = qtrue; for( i = 0; i < 3; i++ ) frontv[i] = frame->scale[i]; v = aliasmesh->vertexes + framenum * aliasmesh->numverts; for( i = 0; i < aliasmesh->numverts; i++, v++ ) { VectorSet( inVertsArray[i], move[0] + v->point[0]*frontv[0], move[1] + v->point[1]*frontv[1], move[2] + v->point[2]*frontv[2] ); if( calcNormals ) R_LatLongToNorm( v->latlong, inNormalsArray[i] ); } } else { calcVerts = qtrue; for( i = 0; i < 3; i++ ) { backv[i] = backlerp * oldframe->scale[i]; frontv[i] = ( 1.0f - backlerp ) * frame->scale[i]; } v = aliasmesh->vertexes + framenum * aliasmesh->numverts; ov = aliasmesh->vertexes + oldframenum * aliasmesh->numverts; for( i = 0; i < aliasmesh->numverts; i++, v++, ov++ ) { VectorSet( inVertsArray[i], move[0] + v->point[0]*frontv[0] + ov->point[0]*backv[0], move[1] + v->point[1]*frontv[1] + ov->point[1]*backv[1], move[2] + v->point[2]*frontv[2] + ov->point[2]*backv[2] ); if( calcNormals ) { R_LatLongToNorm( v->latlong, normal ); R_LatLongToNorm( ov->latlong, oldnormal ); VectorSet( inNormalsArray[i], normal[0] + ( oldnormal[0] - normal[0] ) * backlerp, normal[1] + ( oldnormal[1] - normal[1] ) * backlerp, normal[2] + ( oldnormal[2] - normal[2] ) * backlerp ); } } } if( calcSTVectors ) R_BuildTangentVectors( aliasmesh->numverts, inVertsArray, inNormalsArray, aliasmesh->stArray, aliasmesh->numtris, aliasmesh->elems, inSVectorsArray ); if( !calcVerts ) { rb_mesh->xyzArray = aliasmesh->xyzArray; } rb_mesh->elems = aliasmesh->elems; rb_mesh->numElems = aliasmesh->numtris * 3; rb_mesh->numVerts = aliasmesh->numverts; rb_mesh->stArray = aliasmesh->stArray; if( !calcNormals ) { rb_mesh->normalsArray = aliasmesh->normalsArray; } if( !calcSTVectors ) { rb_mesh->sVectorsArray = aliasmesh->sVectorsArray; } RB_UploadMesh( rb_mesh ); RB_EndBatch(); } return qfalse; }
/* * R_DrawAliasFrameLerp * * Interpolates between two frames and origins */ static void R_DrawAliasFrameLerp( const meshbuffer_t *mb, float backlerp ) { int i, meshnum; int features; float backv[3], frontv[3]; vec3_t normal, oldnormal; qboolean calcVerts, calcNormals, calcSTVectors; vec3_t move; maliasframe_t *frame, *oldframe; maliasmesh_t *mesh; maliasvertex_t *v, *ov; entity_t *e; model_t *mod; maliasmodel_t *model; shader_t *shader; MB_NUM2ENTITY( mb->sortkey, e ); mod = Mod_ForHandle( mb->LODModelHandle ); model = ( maliasmodel_t * )mod->extradata; meshnum = -mb->infokey - 1; if( meshnum < 0 || meshnum >= model->nummeshes ) return; mesh = model->meshes + meshnum; frame = model->frames + e->frame; oldframe = model->frames + e->oldframe; for( i = 0; i < 3; i++ ) move[i] = frame->translate[i] + ( oldframe->translate[i] - frame->translate[i] ) * backlerp; MB_NUM2SHADER( mb->shaderkey, shader ); features = MF_NONBATCHED | shader->features; if( !mb->vboIndex ) { features &= ~MF_HARDWARE; } if( ri.params & RP_SHADOWMAPVIEW ) { features &= ~( MF_COLORS|MF_SVECTORS|MF_ENABLENORMALS ); if( !( shader->features & MF_DEFORMVS ) ) features &= ~MF_NORMALS; } else { if( features & MF_SVECTORS ) features |= MF_NORMALS; #ifdef HARDWARE_OUTLINES if( e->outlineHeight ) features |= MF_NORMALS|(glConfig.ext.GLSL ? MF_ENABLENORMALS : 0); #endif } calcNormals = calcSTVectors = qfalse; calcNormals = ( ( features & MF_NORMALS ) != 0 ) && ( ( e->frame != 0 ) || ( e->oldframe != 0 ) ); calcSTVectors = ( ( features & MF_SVECTORS ) != 0 ) && calcNormals; if( mb->vboIndex != 0 ) { calcVerts = calcNormals = calcSTVectors = qfalse; } else { if( !e->frame && !e->oldframe ) { calcVerts = qfalse; if( calcNormals ) { v = mesh->vertexes; for( i = 0; i < mesh->numverts; i++, v++ ) R_LatLongToNorm( v->latlong, inNormalsArray[i] ); } } else if( e->frame == e->oldframe ) { calcVerts = qtrue; for( i = 0; i < 3; i++ ) frontv[i] = frame->scale[i]; v = mesh->vertexes + e->frame * mesh->numverts; for( i = 0; i < mesh->numverts; i++, v++ ) { Vector4Set( inVertsArray[i], move[0] + v->point[0]*frontv[0], move[1] + v->point[1]*frontv[1], move[2] + v->point[2]*frontv[2], 1 ); if( calcNormals ) R_LatLongToNorm( v->latlong, inNormalsArray[i] ); } } else { calcVerts = qtrue; for( i = 0; i < 3; i++ ) { backv[i] = backlerp * oldframe->scale[i]; frontv[i] = ( 1.0f - backlerp ) * frame->scale[i]; } v = mesh->vertexes + e->frame * mesh->numverts; ov = mesh->vertexes + e->oldframe * mesh->numverts; for( i = 0; i < mesh->numverts; i++, v++, ov++ ) { Vector4Set( inVertsArray[i], move[0] + v->point[0]*frontv[0] + ov->point[0]*backv[0], move[1] + v->point[1]*frontv[1] + ov->point[1]*backv[1], move[2] + v->point[2]*frontv[2] + ov->point[2]*backv[2], 1 ); if( calcNormals ) { R_LatLongToNorm( v->latlong, normal ); R_LatLongToNorm( ov->latlong, oldnormal ); VectorSet( inNormalsArray[i], normal[0] + ( oldnormal[0] - normal[0] ) * backlerp, normal[1] + ( oldnormal[1] - normal[1] ) * backlerp, normal[2] + ( oldnormal[2] - normal[2] ) * backlerp ); } } } if( calcSTVectors ) R_BuildTangentVectors( mesh->numverts, inVertsArray, inNormalsArray, mesh->stArray, mesh->numtris, mesh->elems, inSVectorsArray ); } alias_mesh.xyzArray = calcVerts ? inVertsArray : mesh->xyzArray; alias_mesh.elems = mesh->elems; alias_mesh.numElems = mesh->numtris * 3; alias_mesh.numVerts = mesh->numverts; alias_mesh.stArray = mesh->stArray; if( features & MF_NORMALS ) alias_mesh.normalsArray = calcNormals ? inNormalsArray : mesh->normalsArray; if( features & MF_SVECTORS ) alias_mesh.sVectorsArray = calcSTVectors ? inSVectorsArray : mesh->sVectorsArray; R_RotateForEntity( e ); R_PushMesh( &alias_mesh, mb->vboIndex != 0, features ); R_RenderMeshBuffer( mb, NULL ); }