Quake II RTX doxygen  1.0 dev
poly.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 #include "sw.h"
19 
20 #define AFFINE_SPANLET_SIZE 16
21 #define AFFINE_SPANLET_SIZE_BITS 4
22 
23 typedef struct {
24  byte *pbase, *pdest;
25  short *pz;
26  fixed16_t s, t;
27  fixed16_t sstep, tstep;
28  int izi, izistep;
29  int spancount;
30  unsigned u, v;
32 
34 
35 static fixed8_t r_polyblendcolor[3];
36 
38 
40 
42 
43 static int *r_turb_turb;
44 
45 static int clip_current;
46 static vec5_t r_clip_verts[2][MAXWORKINGVERTS + 2];
47 
48 static int s_minindex, s_maxindex;
49 
50 static void R_DrawPoly(int iswater);
51 
52 static void R_DrawSpanletOpaque(void)
53 {
54  unsigned ts, tt;
55  byte *ptex;
56 
57  do {
58  ts = s_spanletvars.s >> 16;
59  tt = s_spanletvars.t >> 16;
60 
61  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) {
62  ptex = s_spanletvars.pbase + (ts) * TEX_BYTES + (tt) * cachewidth;
63  s_spanletvars.pdest[0] = ptex[2];
64  s_spanletvars.pdest[1] = ptex[1];
65  s_spanletvars.pdest[2] = ptex[0];
67  }
68 
71  s_spanletvars.pz++;
74  } while (--s_spanletvars.spancount > 0);
75 }
76 
78 {
79  int sturb, tturb;
80  byte *ptex;
81 
82  do {
83  sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t >> 16) & (CYCLE - 1)]) >> 16) & TURB_MASK;
84  tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s >> 16) & (CYCLE - 1)]) >> 16) & TURB_MASK;
85 
86  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) {
87  ptex = s_spanletvars.pbase + (sturb) * TEX_BYTES + (tturb) * TURB_SIZE * TEX_BYTES;
91  }
92 
95  s_spanletvars.pz++;
98  } while (--s_spanletvars.spancount > 0);
99 }
100 
102 {
103  do {
104  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) {
108  }
109 
112  s_spanletvars.pz++;
113  } while (--s_spanletvars.spancount > 0);
114 }
115 
116 static void R_DrawSpanletBlended(void)
117 {
118  unsigned ts, tt;
119  byte *ptex;
120 
121  do {
122  ts = s_spanletvars.s >> 16;
123  tt = s_spanletvars.t >> 16;
124 
125  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) {
126  ptex = s_spanletvars.pbase + (ts) * TEX_BYTES + (tt) * cachewidth;
130  }
131 
134  s_spanletvars.pz++;
137  } while (--s_spanletvars.spancount > 0);
138 }
139 
141 {
142  unsigned ts, tt;
143  byte *ptex;
144 
145  do {
146  ts = s_spanletvars.s >> 16;
147  tt = s_spanletvars.t >> 16;
148 
149  ptex = s_spanletvars.pbase + (ts) * TEX_BYTES + (tt) * cachewidth;
150  if (ptex[3] && *s_spanletvars.pz <= (s_spanletvars.izi >> 16)) {
151  int alpha = (ptex[3] * r_polydesc.alpha) >> 8;
152  int one_minus_alpha = 255 - alpha;
153 
154  s_spanletvars.pdest[0] = (s_spanletvars.pdest[0] * one_minus_alpha + ptex[2] * alpha) >> 8;
155  s_spanletvars.pdest[1] = (s_spanletvars.pdest[1] * one_minus_alpha + ptex[1] * alpha) >> 8;
156  s_spanletvars.pdest[2] = (s_spanletvars.pdest[2] * one_minus_alpha + ptex[0] * alpha) >> 8;
157  }
158 
161  s_spanletvars.pz++;
164  } while (--s_spanletvars.spancount > 0);
165 }
166 
167 /*
168 ** R_ClipPolyFace
169 **
170 ** Clips the winding at clip_verts[clip_current] and changes clip_current
171 ** Throws out the back side
172 */
173 static int R_ClipPolyFace(int nump, clipplane_t *pclipplane)
174 {
175  int i, outcount;
176  float dists[MAXWORKINGVERTS + 3];
177  float frac, clipdist, *pclipnormal;
178  float *in, *instep, *outstep, *vert2;
179 
180  clipdist = pclipplane->dist;
181  pclipnormal = pclipplane->normal;
182 
183 // calc dists
184  if (clip_current) {
185  in = r_clip_verts[1][0];
186  outstep = r_clip_verts[0][0];
187  clip_current = 0;
188  } else {
189  in = r_clip_verts[0][0];
190  outstep = r_clip_verts[1][0];
191  clip_current = 1;
192  }
193 
194  instep = in;
195  for (i = 0; i < nump; i++, instep += sizeof(vec5_t) / sizeof(float)) {
196  dists[i] = DotProduct(instep, pclipnormal) - clipdist;
197  }
198 
199 // handle wraparound case
200  dists[nump] = dists[0];
201  memcpy(instep, in, sizeof(vec5_t));
202 
203 
204 // clip the winding
205  instep = in;
206  outcount = 0;
207 
208  for (i = 0; i < nump; i++, instep += sizeof(vec5_t) / sizeof(float)) {
209  if (dists[i] >= 0) {
210  memcpy(outstep, instep, sizeof(vec5_t));
211  outstep += sizeof(vec5_t) / sizeof(float);
212  outcount++;
213  }
214 
215  if (dists[i] == 0 || dists[i + 1] == 0)
216  continue;
217 
218  if ((dists[i] > 0) == (dists[i + 1] > 0))
219  continue;
220 
221  // split it into a new vertex
222  frac = dists[i] / (dists[i] - dists[i + 1]);
223 
224  vert2 = instep + sizeof(vec5_t) / sizeof(float);
225 
226  outstep[0] = instep[0] + frac * (vert2[0] - instep[0]);
227  outstep[1] = instep[1] + frac * (vert2[1] - instep[1]);
228  outstep[2] = instep[2] + frac * (vert2[2] - instep[2]);
229  outstep[3] = instep[3] + frac * (vert2[3] - instep[3]);
230  outstep[4] = instep[4] + frac * (vert2[4] - instep[4]);
231 
232  outstep += sizeof(vec5_t) / sizeof(float);
233  outcount++;
234  }
235 
236  return outcount;
237 }
238 
239 /*
240 ** R_PolygonDrawSpans
241 */
242 static void R_PolygonDrawSpans(espan_t *pspan, int iswater)
243 {
244  int count;
245  fixed16_t snext, tnext;
246  float sdivz, tdivz, zi, z, du, dv, spancountminus1;
247  float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu;
248 
250 
251  if (iswater & SURF_WARP)
252  r_turb_turb = sintable + ((int)(r_newrefdef.time * SPEED) & (CYCLE - 1));
253  else if (iswater & SURF_FLOWING)
255 
256  sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE;
257  tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE;
258  zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE;
259 
260 // we count on FP exceptions being turned off to avoid range problems
261  s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000);
262 
263  s_spanletvars.pz = 0;
264 
265  do {
266  s_spanletvars.pdest = d_spantable[pspan->v] + pspan->u * VID_BYTES;
267  s_spanletvars.pz = d_zspantable[pspan->v] + pspan->u;
268  s_spanletvars.u = pspan->u;
269  s_spanletvars.v = pspan->v;
270 
271  count = pspan->count;
272 
273  if (count <= 0)
274  goto NextSpan;
275 
276  // calculate the initial s/z, t/z, 1/z, s, and t and clamp
277  du = (float)pspan->u;
278  dv = (float)pspan->v;
279 
280  sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
281  tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
282 
283  zi = d_ziorigin + dv * d_zistepv + du * d_zistepu;
284  z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
285  // we count on FP exceptions being turned off to avoid range problems
286  s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000);
287 
288  s_spanletvars.s = (int)(sdivz * z) + sadjust;
289  s_spanletvars.t = (int)(tdivz * z) + tadjust;
290 
291  if (!iswater) {
292  if (s_spanletvars.s > bbextents)
294  else if (s_spanletvars.s < 0)
295  s_spanletvars.s = 0;
296 
297  if (s_spanletvars.t > bbextentt)
299  else if (s_spanletvars.t < 0)
300  s_spanletvars.t = 0;
301  }
302 
303  do {
304  // calculate s and t at the far end of the span
305  if (count >= AFFINE_SPANLET_SIZE)
307  else
308  s_spanletvars.spancount = count;
309 
310  count -= s_spanletvars.spancount;
311 
312  if (count) {
313  // calculate s/z, t/z, zi->fixed s and t at far end of span,
314  // calculate s and t steps across span by shifting
315  sdivz += sdivzspanletstepu;
316  tdivz += tdivzspanletstepu;
317  zi += zispanletstepu;
318  z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
319 
320  snext = (int)(sdivz * z) + sadjust;
321  tnext = (int)(tdivz * z) + tadjust;
322 
323  if (!iswater) {
324  if (snext > bbextents)
325  snext = bbextents;
326  else if (snext < AFFINE_SPANLET_SIZE)
327  snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
328  // from causing overstepping & running off the
329  // edge of the texture
330 
331  if (tnext > bbextentt)
332  tnext = bbextentt;
333  else if (tnext < AFFINE_SPANLET_SIZE)
334  tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
335  }
336 
339  } else {
340  // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
341  // can't step off polygon), clamp, calculate s and t steps across
342  // span by division, biasing steps low so we don't run off the
343  // texture
344  spancountminus1 = (float)(s_spanletvars.spancount - 1);
345  sdivz += d_sdivzstepu * spancountminus1;
346  tdivz += d_tdivzstepu * spancountminus1;
347  zi += d_zistepu * spancountminus1;
348  z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
349  snext = (int)(sdivz * z) + sadjust;
350  tnext = (int)(tdivz * z) + tadjust;
351 
352  if (!iswater) {
353  if (snext > bbextents)
354  snext = bbextents;
355  else if (snext < AFFINE_SPANLET_SIZE)
356  snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
357  // from causing overstepping & running off the
358  // edge of the texture
359 
360  if (tnext > bbextentt)
361  tnext = bbextentt;
362  else if (tnext < AFFINE_SPANLET_SIZE)
363  tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
364  }
365 
366  if (s_spanletvars.spancount > 1) {
369  }
370  }
371 
372  if (iswater) {
373  s_spanletvars.s = s_spanletvars.s & ((CYCLE << 16) - 1);
374  s_spanletvars.t = s_spanletvars.t & ((CYCLE << 16) - 1);
375  }
376 
378 
379  s_spanletvars.s = snext;
380  s_spanletvars.t = tnext;
381 
382  } while (count > 0);
383 
384 NextSpan:
385  pspan++;
386 
387  } while (pspan->count != DS_SPAN_LIST_END);
388 }
389 
390 /*
391 **
392 ** R_PolygonScanLeftEdge
393 **
394 ** Goes through the polygon and scans the left edge, filling in
395 ** screen coordinate data for the spans
396 */
397 static void R_PolygonScanLeftEdge(void)
398 {
399  int i, v, itop, ibottom, lmaxindex;
400  emitpoint_t *pvert, *pnext;
401  espan_t *pspan;
402  float du, dv, vtop, vbottom, slope;
403  fixed16_t u, u_step;
404 
405  pspan = s_polygon_spans;
406  i = s_minindex;
407  if (i == 0)
408  i = r_polydesc.nump;
409 
410  lmaxindex = s_maxindex;
411  if (lmaxindex == 0)
412  lmaxindex = r_polydesc.nump;
413 
414  vtop = ceil(r_polydesc.pverts[i].v);
415 
416  do {
417  pvert = &r_polydesc.pverts[i];
418  pnext = pvert - 1;
419 
420  vbottom = ceil(pnext->v);
421 
422  if (vtop < vbottom) {
423  du = pnext->u - pvert->u;
424  dv = pnext->v - pvert->v;
425 
426  slope = du / dv;
427  u_step = (int)(slope * 0x10000);
428  // adjust u to ceil the integer portion
429  u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
430  (0x10000 - 1);
431  itop = (int)vtop;
432  ibottom = (int)vbottom;
433 
434  for (v = itop; v < ibottom; v++) {
435  pspan->u = u >> 16;
436  pspan->v = v;
437  u += u_step;
438  pspan++;
439  }
440  }
441 
442  vtop = vbottom;
443 
444  i--;
445  if (i == 0)
446  i = r_polydesc.nump;
447 
448  } while (i != lmaxindex);
449 }
450 
451 /*
452 ** R_PolygonScanRightEdge
453 **
454 ** Goes through the polygon and scans the right edge, filling in
455 ** count values.
456 */
457 static void R_PolygonScanRightEdge(void)
458 {
459  int i, v, itop, ibottom;
460  emitpoint_t *pvert, *pnext;
461  espan_t *pspan;
462  float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
463  fixed16_t u, u_step;
464 
465  pspan = s_polygon_spans;
466  i = s_minindex;
467 
468  vvert = r_polydesc.pverts[i].v;
469  if (vvert < r_refdef.fvrecty_adj)
470  vvert = r_refdef.fvrecty_adj;
471  if (vvert > r_refdef.fvrectbottom_adj)
472  vvert = r_refdef.fvrectbottom_adj;
473 
474  vtop = ceil(vvert);
475 
476  do {
477  pvert = &r_polydesc.pverts[i];
478  pnext = pvert + 1;
479 
480  vnext = pnext->v;
481  if (vnext < r_refdef.fvrecty_adj)
482  vnext = r_refdef.fvrecty_adj;
483  if (vnext > r_refdef.fvrectbottom_adj)
484  vnext = r_refdef.fvrectbottom_adj;
485 
486  vbottom = ceil(vnext);
487 
488  if (vtop < vbottom) {
489  uvert = pvert->u;
490  if (uvert < r_refdef.fvrectx_adj)
491  uvert = r_refdef.fvrectx_adj;
492  if (uvert > r_refdef.fvrectright_adj)
493  uvert = r_refdef.fvrectright_adj;
494 
495  unext = pnext->u;
496  if (unext < r_refdef.fvrectx_adj)
497  unext = r_refdef.fvrectx_adj;
498  if (unext > r_refdef.fvrectright_adj)
499  unext = r_refdef.fvrectright_adj;
500 
501  du = unext - uvert;
502  dv = vnext - vvert;
503  slope = du / dv;
504  u_step = (int)(slope * 0x10000);
505  // adjust u to ceil the integer portion
506  u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
507  (0x10000 - 1);
508  itop = (int)vtop;
509  ibottom = (int)vbottom;
510 
511  for (v = itop; v < ibottom; v++) {
512  pspan->count = (u >> 16) - pspan->u;
513  u += u_step;
514  pspan++;
515  }
516  }
517 
518  vtop = vbottom;
519  vvert = vnext;
520 
521  i++;
522  if (i == r_polydesc.nump)
523  i = 0;
524 
525  } while (i != s_maxindex);
526 
527  pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
528 }
529 
530 /*
531 ** R_ClipAndDrawPoly
532 */
533 static void R_ClipAndDrawPoly(float alpha, int isturbulent, int textured)
534 {
535  emitpoint_t outverts[MAXWORKINGVERTS + 3], *pout;
536  float *pv;
537  int i, nump;
538  float scale;
539  vec3_t transformed, local;
540 
541  r_polydesc.alpha = 255 * alpha;
543 
544  if (textured == 0) {
546  } else if (textured == 2) {
548  } else if (alpha == 1) {
549  // isturbulent is ignored because we know that turbulent surfaces
550  // can't be opaque
552  } else if (isturbulent) {
554  } else {
556  }
557 
558  // clip to the frustum in worldspace
559  nump = r_polydesc.nump;
560  clip_current = 0;
561 
562  for (i = 0; i < 4; i++) {
563  nump = R_ClipPolyFace(nump, &view_clipplanes[i]);
564  if (nump < 3)
565  return;
566  if (nump > MAXWORKINGVERTS)
567  Com_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump);
568  }
569 
570 // transform vertices into viewspace and project
571  pv = &r_clip_verts[clip_current][0][0];
572 
573  for (i = 0; i < nump; i++) {
574  VectorSubtract(pv, r_origin, local);
575  R_TransformVector(local, transformed);
576 
577  if (transformed[2] < NEAR_CLIP)
578  transformed[2] = NEAR_CLIP;
579 
580  pout = &outverts[i];
581  pout->zi = 1.0 / transformed[2];
582 
583  pout->s = pv[3];
584  pout->t = pv[4];
585 
586  scale = r_refdef.xscale * pout->zi;
587  pout->u = (r_refdef.xcenter + scale * transformed[0]);
588 
589  scale = r_refdef.yscale * pout->zi;
590  pout->v = (r_refdef.ycenter - scale * transformed[1]);
591 
592  pv += sizeof(vec5_t) / sizeof(vec_t);
593  }
594 
595 // draw it
596  r_polydesc.nump = nump;
597  r_polydesc.pverts = outverts;
598 
599  R_DrawPoly(isturbulent);
600 }
601 
602 /*
603 ** R_BuildPolygonFromSurface
604 */
605 static void R_BuildPolygonFromSurface(mface_t *fa)
606 {
607  int i, lnumverts;
608  msurfedge_t *surfedge;
609  float *vec;
610  vec5_t *pverts;
611  float tmins[2] = { 0, 0 };
612 
613  r_polydesc.nump = 0;
614 
615  // reconstruct the polygon
616  lnumverts = fa->numsurfedges;
617 
618  if (lnumverts > MAXWORKINGVERTS)
619  Com_Error(ERR_DROP, "R_BuildPolygonFromSurface: too many points: %d", lnumverts);
620 
621  pverts = r_clip_verts[0];
622 
623  surfedge = fa->firstsurfedge;
624  for (i = 0; i < lnumverts; i++, surfedge++) {
625  vec = surfedge->edge->v[surfedge->vert]->point;
626  VectorCopy(vec, pverts[i]);
627  }
628 
629  VectorCopy(fa->texinfo->axis[0], r_polydesc.vright);
630  VectorCopy(fa->texinfo->axis[1], r_polydesc.vup);
631  VectorCopy(fa->plane->normal, r_polydesc.vpn);
632  VectorCopy(r_origin, r_polydesc.viewer_position);
633 
634  if (fa->drawflags & DSURF_PLANEBACK) {
635  VectorInverse(r_polydesc.vpn);
636  }
637 
638  if (fa->texinfo->c.flags & (SURF_WARP | SURF_FLOWING)) {
639  r_polydesc.pixels = fa->texinfo->image->pixels[0];
640  r_polydesc.pixel_width = fa->texinfo->image->upload_width;
641  r_polydesc.pixel_height = fa->texinfo->image->upload_height;
642  } else {
643  surfcache_t *scache;
644 
645  scache = D_CacheSurface(fa, 0);
646 
647  r_polydesc.pixels = scache->data;
648  r_polydesc.pixel_width = scache->width;
649  r_polydesc.pixel_height = scache->height;
650 
651  tmins[0] = fa->texturemins[0];
652  tmins[1] = fa->texturemins[1];
653  }
654 
655  r_polydesc.dist = DotProduct(r_polydesc.vpn, pverts[0]);
656 
657  r_polydesc.s_offset = fa->texinfo->offset[0] - tmins[0];
658  r_polydesc.t_offset = fa->texinfo->offset[1] - tmins[1];
659 
660  // scrolling texture addition
661  if (fa->texinfo->c.flags & SURF_FLOWING) {
662  r_polydesc.s_offset += -128 * ((r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25));
663  }
664 
665  r_polydesc.nump = lnumverts;
666 }
667 
668 /*
669 ** R_PolygonCalculateGradients
670 */
672 {
673  vec3_t p_normal, p_saxis, p_taxis;
674  float distinv;
675 
676  R_TransformVector(r_polydesc.vpn, p_normal);
678  R_TransformVector(r_polydesc.vup, p_taxis);
679 
680  distinv = 1.0 / (-(DotProduct(r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist);
681 
682  d_sdivzstepu = p_saxis[0] * r_refdef.xscaleinv;
683  d_sdivzstepv = -p_saxis[1] * r_refdef.yscaleinv;
685 
686  d_tdivzstepu = p_taxis[0] * r_refdef.xscaleinv;
687  d_tdivzstepv = -p_taxis[1] * r_refdef.yscaleinv;
689 
690  d_zistepu = p_normal[0] * r_refdef.xscaleinv * distinv;
691  d_zistepv = -p_normal[1] * r_refdef.yscaleinv * distinv;
692  d_ziorigin = p_normal[2] * distinv - r_refdef.xcenter * d_zistepu - r_refdef.ycenter * d_zistepv;
693 
694  sadjust = (fixed16_t)((DotProduct(r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset) * 0x10000);
695  tadjust = (fixed16_t)((DotProduct(r_polydesc.viewer_position, r_polydesc.vup) + r_polydesc.t_offset) * 0x10000);
696 
697 // -1 (-epsilon) so we never wander off the edge of the texture
698  bbextents = (r_polydesc.pixel_width << 16) - 1;
699  bbextentt = (r_polydesc.pixel_height << 16) - 1;
700 }
701 
702 /*
703 ** R_DrawPoly
704 **
705 ** Polygon drawing function. Uses the polygon described in r_polydesc
706 ** to calculate edges and gradients, then renders the resultant spans.
707 **
708 ** This should NOT be called externally since it doesn't do clipping!
709 */
710 static void R_DrawPoly(int iswater)
711 {
712  int i, nump;
713  float ymin, ymax;
714  emitpoint_t *pverts;
715  espan_t spans[MAXHEIGHT + 1];
716 
717  s_polygon_spans = spans;
718 
719 // find the top and bottom vertices, and make sure there's at least one scan to
720 // draw
721  ymin = 999999.9;
722  ymax = -999999.9;
723  pverts = r_polydesc.pverts;
724 
725  for (i = 0; i < r_polydesc.nump; i++) {
726  if (pverts->v < ymin) {
727  ymin = pverts->v;
728  s_minindex = i;
729  }
730 
731  if (pverts->v > ymax) {
732  ymax = pverts->v;
733  s_maxindex = i;
734  }
735 
736  pverts++;
737  }
738 
739  ymin = ceil(ymin);
740  ymax = ceil(ymax);
741 
742  if (ymin >= ymax)
743  return; // doesn't cross any scans at all
744 
747 
748 // copy the first vertex to the last vertex, so we don't have to deal with
749 // wrapping
750  nump = r_polydesc.nump;
751  pverts = r_polydesc.pverts;
752  pverts[nump] = pverts[0];
753 
757 
759 }
760 
761 /*
762 ** R_DrawAlphaSurfaces
763 */
765 {
766  mface_t *s = r_alpha_surfaces;
767 
768  //currentmodel = r_worldmodel;
769 
770  modelorg[0] = -r_origin[0];
771  modelorg[1] = -r_origin[1];
772  modelorg[2] = -r_origin[2];
773 
774  while (s) {
776 
777  if (s->texinfo->c.flags & SURF_TRANS66)
778  R_ClipAndDrawPoly(0.66f, (s->texinfo->c.flags & (SURF_WARP | SURF_FLOWING)), qtrue);
779  else
780  R_ClipAndDrawPoly(0.33f, (s->texinfo->c.flags & (SURF_WARP | SURF_FLOWING)), qtrue);
781 
782  s = s->next;
783  }
784 
785  r_alpha_surfaces = NULL;
786 }
787 
788 /*
789 ** R_IMFlatShadedQuad
790 */
791 void R_IMFlatShadedQuad(vec3_t a, vec3_t b, vec3_t c, vec3_t d, color_t color, float alpha)
792 {
793  vec3_t s0, s1;
794 
795  r_polydesc.nump = 4;
796  VectorCopy(r_origin, r_polydesc.viewer_position);
797 
798  VectorCopy(a, r_clip_verts[0][0]);
799  VectorCopy(b, r_clip_verts[0][1]);
800  VectorCopy(c, r_clip_verts[0][2]);
801  VectorCopy(d, r_clip_verts[0][3]);
802 
803  r_clip_verts[0][0][3] = 0;
804  r_clip_verts[0][1][3] = 0;
805  r_clip_verts[0][2][3] = 0;
806  r_clip_verts[0][3][3] = 0;
807 
808  r_clip_verts[0][0][4] = 0;
809  r_clip_verts[0][1][4] = 0;
810  r_clip_verts[0][2][4] = 0;
811  r_clip_verts[0][3][4] = 0;
812 
813  VectorSubtract(d, c, s0);
814  VectorSubtract(c, b, s1);
815  CrossProduct(s0, s1, r_polydesc.vpn);
817 
818  r_polydesc.dist = DotProduct(r_polydesc.vpn, r_clip_verts[0][0]);
819 
820  r_polydesc.alpha = 255 * alpha;
821 
822  r_polyblendcolor[0] = color.u8[0] * r_polydesc.alpha;
823  r_polyblendcolor[1] = color.u8[1] * r_polydesc.alpha;
824  r_polyblendcolor[2] = color.u8[2] * r_polydesc.alpha;
825 
826  R_ClipAndDrawPoly(alpha, qfalse, qfalse);
827 }
828 
829 /*
830 ** R_DrawSprite
831 **
832 ** Draw currententity / currentmodel as a single texture
833 ** mapped polygon
834 */
835 void R_DrawSprite(void)
836 {
837  vec5_t *pverts;
838  vec3_t left, up, right, down;
839  mspriteframe_t *frame;
840  int textured;
841 
842  frame = &currentmodel->spriteframes[
843  currententity->frame % currentmodel->numframes];
844 
845  r_polydesc.pixels = frame->image->pixels[0];
846  r_polydesc.pixel_width = frame->image->upload_width;
847  r_polydesc.pixel_height = frame->image->upload_height;
848  r_polydesc.dist = 0;
849 
850  // generate the sprite's axes, completely parallel to the viewplane.
851  VectorCopy(vup, r_polydesc.vup);
852  VectorCopy(vright, r_polydesc.vright);
853  VectorCopy(vpn, r_polydesc.vpn);
854 
855 // build the sprite poster in worldspace
856  VectorScale(r_polydesc.vright,
857  frame->width - frame->origin_x, right);
858  VectorScale(r_polydesc.vup,
859  frame->height - frame->origin_y, up);
860  VectorScale(r_polydesc.vright,
861  -frame->origin_x, left);
862  VectorScale(r_polydesc.vup,
863  -frame->origin_y, down);
864 
865  // invert UP vector for sprites
866  VectorNegate(r_polydesc.vup, r_polydesc.vup);
867 
868  pverts = r_clip_verts[0];
869 
870  pverts[0][0] = r_entorigin[0] + up[0] + left[0];
871  pverts[0][1] = r_entorigin[1] + up[1] + left[1];
872  pverts[0][2] = r_entorigin[2] + up[2] + left[2];
873  pverts[0][3] = 0;
874  pverts[0][4] = 0;
875 
876  pverts[1][0] = r_entorigin[0] + up[0] + right[0];
877  pverts[1][1] = r_entorigin[1] + up[1] + right[1];
878  pverts[1][2] = r_entorigin[2] + up[2] + right[2];
879  pverts[1][3] = frame->width;
880  pverts[1][4] = 0;
881 
882  pverts[2][0] = r_entorigin[0] + down[0] + right[0];
883  pverts[2][1] = r_entorigin[1] + down[1] + right[1];
884  pverts[2][2] = r_entorigin[2] + down[2] + right[2];
885  pverts[2][3] = frame->width;
886  pverts[2][4] = frame->height;
887 
888  pverts[3][0] = r_entorigin[0] + down[0] + left[0];
889  pverts[3][1] = r_entorigin[1] + down[1] + left[1];
890  pverts[3][2] = r_entorigin[2] + down[2] + left[2];
891  pverts[3][3] = 0;
892  pverts[3][4] = frame->height;
893 
894  r_polydesc.nump = 4;
897  VectorCopy(modelorg, r_polydesc.viewer_position);
898 
899  if (frame->image->flags & IF_TRANSPARENT)
900  textured = 2;
901  else
902  textured = 1;
903 
904  if (currententity->flags & RF_TRANSLUCENT)
905  R_ClipAndDrawPoly(currententity->alpha, qfalse, textured);
906  else
907  R_ClipAndDrawPoly(1.0F, qfalse, textured);
908 }
909 
oldrefdef_t::xcenter
float xcenter
Definition: sw.h:145
MAXWORKINGVERTS
#define MAXWORKINGVERTS
Definition: sw.h:54
spanletvars_t::pdest
byte * pdest
Definition: poly.c:24
espan_s
Definition: sw.h:220
oldrefdef_t::fvrectx_adj
float fvrectx_adj
Definition: sw.h:137
r_origin
vec3_t r_origin
Definition: main.c:52
SPEED
#define SPEED
Definition: sw.h:110
r_newrefdef
refdef_t r_newrefdef
Definition: main.c:28
surfcache_s
Definition: sw.h:207
emitpoint_t::u
float u
Definition: sw.h:157
s_minindex
static int s_minindex
Definition: poly.c:48
d_sdivzstepv
float d_sdivzstepv
Definition: main.c:117
r_polydesc
static polydesc_t r_polydesc
Definition: poly.c:39
R_ClipAndDrawPoly
static void R_ClipAndDrawPoly(float alpha, int isturbulent, int textured)
Definition: poly.c:533
surfcache_s::height
unsigned height
Definition: sw.h:214
NEAR_CLIP
#define NEAR_CLIP
Definition: sw.h:103
spanletvars_t::sstep
fixed16_t sstep
Definition: poly.c:27
emitpoint_t::s
float s
Definition: sw.h:158
TURB_MASK
#define TURB_MASK
Definition: sw.h:72
R_DrawPoly
static void R_DrawPoly(int iswater)
Definition: poly.c:710
cacheblock
pixel_t * cacheblock
Definition: main.c:122
spanletvars_t::izistep
int izistep
Definition: poly.c:28
TEX_BYTES
#define TEX_BYTES
Definition: sw.h:50
r_turb_turb
static int * r_turb_turb
Definition: poly.c:43
CYCLE
#define CYCLE
Definition: sw.h:74
polydesc_t::pixel_width
int pixel_width
Definition: sw.h:230
oldrefdef_t::xscaleinv
float xscaleinv
Definition: sw.h:147
r_refdef
oldrefdef_t r_refdef
Definition: main.c:57
d_zistepu
float d_zistepu
Definition: main.c:116
polydesc_t::alpha
int alpha
Definition: sw.h:237
F
#define F(name)
Definition: g_save.c:46
oldrefdef_t::fvrectright_adj
float fvrectright_adj
Definition: sw.h:140
s_spanletvars
static spanletvars_t s_spanletvars
Definition: poly.c:33
oldrefdef_t::yscale
float yscale
Definition: sw.h:146
polydesc_t::vpn
vec3_t vpn
Definition: sw.h:232
polydesc_t::viewer_position
float viewer_position[3]
Definition: sw.h:235
clipplane_s::normal
vec3_t normal
Definition: sw.h:194
blanktable
int blanktable[CYCLE *2]
Definition: main.c:135
vup
vec3_t vup
Definition: main.c:49
R_DrawSpanletOpaque
static void R_DrawSpanletOpaque(void)
Definition: poly.c:52
espan_s::count
int count
Definition: sw.h:221
R_BuildPolygonFromSurface
static void R_BuildPolygonFromSurface(mface_t *fa)
Definition: poly.c:605
polydesc_t::pixels
byte * pixels
Definition: sw.h:229
spanletvars_t::u
unsigned u
Definition: poly.c:30
spanletvars_t::t
fixed16_t t
Definition: poly.c:26
polydesc_t::t_offset
float t_offset
Definition: sw.h:234
R_DrawSprite
void R_DrawSprite(void)
Definition: poly.c:835
spanletvars_t::spancount
int spancount
Definition: poly.c:29
oldrefdef_t::fvrecty_adj
float fvrecty_adj
Definition: sw.h:137
R_ClipPolyFace
static int R_ClipPolyFace(int nump, clipplane_t *pclipplane)
Definition: poly.c:173
polydesc_t::s_offset
float s_offset
Definition: sw.h:234
cachewidth
int cachewidth
Definition: main.c:123
currententity
entity_t * currententity
Definition: bsp.c:26
bbextentt
fixed16_t bbextentt
Definition: main.c:120
spanletvars_t::pbase
byte * pbase
Definition: poly.c:24
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
espan_s::v
int v
Definition: sw.h:221
polydesc_t::nump
int nump
Definition: sw.h:227
d_tdivzorigin
float d_tdivzorigin
Definition: main.c:118
r_clip_verts
static vec5_t r_clip_verts[2][MAXWORKINGVERTS+2]
Definition: poly.c:46
vpn
vec3_t vpn
Definition: main.c:50
oldrefdef_t::fvrectbottom_adj
float fvrectbottom_adj
Definition: sw.h:140
emitpoint_t
Definition: sw.h:156
sw.h
AFFINE_SPANLET_SIZE_BITS
#define AFFINE_SPANLET_SIZE_BITS
Definition: poly.c:21
R_DrawAlphaSurfaces
void R_DrawAlphaSurfaces(void)
Definition: poly.c:764
spanletvars_t::v
unsigned v
Definition: poly.c:30
polydesc_t::dist
float dist
Definition: sw.h:233
d_spantable
byte * d_spantable[MAXHEIGHT]
Definition: main.c:130
spanletvars_t
Definition: poly.c:23
R_DrawSpanletBlended
static void R_DrawSpanletBlended(void)
Definition: poly.c:116
emitpoint_t::v
float v
Definition: sw.h:157
AFFINE_SPANLET_SIZE
#define AFFINE_SPANLET_SIZE
Definition: poly.c:20
emitpoint_t::zi
float zi
Definition: sw.h:159
clipplane_s
Definition: sw.h:193
espan_s::u
int u
Definition: sw.h:221
d_zspantable
short * d_zspantable[MAXHEIGHT]
Definition: main.c:131
d_tdivzstepv
float d_tdivzstepv
Definition: main.c:117
clip_current
static int clip_current
Definition: poly.c:45
TURB_SIZE
#define TURB_SIZE
Definition: sw.h:71
R_PolygonScanRightEdge
static void R_PolygonScanRightEdge(void)
Definition: poly.c:457
sintable
int sintable[CYCLE *2]
Definition: main.c:133
r_entorigin
vec3_t r_entorigin
Definition: bsp.c:29
oldrefdef_t::xscale
float xscale
Definition: sw.h:146
modelorg
vec3_t modelorg
Definition: bsp.c:27
R_DrawSpanletTurbulentBlended
static void R_DrawSpanletTurbulentBlended(void)
Definition: poly.c:77
R_PolygonScanLeftEdge
static void R_PolygonScanLeftEdge(void)
Definition: poly.c:397
spanletvars_t::izi
int izi
Definition: poly.c:28
r_polyblendcolor
static fixed8_t r_polyblendcolor[3]
Definition: poly.c:35
emitpoint_t::t
float t
Definition: sw.h:158
VID_BYTES
#define VID_BYTES
Definition: sw.h:49
R_PolygonCalculateGradients
static void R_PolygonCalculateGradients(void)
Definition: poly.c:671
DS_SPAN_LIST_END
#define DS_SPAN_LIST_END
Definition: sw.h:76
c
statCounters_t c
Definition: main.c:30
d_tdivzstepu
float d_tdivzstepu
Definition: main.c:116
R_DrawSpanletConstantBlended
static void R_DrawSpanletConstantBlended(void)
Definition: poly.c:101
d_zistepv
float d_zistepv
Definition: main.c:117
polydesc_t::one_minus_alpha
int one_minus_alpha
Definition: sw.h:238
s_maxindex
static int s_maxindex
Definition: poly.c:48
sadjust
fixed16_t sadjust
Definition: main.c:120
d_sdivzstepu
float d_sdivzstepu
Definition: main.c:116
oldrefdef_t::yscaleinv
float yscaleinv
Definition: sw.h:147
d_sdivzorigin
float d_sdivzorigin
Definition: main.c:118
polydesc_t::drawspanlet
void(* drawspanlet)(void)
Definition: sw.h:236
up
static vec3_t up
Definition: p_view.c:27
polydesc_t
Definition: sw.h:226
right
static vec3_t right
Definition: p_view.c:27
polydesc_t::vup
vec3_t vup
Definition: sw.h:232
surfcache_s::data
byte data[4]
Definition: sw.h:217
r_alpha_surfaces
mface_t * r_alpha_surfaces
Definition: poly.c:41
D_CacheSurface
surfcache_t * D_CacheSurface(mface_t *surface, int miplevel)
Definition: surf.c:330
color
static vec4_t color
Definition: mesh.c:33
R_TransformVector
void R_TransformVector(vec3_t in, vec3_t out)
Definition: misc.c:96
tadjust
fixed16_t tadjust
Definition: main.c:120
clipplane_s::dist
float dist
Definition: sw.h:195
surfcache_s::width
unsigned width
Definition: sw.h:213
R_IMFlatShadedQuad
void R_IMFlatShadedQuad(vec3_t a, vec3_t b, vec3_t c, vec3_t d, color_t color, float alpha)
Definition: poly.c:791
spanletvars_t::pz
short * pz
Definition: poly.c:25
oldrefdef_t::ycenter
float ycenter
Definition: sw.h:145
polydesc_t::pverts
emitpoint_t * pverts
Definition: sw.h:228
R_PolygonDrawSpans
static void R_PolygonDrawSpans(espan_t *pspan, int iswater)
Definition: poly.c:242
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
MAXHEIGHT
#define MAXHEIGHT
Definition: sw.h:57
R_DrawSpanletAlphaTestBlended
static void R_DrawSpanletAlphaTestBlended(void)
Definition: poly.c:140
polydesc_t::pixel_height
int pixel_height
Definition: sw.h:231
s_polygon_spans
static espan_t * s_polygon_spans
Definition: poly.c:37
view_clipplanes
clipplane_t view_clipplanes[4]
Definition: raster.c:37
bbextents
fixed16_t bbextents
Definition: main.c:120
currentmodel
model_t * currentmodel
Definition: main.c:29
d_ziorigin
float d_ziorigin
Definition: main.c:118
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: shared.c:55
polydesc_t::vright
vec3_t vright
Definition: sw.h:232
spanletvars_t::tstep
fixed16_t tstep
Definition: poly.c:27
spanletvars_t::s
fixed16_t s
Definition: poly.c:26
vright
vec3_t vright
Definition: main.c:51