Quake II RTX doxygen  1.0 dev
bsp.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 // r_bsp.c
19 
20 #include "sw.h"
21 
22 //
23 // current entity info
24 //
25 qboolean insubmodel;
26 entity_t *currententity;
27 vec3_t modelorg; // modelorg is the viewpoint reletive to
28  // the currently rendering entity
29 vec3_t r_entorigin; // the currently rendering entity in world
30  // coordinates
31 
32 vec3_t entity_rotation[3];
33 
35 
36 #define MAX_BMODEL_VERTS 500 // 6K
37 #define MAX_BMODEL_EDGES 1000 // 12K
38 
39 static mvertex_t *pbverts;
40 static bedge_t *pbedges;
41 static int numbverts, numbedges;
42 
43 static mvertex_t *pfrontenter, *pfrontexit;
44 
45 static qboolean makeclippededge;
46 
47 
48 //===========================================================================
49 
50 /*
51 ================
52 R_EntityRotate
53 ================
54 */
55 static void R_EntityRotate(vec3_t vec)
56 {
57  vec3_t tvec;
58 
59  VectorCopy(vec, tvec);
60  vec[0] = DotProduct(entity_rotation[0], tvec);
61  vec[1] = DotProduct(entity_rotation[1], tvec);
62  vec[2] = DotProduct(entity_rotation[2], tvec);
63 }
64 
65 
66 /*
67 ================
68 R_RotateBmodel
69 ================
70 */
71 void R_RotateBmodel(void)
72 {
73  AnglesToAxis(currententity->angles, entity_rotation);
74 
75 //
76 // rotate modelorg and the transformation matrix
77 //
82 
84 }
85 
86 
87 /*
88 ================
89 R_RecursiveClipBPoly
90 
91 Clip a bmodel poly down the world bsp tree
92 ================
93 */
94 static void R_RecursiveClipBPoly(bedge_t *pedges, mnode_t *pnode, mface_t *psurf)
95 {
96  bedge_t *psideedges[2], *pnextedge, *ptedge;
97  int i, side, lastside;
98  float dist, frac, lastdist;
99  cplane_t *splitplane, tplane;
100  mvertex_t *pvert, *plastvert, *ptvert;
101  mnode_t *pn;
102  int area;
103 
104  psideedges[0] = psideedges[1] = NULL;
105 
106  makeclippededge = qfalse;
107 
108 // transform the BSP plane into model space
109 // FIXME: cache these?
110  splitplane = pnode->plane;
111  tplane.dist = -PlaneDiff(r_entorigin, splitplane);
112  tplane.normal[0] = DotProduct(entity_rotation[0], splitplane->normal);
113  tplane.normal[1] = DotProduct(entity_rotation[1], splitplane->normal);
114  tplane.normal[2] = DotProduct(entity_rotation[2], splitplane->normal);
115 
116 // clip edges to BSP plane
117  for (; pedges; pedges = pnextedge) {
118  pnextedge = pedges->pnext;
119 
120  // set the status for the last point as the previous point
121  // FIXME: cache this stuff somehow?
122  plastvert = pedges->v[0];
123  lastdist = PlaneDiff(plastvert->point, &tplane);
124 
125  if (lastdist > 0)
126  lastside = 0;
127  else
128  lastside = 1;
129 
130  pvert = pedges->v[1];
131  dist = PlaneDiff(pvert->point, &tplane);
132 
133  if (dist > 0)
134  side = 0;
135  else
136  side = 1;
137 
138  if (side != lastside) {
139  // clipped
141  return;
142 
143  // generate the clipped vertex
144  frac = lastdist / (lastdist - dist);
145  ptvert = &pbverts[numbverts++];
146  LerpVector(plastvert->point, pvert->point, frac, ptvert->point);
147 
148  // split into two edges, one on each side, and remember entering
149  // and exiting points
150  // FIXME: share the clip edge by having a winding direction flag?
151  if (numbedges >= (MAX_BMODEL_EDGES - 1)) {
152  Com_Printf("Out of edges for bmodel\n");
153  return;
154  }
155 
156  ptedge = &pbedges[numbedges];
157  ptedge->pnext = psideedges[lastside];
158  psideedges[lastside] = ptedge;
159  ptedge->v[0] = plastvert;
160  ptedge->v[1] = ptvert;
161 
162  ptedge = &pbedges[numbedges + 1];
163  ptedge->pnext = psideedges[side];
164  psideedges[side] = ptedge;
165  ptedge->v[0] = ptvert;
166  ptedge->v[1] = pvert;
167 
168  numbedges += 2;
169 
170  if (side == 0) {
171  // entering for front, exiting for back
172  pfrontenter = ptvert;
173  makeclippededge = qtrue;
174  } else {
175  pfrontexit = ptvert;
176  makeclippededge = qtrue;
177  }
178  } else {
179  // add the edge to the appropriate side
180  pedges->pnext = psideedges[side];
181  psideedges[side] = pedges;
182  }
183  }
184 
185 // if anything was clipped, reconstitute and add the edges along the clip
186 // plane to both sides (but in opposite directions)
187  if (makeclippededge) {
188  if (numbedges >= (MAX_BMODEL_EDGES - 2)) {
189  Com_Error(ERR_DROP, "Out of edges for bmodel");
190  }
191 
192  ptedge = &pbedges[numbedges];
193  ptedge->pnext = psideedges[0];
194  psideedges[0] = ptedge;
195  ptedge->v[0] = pfrontexit;
196  ptedge->v[1] = pfrontenter;
197 
198  ptedge = &pbedges[numbedges + 1];
199  ptedge->pnext = psideedges[1];
200  psideedges[1] = ptedge;
201  ptedge->v[0] = pfrontenter;
202  ptedge->v[1] = pfrontexit;
203 
204  numbedges += 2;
205  }
206 
207 // draw or recurse further
208  for (i = 0; i < 2; i++) {
209  if (psideedges[i]) {
210  // draw if we've reached a non-solid leaf, done if all that's left is a
211  // solid leaf, and continue down the tree if it's not a leaf
212  pn = pnode->children[i];
213 
214  // we're done with this branch if the node or leaf isn't in the PVS
215  if (pn->visframe == r_visframecount) {
216  if (!pn->plane) {
217  mleaf_t *pl = (mleaf_t *)pn;
218  if (pl->contents != CONTENTS_SOLID) {
219  if (r_newrefdef.areabits) {
220  area = pl->area;
221  if (!Q_IsBitSet(r_newrefdef.areabits, area))
222  continue; // not visible
223  }
224 
225  r_currentbkey = pl->key;
226  R_RenderBmodelFace(psideedges[i], psurf);
227  }
228  } else {
229  R_RecursiveClipBPoly(psideedges[i], pnode->children[i],
230  psurf);
231  }
232  }
233  }
234  }
235 }
236 
237 
238 /*
239 ================
240 R_DrawSolidClippedSubmodelPolygons
241 
242 Bmodel crosses multiple leafs
243 ================
244 */
245 void R_DrawSolidClippedSubmodelPolygons(mmodel_t *pmodel, mnode_t *topnode)
246 {
247  int i, j;
248  vec_t dot;
249  mface_t *psurf;
250  int numsurfaces;
251  cplane_t *pplane;
252  mvertex_t bverts[MAX_BMODEL_VERTS];
253  bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
254  msurfedge_t *surfedge;
255 
256 // FIXME: use bounding-box-based frustum clipping info?
257 
258  psurf = pmodel->firstface;
259  numsurfaces = pmodel->numfaces;
260 
261  for (i = 0; i < numsurfaces; i++, psurf++) {
262  // find which side of the node we are on
263  pplane = psurf->plane;
264 
265  dot = PlaneDiff(modelorg, pplane);
266 
267  // draw the polygon
268  if ((!(psurf->drawflags & DSURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
269  ((psurf->drawflags & DSURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
270  continue;
271 
272  // FIXME: use bounding-box-based frustum clipping info?
273 
274  // copy the edges to bedges, flipping if necessary so always
275  // clockwise winding
276  // FIXME: if edges and vertices get caches, these assignments must move
277  // outside the loop, and overflow checking must be done here
278  pbverts = bverts;
279  pbedges = bedges;
280  numbverts = numbedges = 0;
281  pbedge = &bedges[numbedges];
282  numbedges += psurf->numsurfedges;
283 
284  if (numbedges >= MAX_BMODEL_EDGES) {
285  Com_Printf("Out of edges for bmodel\n");
286  return;
287  }
288 
289  surfedge = psurf->firstsurfedge;
290  for (j = 0; j < psurf->numsurfedges; j++, surfedge++) {
291  pbedge[j].v[0] = surfedge->edge->v[surfedge->vert ];
292  pbedge[j].v[1] = surfedge->edge->v[surfedge->vert ^ 1];
293  pbedge[j].pnext = &pbedge[j + 1];
294  }
295 
296  pbedge[j - 1].pnext = NULL; // mark end of edges
297 
298  if (!(psurf->texinfo->c.flags & SURF_TRANS_MASK))
299  R_RecursiveClipBPoly(pbedge, topnode, psurf);
300  else
301  R_RenderBmodelFace(pbedge, psurf);
302  }
303 }
304 
305 
306 /*
307 ================
308 R_DrawSubmodelPolygons
309 
310 All in one leaf
311 ================
312 */
313 void R_DrawSubmodelPolygons(mmodel_t *pmodel, int clipflags, mnode_t *topnode)
314 {
315  int i;
316  vec_t dot;
317  mface_t *psurf;
318  int numsurfaces;
319  cplane_t *pplane;
320 
321 // FIXME: use bounding-box-based frustum clipping info?
322 
323  psurf = pmodel->firstface;
324  numsurfaces = pmodel->numfaces;
325 
326  for (i = 0; i < numsurfaces; i++, psurf++) {
327  // find which side of the node we are on
328  pplane = psurf->plane;
329 
330  dot = PlaneDiff(modelorg, pplane);
331 
332  // draw the polygon
333  if (((psurf->drawflags & DSURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
334  (!(psurf->drawflags & DSURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
335  r_currentkey = ((mleaf_t *)topnode)->key;
336 
337  // FIXME: use bounding-box-based frustum clipping info?
338  R_RenderFace(psurf, clipflags);
339  }
340  }
341 }
342 
343 
345 
346 /*
347 ================
348 R_RecursiveWorldNode
349 ================
350 */
351 static void R_RecursiveWorldNode(mnode_t *node, int clipflags)
352 {
353  int i, c, side, *pindex;
354  vec3_t acceptpt, rejectpt;
355  cplane_t *plane;
356  mface_t *surf, **mark;
357  float d, dot;
358  mleaf_t *pleaf;
359 
360  while (node->visframe == r_visframecount) {
361  // cull the clipping planes if not trivial accept
362  // FIXME: the compiler is doing a lousy job of optimizing here; it could be
363  // twice as fast in ASM
364  if (clipflags) {
365  for (i = 0; i < 4; i++) {
366  if (!(clipflags & (1 << i)))
367  continue; // don't need to clip against it
368 
369  // generate accept and reject points
370  // FIXME: do with fast look-ups or integer tests based on the sign bit
371  // of the floating point values
372 
373  pindex = pfrustum_indexes[i];
374 
375  rejectpt[0] = (float)node->minmaxs[pindex[0]];
376  rejectpt[1] = (float)node->minmaxs[pindex[1]];
377  rejectpt[2] = (float)node->minmaxs[pindex[2]];
378 
379  d = PlaneDiff(rejectpt, &view_clipplanes[i]);
380  if (d <= 0)
381  return;
382 
383  acceptpt[0] = (float)node->minmaxs[pindex[3 + 0]];
384  acceptpt[1] = (float)node->minmaxs[pindex[3 + 1]];
385  acceptpt[2] = (float)node->minmaxs[pindex[3 + 2]];
386 
387  d = PlaneDiff(acceptpt, &view_clipplanes[i]);
388  if (d >= 0)
389  clipflags &= ~(1 << i); // node is entirely on screen
390  }
391  }
392 
393  c_drawnode++;
394 
395  // if a leaf node, draw stuff
396  if (!node->plane) {
397  pleaf = (mleaf_t *)node;
398 
399  if (pleaf->contents == CONTENTS_SOLID)
400  return; // solid
401 
402  // check for door connected areas
403  if (r_newrefdef.areabits) {
404  if (! Q_IsBitSet(r_newrefdef.areabits, pleaf->area))
405  return; // not visible
406  }
407 
408  mark = pleaf->firstleafface;
409  c = pleaf->numleaffaces;
410  if (c) {
411  do {
412  (*mark)->drawframe = r_framecount;
413  mark++;
414  } while (--c);
415  }
416 
417  pleaf->key = r_currentkey;
418  r_currentkey++; // all bmodels in a leaf share the same key
419  return;
420  }
421  // node is just a decision point, so go down the apropriate sides
422 
423  // find which side of the node we are on
424  plane = node->plane;
425 
426  dot = PlaneDiffFast(modelorg, plane);
427 
428  if (dot >= 0)
429  side = 0;
430  else
431  side = 1;
432 
433  // recurse down the children, front side first
434  R_RecursiveWorldNode(node->children[side], clipflags);
435 
436  // draw stuff
437  c = node->numfaces;
438  if (c) {
439  surf = node->firstface;
440  if (dot < -BACKFACE_EPSILON) {
441  do {
442  if ((surf->drawflags & DSURF_PLANEBACK) &&
443  (surf->drawframe == r_framecount)) {
444  R_RenderFace(surf, clipflags);
445  }
446  surf++;
447  } while (--c);
448  } else if (dot > BACKFACE_EPSILON) {
449  do {
450  if (!(surf->drawflags & DSURF_PLANEBACK) &&
451  (surf->drawframe == r_framecount)) {
452  R_RenderFace(surf, clipflags);
453  }
454  surf++;
455  } while (--c);
456  }
457 
458  // all surfaces on the same node share the same sequence number
459  r_currentkey++;
460  }
461 
462  // recurse down the back side
463  node = node->children[side ^ 1];
464  }
465 }
466 
467 
468 
469 /*
470 ================
471 R_RenderWorld
472 ================
473 */
474 void R_RenderWorld(void)
475 {
476 
477  if (!r_drawworld->integer)
478  return;
479  if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
480  return;
481 
482  c_drawnode = 0;
483 
484  // auto cycle the world frame for texture animation
485  r_worldentity.frame = (int)(r_newrefdef.time * 2);
487 
488  VectorCopy(r_origin, modelorg);
489 
491 }
492 
493 
pbedges
static bedge_t * pbedges
Definition: bsp.c:40
r_origin
vec3_t r_origin
Definition: main.c:52
r_newrefdef
refdef_t r_newrefdef
Definition: main.c:28
MAX_BMODEL_EDGES
#define MAX_BMODEL_EDGES
Definition: bsp.c:37
entity_rotation
vec3_t entity_rotation[3]
Definition: bsp.c:32
r_drawworld
cvar_t * r_drawworld
Definition: main.c:96
r_framecount
int r_framecount
Definition: main.c:64
makeclippededge
static qboolean makeclippededge
Definition: bsp.c:45
pfrontexit
static mvertex_t * pfrontexit
Definition: bsp.c:43
R_EntityRotate
static void R_EntityRotate(vec3_t vec)
Definition: bsp.c:55
R_RenderFace
void R_RenderFace(mface_t *fa, int clipflags)
Definition: raster.c:328
vup
vec3_t vup
Definition: main.c:49
R_RecursiveWorldNode
static void R_RecursiveWorldNode(mnode_t *node, int clipflags)
Definition: bsp.c:351
numbverts
static int numbverts
Definition: bsp.c:41
bedge_s::pnext
struct bedge_s * pnext
Definition: sw.h:190
currententity
entity_t * currententity
Definition: bsp.c:26
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
R_RecursiveClipBPoly
static void R_RecursiveClipBPoly(bedge_t *pedges, mnode_t *pnode, mface_t *psurf)
Definition: bsp.c:94
numbedges
static int numbedges
Definition: bsp.c:41
vpn
vec3_t vpn
Definition: main.c:50
R_DrawSubmodelPolygons
void R_DrawSubmodelPolygons(mmodel_t *pmodel, int clipflags, mnode_t *topnode)
Definition: bsp.c:313
sw.h
pfrontenter
static mvertex_t * pfrontenter
Definition: bsp.c:43
pbverts
static mvertex_t * pbverts
Definition: bsp.c:39
R_TransformFrustum
void R_TransformFrustum(void)
Definition: misc.c:70
bedge_s
Definition: sw.h:188
c_drawnode
int c_drawnode
Definition: bsp.c:344
r_entorigin
vec3_t r_entorigin
Definition: bsp.c:29
modelorg
vec3_t modelorg
Definition: bsp.c:27
r_worldentity
entity_t r_worldentity
Definition: main.c:26
r_visframecount
int r_visframecount
Definition: main.c:65
r_currentkey
int r_currentkey
Definition: edge.c:46
c
statCounters_t c
Definition: main.c:30
R_RotateBmodel
void R_RotateBmodel(void)
Definition: bsp.c:71
bedge_s::v
mvertex_t * v[2]
Definition: sw.h:189
r_currentbkey
int r_currentbkey
Definition: bsp.c:34
insubmodel
qboolean insubmodel
Definition: bsp.c:25
R_RenderBmodelFace
void R_RenderBmodelFace(bedge_t *pedges, mface_t *psurf)
Definition: raster.c:477
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
R_RenderWorld
void R_RenderWorld(void)
Definition: bsp.c:474
r_worldmodel
bsp_t * r_worldmodel
Definition: main.c:31
pfrustum_indexes
int * pfrustum_indexes[4]
Definition: main.c:70
R_DrawSolidClippedSubmodelPolygons
void R_DrawSolidClippedSubmodelPolygons(mmodel_t *pmodel, mnode_t *topnode)
Definition: bsp.c:245
view_clipplanes
clipplane_t view_clipplanes[4]
Definition: raster.c:37
BACKFACE_EPSILON
#define BACKFACE_EPSILON
Definition: world.c:352
MAX_BMODEL_VERTS
#define MAX_BMODEL_VERTS
Definition: bsp.c:36
vright
vec3_t vright
Definition: main.c:51