|
|
1.1 root 1: /*
2: Copyright (C) 1996-1997 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:
21: // r_draw.c
22:
23: #include "quakedef.h"
24: #include "r_local.h"
25: #include "d_local.h" // FIXME: shouldn't need to include this
26:
27: #define MAXLEFTCLIPEDGES 100
28:
29: // !!! if these are changed, they must be changed in asm_draw.h too !!!
30: #define FULLY_CLIPPED_CACHED 0x80000000
31: #define FRAMECOUNT_MASK 0x7FFFFFFF
32:
33: unsigned int cacheoffset;
34:
35: int c_faceclip; // number of faces clipped
36:
37: zpointdesc_t r_zpointdesc;
38:
39: polydesc_t r_polydesc;
40:
41:
42:
43: clipplane_t *entity_clipplanes;
44: clipplane_t view_clipplanes[4];
45: clipplane_t world_clipplanes[16];
46:
47: medge_t *r_pedge;
48:
49: qboolean r_leftclipped, r_rightclipped;
50: static qboolean makeleftedge, makerightedge;
51: qboolean r_nearzionly;
52:
53: int sintable[1280];
54: int intsintable[1280];
55:
56: mvertex_t r_leftenter, r_leftexit;
57: mvertex_t r_rightenter, r_rightexit;
58:
59: typedef struct
60: {
61: float u,v;
62: int ceilv;
63: } evert_t;
64:
65: int r_emitted;
66: float r_nearzi;
67: float r_u1, r_v1, r_lzi1;
68: int r_ceilv1;
69:
70: qboolean r_lastvertvalid;
71:
72:
73: #if !id386
74:
75: /*
76: ================
77: R_EmitEdge
78: ================
79: */
80: void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
81: {
82: edge_t *edge, *pcheck;
83: int u_check;
84: float u, u_step;
85: vec3_t local, transformed;
86: float *world;
87: int v, v2, ceilv0;
88: float scale, lzi0, u0, v0;
89: int side;
90:
91: if (r_lastvertvalid)
92: {
93: u0 = r_u1;
94: v0 = r_v1;
95: lzi0 = r_lzi1;
96: ceilv0 = r_ceilv1;
97: }
98: else
99: {
100: world = &pv0->position[0];
101:
102: // transform and project
103: VectorSubtract (world, modelorg, local);
104: TransformVector (local, transformed);
105:
106: if (transformed[2] < NEAR_CLIP)
107: transformed[2] = NEAR_CLIP;
108:
109: lzi0 = 1.0 / transformed[2];
110:
111: // FIXME: build x/yscale into transform?
112: scale = xscale * lzi0;
113: u0 = (xcenter + scale*transformed[0]);
114: if (u0 < r_refdef.fvrectx_adj)
115: u0 = r_refdef.fvrectx_adj;
116: if (u0 > r_refdef.fvrectright_adj)
117: u0 = r_refdef.fvrectright_adj;
118:
119: scale = yscale * lzi0;
120: v0 = (ycenter - scale*transformed[1]);
121: if (v0 < r_refdef.fvrecty_adj)
122: v0 = r_refdef.fvrecty_adj;
123: if (v0 > r_refdef.fvrectbottom_adj)
124: v0 = r_refdef.fvrectbottom_adj;
125:
126: ceilv0 = (int) ceil(v0);
127: }
128:
129: world = &pv1->position[0];
130:
131: // transform and project
132: VectorSubtract (world, modelorg, local);
133: TransformVector (local, transformed);
134:
135: if (transformed[2] < NEAR_CLIP)
136: transformed[2] = NEAR_CLIP;
137:
138: r_lzi1 = 1.0 / transformed[2];
139:
140: scale = xscale * r_lzi1;
141: r_u1 = (xcenter + scale*transformed[0]);
142: if (r_u1 < r_refdef.fvrectx_adj)
143: r_u1 = r_refdef.fvrectx_adj;
144: if (r_u1 > r_refdef.fvrectright_adj)
145: r_u1 = r_refdef.fvrectright_adj;
146:
147: scale = yscale * r_lzi1;
148: r_v1 = (ycenter - scale*transformed[1]);
149: if (r_v1 < r_refdef.fvrecty_adj)
150: r_v1 = r_refdef.fvrecty_adj;
151: if (r_v1 > r_refdef.fvrectbottom_adj)
152: r_v1 = r_refdef.fvrectbottom_adj;
153:
154: if (r_lzi1 > lzi0)
155: lzi0 = r_lzi1;
156:
157: if (lzi0 > r_nearzi) // for mipmap finding
158: r_nearzi = lzi0;
159:
160: // for right edges, all we want is the effect on 1/z
161: if (r_nearzionly)
162: return;
163:
164: r_emitted = 1;
165:
166: r_ceilv1 = (int) ceil(r_v1);
167:
168:
169: // create the edge
170: if (ceilv0 == r_ceilv1)
171: {
172: // we cache unclipped horizontal edges as fully clipped
173: if (cacheoffset != 0x7FFFFFFF)
174: {
175: cacheoffset = FULLY_CLIPPED_CACHED |
176: (r_framecount & FRAMECOUNT_MASK);
177: }
178:
179: return; // horizontal edge
180: }
181:
182: side = ceilv0 > r_ceilv1;
183:
184: edge = edge_p++;
185:
186: edge->owner = r_pedge;
187:
188: edge->nearzi = lzi0;
189:
190: if (side == 0)
191: {
192: // trailing edge (go from p1 to p2)
193: v = ceilv0;
194: v2 = r_ceilv1 - 1;
195:
196: edge->surfs[0] = surface_p - surfaces;
197: edge->surfs[1] = 0;
198:
199: u_step = ((r_u1 - u0) / (r_v1 - v0));
200: u = u0 + ((float)v - v0) * u_step;
201: }
202: else
203: {
204: // leading edge (go from p2 to p1)
205: v2 = ceilv0 - 1;
206: v = r_ceilv1;
207:
208: edge->surfs[0] = 0;
209: edge->surfs[1] = surface_p - surfaces;
210:
211: u_step = ((u0 - r_u1) / (v0 - r_v1));
212: u = r_u1 + ((float)v - r_v1) * u_step;
213: }
214:
215: edge->u_step = u_step*0x100000;
216: edge->u = u*0x100000 + 0xFFFFF;
217:
218: // we need to do this to avoid stepping off the edges if a very nearly
219: // horizontal edge is less than epsilon above a scan, and numeric error causes
220: // it to incorrectly extend to the scan, and the extension of the line goes off
221: // the edge of the screen
222: // FIXME: is this actually needed?
223: if (edge->u < r_refdef.vrect_x_adj_shift20)
224: edge->u = r_refdef.vrect_x_adj_shift20;
225: if (edge->u > r_refdef.vrectright_adj_shift20)
226: edge->u = r_refdef.vrectright_adj_shift20;
227:
228: //
229: // sort the edge in normally
230: //
231: u_check = edge->u;
232: if (edge->surfs[0])
233: u_check++; // sort trailers after leaders
234:
235: if (!newedges[v] || newedges[v]->u >= u_check)
236: {
237: edge->next = newedges[v];
238: newedges[v] = edge;
239: }
240: else
241: {
242: pcheck = newedges[v];
243: while (pcheck->next && pcheck->next->u < u_check)
244: pcheck = pcheck->next;
245: edge->next = pcheck->next;
246: pcheck->next = edge;
247: }
248:
249: edge->nextremove = removeedges[v2];
250: removeedges[v2] = edge;
251: }
252:
253:
254: /*
255: ================
256: R_ClipEdge
257: ================
258: */
259: void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
260: {
261: float d0, d1, f;
262: mvertex_t clipvert;
263:
264: if (clip)
265: {
266: do
267: {
268: d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
269: d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
270:
271: if (d0 >= 0)
272: {
273: // point 0 is unclipped
274: if (d1 >= 0)
275: {
276: // both points are unclipped
277: continue;
278: }
279:
280: // only point 1 is clipped
281:
282: // we don't cache clipped edges
283: cacheoffset = 0x7FFFFFFF;
284:
285: f = d0 / (d0 - d1);
286: clipvert.position[0] = pv0->position[0] +
287: f * (pv1->position[0] - pv0->position[0]);
288: clipvert.position[1] = pv0->position[1] +
289: f * (pv1->position[1] - pv0->position[1]);
290: clipvert.position[2] = pv0->position[2] +
291: f * (pv1->position[2] - pv0->position[2]);
292:
293: if (clip->leftedge)
294: {
295: r_leftclipped = true;
296: r_leftexit = clipvert;
297: }
298: else if (clip->rightedge)
299: {
300: r_rightclipped = true;
301: r_rightexit = clipvert;
302: }
303:
304: R_ClipEdge (pv0, &clipvert, clip->next);
305: return;
306: }
307: else
308: {
309: // point 0 is clipped
310: if (d1 < 0)
311: {
312: // both points are clipped
313: // we do cache fully clipped edges
314: if (!r_leftclipped)
315: cacheoffset = FULLY_CLIPPED_CACHED |
316: (r_framecount & FRAMECOUNT_MASK);
317: return;
318: }
319:
320: // only point 0 is clipped
321: r_lastvertvalid = false;
322:
323: // we don't cache partially clipped edges
324: cacheoffset = 0x7FFFFFFF;
325:
326: f = d0 / (d0 - d1);
327: clipvert.position[0] = pv0->position[0] +
328: f * (pv1->position[0] - pv0->position[0]);
329: clipvert.position[1] = pv0->position[1] +
330: f * (pv1->position[1] - pv0->position[1]);
331: clipvert.position[2] = pv0->position[2] +
332: f * (pv1->position[2] - pv0->position[2]);
333:
334: if (clip->leftedge)
335: {
336: r_leftclipped = true;
337: r_leftenter = clipvert;
338: }
339: else if (clip->rightedge)
340: {
341: r_rightclipped = true;
342: r_rightenter = clipvert;
343: }
344:
345: R_ClipEdge (&clipvert, pv1, clip->next);
346: return;
347: }
348: } while ((clip = clip->next) != NULL);
349: }
350:
351: // add the edge
352: R_EmitEdge (pv0, pv1);
353: }
354:
355: #endif // !id386
356:
357:
358: /*
359: ================
360: R_EmitCachedEdge
361: ================
362: */
363: void R_EmitCachedEdge (void)
364: {
365: edge_t *pedge_t;
366:
367: pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
368:
369: if (!pedge_t->surfs[0])
370: pedge_t->surfs[0] = surface_p - surfaces;
371: else
372: pedge_t->surfs[1] = surface_p - surfaces;
373:
374: if (pedge_t->nearzi > r_nearzi) // for mipmap finding
375: r_nearzi = pedge_t->nearzi;
376:
377: r_emitted = 1;
378: }
379:
380:
381: /*
382: ================
383: R_RenderFace
384: ================
385: */
386: void R_RenderFace (msurface_t *fa, int clipflags)
387: {
388: int i, lindex;
389: unsigned mask;
390: mplane_t *pplane;
391: float distinv;
392: vec3_t p_normal;
393: medge_t *pedges, tedge;
394: clipplane_t *pclip;
395:
396: // skip out if no more surfs
397: if ((surface_p) >= surf_max)
398: {
399: r_outofsurfaces++;
400: return;
401: }
402:
403: // ditto if not enough edges left, or switch to auxedges if possible
404: if ((edge_p + fa->numedges + 4) >= edge_max)
405: {
406: r_outofedges += fa->numedges;
407: return;
408: }
409:
410: c_faceclip++;
411:
412: // set up clip planes
413: pclip = NULL;
414:
415: for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
416: {
417: if (clipflags & mask)
418: {
419: view_clipplanes[i].next = pclip;
420: pclip = &view_clipplanes[i];
421: }
422: }
423:
424: // push the edges through
425: r_emitted = 0;
426: r_nearzi = 0;
427: r_nearzionly = false;
428: makeleftedge = makerightedge = false;
429: pedges = currententity->model->edges;
430: r_lastvertvalid = false;
431:
432: for (i=0 ; i<fa->numedges ; i++)
433: {
434: lindex = currententity->model->surfedges[fa->firstedge + i];
435:
436: if (lindex > 0)
437: {
438: r_pedge = &pedges[lindex];
439:
440: // if the edge is cached, we can just reuse the edge
441: if (!insubmodel)
442: {
443: if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
444: {
445: if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
446: r_framecount)
447: {
448: r_lastvertvalid = false;
449: continue;
450: }
451: }
452: else
453: {
454: if ((((unsigned long)edge_p - (unsigned long)r_edges) >
455: r_pedge->cachededgeoffset) &&
456: (((edge_t *)((unsigned long)r_edges +
457: r_pedge->cachededgeoffset))->owner == r_pedge))
458: {
459: R_EmitCachedEdge ();
460: r_lastvertvalid = false;
461: continue;
462: }
463: }
464: }
465:
466: // assume it's cacheable
467: cacheoffset = (byte *)edge_p - (byte *)r_edges;
468: r_leftclipped = r_rightclipped = false;
469: R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
470: &r_pcurrentvertbase[r_pedge->v[1]],
471: pclip);
472: r_pedge->cachededgeoffset = cacheoffset;
473:
474: if (r_leftclipped)
475: makeleftedge = true;
476: if (r_rightclipped)
477: makerightedge = true;
478: r_lastvertvalid = true;
479: }
480: else
481: {
482: lindex = -lindex;
483: r_pedge = &pedges[lindex];
484: // if the edge is cached, we can just reuse the edge
485: if (!insubmodel)
486: {
487: if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
488: {
489: if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
490: r_framecount)
491: {
492: r_lastvertvalid = false;
493: continue;
494: }
495: }
496: else
497: {
498: // it's cached if the cached edge is valid and is owned
499: // by this medge_t
500: if ((((unsigned long)edge_p - (unsigned long)r_edges) >
501: r_pedge->cachededgeoffset) &&
502: (((edge_t *)((unsigned long)r_edges +
503: r_pedge->cachededgeoffset))->owner == r_pedge))
504: {
505: R_EmitCachedEdge ();
506: r_lastvertvalid = false;
507: continue;
508: }
509: }
510: }
511:
512: // assume it's cacheable
513: cacheoffset = (byte *)edge_p - (byte *)r_edges;
514: r_leftclipped = r_rightclipped = false;
515: R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
516: &r_pcurrentvertbase[r_pedge->v[0]],
517: pclip);
518: r_pedge->cachededgeoffset = cacheoffset;
519:
520: if (r_leftclipped)
521: makeleftedge = true;
522: if (r_rightclipped)
523: makerightedge = true;
524: r_lastvertvalid = true;
525: }
526: }
527:
528: // if there was a clip off the left edge, add that edge too
529: // FIXME: faster to do in screen space?
530: // FIXME: share clipped edges?
531: if (makeleftedge)
532: {
533: r_pedge = &tedge;
534: r_lastvertvalid = false;
535: R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
536: }
537:
538: // if there was a clip off the right edge, get the right r_nearzi
539: if (makerightedge)
540: {
541: r_pedge = &tedge;
542: r_lastvertvalid = false;
543: r_nearzionly = true;
544: R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
545: }
546:
547: // if no edges made it out, return without posting the surface
548: if (!r_emitted)
549: return;
550:
551: r_polycount++;
552:
553: surface_p->data = (void *)fa;
554: surface_p->nearzi = r_nearzi;
555: surface_p->flags = fa->flags;
556: surface_p->insubmodel = insubmodel;
557: surface_p->spanstate = 0;
558: surface_p->entity = currententity;
559: surface_p->key = r_currentkey++;
560: surface_p->spans = NULL;
561:
562: pplane = fa->plane;
563: // FIXME: cache this?
564: TransformVector (pplane->normal, p_normal);
565: // FIXME: cache this?
566: distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
567:
568: surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
569: surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
570: surface_p->d_ziorigin = p_normal[2] * distinv -
571: xcenter * surface_p->d_zistepu -
572: ycenter * surface_p->d_zistepv;
573:
574: //JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
575: surface_p++;
576: }
577:
578:
579: /*
580: ================
581: R_RenderBmodelFace
582: ================
583: */
584: void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
585: {
586: int i;
587: unsigned mask;
588: mplane_t *pplane;
589: float distinv;
590: vec3_t p_normal;
591: medge_t tedge;
592: clipplane_t *pclip;
593:
594: // skip out if no more surfs
595: if (surface_p >= surf_max)
596: {
597: r_outofsurfaces++;
598: return;
599: }
600:
601: // ditto if not enough edges left, or switch to auxedges if possible
602: if ((edge_p + psurf->numedges + 4) >= edge_max)
603: {
604: r_outofedges += psurf->numedges;
605: return;
606: }
607:
608: c_faceclip++;
609:
610: // this is a dummy to give the caching mechanism someplace to write to
611: r_pedge = &tedge;
612:
613: // set up clip planes
614: pclip = NULL;
615:
616: for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
617: {
618: if (r_clipflags & mask)
619: {
620: view_clipplanes[i].next = pclip;
621: pclip = &view_clipplanes[i];
622: }
623: }
624:
625: // push the edges through
626: r_emitted = 0;
627: r_nearzi = 0;
628: r_nearzionly = false;
629: makeleftedge = makerightedge = false;
630: // FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
631: // can be used?
632: r_lastvertvalid = false;
633:
634: for ( ; pedges ; pedges = pedges->pnext)
635: {
636: r_leftclipped = r_rightclipped = false;
637: R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
638:
639: if (r_leftclipped)
640: makeleftedge = true;
641: if (r_rightclipped)
642: makerightedge = true;
643: }
644:
645: // if there was a clip off the left edge, add that edge too
646: // FIXME: faster to do in screen space?
647: // FIXME: share clipped edges?
648: if (makeleftedge)
649: {
650: r_pedge = &tedge;
651: R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
652: }
653:
654: // if there was a clip off the right edge, get the right r_nearzi
655: if (makerightedge)
656: {
657: r_pedge = &tedge;
658: r_nearzionly = true;
659: R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
660: }
661:
662: // if no edges made it out, return without posting the surface
663: if (!r_emitted)
664: return;
665:
666: r_polycount++;
667:
668: surface_p->data = (void *)psurf;
669: surface_p->nearzi = r_nearzi;
670: surface_p->flags = psurf->flags;
671: surface_p->insubmodel = true;
672: surface_p->spanstate = 0;
673: surface_p->entity = currententity;
674: surface_p->key = r_currentbkey;
675: surface_p->spans = NULL;
676:
677: pplane = psurf->plane;
678: // FIXME: cache this?
679: TransformVector (pplane->normal, p_normal);
680: // FIXME: cache this?
681: distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
682:
683: surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
684: surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
685: surface_p->d_ziorigin = p_normal[2] * distinv -
686: xcenter * surface_p->d_zistepu -
687: ycenter * surface_p->d_zistepv;
688:
689: //JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
690: surface_p++;
691: }
692:
693:
694: /*
695: ================
696: R_RenderPoly
697: ================
698: */
699: void R_RenderPoly (msurface_t *fa, int clipflags)
700: {
701: int i, lindex, lnumverts, s_axis, t_axis;
702: float dist, lastdist, lzi, scale, u, v, frac;
703: unsigned mask;
704: vec3_t local, transformed;
705: clipplane_t *pclip;
706: medge_t *pedges;
707: mplane_t *pplane;
708: mvertex_t verts[2][100]; //FIXME: do real number
709: polyvert_t pverts[100]; //FIXME: do real number, safely
710: int vertpage, newverts, newpage, lastvert;
711: qboolean visible;
712:
713: // FIXME: clean this up and make it faster
714: // FIXME: guard against running out of vertices
715:
716: s_axis = t_axis = 0; // keep compiler happy
717:
718: // set up clip planes
719: pclip = NULL;
720:
721: for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
722: {
723: if (clipflags & mask)
724: {
725: view_clipplanes[i].next = pclip;
726: pclip = &view_clipplanes[i];
727: }
728: }
729:
730: // reconstruct the polygon
731: // FIXME: these should be precalculated and loaded off disk
732: pedges = currententity->model->edges;
733: lnumverts = fa->numedges;
734: vertpage = 0;
735:
736: for (i=0 ; i<lnumverts ; i++)
737: {
738: lindex = currententity->model->surfedges[fa->firstedge + i];
739:
740: if (lindex > 0)
741: {
742: r_pedge = &pedges[lindex];
743: verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]];
744: }
745: else
746: {
747: r_pedge = &pedges[-lindex];
748: verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]];
749: }
750: }
751:
752: // clip the polygon, done if not visible
753: while (pclip)
754: {
755: lastvert = lnumverts - 1;
756: lastdist = DotProduct (verts[vertpage][lastvert].position,
757: pclip->normal) - pclip->dist;
758:
759: visible = false;
760: newverts = 0;
761: newpage = vertpage ^ 1;
762:
763: for (i=0 ; i<lnumverts ; i++)
764: {
765: dist = DotProduct (verts[vertpage][i].position, pclip->normal) -
766: pclip->dist;
767:
768: if ((lastdist > 0) != (dist > 0))
769: {
770: frac = dist / (dist - lastdist);
771: verts[newpage][newverts].position[0] =
772: verts[vertpage][i].position[0] +
773: ((verts[vertpage][lastvert].position[0] -
774: verts[vertpage][i].position[0]) * frac);
775: verts[newpage][newverts].position[1] =
776: verts[vertpage][i].position[1] +
777: ((verts[vertpage][lastvert].position[1] -
778: verts[vertpage][i].position[1]) * frac);
779: verts[newpage][newverts].position[2] =
780: verts[vertpage][i].position[2] +
781: ((verts[vertpage][lastvert].position[2] -
782: verts[vertpage][i].position[2]) * frac);
783: newverts++;
784: }
785:
786: if (dist >= 0)
787: {
788: verts[newpage][newverts] = verts[vertpage][i];
789: newverts++;
790: visible = true;
791: }
792:
793: lastvert = i;
794: lastdist = dist;
795: }
796:
797: if (!visible || (newverts < 3))
798: return;
799:
800: lnumverts = newverts;
801: vertpage ^= 1;
802: pclip = pclip->next;
803: }
804:
805: // transform and project, remembering the z values at the vertices and
806: // r_nearzi, and extract the s and t coordinates at the vertices
807: pplane = fa->plane;
808: switch (pplane->type)
809: {
810: case PLANE_X:
811: case PLANE_ANYX:
812: s_axis = 1;
813: t_axis = 2;
814: break;
815: case PLANE_Y:
816: case PLANE_ANYY:
817: s_axis = 0;
818: t_axis = 2;
819: break;
820: case PLANE_Z:
821: case PLANE_ANYZ:
822: s_axis = 0;
823: t_axis = 1;
824: break;
825: }
826:
827: r_nearzi = 0;
828:
829: for (i=0 ; i<lnumverts ; i++)
830: {
831: // transform and project
832: VectorSubtract (verts[vertpage][i].position, modelorg, local);
833: TransformVector (local, transformed);
834:
835: if (transformed[2] < NEAR_CLIP)
836: transformed[2] = NEAR_CLIP;
837:
838: lzi = 1.0 / transformed[2];
839:
840: if (lzi > r_nearzi) // for mipmap finding
841: r_nearzi = lzi;
842:
843: // FIXME: build x/yscale into transform?
844: scale = xscale * lzi;
845: u = (xcenter + scale*transformed[0]);
846: if (u < r_refdef.fvrectx_adj)
847: u = r_refdef.fvrectx_adj;
848: if (u > r_refdef.fvrectright_adj)
849: u = r_refdef.fvrectright_adj;
850:
851: scale = yscale * lzi;
852: v = (ycenter - scale*transformed[1]);
853: if (v < r_refdef.fvrecty_adj)
854: v = r_refdef.fvrecty_adj;
855: if (v > r_refdef.fvrectbottom_adj)
856: v = r_refdef.fvrectbottom_adj;
857:
858: pverts[i].u = u;
859: pverts[i].v = v;
860: pverts[i].zi = lzi;
861: pverts[i].s = verts[vertpage][i].position[s_axis];
862: pverts[i].t = verts[vertpage][i].position[t_axis];
863: }
864:
865: // build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z
866: // for each vertex
867: r_polydesc.numverts = lnumverts;
868: r_polydesc.nearzi = r_nearzi;
869: r_polydesc.pcurrentface = fa;
870: r_polydesc.pverts = pverts;
871:
872: // draw the polygon
873: D_DrawPoly ();
874: }
875:
876:
877: /*
878: ================
879: R_ZDrawSubmodelPolys
880: ================
881: */
882: void R_ZDrawSubmodelPolys (model_t *pmodel)
883: {
884: int i, numsurfaces;
885: msurface_t *psurf;
886: float dot;
887: mplane_t *pplane;
888:
889: psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
890: numsurfaces = pmodel->nummodelsurfaces;
891:
892: for (i=0 ; i<numsurfaces ; i++, psurf++)
893: {
894: // find which side of the node we are on
895: pplane = psurf->plane;
896:
897: dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
898:
899: // draw the polygon
900: if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
901: (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
902: {
903: // FIXME: use bounding-box-based frustum clipping info?
904: R_RenderPoly (psurf, 15);
905: }
906: }
907: }
908:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.