static void GL_WorldNode_r( mnode_t *node, int clipflags ) { int side; vec_t dot; while( node->visframe == glr.visframe ) { if( !GL_ClipNode( node, &clipflags ) ) { c.nodesCulled++; break; } if( !node->plane ) { GL_DrawLeaf( ( mleaf_t * )node ); break; } dot = PlaneDiffFast( glr.fd.vieworg, node->plane ); side = dot < 0; GL_WorldNode_r( node->children[side], clipflags ); GL_DrawNode( node, dot ); node = node->children[ side ^ 1 ]; } }
static void GL_MarkLights_r( mnode_t *node, dlight_t *light, int lightbit ) { vec_t dot; int count; mface_t *face; while( node->plane ) { dot = PlaneDiffFast( light->transformed, node->plane ); if( dot > light->intensity - DLIGHT_CUTOFF ) { node = node->children[0]; continue; } if( dot < -light->intensity + DLIGHT_CUTOFF ) { node = node->children[1]; continue; } face = node->firstface; count = node->numfaces; while( count-- ) { if( !( face->drawflags & SURF_NOLM_MASK ) ) { if( face->dlightframe != glr.dlightframe ) { face->dlightframe = glr.dlightframe; face->dlightbits = 0; } face->dlightbits |= lightbit; } face++; } GL_MarkLights_r( node->children[0], light, lightbit ); node = node->children[1]; } }
/* ================ 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 GL_DrawBspModel( mmodel_t *model ) { mface_t *face; int count, mask = 0; vec3_t bounds[2]; vec_t dot; vec3_t transformed, temp; entity_t *ent = glr.ent; glCullResult_t cull; if( glr.entrotated ) { cull = GL_CullSphere( ent->origin, model->radius ); if( cull == CULL_OUT ) { c.spheresCulled++; return; } if( cull == CULL_CLIP ) { VectorCopy( model->mins, bounds[0] ); VectorCopy( model->maxs, bounds[1] ); cull = GL_CullLocalBox( ent->origin, bounds ); if( cull == CULL_OUT ) { c.rotatedBoxesCulled++; return; } } VectorSubtract( glr.fd.vieworg, ent->origin, temp ); transformed[0] = DotProduct( temp, glr.entaxis[0] ); transformed[1] = DotProduct( temp, glr.entaxis[1] ); transformed[2] = DotProduct( temp, glr.entaxis[2] ); } else { VectorAdd( model->mins, ent->origin, bounds[0] ); VectorAdd( model->maxs, ent->origin, bounds[1] ); cull = GL_CullBox( bounds ); if( cull == CULL_OUT ) { c.boxesCulled++; return; } VectorSubtract( glr.fd.vieworg, ent->origin, transformed ); if( VectorEmpty( ent->origin ) && model->drawframe != glr.drawframe ) { mask = SURF_TRANS33|SURF_TRANS66; } } // protect against infinite loop if the same inline model // with alpha faces is referenced by multiple entities model->drawframe = glr.drawframe; #if USE_DLIGHTS glr.dlightframe++; if( gl_dynamic->integer == 1 ) { GL_TransformLights( model ); } #endif if( gl_dynamic->integer ) { GL_BeginLights(); } qglPushMatrix(); qglTranslatef( ent->origin[0], ent->origin[1], ent->origin[2] ); if( glr.entrotated ) { qglRotatef( ent->angles[YAW], 0, 0, 1 ); qglRotatef( ent->angles[PITCH], 0, 1, 0 ); qglRotatef( ent->angles[ROLL], 1, 0, 0 ); } // draw visible faces // FIXME: go by headnode instead? face = model->firstface; count = model->numfaces; while( count-- ) { dot = PlaneDiffFast( transformed, face->plane ); if( BSP_CullFace( face, dot ) ) { c.facesCulled++; } else if( face->drawflags & mask ) { // FIXME: alpha faces are not supported // on rotated or translated inline models GL_AddAlphaFace( face ); } else { GL_AddSolidFace( face ); } face++; } if( gl_dynamic->integer ) { GL_EndLights(); } GL_DrawSolidFaces(); qglPopMatrix(); }