Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_mesh.c File Reference

#include "tr_local.h"

Include dependency graph for tr_mesh.c:

Include dependency graph

Go to the source code of this file.

Functions

float ProjectRadius (float r, vec3_t location)
void R_AddMD3Surfaces (trRefEntity_t *ent)
int R_ComputeFogNum (md3Header_t *header, trRefEntity_t *ent)
int R_ComputeLOD (trRefEntity_t *ent)
int R_CullModel (md3Header_t *header, trRefEntity_t *ent)


Function Documentation

float ProjectRadius float  r,
vec3_t  location
[static]
 

Definition at line 26 of file tr_mesh.c.

References orientationr_t::axis, c, DotProduct, fabs(), viewParms_t::or, orientationr_t::origin, p, viewParms_t::projectionMatrix, r, tr, vec3_t, and trGlobals_t::viewParms.

Referenced by R_ComputeLOD().

00027 {
00028     float pr;
00029     float dist;
00030     float c;
00031     vec3_t  p;
00032     float   projected[4];
00033 
00034     c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin );
00035     dist = DotProduct( tr.viewParms.or.axis[0], location ) - c;
00036 
00037     if ( dist <= 0 )
00038         return 0;
00039 
00040     p[0] = 0;
00041     p[1] = fabs( r );
00042     p[2] = -dist;
00043 
00044     projected[0] = p[0] * tr.viewParms.projectionMatrix[0] + 
00045                    p[1] * tr.viewParms.projectionMatrix[4] +
00046                    p[2] * tr.viewParms.projectionMatrix[8] +
00047                    tr.viewParms.projectionMatrix[12];
00048 
00049     projected[1] = p[0] * tr.viewParms.projectionMatrix[1] + 
00050                    p[1] * tr.viewParms.projectionMatrix[5] +
00051                    p[2] * tr.viewParms.projectionMatrix[9] +
00052                    tr.viewParms.projectionMatrix[13];
00053 
00054     projected[2] = p[0] * tr.viewParms.projectionMatrix[2] + 
00055                    p[1] * tr.viewParms.projectionMatrix[6] +
00056                    p[2] * tr.viewParms.projectionMatrix[10] +
00057                    tr.viewParms.projectionMatrix[14];
00058 
00059     projected[3] = p[0] * tr.viewParms.projectionMatrix[3] + 
00060                    p[1] * tr.viewParms.projectionMatrix[7] +
00061                    p[2] * tr.viewParms.projectionMatrix[11] +
00062                    tr.viewParms.projectionMatrix[15];
00063 
00064 
00065     pr = projected[1] / projected[3];
00066 
00067     if ( pr > 1.0f )
00068         pr = 1.0f;
00069 
00070     return pr;
00071 }

Here is the call graph for this function:

void R_AddMD3Surfaces trRefEntity_t ent  ) 
 

Definition at line 267 of file tr_mesh.c.

References byte, trGlobals_t::currentModel, refEntity_t::customShader, refEntity_t::customSkin, shader_s::defaultShader, trGlobals_t::defaultShader, trRefEntity_t::e, refEntity_t::frame, header, i, cvar_s::integer, viewParms_t::isPortal, j, model_s::md3, shader_s::name, skin_s::name, md3Surface_t::name, skinSurface_t::name, model_s::name, md3Header_t::numFrames, md3Surface_t::numShaders, trGlobals_t::numSkins, skin_s::numSurfaces, md3Surface_t::ofsEnd, md3Surface_t::ofsShaders, refEntity_t::oldframe, PRINT_DEVELOPER, trGlobals_t::projectionShadowShader, qboolean, qfalse, R_AddDrawSurf(), R_ComputeFogNum(), R_ComputeLOD(), R_CullModel(), R_GetShaderByHandle(), R_GetSkinByHandle(), R_SetupEntityLighting(), r_shadows, trGlobals_t::refdef, refEntity_t::renderfx, RF_NOSHADOW, ri, skinSurface_t::shader, shader_t, md3Shader_t::shaderIndex, trGlobals_t::shaders, trGlobals_t::shadowShader, skin_t, refEntity_t::skinNum, shader_s::sort, strcmp(), skin_s::surfaces, tr, and trGlobals_t::viewParms.

