/* ============== R_DrawCulledPolys ============== */ void R_DrawCulledPolys(void) { surf_t *s; msurface_t *pface; currententity = &r_worldentity; if (r_worldpolysbacktofront) { for (s = surface_p - 1; s > &surfaces[1]; s--) { if (!s->spans) continue; if (!(s->flags & SURF_DRAWBACKGROUND)) { pface = (msurface_t *)s->data; R_RenderPoly(pface, 15); } } } else { for (s = &surfaces[1]; s < surface_p; s++) { if (!s->spans) continue; if (!(s->flags & SURF_DRAWBACKGROUND)) { pface = (msurface_t *)s->data; R_RenderPoly(pface, 15); } } } }
/* ================ R_ZDrawSubmodelPolys ================ */ void R_ZDrawSubmodelPolys(model_t * pmodel) { int i, numsurfaces; msurface_t *psurf; float dot; mplane_t *pplane; psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; numsurfaces = pmodel->nummodelsurfaces; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on pplane = psurf->plane; dot = DotProduct(modelorg, pplane->normal) - pplane->dist; // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { // FIXME: use bounding-box-based frustum clipping info? R_RenderPoly(psurf, 15); } } }
/* ================ 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); } } }
/* ================ 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); } }