/* ================ R_RenderBmodelFace ================ */ void R_RenderBmodelFace(bedge_t * pedges, msurface_t * psurf) { int i; unsigned mask; mplane_t *pplane; float distinv; vec3_t p_normal; medge_t 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 + psurf->numedges + 4) >= edge_max) { r_outofedges += psurf->numedges; return; } c_faceclip++; // this is a dummy to give the caching mechanism someplace to write to r_pedge = &tedge; // set up clip planes pclip = NULL; for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { if (r_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; // FIXME: keep clipped bmodel edges in clockwise order so last vertex caching // can be used? r_lastvertvalid = false; for (; pedges; pedges = pedges->pnext) { r_leftclipped = r_rightclipped = false; R_ClipEdge(pedges->v[0], pedges->v[1], pclip); if (r_leftclipped) makeleftedge = true; if (r_rightclipped) makerightedge = 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_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_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 *) psurf; surface_p->nearzi = r_nearzi; surface_p->flags = psurf->flags; surface_p->insubmodel = true; surface_p->spanstate = 0; surface_p->entity = currententity; surface_p->key = r_currentbkey; surface_p->spans = NULL; pplane = psurf->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(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++; }
/* ================ R_ClipEdge ================ */ void R_ClipEdge(mvertex_t * pv0, mvertex_t * pv1, clipplane_t * clip) { float d0, d1, f; mvertex_t clipvert; if (clip) { do { d0 = DotProduct(pv0->position, clip->normal) - clip->dist; d1 = DotProduct(pv1->position, clip->normal) - clip->dist; if (d0 >= 0) { // point 0 is unclipped if (d1 >= 0) { // both points are unclipped continue; } // only point 1 is clipped // we don't cache clipped edges cacheoffset = 0x7FFFFFFF; f = d0 / (d0 - d1); clipvert.position[0] = pv0->position[0] + f * (pv1->position[0] - pv0->position[0]); clipvert.position[1] = pv0->position[1] + f * (pv1->position[1] - pv0->position[1]); clipvert.position[2] = pv0->position[2] + f * (pv1->position[2] - pv0->position[2]); if (clip->leftedge) { r_leftclipped = true; r_leftexit = clipvert; } else if (clip->rightedge) { r_rightclipped = true; r_rightexit = clipvert; } R_ClipEdge(pv0, &clipvert, clip->next); return; } else { // point 0 is clipped if (d1 < 0) { // both points are clipped // we do cache fully clipped edges if (!r_leftclipped) cacheoffset = FULLY_CLIPPED_CACHED | (r_framecount & FRAMECOUNT_MASK); return; } // only point 0 is clipped r_lastvertvalid = false; // we don't cache partially clipped edges cacheoffset = 0x7FFFFFFF; f = d0 / (d0 - d1); clipvert.position[0] = pv0->position[0] + f * (pv1->position[0] - pv0->position[0]); clipvert.position[1] = pv0->position[1] + f * (pv1->position[1] - pv0->position[1]); clipvert.position[2] = pv0->position[2] + f * (pv1->position[2] - pv0->position[2]); if (clip->leftedge) { r_leftclipped = true; r_leftenter = clipvert; } else if (clip->rightedge) { r_rightclipped = true; r_rightenter = clipvert; } R_ClipEdge(&clipvert, pv1, clip->next); return; } } while ((clip = clip->next) != NULL); } // add the edge R_EmitEdge(pv0, pv1); }
/* ================ R_ClipEdge ================ */ void R_ClipEdge(mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) { float d0, d1, f; mvertex_t clipvert; for (; clip; clip = clip->next) { d0 = DotProduct(pv0->point, clip->normal) - clip->dist; d1 = DotProduct(pv1->point, clip->normal) - clip->dist; if (d0 >= 0) { // point 0 is unclipped if (d1 >= 0) { // both points are unclipped continue; } // only point 1 is clipped // we don't cache clipped edges cacheoffset = CLIPPED_NOT_CACHED; f = d0 / (d0 - d1); LerpVector(pv0->point, pv1->point, f, clipvert.point); if (clip->leftedge) { r_leftclipped = qtrue; r_leftexit = clipvert; } else if (clip->rightedge) { r_rightclipped = qtrue; r_rightexit = clipvert; } R_ClipEdge(pv0, &clipvert, clip->next); return; } else { // point 0 is clipped if (d1 < 0) { // both points are clipped // we do cache fully clipped edges if (!r_leftclipped) cacheoffset = FULLY_CLIPPED_CACHED | (r_framecount & FRAMECOUNT_MASK); return; } // only point 0 is clipped r_lastvertvalid = qfalse; // we don't cache partially clipped edges cacheoffset = CLIPPED_NOT_CACHED; f = d0 / (d0 - d1); LerpVector(pv0->point, pv1->point, f, clipvert.point); if (clip->leftedge) { r_leftclipped = qtrue; r_leftenter = clipvert; } else if (clip->rightedge) { r_rightclipped = qtrue; r_rightenter = clipvert; } R_ClipEdge(&clipvert, pv1, clip->next); return; } } // add the edge R_EmitEdge(pv0, pv1); }