|
|
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.