/** * @brief Recurse down the bsp tree and mark surfaces that are visible (not culled) * for being rendered * @sa R_DrawWorld * @sa R_RecurseWorld * @sa R_RecursiveVisibleWorldNode * @param[in] node The bsp node to check * @param[in] tile The maptile (map assembly) */ static void R_RecursiveWorldNode (const mBspNode_t* node, int tile) { int i; int cullState; mBspSurface_t* surf; /* if a leaf node, nothing to mark */ if (node->contents > CONTENTS_NODE) return; cullState = R_CullBox(node->minmaxs, node->minmaxs + 3); if (cullState == PSIDE_BACK) return; /* culled out */ /* pathfinding nodes are invalid here */ assert(node->plane); surf = r_mapTiles[tile]->bsp.surfaces + node->firstsurface; for (i = 0; i < node->numsurfaces; i++, surf++) surf->frame = r_locals.frame; /* recurse down the children */ /** @todo avoid being too precise, it's a waste of CPU time; possibly, granularity of 256x256x256 should be enough */ if (cullState == PSIDE_FRONT) { /* completely inside the frustum - no need to do any further checks */ R_RecursiveVisibleWorldNode(node->children[0], tile); R_RecursiveVisibleWorldNode(node->children[1], tile); } else { /* partially clipped by frustum - recurse to do finer checks */ R_RecursiveWorldNode(node->children[0], tile); R_RecursiveWorldNode(node->children[1], tile); } }
/* ================ R_RenderWorld ================ */ void R_RenderWorld(void) { VectorCopy(r_origin, modelorg); r_pcurrentvertbase = r_worldentity.model->vertexes; R_RecursiveWorldNode(&r_worldentity, r_worldentity.model->nodes); }
/* ================ R_RenderWorld ================ */ void R_RenderWorld (void) { int i; model_t *clmodel; btofpoly_t btofpolys[MAX_BTOFPOLYS]; pbtofpolys = btofpolys; currententity = &cl_entities[0]; VectorCopy (r_origin, modelorg); clmodel = currententity->model; r_pcurrentvertbase = clmodel->vertexes; R_RecursiveWorldNode (clmodel->nodes, 15); // if the driver wants the polygons back to front, play the visible ones back // in that order if (r_worldpolysbacktofront) { for (i=numbtofpolys-1 ; i>=0 ; i--) { R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); } } }
/** * @brief Wrapper that recurses the bsp nodes but skip the pathfinding nodes * @sa R_GetLevelSurfaceLists * @param[in] node The bsp node to check * @param[in] tile The maptile (map assembly) * @sa R_ModLoadNodes about pathfinding nodes */ static void R_RecurseWorld (const mBspNode_t* node, int tile) { /* skip special pathfinding nodes */ if (node->contents == CONTENTS_PATHFINDING_NODE) { R_RecurseWorld(node->children[0], tile); R_RecurseWorld(node->children[1], tile); } else { R_RecursiveWorldNode(node, tile); } }
void R_RenderWorld (void) { model_t *clmodel; currententity = &r_worldentity; VectorCopy (r_origin, modelorg); clmodel = currententity->model; r_pcurrentvertbase = clmodel->vertexes; R_RecursiveWorldNode (clmodel->nodes, 15); }
/* * R_DrawWorld */ void R_DrawWorld( void ) { int clipFlags, msec = 0; unsigned int dlightBits; unsigned int shadowBits; bool worldOutlines; if( !r_drawworld->integer ) return; if( !rsh.worldModel ) return; if( rn.renderFlags & RF_SHADOWMAPVIEW ) return; VectorCopy( rn.refdef.vieworg, modelOrg ); worldOutlines = mapConfig.forceWorldOutlines || ( rn.refdef.rdflags & RDF_WORLDOUTLINES ); if( worldOutlines && (rf.viewcluster != -1) && r_outlines_scale->value > 0 ) rsc.worldent->outlineHeight = max( 0.0f, r_outlines_world->value ); else rsc.worldent->outlineHeight = 0; Vector4Copy( mapConfig.outlineColor, rsc.worldent->outlineColor ); if( r_nocull->integer ) clipFlags = 0; else clipFlags = rn.clipFlags; // dynamic lights if( r_dynamiclight->integer != 1 || r_fullbright->integer || rn.renderFlags & RF_ENVVIEW ) { dlightBits = 0; } else { dlightBits = rsc.numDlights < 32 ? ( 1 << rsc.numDlights ) - 1 : ~0; } // shadowmaps if( rn.renderFlags & RF_ENVVIEW ) { shadowBits = 0; } else { shadowBits = rsc.numShadowGroups < 32 ? ( 1 << rsc.numShadowGroups ) - 1 : ~0; } if( r_speeds->integer ) msec = ri.Sys_Milliseconds(); R_RecursiveWorldNode( rsh.worldBrushModel->nodes, clipFlags, dlightBits, shadowBits ); if( r_speeds->integer ) rf.stats.t_world_node += ri.Sys_Milliseconds() - msec; }
/* ================ R_RenderWorld ================ */ void R_RenderWorld(void) { if (!r_drawworld->integer) return; if (r_newrefdef.rdflags & RDF_NOWORLDMODEL) return; c_drawnode = 0; // auto cycle the world frame for texture animation r_worldentity.frame = (int)(r_newrefdef.time * 2); currententity = &r_worldentity; VectorCopy(r_origin, modelorg); R_RecursiveWorldNode(r_worldmodel->nodes, 15); }
void R_DrawWorld(void) { entity_t ent; float modelorg[3]; memset(&ent, 0, sizeof (ent)); ent.model = cl.worldmodel; VectorCopy(r_refdef.vieworg, modelorg); glColor3f(1, 1, 1); memset(lightmap_polys, 0, sizeof (lightmap_polys)); //draw the display list R_RecursiveWorldNode(cl.worldmodel->nodes, &modelorg[0]); //draw the world normally Surf_DrawTextureChainsFour(cl.worldmodel); }
/* * R_RecursiveWorldNode */ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipFlags, unsigned int dlightBits, unsigned int shadowBits ) { unsigned int i; unsigned int dlightBits1; unsigned int shadowBits1; unsigned int bit; const cplane_t *clipplane; mleaf_t *pleaf; while( 1 ) { if( node->pvsframe != rf.pvsframecount ) return; if( clipFlags ) { for( i = sizeof( rn.frustum )/sizeof( rn.frustum[0] ), bit = 1, clipplane = rn.frustum; i > 0; i--, bit<<=1, clipplane++ ) { if( clipFlags & bit ) { int clipped = BoxOnPlaneSide( node->mins, node->maxs, clipplane ); if( clipped == 2 ) return; else if( clipped == 1 ) clipFlags &= ~bit; // node is entirely on screen } } } if( !node->plane ) break; dlightBits1 = 0; if( dlightBits ) { float dist; unsigned int checkBits = dlightBits; for( i = 0, bit = 1; i < rsc.numDlights; i++, bit <<= 1 ) { dlight_t *dl = rsc.dlights + i; if( dlightBits & bit ) { dist = PlaneDiff( dl->origin, node->plane ); if( dist < -dl->intensity ) dlightBits &= ~bit; if( dist < dl->intensity ) dlightBits1 |= bit; checkBits &= ~bit; if( !checkBits ) break; } } } shadowBits1 = 0; if( shadowBits ) { unsigned int checkBits = shadowBits; for( i = 0; i < rsc.numShadowGroups; i++ ) { shadowGroup_t *group = rsc.shadowGroups + i; bit = group->bit; if( checkBits & bit ) { int clipped = BOX_ON_PLANE_SIDE( group->visMins, group->visMaxs, node->plane ); if( !(clipped & 1) ) shadowBits &= ~bit; if( clipped & 2 ) shadowBits1 |= bit; checkBits &= ~bit; if( !checkBits ) break; } } } R_RecursiveWorldNode( node->children[0], clipFlags, dlightBits, shadowBits ); node = node->children[1]; dlightBits = dlightBits1; shadowBits = shadowBits1; } // if a leaf node, draw stuff pleaf = ( mleaf_t * )node; pleaf->visframe = rf.frameCount; // add leaf bounds to view bounds for( i = 0; i < 3; i++ ) { rn.visMins[i] = min( rn.visMins[i], pleaf->mins[i] ); rn.visMaxs[i] = max( rn.visMaxs[i], pleaf->maxs[i] ); } rn.dlightBits |= dlightBits; rn.shadowBits |= shadowBits; R_MarkLeafSurfaces( pleaf->firstVisSurface, clipFlags, dlightBits, shadowBits ); rf.stats.c_world_leafs++; }
/* ================ R_RecursiveWorldNode ================ */ static void R_RecursiveWorldNode(mnode_t *node, int clipflags) { int i, c, side, *pindex; vec3_t acceptpt, rejectpt; cplane_t *plane; mface_t *surf, **mark; float d, dot; mleaf_t *pleaf; while (node->visframe == r_visframecount) { // cull the clipping planes if not trivial accept // FIXME: the compiler is doing a lousy job of optimizing here; it could be // twice as fast in ASM if (clipflags) { for (i = 0; i < 4; i++) { if (!(clipflags & (1 << i))) continue; // don't need to clip against it // generate accept and reject points // FIXME: do with fast look-ups or integer tests based on the sign bit // of the floating point values pindex = pfrustum_indexes[i]; rejectpt[0] = (float)node->minmaxs[pindex[0]]; rejectpt[1] = (float)node->minmaxs[pindex[1]]; rejectpt[2] = (float)node->minmaxs[pindex[2]]; d = PlaneDiff(rejectpt, &view_clipplanes[i]); if (d <= 0) return; acceptpt[0] = (float)node->minmaxs[pindex[3 + 0]]; acceptpt[1] = (float)node->minmaxs[pindex[3 + 1]]; acceptpt[2] = (float)node->minmaxs[pindex[3 + 2]]; d = PlaneDiff(acceptpt, &view_clipplanes[i]); if (d >= 0) clipflags &= ~(1 << i); // node is entirely on screen } } c_drawnode++; // if a leaf node, draw stuff if (!node->plane) { pleaf = (mleaf_t *)node; if (pleaf->contents == CONTENTS_SOLID) return; // solid // check for door connected areas if (r_newrefdef.areabits) { if (! Q_IsBitSet(r_newrefdef.areabits, pleaf->area)) return; // not visible } mark = pleaf->firstleafface; c = pleaf->numleaffaces; if (c) { do { (*mark)->drawframe = r_framecount; mark++; } while (--c); } pleaf->key = r_currentkey; r_currentkey++; // all bmodels in a leaf share the same key return; } // node is just a decision point, so go down the apropriate sides // find which side of the node we are on plane = node->plane; dot = PlaneDiffFast(modelorg, plane); if (dot >= 0) side = 0; else side = 1; // recurse down the children, front side first R_RecursiveWorldNode(node->children[side], clipflags); // draw stuff c = node->numfaces; if (c) { surf = node->firstface; if (dot < -BACKFACE_EPSILON) { do { if ((surf->drawflags & DSURF_PLANEBACK) && (surf->drawframe == r_framecount)) { R_RenderFace(surf, clipflags); } surf++; } while (--c); } else if (dot > BACKFACE_EPSILON) { do { if (!(surf->drawflags & DSURF_PLANEBACK) && (surf->drawframe == r_framecount)) { R_RenderFace(surf, clipflags); } surf++; } while (--c); } // all surfaces on the same node share the same sequence number r_currentkey++; } // recurse down the back side node = node->children[side ^ 1]; } }
void R_RecursiveWorldNode(mnode_t *node, float *modelorg) { int c, side; mplane_t *plane; msurface_t *surf, **mark; mleaf_t *pleaf; double dot; //make sure we are still inside the world if (node->contents == CONTENTS_SOLID) return; // solid //is this node visable if (node->visframe != r_visframecount) return; //i think this checks if its on the screen and not behind the viewer if (R_CullBox(node->minmaxs, node->minmaxs + 3)) return; // if a leaf node, draw stuff if (node->contents < 0) { pleaf = (mleaf_t *) node; mark = pleaf->firstmarksurface; c = pleaf->nummarksurfaces; if (c) { do { (*mark)->visframe = r_framecount; mark++; } while (--c); } // deal with model fragments in this leaf if (pleaf->efrags) R_StoreEfrags(&pleaf->efrags); return; } // node is just a decision point, so go down the apropriate sides // find which side of the node we are on plane = node->plane; switch (plane->type) { case PLANE_X: dot = modelorg[0] - plane->dist; break; case PLANE_Y: dot = modelorg[1] - plane->dist; break; case PLANE_Z: dot = modelorg[2] - plane->dist; break; default: dot = DotProduct(modelorg, plane->normal) - plane->dist; break; } if (dot >= 0) side = 0; else side = 1; // recurse down the children, front side first R_RecursiveWorldNode(node->children[side], modelorg); // recurse down the back side if (r_outline.getBool()) R_RecursiveWorldNode(node->children[!side], modelorg); // draw stuff c = node->numsurfaces; if (c) { surf = cl.worldmodel->surfaces + node->firstsurface; { for (; c; c--, surf++) { if (surf->visframe != r_framecount) continue; if (surf->flags & SURF_DRAWSKY) { surf->texturechain = skychain; skychain = surf; } else if (surf->flags & SURF_DRAWTURB) { surf->texturechain = waterchain; waterchain = surf; } else { //add chain for drawing. surf->texturechain = surf->texinfo->texture->texturechain; surf->texinfo->texture->texturechain = surf; //setup eyecandy chain if ((surf->flags & SURF_UNDERWATER && gl_caustics.getBool()) || (surf->flags & SURF_SHINY_METAL && gl_shiny.getBool()) || (surf->flags & SURF_SHINY_GLASS && gl_shiny.getBool())) { surf->extra = extrachain; extrachain = surf; } if (r_outline.getBool()) { surf->outline = outlinechain; outlinechain = surf; } } } } } // recurse down the back side if (!r_outline.getBool()) R_RecursiveWorldNode(node->children[!side], modelorg); }
/* ================ R_RenderWorld ================ */ void R_RenderWorld (void) { int i; model_t *clmodel; btofpoly_t btofpolys[MAX_BTOFPOLYS]; GpError("A",8); pbtofpolys = btofpolys; currententity = &cl_entities[0]; VectorCopy (r_origin, modelorg); #ifdef USE_PQ_OPT1 modelorg_fxp[0]=(int)(r_origin[0]*524288.0); modelorg_fxp[1]=(int)(r_origin[1]*524288.0); modelorg_fxp[2]=(int)(r_origin[2]*524288.0); //modelorg_fxp[0]=(int)(r_origin[0]*65536.0); //modelorg_fxp[1]=(int)(r_origin[1]*65536.0); //modelorg_fxp[2]=(int)(r_origin[2]*65536.0); vright_fxp[0]=(int)(256.0/vright[0]); if (!vright_fxp[0]) vright_fxp[0]=0x7fffffff; vright_fxp[1]=(int)(256.0/vright[1]); if (!vright_fxp[1]) vright_fxp[1]=0x7fffffff; vright_fxp[2]=(int)(256.0/vright[2]); if (!vright_fxp[2]) vright_fxp[2]=0x7fffffff; vpn_fxp[0]=(int)(256.0/vpn[0]); if (!vpn_fxp[0]) vpn_fxp[0]=0x7fffffff; vpn_fxp[1]=(int)(256.0/vpn[1]); if (!vpn_fxp[1]) vpn_fxp[1]=0x7fffffff; vpn_fxp[2]=(int)(256.0/vpn[2]); if (!vpn_fxp[2]) vpn_fxp[2]=0x7fffffff; vup_fxp[0]=(int)(256.0/vup[0]); if (!vup_fxp[0]) vup_fxp[0]=0x7fffffff; vup_fxp[1]=(int)(256.0/vup[1]); if (!vup_fxp[1]) vup_fxp[1]=0x7fffffff; vup_fxp[2]=(int)(256.0/vup[2]); if (!vup_fxp[2]) vup_fxp[2]=0x7fffffff; #endif clmodel = currententity->model; r_pcurrentvertbase = clmodel->vertexes; #ifdef USE_PQ_OPT2 r_pcurrentvertbase_fxp = clmodel->vertexes_fxp; #endif #ifdef USE_PQ_OPT1 //Dan Fixed point conversion stuff for (i=0; i<4; i++) { clipplanes_fxp[i][0]=(int)(view_clipplanes[i].normal[0]*65536.0); clipplanes_fxp[i][1]=(int)(view_clipplanes[i].normal[1]*65536.0); clipplanes_fxp[i][2]=(int)(view_clipplanes[i].normal[2]*65536.0); clipdist_fxp[i] =(int)(view_clipplanes[i].dist*65536.0); #ifdef USE_PQ_OPT2 view_clipplanes_fxp[i].leftedge=view_clipplanes[i].leftedge; view_clipplanes_fxp[i].rightedge=view_clipplanes[i].rightedge; if (!view_clipplanes[i].normal[0]) view_clipplanes_fxp[i].normal[0]=2<<29; else view_clipplanes_fxp[i].normal[0]=(int)(4096.0f/view_clipplanes[i].normal[0]); if (!view_clipplanes[i].normal[0]) view_clipplanes_fxp[i].normal[0]=2<<29; if (!view_clipplanes[i].normal[1]) view_clipplanes_fxp[i].normal[1]=2<<29; else view_clipplanes_fxp[i].normal[1]=(int)(4096.0f/view_clipplanes[i].normal[1]); if (!view_clipplanes[i].normal[1]) view_clipplanes_fxp[i].normal[1]=2<<29; if (!view_clipplanes[i].normal[2]) view_clipplanes_fxp[i].normal[2]=2<<29; else view_clipplanes_fxp[i].normal[2]=(int)(4096.0f/view_clipplanes[i].normal[2]); if (!view_clipplanes[i].normal[2]) view_clipplanes_fxp[i].normal[2]=2<<29; view_clipplanes_fxp[i].dist=(int)(view_clipplanes[i].dist*128.0f); #endif #if defined(_X86_)&&defined(DEBUG) LogFloat(view_clipplanes[i].normal[0], "view_clipplanes[i].normal[0]", i, -1); LogFloat(view_clipplanes[i].normal[1], "view_clipplanes[i].normal[1]", i, -1); LogFloat(view_clipplanes[i].normal[2], "view_clipplanes[i].normal[2]", i, -1); #endif } #endif R_RecursiveWorldNode (clmodel->nodes, 15); // if the driver wants the polygons back to front, play the visible ones back // in that order if (r_worldpolysbacktofront) { for (i=numbtofpolys-1 ; i>=0 ; i--) { R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); } } }
/* ================ R_RecursiveWorldNode ================ */ void R_RecursiveWorldNode (mnode_t *node, int clipflags) { int i, c, side, *pindex; mplane_t *plane; msurface_t *surf, **mark; mleaf_t *pleaf; double dot; #ifdef USE_PQ_OPT1 int d_fxp; #else double d; vec3_t acceptpt, rejectpt; #endif if (node->contents == CONTENTS_SOLID) return; // solid if (node->visframe != r_visframecount) return; // cull the clipping planes if not trivial accept // FIXME: the compiler is doing a lousy job of optimizing here; it could be // twice as fast in ASM if (clipflags) { for (i=0 ; i<4 ; i++) { if (! (clipflags & (1<<i)) ) continue; // don't need to clip against it // generate accept and reject points // FIXME: do with fast look-ups or integer tests based on the sign bit // of the floating point values pindex = pfrustum_indexes[i]; #ifdef USE_PQ_OPT1 d_fxp=node->minmaxs[pindex[0]]*clipplanes_fxp[i][0]+node->minmaxs[pindex[1]]*clipplanes_fxp[i][1]+node->minmaxs[pindex[2]]*clipplanes_fxp[i][2]; d_fxp-=clipdist_fxp[i]; if (d_fxp <= 0) return; d_fxp=node->minmaxs[pindex[3]]*clipplanes_fxp[i][0]+node->minmaxs[pindex[4]]*clipplanes_fxp[i][1]+node->minmaxs[pindex[5]]*clipplanes_fxp[i][2]; d_fxp-=clipdist_fxp[i]; if (d_fxp >= 0) clipflags &= ~(1<<i); // node is entirely on screen #else rejectpt[0] = (float)node->minmaxs[pindex[0]]; rejectpt[1] = (float)node->minmaxs[pindex[1]]; rejectpt[2] = (float)node->minmaxs[pindex[2]]; d = DotProduct (rejectpt, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) return; acceptpt[0] = (float)node->minmaxs[pindex[3+0]]; acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; d = DotProduct (acceptpt, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d >= 0) clipflags &= ~(1<<i); // node is entirely on screen #endif } } // if a leaf node, draw stuff if (node->contents < 0) { pleaf = (mleaf_t *)node; mark = pleaf->firstmarksurface; c = pleaf->nummarksurfaces; if (c) { do { (*mark)->visframe = r_framecount; mark++; } while (--c); } // deal with model fragments in this leaf if (pleaf->efrags) { R_StoreEfrags (&pleaf->efrags); } pleaf->key = r_currentkey; r_currentkey++; // all bmodels in a leaf share the same key } else { // node is just a decision point, so go down the apropriate sides // find which side of the node we are on plane = node->plane; switch (plane->type) { case PLANE_X: dot = modelorg[0] - plane->dist; break; case PLANE_Y: dot = modelorg[1] - plane->dist; break; case PLANE_Z: dot = modelorg[2] - plane->dist; break; default: dot = DotProduct (modelorg, plane->normal) - plane->dist; break; } if (dot >= 0) side = 0; else side = 1; // recurse down the children, front side first R_RecursiveWorldNode (node->children[side], clipflags); // draw stuff c = node->numsurfaces; if (c) { surf = cl.worldmodel->surfaces + node->firstsurface; if (dot < -BACKFACE_EPSILON) { do { if ((surf->flags & SURF_PLANEBACK) && (surf->visframe == r_framecount)) { if (r_drawpolys) { if (r_worldpolysbacktofront) { if (numbtofpolys < MAX_BTOFPOLYS) { pbtofpolys[numbtofpolys].clipflags = clipflags; pbtofpolys[numbtofpolys].psurf = surf; numbtofpolys++; } } else { R_RenderPoly (surf, clipflags); } } else { R_RenderFace (surf, clipflags); } } surf++; } while (--c); } else if (dot > BACKFACE_EPSILON) { do { if (!(surf->flags & SURF_PLANEBACK) && (surf->visframe == r_framecount)) { if (r_drawpolys) { if (r_worldpolysbacktofront) { if (numbtofpolys < MAX_BTOFPOLYS) { pbtofpolys[numbtofpolys].clipflags = clipflags; pbtofpolys[numbtofpolys].psurf = surf; numbtofpolys++; } } else { R_RenderPoly (surf, clipflags); } } else { R_RenderFace (surf, clipflags); } } surf++; } while (--c); } // all surfaces on the same node share the same sequence number r_currentkey++; } // recurse down the back side R_RecursiveWorldNode (node->children[!side], clipflags); } }
/* ================ R_RecursiveWorldNode ================ */ static void R_RecursiveWorldNode(const entity_t *e, mnode_t *node) { int count, side; mplane_t *plane; msurface_t *surf; mleaf_t *pleaf; vec_t dot; if (node->contents == CONTENTS_SOLID) return; if (node->visframe != r_visframecount) return; if (node->clipflags == BMODEL_FULLY_CLIPPED) return; /* if a leaf node, draw stuff */ if (node->contents < 0) { pleaf = (mleaf_t *)node; pleaf->key = r_currentkey; r_currentkey++; // all bmodels in a leaf share the same key return; } /* * The node is a decision point, so go down the apropriate sides. * Find which side of the node we are on. */ plane = node->plane; switch (plane->type) { case PLANE_X: dot = modelorg[0] - plane->dist; break; case PLANE_Y: dot = modelorg[1] - plane->dist; break; case PLANE_Z: dot = modelorg[2] - plane->dist; break; default: dot = DotProduct(modelorg, plane->normal) - plane->dist; break; } side = (dot >= 0) ? 0 : 1; /* recurse down the children, front side first */ R_RecursiveWorldNode(e, node->children[side]); /* draw stuff */ count = node->numsurfaces; if (count) { surf = cl.worldmodel->surfaces + node->firstsurface; for (count = node->numsurfaces; count; count--, surf++) { if (surf->visframe != r_visframecount) continue; if (surf->clipflags == BMODEL_FULLY_CLIPPED) continue; R_RenderFace(e, surf, surf->clipflags); } /* all surfaces on the same node share the same sequence number */ r_currentkey++; } /* recurse down the back side */ R_RecursiveWorldNode(e, node->children[!side]); }
/* * R_DrawWorld */ void R_DrawWorld( void ) { unsigned int i; int clipFlags, msec = 0; unsigned int dlightBits; unsigned int shadowBits; bool worldOutlines; if( !r_drawworld->integer ) return; if( !rsh.worldModel ) return; if( rn.renderFlags & RF_SHADOWMAPVIEW ) return; VectorCopy( rn.refdef.vieworg, modelOrg ); worldOutlines = mapConfig.forceWorldOutlines || ( rn.refdef.rdflags & RDF_WORLDOUTLINES ); if( worldOutlines && (rf.viewcluster != -1) && r_outlines_scale->value > 0 ) rsc.worldent->outlineHeight = max( 0.0f, r_outlines_world->value ); else rsc.worldent->outlineHeight = 0; Vector4Copy( mapConfig.outlineColor, rsc.worldent->outlineColor ); clipFlags = rn.clipFlags; dlightBits = 0; shadowBits = 0; if( r_nocull->integer ) clipFlags = 0; // cull dynamic lights if( !( rn.renderFlags & RF_ENVVIEW ) ) { if( r_dynamiclight->integer == 1 && !r_fullbright->integer ) { for( i = 0; i < rsc.numDlights; i++ ) { if( R_CullSphere( rsc.dlights[i].origin, rsc.dlights[i].intensity, clipFlags ) ) { continue; } dlightBits |= 1<<i; } } } // cull shadowmaps if( !( rn.renderFlags & RF_ENVVIEW ) ) { for( i = 0; i < rsc.numShadowGroups; i++ ) { shadowGroup_t *grp = rsc.shadowGroups + i; if( R_CullBox( grp->visMins, grp->visMaxs, clipFlags ) ) { continue; } shadowBits |= grp->bit; } } rn.dlightBits = dlightBits; rn.shadowBits = shadowBits; if( r_speeds->integer ) msec = ri.Sys_Milliseconds(); R_RecursiveWorldNode( rsh.worldBrushModel->nodes, clipFlags, dlightBits, shadowBits ); if( r_speeds->integer ) rf.stats.t_world_node += ri.Sys_Milliseconds() - msec; }
void R_RecursiveWorldNode (mnode_t *node, int clipflags) { int i, c, side, *pindex; vec3_t acceptpt, rejectpt; mplane_t *plane; msurface_t *surf, **mark; mleaf_t *pleaf; double d, dot; if (node->contents == CONTENTS_SOLID) return; // solid if (node->visframe != r_visframecount) return; // cull the clipping planes if not trivial accept // FIXME: the compiler is doing a lousy job of optimizing here; it could be twice as fast in ASM if (clipflags) { for (i = 0; i < 4; i++) { if (!(clipflags & (1<<i)) ) continue; // don't need to clip against it // generate accept and reject points // FIXME: do with fast look-ups or integer tests based on the sign bit of the floating point values pindex = pfrustum_indexes[i]; rejectpt[0] = (float)node->minmaxs[pindex[0]]; rejectpt[1] = (float)node->minmaxs[pindex[1]]; rejectpt[2] = (float)node->minmaxs[pindex[2]]; d = DotProduct (rejectpt, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) return; acceptpt[0] = (float)node->minmaxs[pindex[3+0]]; acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; d = DotProduct (acceptpt, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d >= 0) clipflags &= ~(1<<i); // node is entirely on screen } } // if a leaf node, draw stuff if (node->contents < 0) { pleaf = (mleaf_t *)node; mark = pleaf->firstmarksurface; c = pleaf->nummarksurfaces; if (c) { do { (*mark)->visframe = r_framecount; mark++; } while (--c); } // deal with model fragments in this leaf if (pleaf->efrags) R_StoreEfrags (&pleaf->efrags); pleaf->key = r_currentkey; r_currentkey++; // all bmodels in a leaf share the same key } else { // node is just a decision point, so go down the apropriate sides // find which side of the node we are on plane = node->plane; dot = PlaneDiff (modelorg, plane); side = (dot < 0); // recurse down the children, front side first R_RecursiveWorldNode (node->children[side], clipflags); // draw stuff c = node->numsurfaces; if (c) { surf = cl.worldmodel->surfaces + node->firstsurface; if (dot < -BACKFACE_EPSILON) { do { if ((surf->flags & SURF_PLANEBACK) && surf->visframe == r_framecount) R_RenderFace (surf, clipflags); surf++; } while (--c); } else if (dot > BACKFACE_EPSILON) { do { if (!(surf->flags & SURF_PLANEBACK) && surf->visframe == r_framecount) R_RenderFace (surf, clipflags); surf++; } while (--c); } // all surfaces on the same node share the same sequence number r_currentkey++; } // recurse down the back side R_RecursiveWorldNode (node->children[!side], clipflags); } }