icculus quake2 doxygen  1.0 dev
r_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
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (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.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 */
20 #include <assert.h>
21 #include "r_local.h"
22 
23 #define AFFINE_SPANLET_SIZE 16
24 #define AFFINE_SPANLET_SIZE_BITS 4
25 
26 typedef struct
27 {
28  byte *pbase, *pdest;
29  short *pz;
31  fixed16_t sstep, tstep;
32  int izi, izistep, izistep_times_2;
33  int spancount;
34  unsigned u, v;
36 
38 
39 static int r_polyblendcolor;
40 
42 
44 
46 
47 extern int *r_turb_turb;
48 
49 static int clip_current;
51 
52 static int s_minindex, s_maxindex;
53 
54 static void R_DrawPoly( int iswater );
55 
56 /*
57 ** R_DrawSpanletOpaque
58 */
59 void R_DrawSpanletOpaque( void )
60 {
61  unsigned btemp;
62 
63  do
64  {
65  unsigned ts, tt;
66 
67  ts = s_spanletvars.s >> 16;
68  tt = s_spanletvars.t >> 16;
69 
70  btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
71  if (btemp != 255)
72  {
73  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
74  {
76  *s_spanletvars.pdest = btemp;
77  }
78  }
79 
82  s_spanletvars.pz++;
85  } while (--s_spanletvars.spancount > 0);
86 }
87 
88 /*
89 ** R_DrawSpanletTurbulentStipple33
90 */
92 {
93  unsigned btemp;
94  int sturb, tturb;
95  byte *pdest = s_spanletvars.pdest;
96  short *pz = s_spanletvars.pz;
97  int izi = s_spanletvars.izi;
98 
99  if ( s_spanletvars.v & 1 )
100  {
103 
106  else
108 
109  if ( s_spanletvars.u & 1 )
110  {
111  izi += s_spanletvars.izistep;
114 
115  pdest++;
116  pz++;
118  }
119 
120  s_spanletvars.sstep *= 2;
121  s_spanletvars.tstep *= 2;
122 
123  while ( s_spanletvars.spancount > 0 )
124  {
125  sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
126  tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
127 
128  btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
129 
130  if ( *pz <= ( izi >> 16 ) )
131  *pdest = btemp;
132 
136 
137  pdest += 2;
138  pz += 2;
139 
141  }
142  }
143 }
144 
145 /*
146 ** R_DrawSpanletTurbulentStipple66
147 */
149 {
150  unsigned btemp;
151  int sturb, tturb;
152  byte *pdest = s_spanletvars.pdest;
153  short *pz = s_spanletvars.pz;
154  int izi = s_spanletvars.izi;
155 
156  if ( !( s_spanletvars.v & 1 ) )
157  {
160 
163  else
165 
166  if ( s_spanletvars.u & 1 )
167  {
168  izi += s_spanletvars.izistep;
171 
172  pdest++;
173  pz++;
175  }
176 
177  s_spanletvars.sstep *= 2;
178  s_spanletvars.tstep *= 2;
179 
180  while ( s_spanletvars.spancount > 0 )
181  {
182  sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
183  tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
184 
185  btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
186 
187  if ( *pz <= ( izi >> 16 ) )
188  *pdest = btemp;
189 
193 
194  pdest += 2;
195  pz += 2;
196 
198  }
199  }
200  else
201  {
204 
207  else
209 
210  while ( s_spanletvars.spancount > 0 )
211  {
212  sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
213  tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
214 
215  btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
216 
217  if ( *pz <= ( izi >> 16 ) )
218  *pdest = btemp;
219 
220  izi += s_spanletvars.izistep;
223 
224  pdest++;
225  pz++;
226 
228  }
229  }
230 }
231 
232 /*
233 ** R_DrawSpanletTurbulentBlended
234 */
236 {
237  unsigned btemp;
238  int sturb, tturb;
239 
240  do
241  {
242  sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
243  tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
244 
245  btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
246 
247  if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
249 
252  s_spanletvars.pz++;
255 
256  } while ( --s_spanletvars.spancount > 0 );
257 }
258 
260 {
261  unsigned btemp;
262  int sturb, tturb;
263 
264  do
265  {
266  sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
267  tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
268 
269  btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
270 
271  if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
273 
276  s_spanletvars.pz++;
279 
280  } while ( --s_spanletvars.spancount > 0 );
281 }
282 
283 /*
284 ** R_DrawSpanlet33
285 */
286 void R_DrawSpanlet33( void )
287 {
288  unsigned btemp;
289 
290  do
291  {
292  unsigned ts, tt;
293 
294  ts = s_spanletvars.s >> 16;
295  tt = s_spanletvars.t >> 16;
296 
297  btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
298 
299  if ( btemp != 255 )
300  {
301  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
302  {
304  }
305  }
306 
309  s_spanletvars.pz++;
312  } while (--s_spanletvars.spancount > 0);
313 }
314 
316 {
317  do
318  {
319  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
320  {
322  }
323 
326  s_spanletvars.pz++;
327  } while (--s_spanletvars.spancount > 0);
328 }
329 
330 /*
331 ** R_DrawSpanlet66
332 */
333 void R_DrawSpanlet66( void )
334 {
335  unsigned btemp;
336 
337  do
338  {
339  unsigned ts, tt;
340 
341  ts = s_spanletvars.s >> 16;
342  tt = s_spanletvars.t >> 16;
343 
344  btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
345 
346  if ( btemp != 255 )
347  {
348  if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
349  {
351  }
352  }
353 
356  s_spanletvars.pz++;
359  } while (--s_spanletvars.spancount > 0);
360 }
361 
362 /*
363 ** R_DrawSpanlet33Stipple
364 */
366 {
367  unsigned btemp;
368  byte *pdest = s_spanletvars.pdest;
369  short *pz = s_spanletvars.pz;
370  int izi = s_spanletvars.izi;
371 
372  if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
373  {
376 
379  else
381 
382  if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
383  {
384  izi += s_spanletvars.izistep;
387 
388  pdest++;
389  pz++;
391  }
392 
393  s_spanletvars.sstep *= 2;
394  s_spanletvars.tstep *= 2;
395 
396  while ( s_spanletvars.spancount > 0 )
397  {
398  unsigned s = s_spanletvars.s >> 16;
399  unsigned t = s_spanletvars.t >> 16;
400 
401  btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
402 
403  if ( btemp != 255 )
404  {
405  if ( *pz <= ( izi >> 16 ) )
406  *pdest = btemp;
407  }
408 
412 
413  pdest += 2;
414  pz += 2;
415 
417  }
418  }
419 }
420 
421 /*
422 ** R_DrawSpanlet66Stipple
423 */
425 {
426  unsigned btemp;
427  byte *pdest = s_spanletvars.pdest;
428  short *pz = s_spanletvars.pz;
429  int izi = s_spanletvars.izi;
430 
433 
436  else
438 
439  if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
440  {
441  if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
442  {
443  izi += s_spanletvars.izistep;
446 
447  pdest++;
448  pz++;
450  }
451 
452  s_spanletvars.sstep *= 2;
453  s_spanletvars.tstep *= 2;
454 
455  while ( s_spanletvars.spancount > 0 )
456  {
457  unsigned s = s_spanletvars.s >> 16;
458  unsigned t = s_spanletvars.t >> 16;
459 
460  btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
461 
462  if ( btemp != 255 )
463  {
464  if ( *pz <= ( izi >> 16 ) )
465  *pdest = btemp;
466  }
467 
471 
472  pdest += 2;
473  pz += 2;
474 
476  }
477  }
478  else
479  {
480  while ( s_spanletvars.spancount > 0 )
481  {
482  unsigned s = s_spanletvars.s >> 16;
483  unsigned t = s_spanletvars.t >> 16;
484 
485  btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
486 
487  if ( btemp != 255 )
488  {
489  if ( *pz <= ( izi >> 16 ) )
490  *pdest = btemp;
491  }
492 
493  izi += s_spanletvars.izistep;
496 
497  pdest++;
498  pz++;
499 
501  }
502  }
503 }
504 
505 /*
506 ** R_ClipPolyFace
507 **
508 ** Clips the winding at clip_verts[clip_current] and changes clip_current
509 ** Throws out the back side
510 */
511 int R_ClipPolyFace (int nump, clipplane_t *pclipplane)
512 {
513  int i, outcount;
514  float dists[MAXWORKINGVERTS+3];
515  float frac, clipdist, *pclipnormal;
516  float *in, *instep, *outstep, *vert2;
517 
518  clipdist = pclipplane->dist;
519  pclipnormal = pclipplane->normal;
520 
521 // calc dists
522  if (clip_current)
523  {
524  in = r_clip_verts[1][0];
525  outstep = r_clip_verts[0][0];
526  clip_current = 0;
527  }
528  else
529  {
530  in = r_clip_verts[0][0];
531  outstep = r_clip_verts[1][0];
532  clip_current = 1;
533  }
534 
535  instep = in;
536  for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
537  {
538  dists[i] = DotProduct (instep, pclipnormal) - clipdist;
539  }
540 
541 // handle wraparound case
542  dists[nump] = dists[0];
543  memcpy (instep, in, sizeof (vec5_t));
544 
545 
546 // clip the winding
547  instep = in;
548  outcount = 0;
549 
550  for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
551  {
552  if (dists[i] >= 0)
553  {
554  memcpy (outstep, instep, sizeof (vec5_t));
555  outstep += sizeof (vec5_t) / sizeof (float);
556  outcount++;
557  }
558 
559  if (dists[i] == 0 || dists[i+1] == 0)
560  continue;
561 
562  if ( (dists[i] > 0) == (dists[i+1] > 0) )
563  continue;
564 
565  // split it into a new vertex
566  frac = dists[i] / (dists[i] - dists[i+1]);
567 
568  vert2 = instep + sizeof (vec5_t) / sizeof (float);
569 
570  outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
571  outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
572  outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
573  outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
574  outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
575 
576  outstep += sizeof (vec5_t) / sizeof (float);
577  outcount++;
578  }
579 
580  return outcount;
581 }
582 
583 /*
584 ** R_PolygonDrawSpans
585 */
586 // PGM - iswater was qboolean. changed to allow passing more flags
587 void R_PolygonDrawSpans(espan_t *pspan, int iswater )
588 {
589  int count;
590  fixed16_t snext, tnext;
591  float sdivz, tdivz, zi, z, du, dv, spancountminus1;
592  float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu;
593 
595 
596 //PGM
597  if ( iswater & SURF_WARP)
599  else if (iswater & SURF_FLOWING)
601 //PGM
602 
603  sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE;
604  tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE;
605  zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE;
606 
607 // we count on FP exceptions being turned off to avoid range problems
608  s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000);
610 
611  s_spanletvars.pz = 0;
612 
613  do
614  {
615  s_spanletvars.pdest = (byte *)d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u;
616  s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
617  s_spanletvars.u = pspan->u;
618  s_spanletvars.v = pspan->v;
619 
620  count = pspan->count;
621 
622  if (count <= 0)
623  goto NextSpan;
624 
625  // calculate the initial s/z, t/z, 1/z, s, and t and clamp
626  du = (float)pspan->u;
627  dv = (float)pspan->v;
628 
629  sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
630  tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
631 
632  zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
633  z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
634  // we count on FP exceptions being turned off to avoid range problems
635  s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000);
636 
637  s_spanletvars.s = (int)(sdivz * z) + sadjust;
638  s_spanletvars.t = (int)(tdivz * z) + tadjust;
639 
640  if ( !iswater )
641  {
642  if (s_spanletvars.s > bbextents)
644  else if (s_spanletvars.s < 0)
645  s_spanletvars.s = 0;
646 
647  if (s_spanletvars.t > bbextentt)
649  else if (s_spanletvars.t < 0)
650  s_spanletvars.t = 0;
651  }
652 
653  do
654  {
655  // calculate s and t at the far end of the span
656  if (count >= AFFINE_SPANLET_SIZE )
658  else
660 
662 
663  if (count)
664  {
665  // calculate s/z, t/z, zi->fixed s and t at far end of span,
666  // calculate s and t steps across span by shifting
667  sdivz += sdivzspanletstepu;
668  tdivz += tdivzspanletstepu;
669  zi += zispanletstepu;
670  z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
671 
672  snext = (int)(sdivz * z) + sadjust;
673  tnext = (int)(tdivz * z) + tadjust;
674 
675  if ( !iswater )
676  {
677  if (snext > bbextents)
678  snext = bbextents;
679  else if (snext < AFFINE_SPANLET_SIZE)
680  snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
681  // from causing overstepping & running off the
682  // edge of the texture
683 
684  if (tnext > bbextentt)
685  tnext = bbextentt;
686  else if (tnext < AFFINE_SPANLET_SIZE)
687  tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
688  }
689 
692  }
693  else
694  {
695  // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
696  // can't step off polygon), clamp, calculate s and t steps across
697  // span by division, biasing steps low so we don't run off the
698  // texture
699  spancountminus1 = (float)(s_spanletvars.spancount - 1);
700  sdivz += d_sdivzstepu * spancountminus1;
701  tdivz += d_tdivzstepu * spancountminus1;
702  zi += d_zistepu * spancountminus1;
703  z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
704  snext = (int)(sdivz * z) + sadjust;
705  tnext = (int)(tdivz * z) + tadjust;
706 
707  if ( !iswater )
708  {
709  if (snext > bbextents)
710  snext = bbextents;
711  else if (snext < AFFINE_SPANLET_SIZE)
712  snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
713  // from causing overstepping & running off the
714  // edge of the texture
715 
716  if (tnext > bbextentt)
717  tnext = bbextentt;
718  else if (tnext < AFFINE_SPANLET_SIZE)
719  tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
720  }
721 
722  if (s_spanletvars.spancount > 1)
723  {
726  }
727  }
728 
729  if ( iswater )
730  {
731  s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1);
732  s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1);
733  }
734 
736 
737  s_spanletvars.s = snext;
738  s_spanletvars.t = tnext;
739 
740  } while (count > 0);
741 
742 NextSpan:
743  pspan++;
744 
745  } while (pspan->count != DS_SPAN_LIST_END);
746 }
747 
748 /*
749 **
750 ** R_PolygonScanLeftEdge
751 **
752 ** Goes through the polygon and scans the left edge, filling in
753 ** screen coordinate data for the spans
754 */
756 {
757  int i, v, itop, ibottom, lmaxindex;
758  emitpoint_t *pvert, *pnext;
759  espan_t *pspan;
760  float du, dv, vtop, vbottom, slope;
761  fixed16_t u, u_step;
762 
763  pspan = s_polygon_spans;
764  i = s_minindex;
765  if (i == 0)
766  i = r_polydesc.nump;
767 
768  lmaxindex = s_maxindex;
769  if (lmaxindex == 0)
770  lmaxindex = r_polydesc.nump;
771 
772  vtop = ceil (r_polydesc.pverts[i].v);
773 
774  do
775  {
776  pvert = &r_polydesc.pverts[i];
777  pnext = pvert - 1;
778 
779  vbottom = ceil (pnext->v);
780 
781  if (vtop < vbottom)
782  {
783  du = pnext->u - pvert->u;
784  dv = pnext->v - pvert->v;
785 
786  slope = du / dv;
787  u_step = (int)(slope * 0x10000);
788  // adjust u to ceil the integer portion
789  u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
790  (0x10000 - 1);
791  itop = (int)vtop;
792  ibottom = (int)vbottom;
793 
794  for (v=itop ; v<ibottom ; v++)
795  {
796  pspan->u = u >> 16;
797  pspan->v = v;
798  u += u_step;
799  pspan++;
800  }
801  }
802 
803  vtop = vbottom;
804 
805  i--;
806  if (i == 0)
807  i = r_polydesc.nump;
808 
809  } while (i != lmaxindex);
810 }
811 
812 /*
813 ** R_PolygonScanRightEdge
814 **
815 ** Goes through the polygon and scans the right edge, filling in
816 ** count values.
817 */
819 {
820  int i, v, itop, ibottom;
821  emitpoint_t *pvert, *pnext;
822  espan_t *pspan;
823  float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
824  fixed16_t u, u_step;
825 
826  pspan = s_polygon_spans;
827  i = s_minindex;
828 
829  vvert = r_polydesc.pverts[i].v;
830  if (vvert < r_refdef.fvrecty_adj)
831  vvert = r_refdef.fvrecty_adj;
832  if (vvert > r_refdef.fvrectbottom_adj)
833  vvert = r_refdef.fvrectbottom_adj;
834 
835  vtop = ceil (vvert);
836 
837  do
838  {
839  pvert = &r_polydesc.pverts[i];
840  pnext = pvert + 1;
841 
842  vnext = pnext->v;
843  if (vnext < r_refdef.fvrecty_adj)
844  vnext = r_refdef.fvrecty_adj;
845  if (vnext > r_refdef.fvrectbottom_adj)
846  vnext = r_refdef.fvrectbottom_adj;
847 
848  vbottom = ceil (vnext);
849 
850  if (vtop < vbottom)
851  {
852  uvert = pvert->u;
853  if (uvert < r_refdef.fvrectx_adj)
854  uvert = r_refdef.fvrectx_adj;
855  if (uvert > r_refdef.fvrectright_adj)
856  uvert = r_refdef.fvrectright_adj;
857 
858  unext = pnext->u;
859  if (unext < r_refdef.fvrectx_adj)
860  unext = r_refdef.fvrectx_adj;
861  if (unext > r_refdef.fvrectright_adj)
862  unext = r_refdef.fvrectright_adj;
863 
864  du = unext - uvert;
865  dv = vnext - vvert;
866  slope = du / dv;
867  u_step = (int)(slope * 0x10000);
868  // adjust u to ceil the integer portion
869  u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
870  (0x10000 - 1);
871  itop = (int)vtop;
872  ibottom = (int)vbottom;
873 
874  for (v=itop ; v<ibottom ; v++)
875  {
876  pspan->count = (u >> 16) - pspan->u;
877  u += u_step;
878  pspan++;
879  }
880  }
881 
882  vtop = vbottom;
883  vvert = vnext;
884 
885  i++;
886  if (i == r_polydesc.nump)
887  i = 0;
888 
889  } while (i != s_maxindex);
890 
891  pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
892 }
893 
894 /*
895 ** R_ClipAndDrawPoly
896 */
897 // PGM - isturbulent was qboolean. changed to int to allow passing more flags
898 void R_ClipAndDrawPoly ( float alpha, int isturbulent, qboolean textured )
899 {
900  emitpoint_t outverts[MAXWORKINGVERTS+3], *pout;
901  float *pv;
902  int i, nump;
903  float scale;
904  vec3_t transformed, local;
905 
906  if ( !textured )
907  {
909  }
910  else
911  {
912 
913  /*
914  ** choose the correct spanlet routine based on alpha
915  */
916  if ( alpha == 1 )
917  {
918  // isturbulent is ignored because we know that turbulent surfaces
919  // can't be opaque
921  }
922  else
923  {
924  if ( sw_stipplealpha->value )
925  {
926  if ( isturbulent )
927  {
928  if ( alpha > 0.33 )
930  else
932  }
933  else
934  {
935  if ( alpha > 0.33 )
937  else
939  }
940  }
941  else
942  {
943  if ( isturbulent )
944  {
945  if ( alpha > 0.33 )
947  else
949  }
950  else
951  {
952  if ( alpha > 0.33 )
954  else
956  }
957  }
958  }
959  }
960 
961  // clip to the frustum in worldspace
962  nump = r_polydesc.nump;
963  clip_current = 0;
964 
965  for (i=0 ; i<4 ; i++)
966  {
967  nump = R_ClipPolyFace (nump, &view_clipplanes[i]);
968  if (nump < 3)
969  return;
970  if (nump > MAXWORKINGVERTS)
971  ri.Sys_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump );
972  }
973 
974 // transform vertices into viewspace and project
975  pv = &r_clip_verts[clip_current][0][0];
976 
977  for (i=0 ; i<nump ; i++)
978  {
979  VectorSubtract (pv, r_origin, local);
980  TransformVector (local, transformed);
981 
982  if (transformed[2] < NEAR_CLIP)
983  transformed[2] = NEAR_CLIP;
984 
985  pout = &outverts[i];
986  pout->zi = 1.0 / transformed[2];
987 
988  pout->s = pv[3];
989  pout->t = pv[4];
990 
991  scale = xscale * pout->zi;
992  pout->u = (xcenter + scale * transformed[0]);
993 
994  scale = yscale * pout->zi;
995  pout->v = (ycenter - scale * transformed[1]);
996 
997  pv += sizeof (vec5_t) / sizeof (pv);
998  }
999 
1000 // draw it
1001  r_polydesc.nump = nump;
1002  r_polydesc.pverts = outverts;
1003 
1004  R_DrawPoly( isturbulent );
1005 }
1006 
1007 /*
1008 ** R_BuildPolygonFromSurface
1009 */
1011 {
1012  int i, lindex, lnumverts;
1013  medge_t *pedges, *r_pedge;
1014  int vertpage;
1015  float *vec;
1016  vec5_t *pverts;
1017  float tmins[2] = { 0, 0 };
1018 
1019  r_polydesc.nump = 0;
1020 
1021  // reconstruct the polygon
1022  pedges = currentmodel->edges;
1023  lnumverts = fa->numedges;
1024  vertpage = 0;
1025 
1026  pverts = r_clip_verts[0];
1027 
1028  for (i=0 ; i<lnumverts ; i++)
1029  {
1030  lindex = currentmodel->surfedges[fa->firstedge + i];
1031 
1032  if (lindex > 0)
1033  {
1034  r_pedge = &pedges[lindex];
1035  vec = currentmodel->vertexes[r_pedge->v[0]].position;
1036  }
1037  else
1038  {
1039  r_pedge = &pedges[-lindex];
1040  vec = currentmodel->vertexes[r_pedge->v[1]].position;
1041  }
1042 
1043  VectorCopy (vec, pverts[i] );
1044  }
1045 
1046  VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright );
1047  VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup );
1050 
1051  if ( fa->flags & SURF_PLANEBACK )
1052  {
1054  }
1055 
1056 // PGM 09/16/98
1057  if ( fa->texinfo->flags & (SURF_WARP|SURF_FLOWING) )
1058  {
1059  r_polydesc.pixels = fa->texinfo->image->pixels[0];
1062  }
1063 // PGM 09/16/98
1064  else
1065  {
1066  surfcache_t *scache;
1067 
1068  scache = D_CacheSurface( fa, 0 );
1069 
1070  r_polydesc.pixels = scache->data;
1071  r_polydesc.pixel_width = scache->width;
1072  r_polydesc.pixel_height = scache->height;
1073 
1074  tmins[0] = fa->texturemins[0];
1075  tmins[1] = fa->texturemins[1];
1076  }
1077 
1078  r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] );
1079 
1080  r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0];
1081  r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1];
1082 
1083  // scrolling texture addition
1084  if (fa->texinfo->flags & SURF_FLOWING)
1085  {
1086  r_polydesc.s_offset += -128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) );
1087  }
1088 
1089  r_polydesc.nump = lnumverts;
1090 }
1091 
1092 /*
1093 ** R_PolygonCalculateGradients
1094 */
1096 {
1097  vec3_t p_normal, p_saxis, p_taxis;
1098  float distinv;
1099 
1100  TransformVector (r_polydesc.vpn, p_normal);
1101  TransformVector (r_polydesc.vright, p_saxis);
1102  TransformVector (r_polydesc.vup, p_taxis);
1103 
1104  distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist );
1105 
1106  d_sdivzstepu = p_saxis[0] * xscaleinv;
1107  d_sdivzstepv = -p_saxis[1] * yscaleinv;
1108  d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;
1109 
1110  d_tdivzstepu = p_taxis[0] * xscaleinv;
1111  d_tdivzstepv = -p_taxis[1] * yscaleinv;
1112  d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;
1113 
1114  d_zistepu = p_normal[0] * xscaleinv * distinv;
1115  d_zistepv = -p_normal[1] * yscaleinv * distinv;
1116  d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;
1117 
1120 
1121 // -1 (-epsilon) so we never wander off the edge of the texture
1122  bbextents = (r_polydesc.pixel_width << 16) - 1;
1123  bbextentt = (r_polydesc.pixel_height << 16) - 1;
1124 }
1125 
1126 /*
1127 ** R_DrawPoly
1128 **
1129 ** Polygon drawing function. Uses the polygon described in r_polydesc
1130 ** to calculate edges and gradients, then renders the resultant spans.
1131 **
1132 ** This should NOT be called externally since it doesn't do clipping!
1133 */
1134 // PGM - iswater was qboolean. changed to support passing more flags
1135 static void R_DrawPoly( int iswater )
1136 {
1137  int i, nump;
1138  float ymin, ymax;
1139  emitpoint_t *pverts;
1140  espan_t spans[MAXHEIGHT+1];
1141 
1142  s_polygon_spans = spans;
1143 
1144 // find the top and bottom vertices, and make sure there's at least one scan to
1145 // draw
1146  ymin = 999999.9;
1147  ymax = -999999.9;
1148  pverts = r_polydesc.pverts;
1149 
1150  for (i=0 ; i<r_polydesc.nump ; i++)
1151  {
1152  if (pverts->v < ymin)
1153  {
1154  ymin = pverts->v;
1155  s_minindex = i;
1156  }
1157 
1158  if (pverts->v > ymax)
1159  {
1160  ymax = pverts->v;
1161  s_maxindex = i;
1162  }
1163 
1164  pverts++;
1165  }
1166 
1167  ymin = ceil (ymin);
1168  ymax = ceil (ymax);
1169 
1170  if (ymin >= ymax)
1171  return; // doesn't cross any scans at all
1172 
1175 
1176 // copy the first vertex to the last vertex, so we don't have to deal with
1177 // wrapping
1178  nump = r_polydesc.nump;
1179  pverts = r_polydesc.pverts;
1180  pverts[nump] = pverts[0];
1181 
1185 
1186  R_PolygonDrawSpans( s_polygon_spans, iswater );
1187 }
1188 
1189 /*
1190 ** R_DrawAlphaSurfaces
1191 */
1193 {
1195 
1197 
1198  modelorg[0] = -r_origin[0];
1199  modelorg[1] = -r_origin[1];
1200  modelorg[2] = -r_origin[2];
1201 
1202  while ( s )
1203  {
1205 
1206 //=======
1207 //PGM
1208 // if (s->texinfo->flags & SURF_TRANS66)
1209 // R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
1210 // else
1211 // R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );
1212 
1213  // PGM - pass down all the texinfo flags, not just SURF_WARP.
1214  if (s->texinfo->flags & SURF_TRANS66)
1215  R_ClipAndDrawPoly( 0.60f, (s->texinfo->flags & (SURF_WARP|SURF_FLOWING)), true );
1216  else
1217  R_ClipAndDrawPoly( 0.30f, (s->texinfo->flags & (SURF_WARP|SURF_FLOWING)), true );
1218 //PGM
1219 //=======
1220 
1221  s = s->nextalphasurface;
1222  }
1223 
1225 }
1226 
1227 /*
1228 ** R_IMFlatShadedQuad
1229 */
1230 void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha )
1231 {
1232  vec3_t s0, s1;
1233 
1234  r_polydesc.nump = 4;
1236 
1237  VectorCopy( a, r_clip_verts[0][0] );
1238  VectorCopy( b, r_clip_verts[0][1] );
1239  VectorCopy( c, r_clip_verts[0][2] );
1240  VectorCopy( d, r_clip_verts[0][3] );
1241 
1242  r_clip_verts[0][0][3] = 0;
1243  r_clip_verts[0][1][3] = 0;
1244  r_clip_verts[0][2][3] = 0;
1245  r_clip_verts[0][3][3] = 0;
1246 
1247  r_clip_verts[0][0][4] = 0;
1248  r_clip_verts[0][1][4] = 0;
1249  r_clip_verts[0][2][4] = 0;
1250  r_clip_verts[0][3][4] = 0;
1251 
1252  VectorSubtract( d, c, s0 );
1253  VectorSubtract( c, b, s1 );
1254  CrossProduct( s0, s1, r_polydesc.vpn );
1256 
1258 
1259  r_polyblendcolor = color;
1260 
1261  R_ClipAndDrawPoly( alpha, false, false );
1262 }
1263 
cachewidth
int cachewidth
Definition: r_main.c:180
R_DrawSpanlet66Stipple
void R_DrawSpanlet66Stipple(void)
Definition: r_poly.c:424
R_DrawAlphaSurfaces
void R_DrawAlphaSurfaces(void)
Definition: r_poly.c:1192
R_ClipPolyFace
int R_ClipPolyFace(int nump, clipplane_t *pclipplane)
Definition: r_poly.c:511
R_PolygonCalculateGradients
void R_PolygonCalculateGradients(void)
Definition: r_poly.c:1095
spanletvars_t::pdest
byte * pdest
Definition: r_poly.c:28
espan_s
Definition: r_local.h:375
currentmodel
model_t * currentmodel
Definition: r_main.c:37
oldrefdef_t::fvrectx_adj
float fvrectx_adj
Definition: r_local.h:120
MAXWORKINGVERTS
#define MAXWORKINGVERTS
Definition: r_local.h:161
d_sdivzorigin
float d_sdivzorigin
Definition: r_main.c:175
r_clip_verts
vec5_t r_clip_verts[2][MAXWORKINGVERTS+2]
Definition: r_poly.c:50
int
CONST PIXELFORMATDESCRIPTOR int
Definition: qgl_win.c:35
VectorSubtract
#define VectorSubtract(a, b, c)
Definition: q_shared.h:156
surfcache_s
Definition: r_local.h:360
emitpoint_t::u
float u
Definition: r_local.h:246
CYCLE
#define CYCLE
Definition: asm_draw.h:16
ri
refimport_t ri
Definition: r_main.c:25
surfcache_s::height
unsigned height
Definition: r_local.h:368
R_DrawSpanletTurbulentBlended33
void R_DrawSpanletTurbulentBlended33(void)
Definition: r_poly.c:259
v
GLdouble v
Definition: qgl_win.c:143
yscaleinv
float yscaleinv
Definition: r_local.h:540
d_tdivzstepv
float d_tdivzstepv
Definition: r_local.h:482
D_CacheSurface
surfcache_t * D_CacheSurface(msurface_t *surface, int miplevel)
Definition: r_surf.c:575
spanletvars_t::sstep
fixed16_t sstep
Definition: r_poly.c:31
MAXHEIGHT
#define MAXHEIGHT
Definition: d_ifacea.h:19
emitpoint_t::s
float s
Definition: r_local.h:247
model_s::edges
medge_t * edges
Definition: r_model.h:211
spanletvars_t::izistep
int izistep
Definition: r_poly.c:32
R_IMFlatShadedQuad
void R_IMFlatShadedQuad(vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha)
Definition: r_poly.c:1230
qboolean
qboolean
Definition: q_shared.h:56
s_maxindex
static int s_maxindex
Definition: r_poly.c:52
z
GLdouble GLdouble z
Definition: qgl_win.c:283
i
int i
Definition: q_shared.c:305
d_viewbuffer
pixel_t * d_viewbuffer
Definition: r_main.c:181
msurface_s::numedges
int numedges
Definition: r_model.h:104
modelorg
vec3_t modelorg
Definition: r_bsp.c:29
d_tdivzorigin
float d_tdivzorigin
Definition: r_local.h:483
polydesc_t::pixel_width
int pixel_width
Definition: r_local.h:387
polydesc_t::stipple_parity
int stipple_parity
Definition: r_local.h:394
r_origin
vec3_t r_origin
Definition: r_main.c:69
oldrefdef_t::fvrectright_adj
float fvrectright_adj
Definition: r_local.h:123
SPEED
#define SPEED
Definition: r_local.h:233
xscaleinv
float xscaleinv
Definition: r_main.c:77
r_alpha_surfaces
msurface_t * r_alpha_surfaces
Definition: r_poly.c:45
s_minindex
static int s_minindex
Definition: r_poly.c:52
SURF_WARP
#define SURF_WARP
Definition: qfiles.h:372
r_local.h
mplane_s::normal
vec3_t normal
Definition: r_model.h:59
polydesc_t::vpn
vec3_t vpn
Definition: r_local.h:389
R_DrawSpanletTurbulentStipple66
void R_DrawSpanletTurbulentStipple66(void)
Definition: r_poly.c:148
polydesc_t::viewer_position
float viewer_position[3]
Definition: r_local.h:392
SURF_TRANS66
#define SURF_TRANS66
Definition: qfiles.h:374
clipplane_s::normal
vec3_t normal
Definition: r_local.h:351
msurface_s::plane
mplane_t * plane
Definition: r_model.h:100
mvertex_t::position
vec3_t position
Definition: r_model.h:47
espan_s::count
int count
Definition: r_local.h:377
polydesc_t::pixels
byte * pixels
Definition: r_local.h:386
spanletvars_t::u
unsigned u
Definition: r_poly.c:34
spanletvars_t::t
fixed16_t t
Definition: r_poly.c:30
SURF_PLANEBACK
#define SURF_PLANEBACK
Definition: r_model.h:68
R_PolygonScanRightEdge
void R_PolygonScanRightEdge(void)
Definition: r_poly.c:818
polydesc_t::t_offset
float t_offset
Definition: r_local.h:391
spanletvars_t::spancount
int spancount
Definition: r_poly.c:33
oldrefdef_t::fvrecty_adj
float fvrecty_adj
Definition: r_local.h:120
mtexinfo_s::image
image_t * image
Definition: r_model.h:87
polydesc_t::s_offset
float s_offset
Definition: r_local.h:391
CrossProduct
void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross)
Definition: q_shared.c:753
d_ziorigin
float d_ziorigin
Definition: r_local.h:483
spanletvars_t::pbase
byte * pbase
Definition: r_poly.c:28
medge_t
Definition: r_model.h:77
R_BuildPolygonFromSurface
void R_BuildPolygonFromSurface(msurface_t *fa)
Definition: r_poly.c:1010
image_s::height
int height
Definition: r_local.h:69
bbextentt
fixed16_t bbextentt
Definition: r_local.h:486
sintable
int sintable[1280]
Definition: r_rast.c:47
espan_s::v
int v
Definition: r_local.h:377
polydesc_t::nump
int nump
Definition: r_local.h:384
AFFINE_SPANLET_SIZE_BITS
#define AFFINE_SPANLET_SIZE_BITS
Definition: r_poly.c:24
msurface_s::texinfo
mtexinfo_t * texinfo
Definition: r_model.h:112
oldrefdef_t::fvrectbottom_adj
float fvrectbottom_adj
Definition: r_local.h:123
emitpoint_t
Definition: r_local.h:244
t
GLdouble t
Definition: qgl_win.c:328
spanletvars_t::izistep_times_2
int izistep_times_2
Definition: r_poly.c:32
refimport_t::Sys_Error
void(* Sys_Error)(int err_level, char *str,...)
Definition: ref.h:220
spanletvars_t::v
unsigned v
Definition: r_poly.c:34
polydesc_t::dist
float dist
Definition: r_local.h:390
SURF_FLOWING
#define SURF_FLOWING
Definition: qfiles.h:375
sadjust
fixed16_t sadjust
Definition: r_local.h:672
d_tdivzstepu
float d_tdivzstepu
Definition: r_local.h:481
r_newrefdef
refdef_t r_newrefdef
Definition: r_main.c:36
DotProduct
#define DotProduct(x, y)
Definition: q_shared.h:155
spanletvars_t
Definition: r_poly.c:26
r_worldmodel
model_t * r_worldmodel
Definition: r_main.c:39
cvar_s::value
float value
Definition: q_shared.h:324
xscale
float xscale
Definition: r_main.c:76
s_polygon_spans
static espan_t * s_polygon_spans
Definition: r_poly.c:41
emitpoint_t::v
float v
Definition: r_local.h:246
emitpoint_t::zi
float zi
Definition: r_local.h:248
R_ClipAndDrawPoly
void R_ClipAndDrawPoly(float alpha, int isturbulent, qboolean textured)
Definition: r_poly.c:898
clipplane_s
Definition: r_local.h:349
R_DrawSpanlet66
void R_DrawSpanlet66(void)
Definition: r_poly.c:333
espan_s::u
int u
Definition: r_local.h:377
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: q_shared.c:681
NULL
#define NULL
Definition: q_shared.h:60
bbextents
fixed16_t bbextents
Definition: r_local.h:673
refdef_t::time
float time
Definition: ref.h:127
d_scantable
int d_scantable[MAXHEIGHT]
Definition: r_misc.c:42
d_zistepv
float d_zistepv
Definition: r_local.h:482
model_s::surfedges
int * surfedges
Definition: r_model.h:224
image_s::pixels
byte * pixels[4]
Definition: r_local.h:72
image_s::width
int width
Definition: r_local.h:69
R_DrawSpanletTurbulentStipple33
void R_DrawSpanletTurbulentStipple33(void)
Definition: r_poly.c:91
R_DrawSpanletOpaque
void R_DrawSpanletOpaque(void)
Definition: r_poly.c:59
alpha
GLfloat GLfloat GLfloat alpha
Definition: qgl_win.c:74
d_zistepu
float d_zistepu
Definition: r_local.h:481
ycenter
float ycenter
Definition: r_local.h:538
ERR_DROP
#define ERR_DROP
Definition: qcommon.h:736
blanktable
int blanktable[1280]
Definition: r_rast.c:49
spanletvars_t::izi
int izi
Definition: r_poly.c:32
msurface_s::flags
int flags
Definition: r_model.h:101
R_PolygonDrawSpans
void R_PolygonDrawSpans(espan_t *pspan, int iswater)
Definition: r_poly.c:587
emitpoint_t::t
float t
Definition: r_local.h:247
r_pedge
medge_t * r_pedge
Definition: r_rast.c:41
s_spanletvars
spanletvars_t s_spanletvars
Definition: r_poly.c:37
r_polydesc
polydesc_t r_polydesc
Definition: r_poly.c:43
R_DrawSpanletTurbulentBlended66
void R_DrawSpanletTurbulentBlended66(void)
Definition: r_poly.c:235
VectorCopy
#define VectorCopy(a, b)
Definition: q_shared.h:158
r_turb_turb
int * r_turb_turb
Definition: r_scan.c:28
mtexinfo_s::vecs
float vecs[2][4]
Definition: r_model.h:85
R_DrawSpanlet33Stipple
void R_DrawSpanlet33Stipple(void)
Definition: r_poly.c:365
fixed16_t
int fixed16_t
Definition: q_shared.h:132
vec3_origin
vec3_t vec3_origin
Definition: q_shared.c:24
polydesc_t::drawspanlet
void(* drawspanlet)(void)
Definition: r_local.h:393
DS_SPAN_LIST_END
#define DS_SPAN_LIST_END
Definition: r_local.h:194
polydesc_t
Definition: r_local.h:382
polydesc_t::vup
vec3_t vup
Definition: r_local.h:389
view_clipplanes
clipplane_t view_clipplanes[4]
Definition: r_rast.c:38
surfcache_s::data
byte data[4]
Definition: r_local.h:371
medge_t::v
unsigned short v[2]
Definition: r_model.h:79
vec5_t
vec_t vec5_t[5]
Definition: q_shared.h:128
d_zwidth
unsigned int d_zwidth
Definition: r_local.h:502
NEAR_CLIP
#define NEAR_CLIP
Definition: asm_draw.h:13
msurface_s
Definition: r_model.h:93
R_DrawSpanlet33
void R_DrawSpanlet33(void)
Definition: r_poly.c:286
d_sdivzstepu
float d_sdivzstepu
Definition: r_main.c:173
mtexinfo_s::flags
int flags
Definition: r_model.h:88
msurface_s::texturemins
short texturemins[2]
Definition: r_model.h:109
clipplane_s::dist
float dist
Definition: r_local.h:352
surfcache_s::width
unsigned width
Definition: r_local.h:367
sw_stipplealpha
static cvar_t * sw_stipplealpha
Definition: vid_menu.c:41
spanletvars_t::pz
short * pz
Definition: r_poly.c:29
d_sdivzstepv
float d_sdivzstepv
Definition: r_main.c:174
R_DrawSpanletConstant33
void R_DrawSpanletConstant33(void)
Definition: r_poly.c:315
polydesc_t::pverts
emitpoint_t * pverts
Definition: r_local.h:385
cacheblock
pixel_t * cacheblock
Definition: r_main.c:179
clip_current
static int clip_current
Definition: r_poly.c:49
d_pzbuffer
short * d_pzbuffer
Definition: r_main.c:182
r_polyblendcolor
static int r_polyblendcolor
Definition: r_poly.c:39
model_s::vertexes
mvertex_t * vertexes
Definition: r_model.h:208
tadjust
fixed16_t tadjust
Definition: r_local.h:485
polydesc_t::pixel_height
int pixel_height
Definition: r_local.h:388
msurface_s::nextalphasurface
struct msurface_s * nextalphasurface
Definition: r_model.h:118
xcenter
float xcenter
Definition: r_main.c:75
viddef_t::alphamap
pixel_t * alphamap
Definition: r_local.h:90
AFFINE_SPANLET_SIZE
#define AFFINE_SPANLET_SIZE
Definition: r_poly.c:23
TransformVector
void TransformVector(vec3_t in, vec3_t out)
Definition: r_misc.c:215
vec3_t
vec_t vec3_t[3]
Definition: q_shared.h:127
yscale
float yscale
Definition: r_local.h:539
r_refdef
oldrefdef_t r_refdef
Definition: r_main.c:74
count
GLint GLsizei count
Definition: qgl_win.c:128
polydesc_t::vright
vec3_t vright
Definition: r_local.h:389
msurface_s::firstedge
int firstedge
Definition: r_model.h:103
R_DrawPoly
static void R_DrawPoly(int iswater)
Definition: r_poly.c:1135
R_PolygonScanLeftEdge
void R_PolygonScanLeftEdge(void)
Definition: r_poly.c:755
spanletvars_t::tstep
fixed16_t tstep
Definition: r_poly.c:31
vid
viddef_t vid
Definition: r_main.c:24
spanletvars_t::s
fixed16_t s
Definition: r_poly.c:30