Referenced by R_AddEntitySurfaces().

00267                                             {
00268     int             i;
00269     md3Header_t     *header = 0;
00270     md3Surface_t    *surface = 0;
00271     md3Shader_t     *md3Shader = 0;
00272     shader_t        *shader = 0;
00273     int             cull;
00274     int             lod;
00275     int             fogNum;
00276     qboolean        personalModel;
00277 
00278     // don't add third_person objects if not in a portal
00279     personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
00280 
00281     if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
00282         ent->e.frame %= tr.currentModel->md3[0]->numFrames;
00283         ent->e.oldframe %= tr.currentModel->md3[0]->numFrames;
00284     }
00285 
00286     //
00287     // Validate the frames so there is no chance of a crash.
00288     // This will write directly into the entity structure, so
00289     // when the surfaces are rendered, they don't need to be
00290     // range checked again.
00291     //
00292     if ( (ent->e.frame >= tr.currentModel->md3[0]->numFrames) 
00293         || (ent->e.frame < 0)
00294         || (ent->e.oldframe >= tr.currentModel->md3[0]->numFrames)
00295         || (ent->e.oldframe < 0) ) {
00296             ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
00297                 ent->e.oldframe, ent->e.frame,
00298                 tr.currentModel->name );
00299             ent->e.frame = 0;
00300             ent->e.oldframe = 0;
00301     }
00302 
00303     //
00304     // compute LOD
00305     //
00306     lod = R_ComputeLOD( ent );
00307 
00308     header = tr.currentModel->md3[lod];
00309 
00310     //
00311     // cull the entire model if merged bounding box of both frames
00312     // is outside the view frustum.
00313     //
00314     cull = R_CullModel ( header, ent );
00315     if ( cull == CULL_OUT ) {
00316         return;
00317     }
00318 
00319     //
00320     // set up lighting now that we know we aren't culled
00321     //
00322     if ( !personalModel || r_shadows->integer > 1 ) {
00323         R_SetupEntityLighting( &tr.refdef, ent );
00324     }
00325 
00326     //
00327     // see if we are in a fog volume
00328     //
00329     fogNum = R_ComputeFogNum( header, ent );
00330 
00331     //
00332     // draw all surfaces
00333     //
00334     surface = (md3Surface_t *)( (byte *)header + header->ofsSurfaces );
00335     for ( i = 0 ; i < header->numSurfaces ; i++ ) {
00336 
00337         if ( ent->e.customShader ) {
00338             shader = R_GetShaderByHandle( ent->e.customShader );
00339         } else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
00340             skin_t *skin;
00341             int     j;
00342 
00343             skin = R_GetSkinByHandle( ent->e.customSkin );
00344 
00345             // match the surface name to something in the skin file
00346             shader = tr.defaultShader;
00347             for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
00348                 // the names have both been lowercased
00349                 if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
00350                     shader = skin->surfaces[j]->shader;
00351                     break;
00352                 }
00353             }
00354             if (shader == tr.defaultShader) {
00355                 ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name);
00356             }
00357             else if (shader->defaultShader) {
00358                 ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
00359             }
00360         } else if ( surface->numShaders <= 0 ) {
00361             shader = tr.defaultShader;
00362         } else {
00363             md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
00364             md3Shader += ent->e.skinNum % surface->numShaders;
00365             shader = tr.shaders[ md3Shader->shaderIndex ];
00366         }
00367 
00368 
00369         // we will add shadows even if the main object isn't visible in the view
00370 
00371         // stencil shadows can't do personal models unless I polyhedron clip
00372         if ( !personalModel
00373             && r_shadows->integer == 2 
00374             && fogNum == 0
00375             && !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) 
00376             && shader->sort == SS_OPAQUE ) {
00377             R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse );
00378         }
00379 
00380         // projection shadows work fine with personal models
00381         if ( r_shadows->integer == 3
00382             && fogNum == 0
00383             && (ent->e.renderfx & RF_SHADOW_PLANE )
00384             && shader->sort == SS_OPAQUE ) {
00385             R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
00386         }
00387 
00388         // don't add third_person objects if not viewing through a portal
00389         if ( !personalModel ) {
00390             R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
00391         }
00392 
00393         surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
00394     }
00395 
00396 }

