r_bsp.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "r_local.h"
00027 #include "r_lightmap.h"
00028 #include "r_material.h"
00029 #include "r_light.h"
00030 #include "r_draw.h"
00031 
00032 /*
00033 =============================================================
00034 BRUSH MODELS
00035 =============================================================
00036 */
00037 
00038 #define BACKFACE_EPSILON 0.01
00039 
00040 
00047 static qboolean R_CullBox (const vec3_t mins, const vec3_t maxs)
00048 {
00049     int i;
00050 
00051     if (r_nocull->integer)
00052         return qfalse;
00053 
00054     for (i = lengthof(r_locals.frustum) - 1; i >= 0; i--)
00055         if (TR_BoxOnPlaneSide(mins, maxs, &r_locals.frustum[i]) == PSIDE_BACK)
00056             return qtrue;
00057     return qfalse;
00058 }
00059 
00060 
00068 qboolean R_CullSphere (const vec3_t centre, const float radius, const unsigned int clipflags)
00069 {
00070     unsigned int i;
00071     unsigned int bit;
00072     const cBspPlane_t *p;
00073 
00074     if (r_nocull->integer)
00075         return qfalse;
00076 
00077     for (i = lengthof(r_locals.frustum), bit = 1, p = r_locals.frustum; i > 0; i--, bit <<= 1, p++) {
00078         if (!(clipflags & bit))
00079             continue;
00080         if (DotProduct(centre, p->normal) - p->dist <= -radius)
00081             return qtrue;
00082     }
00083 
00084     return qfalse;
00085 }
00086 
00093 qboolean R_CullBspModel (const entity_t *e)
00094 {
00095     vec3_t mins, maxs, entOrigin;
00096 
00097     /* no surfaces */
00098     if (!e->model->bsp.nummodelsurfaces)
00099         return qtrue;
00100 
00101     VectorCopy(*R_EntityGetOrigin(e), entOrigin);
00102     if (e->isOriginBrushModel) {
00103         int i;
00104         for (i = 0; i < 3; i++) {
00105             mins[i] = entOrigin[i] - e->model->radius;
00106             maxs[i] = entOrigin[i] + e->model->radius;
00107         }
00108     } else {
00109         VectorAdd(entOrigin, e->model->mins, mins);
00110         VectorAdd(entOrigin, e->model->maxs, maxs);
00111     }
00112 
00113     return R_CullBox(mins, maxs);
00114 }
00115 
00121 static void R_DrawBspModelSurfaces (const entity_t *e, const vec3_t modelorg)
00122 {
00123     int i;
00124     mBspSurface_t *surf;
00125 
00126     /* temporarily swap the view frame so that the surface drawing
00127      * routines pickup only the bsp model's surfaces */
00128     const int f = r_locals.frame;
00129     r_locals.frame = -1;
00130 
00131     surf = &e->model->bsp.surfaces[e->model->bsp.firstmodelsurface];
00132 
00133     for (i = 0; i < e->model->bsp.nummodelsurfaces; i++, surf++) {
00135 #if 0
00136         float dot;
00137         /* find which side of the surf we are on  */
00138         if (AXIAL(surf->plane))
00139             dot = modelorg[surf->plane->type] - surf->plane->dist;
00140         else
00141             dot = DotProduct(modelorg, surf->plane->normal) - surf->plane->dist;
00142 
00143         if (((surf->flags & MSURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
00144             (!(surf->flags & MSURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
00145 #endif
00146             /* visible flag for rendering */
00147             surf->frame = r_locals.frame;
00148     }
00149 
00150     R_DrawOpaqueSurfaces(e->model->bsp.opaque_surfaces);
00151 
00152     R_DrawOpaqueWarpSurfaces(e->model->bsp.opaque_warp_surfaces);
00153 
00154     R_DrawAlphaTestSurfaces(e->model->bsp.alpha_test_surfaces);
00155 
00156     R_EnableBlend(qtrue);
00157 
00158     R_DrawMaterialSurfaces(e->model->bsp.material_surfaces);
00159 
00160     R_DrawFlareSurfaces(e->model->bsp.flare_surfaces);
00161 
00162     R_EnableFog(qfalse);
00163 
00164     R_DrawBlendSurfaces(e->model->bsp.blend_surfaces);
00165 
00166     R_DrawBlendWarpSurfaces(e->model->bsp.blend_warp_surfaces);
00167 
00168     R_EnableFog(qtrue);
00169 
00170     R_EnableBlend(qfalse);
00171 
00172     /* undo the swap */
00173     r_locals.frame = f;
00174 }
00175 
00181 void R_DrawBrushModel (const entity_t * e)
00182 {
00183     /* relative to viewpoint */
00184     vec3_t modelorg, entOrigin;
00185 
00186     VectorCopy(*R_EntityGetOrigin(e), entOrigin);
00187 
00188     /* set the relative origin, accounting for rotation if necessary */
00189     VectorSubtract(refdef.viewOrigin, entOrigin, modelorg);
00190     if (VectorNotEmpty(e->angles)) {
00191         vec3_t rotationMatrix[3];
00192         VectorCreateRotationMatrix(e->angles, rotationMatrix);
00193         VectorRotatePoint(modelorg, rotationMatrix);
00194     }
00195 
00196     R_ShiftLights(entOrigin);
00197 
00198     glPushMatrix();
00199 
00200     glTranslatef(entOrigin[0], entOrigin[1], entOrigin[2]);
00201     glRotatef(e->angles[YAW], 0, 0, 1);
00202     glRotatef(e->angles[PITCH], 0, 1, 0);
00203     glRotatef(e->angles[ROLL], 1, 0, 0);
00204 
00205     R_DrawBspModelSurfaces(e, modelorg);
00206 
00207     /* show model bounding box */
00208     if (r_showbox->integer)
00209         R_DrawBoundingBox(e->model->mins, e->model->maxs);
00210 
00211     glPopMatrix();
00212 
00213     R_ShiftLights(vec3_origin);
00214 }
00215 
00216 
00217 /*
00218 =============================================================
00219 WORLD MODEL
00220 =============================================================
00221 */
00222 
00227 void R_DrawBspNormals (int tile)
00228 {
00229     int i, j, k;
00230     const mBspSurface_t *surf;
00231     const mBspModel_t *bsp;
00232     const vec4_t color = {1.0, 0.0, 0.0, 1.0};
00233 
00234     if (!r_shownormals->integer)
00235         return;
00236 
00237     R_EnableTexture(&texunit_diffuse, qfalse);
00238 
00239     R_ResetArrayState();  /* default arrays */
00240 
00241     R_Color(color);
00242 
00243     k = 0;
00244     bsp = &r_mapTiles[tile]->bsp;
00245     surf = bsp->surfaces;
00246     for (i = 0; i < bsp->numsurfaces; i++, surf++) {
00247         if (surf->frame != r_locals.frame)
00248             continue; /* not visible */
00249 
00250         if (surf->texinfo->flags & SURF_WARP)
00251             continue;  /* don't care */
00252 
00253         if (r_shownormals->integer > 1 && !(surf->texinfo->flags & SURF_PHONG))
00254             continue;  /* don't care */
00255 
00256         /* avoid overflows, draw in batches */
00257         if (k > MAX_GL_ARRAY_LENGTH - 512) {
00258             glDrawArrays(GL_LINES, 0, k / 3);
00259             k = 0;
00260         }
00261 
00262         for (j = 0; j < surf->numedges; j++) {
00263             vec3_t end;
00264             const GLfloat *vertex = &bsp->verts[(surf->index + j) * 3];
00265             const GLfloat *normal = &bsp->normals[(surf->index + j) * 3];
00266 
00267             VectorMA(vertex, 12.0, normal, end);
00268 
00269             memcpy(&r_state.vertex_array_3d[k], vertex, sizeof(vec3_t));
00270             memcpy(&r_state.vertex_array_3d[k + 3], end, sizeof(vec3_t));
00271             k += sizeof(vec3_t) / sizeof(vec_t) * 2;
00272             if (k > MAX_GL_ARRAY_LENGTH)
00273                 Com_Error(ERR_DROP, "R_DrawBspNormals: Overflow in array buffer");
00274         }
00275     }
00276 
00277     glDrawArrays(GL_LINES, 0, k / 3);
00278 
00279     R_EnableTexture(&texunit_diffuse, qtrue);
00280 
00281     R_Color(NULL);
00282 }
00283 
00292 static void R_RecursiveWorldNode (const mBspNode_t * node, int tile)
00293 {
00294     int i, side, sidebit;
00295     mBspSurface_t *surf;
00296     float dot;
00297 
00298     if (node->contents == CONTENTS_SOLID)
00299         return;                 /* solid */
00300 
00301     if (R_CullBox(node->minmaxs, node->minmaxs + 3))
00302         return;                 /* culled out */
00303 
00304     /* if a leaf node, draw stuff */
00305     if (node->contents > CONTENTS_NODE)
00306         return;
00307 
00308     /* pathfinding nodes are invalid here */
00309     assert(node->plane);
00310 
00311     /* node is just a decision point, so go down the appropriate sides
00312      * find which side of the node we are on */
00313     if (r_isometric->integer) {
00314         dot = -DotProduct(r_locals.forward, node->plane->normal);
00315     } else if (!AXIAL(node->plane)) {
00316         dot = DotProduct(refdef.viewOrigin, node->plane->normal) - node->plane->dist;
00317     } else {
00318         dot = refdef.viewOrigin[node->plane->type] - node->plane->dist;
00319     }
00320 
00321     if (dot >= 0) {
00322         side = 0;
00323         sidebit = 0;
00324     } else {
00325         side = 1;
00326         sidebit = MSURF_PLANEBACK;
00327     }
00328 
00329     /* recurse down the children, front side first */
00330     R_RecursiveWorldNode(node->children[side], tile);
00331 
00332     surf = r_mapTiles[tile]->bsp.surfaces + node->firstsurface;
00333     for (i = 0; i < node->numsurfaces; i++, surf++) {
00334         /* visible (front) side */
00335         if ((surf->flags & MSURF_PLANEBACK) == sidebit)
00336             surf->frame = r_locals.frame;
00337     }
00338 
00339     /* recurse down the back side */
00340     R_RecursiveWorldNode(node->children[!side], tile);
00341 }
00342 
00350 static void R_RecurseWorld (const mBspNode_t * node, int tile)
00351 {
00352     /* skip special pathfinding nodes */
00353     if (node->contents == CONTENTS_PATHFINDING_NODE) {
00354         R_RecurseWorld(node->children[0], tile);
00355         R_RecurseWorld(node->children[1], tile);
00356     } else {
00357         R_RecursiveWorldNode(node, tile);
00358     }
00359 }
00360 
00361 
00366 void R_GetLevelSurfaceLists (void)
00367 {
00368     int i, tile, mask;
00369 
00370     r_locals.frame++;
00371 
00372     /* avoid overflows, negatives are reserved */
00373     if (r_locals.frame > 0xffff)
00374         r_locals.frame = 0;
00375 
00376     if (!r_drawworld->integer)
00377         return;
00378 
00379     mask = 1 << refdef.worldlevel;
00380 
00381     for (tile = 0; tile < r_numMapTiles; tile++) {
00382         /* don't draw weaponclip, actorclip and stepon */
00383         for (i = 0; i <= LEVEL_LASTVISIBLE; i++) {
00384             /* check the worldlevel flags */
00385             if (i && !(i & mask))
00386                 continue;
00387 
00388             if (!r_mapTiles[tile]->bsp.submodels[i].numfaces)
00389                 continue;
00390 
00391             R_RecurseWorld(r_mapTiles[tile]->bsp.nodes + r_mapTiles[tile]->bsp.submodels[i].headnode, tile);
00392         }
00393     }
00394 }

Generated by  doxygen 1.6.2