/* ================ R_RenderFace ================ */ void R_RenderFace(msurface_t * fa, int clipflags) { int i, lindex; unsigned mask; mplane_t *pplane; float distinv; vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; // skip out if no more surfs if ((surface_p) >= surf_max) { r_outofsurfaces++; return; } // ditto if not enough edges left, or switch to auxedges if possible if ((edge_p + fa->numedges + 4) >= edge_max) { r_outofedges += fa->numedges; return; } c_faceclip++; // set up clip planes pclip = NULL; for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { if (clipflags & mask) { view_clipplanes[i].next = pclip; pclip = &view_clipplanes[i]; } } // push the edges through r_emitted = 0; r_nearzi = 0; r_nearzionly = false; makeleftedge = makerightedge = false; pedges = currententity->model->edges; r_lastvertvalid = false; for (i = 0; i < fa->numedges; i++) { lindex = currententity->model->surfedges[fa->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; // if the edge is cached, we can just reuse the edge if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == r_framecount) { r_lastvertvalid = false; continue; } } else { if ((((unsigned long) edge_p - (unsigned long) r_edges) > r_pedge->cachededgeoffset) && (((edge_t *) ((unsigned long) r_edges + r_pedge->cachededgeoffset))->owner == r_pedge)) { R_EmitCachedEdge(); r_lastvertvalid = false; continue; } } } // assume it's cacheable cacheoffset = (byte *) edge_p - (byte *) r_edges; r_leftclipped = r_rightclipped = false; R_ClipEdge(&r_pcurrentvertbase[r_pedge->v[0]], &r_pcurrentvertbase[r_pedge->v[1]], pclip); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) makeleftedge = true; if (r_rightclipped) makerightedge = true; r_lastvertvalid = true; } else { lindex = -lindex; r_pedge = &pedges[lindex]; // if the edge is cached, we can just reuse the edge if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == r_framecount) { r_lastvertvalid = false; continue; } } else { // it's cached if the cached edge is valid and is owned // by this medge_t if ((((unsigned long) edge_p - (unsigned long) r_edges) > r_pedge->cachededgeoffset) && (((edge_t *) ((unsigned long) r_edges + r_pedge->cachededgeoffset))->owner == r_pedge)) { R_EmitCachedEdge(); r_lastvertvalid = false; continue; } } } // assume it's cacheable cacheoffset = (byte *) edge_p - (byte *) r_edges; r_leftclipped = r_rightclipped = false; R_ClipEdge(&r_pcurrentvertbase[r_pedge->v[1]], &r_pcurrentvertbase[r_pedge->v[0]], pclip); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) makeleftedge = true; if (r_rightclipped) makerightedge = true; r_lastvertvalid = true; } } // if there was a clip off the left edge, add that edge too // FIXME: faster to do in screen space? // FIXME: share clipped edges? if (makeleftedge) { r_pedge = &tedge; r_lastvertvalid = false; R_ClipEdge(&r_leftexit, &r_leftenter, pclip->next); } // if there was a clip off the right edge, get the right r_nearzi if (makerightedge) { r_pedge = &tedge; r_lastvertvalid = false; r_nearzionly = true; R_ClipEdge(&r_rightexit, &r_rightenter, view_clipplanes[1].next); } // if no edges made it out, return without posting the surface if (!r_emitted) return; r_polycount++; surface_p->data = (void *) fa; surface_p->nearzi = r_nearzi; surface_p->flags = fa->flags; surface_p->insubmodel = insubmodel; surface_p->spanstate = 0; surface_p->entity = currententity; surface_p->key = r_currentkey++; surface_p->spans = NULL; pplane = fa->plane; // FIXME: cache this? TransformVector(pplane->normal, p_normal); // FIXME: cache this? distinv = 1.0 / (pplane->dist - DotProduct(modelorg, pplane->normal)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; //JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); surface_p++; }
/* ================ R_RenderFace ================ */ void R_RenderFace(mface_t *fa, int clipflags) { int i; unsigned mask; cplane_t *pplane; float distinv; vec3_t p_normal; medge_t tedge; msurfedge_t *surfedge; clipplane_t *pclip; qboolean makeleftedge, makerightedge; // translucent surfaces are not drawn by the edge renderer if (fa->texinfo->c.flags & (SURF_TRANS33 | SURF_TRANS66)) { fa->next = r_alpha_surfaces; r_alpha_surfaces = fa; return; } // sky surfaces encountered in the world will cause the // environment box surfaces to be emited if (fa->texinfo->c.flags & SURF_SKY) { R_EmitSkyBox(); return; } // skip out if no more surfs if ((surface_p) >= surf_max) { r_outofsurfaces++; return; } // ditto if not enough edges left, or switch to auxedges if possible if ((edge_p + fa->numsurfedges + 4) >= edge_max) { r_outofedges += fa->numsurfedges; return; } c_faceclip++; // set up clip planes pclip = NULL; for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { if (clipflags & mask) { view_clipplanes[i].next = pclip; pclip = &view_clipplanes[i]; } } // push the edges through r_emitted = 0; r_nearzi = 0; r_nearzionly = qfalse; makeleftedge = makerightedge = qfalse; r_lastvertvalid = qfalse; surfedge = fa->firstsurfedge; for (i = 0; i < fa->numsurfedges; i++, surfedge++) { r_pedge = surfedge->edge; // if the edge is cached, we can just reuse the edge if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == r_framecount) { r_lastvertvalid = qfalse; continue; } } else { if ((((byte *)edge_p - (byte *)r_edges) > r_pedge->cachededgeoffset) && (((edge_t *)((byte *)r_edges + r_pedge->cachededgeoffset))->owner == r_pedge)) { R_EmitCachedEdge(); r_lastvertvalid = qfalse; continue; } } } // assume it's cacheable cacheoffset = (byte *)edge_p - (byte *)r_edges; r_leftclipped = r_rightclipped = qfalse; R_ClipEdge(r_pedge->v[surfedge->vert ], r_pedge->v[surfedge->vert ^ 1], pclip); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) makeleftedge = qtrue; if (r_rightclipped) makerightedge = qtrue; r_lastvertvalid = qtrue; } // if there was a clip off the left edge, add that edge too // FIXME: faster to do in screen space? // FIXME: share clipped edges? if (makeleftedge) { r_pedge = &tedge; r_lastvertvalid = qfalse; R_ClipEdge(&r_leftexit, &r_leftenter, pclip->next); } // if there was a clip off the right edge, get the right r_nearzi if (makerightedge) { r_pedge = &tedge; r_lastvertvalid = qfalse; r_nearzionly = qtrue; R_ClipEdge(&r_rightexit, &r_rightenter, view_clipplanes[1].next); } // if no edges made it out, return without posting the surface if (!r_emitted) return; r_polycount++; surface_p->msurf = fa; surface_p->nearzi = r_nearzi; surface_p->flags = fa->drawflags; surface_p->insubmodel = insubmodel; surface_p->spanstate = 0; surface_p->entity = currententity; surface_p->key = r_currentkey++; surface_p->spans = NULL; pplane = fa->plane; // FIXME: cache this? R_TransformVector(pplane->normal, p_normal); // FIXME: cache this? distinv = 1.0 / (pplane->dist - DotProduct(modelorg, pplane->normal)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; surface_p++; }