Here is the call graph for this function:

int R_ComputeFogNum md3Header_t header,
trRefEntity_t ent
 

Definition at line 230 of file tr_mesh.c.

References fog_t::bounds, byte, trRefEntity_t::e, world_t::fogs, refEntity_t::frame, header, i, j, md3Frame_s::localOrigin, md3Frame_t, world_t::numfogs, refEntity_t::origin, md3Frame_s::radius, trRefdef_t::rdflags, trGlobals_t::refdef, tr, vec3_t, VectorAdd, and trGlobals_t::world.

Referenced by R_AddMD3Surfaces().

00230                                                                {
00231     int             i, j;
00232     fog_t           *fog;
00233     md3Frame_t      *md3Frame;
00234     vec3_t          localOrigin;
00235 
00236     if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
00237         return 0;
00238     }
00239 
00240     // FIXME: non-normalized axis issues
00241     md3Frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
00242     VectorAdd( ent->e.origin, md3Frame->localOrigin, localOrigin );
00243     for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
00244         fog = &tr.world->fogs[i];
00245         for ( j = 0 ; j < 3 ; j++ ) {
00246             if ( localOrigin[j] - md3Frame->radius >= fog->bounds[1][j] ) {
00247                 break;
00248             }
00249             if ( localOrigin[j] + md3Frame->radius <= fog->bounds[0][j] ) {
00250                 break;
00251             }
00252         }
00253         if ( j == 3 ) {
00254             return i;
00255         }
00256     }
00257 
00258     return 0;
00259 }

int R_ComputeLOD trRefEntity_t ent  ) 
 

Definition at line 166 of file tr_mesh.c.

References md3Frame_s::bounds, trGlobals_t::currentModel, trRefEntity_t::e, refEntity_t::frame, cvar_s::integer, model_s::md3, md3Frame_t, myftol, model_s::numLods, md3Header_t::ofsFrames, refEntity_t::origin, ProjectRadius(), r_lodbias, r_lodscale, RadiusFromBounds(), tr, and cvar_s::value.

Referenced by R_AddMD3Surfaces().

00166                                        {
00167     float radius;
00168     float flod, lodscale;
00169     float projectedRadius;
00170     md3Frame_t *frame;
00171     int lod;
00172 
00173     if ( tr.currentModel->numLods < 2 )
00174     {
00175         // model has only 1 LOD level, skip computations and bias
00176         lod = 0;
00177     }
00178     else
00179     {
00180         // multiple LODs exist, so compute projected bounding sphere
00181         // and use that as a criteria for selecting LOD
00182 
00183         frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
00184 
00185         frame += ent->e.frame;
00186 
00187         radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
00188 
00189         if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
00190         {
00191             lodscale = r_lodscale->value;
00192             if (lodscale > 20) lodscale = 20;
00193             flod = 1.0f - projectedRadius * lodscale;
00194         }
00195         else
00196         {
00197             // object intersects near view plane, e.g. view weapon
00198             flod = 0;
00199         }
00200 
00201         flod *= tr.currentModel->numLods;
00202         lod = myftol( flod );
00203 
00204         if ( lod < 0 )
00205         {
00206             lod = 0;
00207         }
00208         else if ( lod >= tr.currentModel->numLods )
00209         {
00210             lod = tr.currentModel->numLods - 1;
00211         }
00212     }
00213 
00214     lod += r_lodbias->integer;
00215     
00216     if ( lod >= tr.currentModel->numLods )
00217         lod = tr.currentModel->numLods - 1;
00218     if ( lod < 0 )
00219         lod = 0;
00220 
00221     return lod;
00222 }

Here is the call graph for this function:

int R_CullModel md3Header_t header,
trRefEntity_t ent
[static]
 

Definition at line 78 of file tr_mesh.c.

References md3Frame_s::bounds, byte, frontEndCounters_t::c_box_cull_md3_clip, frontEndCounters_t::c_box_cull_md3_in, frontEndCounters_t::c_box_cull_md3_out, frontEndCounters_t::c_sphere_cull_md3_clip, frontEndCounters_t::c_sphere_cull_md3_in, frontEndCounters_t::c_sphere_cull_md3_out, CULL_CLIP, CULL_IN, CULL_OUT, trRefEntity_t::e, refEntity_t::frame, header, i, md3Frame_s::localOrigin, md3Frame_t, refEntity_t::nonNormalizedAxes, refEntity_t::oldframe, trGlobals_t::pc, R_CullLocalBox(), R_CullLocalPointAndRadius(), md3Frame_s::radius, tr, and vec3_t.

Referenced by R_AddMD3Surfaces().

00078                                                                   {
00079     vec3_t      bounds[2];
00080     md3Frame_t  *oldFrame, *newFrame;
00081     int         i;
00082 
00083     // compute frame pointers
00084     newFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
00085     oldFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.oldframe;
00086 
00087     // cull bounding sphere ONLY if this is not an upscaled entity
00088     if ( !ent->e.nonNormalizedAxes )
00089     {
00090         if ( ent->e.frame == ent->e.oldframe )
00091         {
00092             switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
00093             {
00094             case CULL_OUT:
00095                 tr.pc.c_sphere_cull_md3_out++;
00096                 return CULL_OUT;
00097 
00098             case CULL_IN:
00099                 tr.pc.c_sphere_cull_md3_in++;
00100                 return CULL_IN;
00101 
00102             case CULL_CLIP:
00103                 tr.pc.c_sphere_cull_md3_clip++;
00104                 break;
00105             }
00106         }
00107         else
00108         {
00109             int sphereCull, sphereCullB;
00110 
00111             sphereCull  = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
00112             if ( newFrame == oldFrame ) {
00113                 sphereCullB = sphereCull;
00114             } else {
00115                 sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
00116             }
00117 
00118             if ( sphereCull == sphereCullB )
00119             {
00120                 if ( sphereCull == CULL_OUT )
00121                 {
00122                     tr.pc.c_sphere_cull_md3_out++;
00123                     return CULL_OUT;
00124                 }
00125                 else if ( sphereCull == CULL_IN )
00126                 {
00127                     tr.pc.c_sphere_cull_md3_in++;
00128                     return CULL_IN;
00129                 }
00130                 else
00131                 {
00132                     tr.pc.c_sphere_cull_md3_clip++;
00133                 }
00134             }
00135         }
00136     }
00137     
00138     // calculate a bounding box in the current coordinate system
00139     for (i = 0 ; i < 3 ; i++) {
00140         bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
00141         bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
00142     }
00143 
00144     switch ( R_CullLocalBox( bounds ) )
00145     {
00146     case CULL_IN:
00147         tr.pc.c_box_cull_md3_in++;
00148         return CULL_IN;
00149     case CULL_CLIP:
00150         tr.pc.c_box_cull_md3_clip++;
00151         return CULL_CLIP;
00152     case CULL_OUT:
00153     default:
00154         tr.pc.c_box_cull_md3_out++;
00155         return CULL_OUT;
00156     }
00157 }

Here is the call graph for this function:


Generated on Thu Aug 25 15:16:31 2005 for Quake III Arena by  doxygen 1.3.9.1