|
|
1.1 ! root 1: // r_bsp.c ! 2: ! 3: #include "quakedef.h" ! 4: #include "r_local.h" ! 5: ! 6: // ! 7: // current entity info ! 8: // ! 9: qboolean insubmodel; ! 10: entity_t *currententity; ! 11: vec3_t modelorg; // modelorg is the viewpoint reletive to ! 12: // the currently rendering entity ! 13: vec3_t r_entorigin; // the currently rendering entity in world ! 14: // coordinates ! 15: ! 16: float entity_rotation[3][3]; ! 17: ! 18: vec3_t r_worldmodelorg; ! 19: ! 20: int r_currentbkey; ! 21: ! 22: typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; ! 23: ! 24: #define MAX_BMODEL_VERTS 500 // 6K ! 25: #define MAX_BMODEL_EDGES 1000 // 12K ! 26: ! 27: static mvertex_t *pbverts; ! 28: static bedge_t *pbedges; ! 29: static int numbverts, numbedges; ! 30: ! 31: static mvertex_t *pfrontenter, *pfrontexit; ! 32: ! 33: static qboolean makeclippededge; ! 34: ! 35: ! 36: //=========================================================================== ! 37: ! 38: /* ! 39: ================ ! 40: R_EntityRotate ! 41: ================ ! 42: */ ! 43: void R_EntityRotate (vec3_t vec) ! 44: { ! 45: vec3_t tvec; ! 46: ! 47: VectorCopy (vec, tvec); ! 48: vec[0] = DotProduct (entity_rotation[0], tvec); ! 49: vec[1] = DotProduct (entity_rotation[1], tvec); ! 50: vec[2] = DotProduct (entity_rotation[2], tvec); ! 51: } ! 52: ! 53: ! 54: /* ! 55: ================ ! 56: R_RotateBmodel ! 57: ================ ! 58: */ ! 59: void R_RotateBmodel (void) ! 60: { ! 61: float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3]; ! 62: ! 63: // TODO: should use a look-up table ! 64: // TODO: should really be stored with the entity instead of being reconstructed ! 65: // TODO: could cache lazily, stored in the entity ! 66: // TODO: share work with R_SetUpAliasTransform ! 67: ! 68: // yaw ! 69: angle = currententity->angles[YAW]; ! 70: angle = angle * M_PI*2 / 360; ! 71: s = sin(angle); ! 72: c = cos(angle); ! 73: ! 74: temp1[0][0] = c; ! 75: temp1[0][1] = s; ! 76: temp1[0][2] = 0; ! 77: temp1[1][0] = -s; ! 78: temp1[1][1] = c; ! 79: temp1[1][2] = 0; ! 80: temp1[2][0] = 0; ! 81: temp1[2][1] = 0; ! 82: temp1[2][2] = 1; ! 83: ! 84: ! 85: // pitch ! 86: angle = currententity->angles[PITCH]; ! 87: angle = angle * M_PI*2 / 360; ! 88: s = sin(angle); ! 89: c = cos(angle); ! 90: ! 91: temp2[0][0] = c; ! 92: temp2[0][1] = 0; ! 93: temp2[0][2] = -s; ! 94: temp2[1][0] = 0; ! 95: temp2[1][1] = 1; ! 96: temp2[1][2] = 0; ! 97: temp2[2][0] = s; ! 98: temp2[2][1] = 0; ! 99: temp2[2][2] = c; ! 100: ! 101: R_ConcatRotations (temp2, temp1, temp3); ! 102: ! 103: // roll ! 104: angle = currententity->angles[ROLL]; ! 105: angle = angle * M_PI*2 / 360; ! 106: s = sin(angle); ! 107: c = cos(angle); ! 108: ! 109: temp1[0][0] = 1; ! 110: temp1[0][1] = 0; ! 111: temp1[0][2] = 0; ! 112: temp1[1][0] = 0; ! 113: temp1[1][1] = c; ! 114: temp1[1][2] = s; ! 115: temp1[2][0] = 0; ! 116: temp1[2][1] = -s; ! 117: temp1[2][2] = c; ! 118: ! 119: R_ConcatRotations (temp1, temp3, entity_rotation); ! 120: ! 121: // ! 122: // rotate modelorg and the transformation matrix ! 123: // ! 124: R_EntityRotate (modelorg); ! 125: R_EntityRotate (vpn); ! 126: R_EntityRotate (vright); ! 127: R_EntityRotate (vup); ! 128: ! 129: R_TransformFrustum (); ! 130: } ! 131: ! 132: ! 133: /* ! 134: ================ ! 135: R_RecursiveClipBPoly ! 136: ================ ! 137: */ ! 138: void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) ! 139: { ! 140: bedge_t *psideedges[2], *pnextedge, *ptedge; ! 141: int i, side, lastside; ! 142: float dist, frac, lastdist; ! 143: mplane_t *splitplane, tplane; ! 144: mvertex_t *pvert, *plastvert, *ptvert; ! 145: mnode_t *pn; ! 146: ! 147: psideedges[0] = psideedges[1] = NULL; ! 148: ! 149: makeclippededge = false; ! 150: ! 151: // transform the BSP plane into model space ! 152: // FIXME: cache these? ! 153: splitplane = pnode->plane; ! 154: tplane.dist = splitplane->dist - ! 155: DotProduct(r_entorigin, splitplane->normal); ! 156: tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); ! 157: tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); ! 158: tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); ! 159: ! 160: // clip edges to BSP plane ! 161: for ( ; pedges ; pedges = pnextedge) ! 162: { ! 163: pnextedge = pedges->pnext; ! 164: ! 165: // set the status for the last point as the previous point ! 166: // FIXME: cache this stuff somehow? ! 167: plastvert = pedges->v[0]; ! 168: lastdist = DotProduct (plastvert->position, tplane.normal) - ! 169: tplane.dist; ! 170: ! 171: if (lastdist > 0) ! 172: lastside = 0; ! 173: else ! 174: lastside = 1; ! 175: ! 176: pvert = pedges->v[1]; ! 177: ! 178: dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; ! 179: ! 180: if (dist > 0) ! 181: side = 0; ! 182: else ! 183: side = 1; ! 184: ! 185: if (side != lastside) ! 186: { ! 187: // clipped ! 188: if (numbverts >= MAX_BMODEL_VERTS) ! 189: return; ! 190: ! 191: // generate the clipped vertex ! 192: frac = lastdist / (lastdist - dist); ! 193: ptvert = &pbverts[numbverts++]; ! 194: ptvert->position[0] = plastvert->position[0] + ! 195: frac * (pvert->position[0] - ! 196: plastvert->position[0]); ! 197: ptvert->position[1] = plastvert->position[1] + ! 198: frac * (pvert->position[1] - ! 199: plastvert->position[1]); ! 200: ptvert->position[2] = plastvert->position[2] + ! 201: frac * (pvert->position[2] - ! 202: plastvert->position[2]); ! 203: ! 204: // split into two edges, one on each side, and remember entering ! 205: // and exiting points ! 206: // FIXME: share the clip edge by having a winding direction flag? ! 207: if (numbedges >= (MAX_BMODEL_EDGES - 1)) ! 208: { ! 209: Con_Printf ("Out of edges for bmodel\n"); ! 210: return; ! 211: } ! 212: ! 213: ptedge = &pbedges[numbedges]; ! 214: ptedge->pnext = psideedges[lastside]; ! 215: psideedges[lastside] = ptedge; ! 216: ptedge->v[0] = plastvert; ! 217: ptedge->v[1] = ptvert; ! 218: ! 219: ptedge = &pbedges[numbedges + 1]; ! 220: ptedge->pnext = psideedges[side]; ! 221: psideedges[side] = ptedge; ! 222: ptedge->v[0] = ptvert; ! 223: ptedge->v[1] = pvert; ! 224: ! 225: numbedges += 2; ! 226: ! 227: if (side == 0) ! 228: { ! 229: // entering for front, exiting for back ! 230: pfrontenter = ptvert; ! 231: makeclippededge = true; ! 232: } ! 233: else ! 234: { ! 235: pfrontexit = ptvert; ! 236: makeclippededge = true; ! 237: } ! 238: } ! 239: else ! 240: { ! 241: // add the edge to the appropriate side ! 242: pedges->pnext = psideedges[side]; ! 243: psideedges[side] = pedges; ! 244: } ! 245: } ! 246: ! 247: // if anything was clipped, reconstitute and add the edges along the clip ! 248: // plane to both sides (but in opposite directions) ! 249: if (makeclippededge) ! 250: { ! 251: if (numbedges >= (MAX_BMODEL_EDGES - 2)) ! 252: { ! 253: Con_Printf ("Out of edges for bmodel\n"); ! 254: return; ! 255: } ! 256: ! 257: ptedge = &pbedges[numbedges]; ! 258: ptedge->pnext = psideedges[0]; ! 259: psideedges[0] = ptedge; ! 260: ptedge->v[0] = pfrontexit; ! 261: ptedge->v[1] = pfrontenter; ! 262: ! 263: ptedge = &pbedges[numbedges + 1]; ! 264: ptedge->pnext = psideedges[1]; ! 265: psideedges[1] = ptedge; ! 266: ptedge->v[0] = pfrontenter; ! 267: ptedge->v[1] = pfrontexit; ! 268: ! 269: numbedges += 2; ! 270: } ! 271: ! 272: // draw or recurse further ! 273: for (i=0 ; i<2 ; i++) ! 274: { ! 275: if (psideedges[i]) ! 276: { ! 277: // draw if we've reached a non-solid leaf, done if all that's left is a ! 278: // solid leaf, and continue down the tree if it's not a leaf ! 279: pn = pnode->children[i]; ! 280: ! 281: // we're done with this branch if the node or leaf isn't in the PVS ! 282: if (pn->visframe == r_visframecount) ! 283: { ! 284: if (pn->contents < 0) ! 285: { ! 286: if (pn->contents != CONTENTS_SOLID) ! 287: { ! 288: r_currentbkey = ((mleaf_t *)pn)->key; ! 289: R_RenderBmodelFace (psideedges[i], psurf); ! 290: } ! 291: } ! 292: else ! 293: { ! 294: R_RecursiveClipBPoly (psideedges[i], pnode->children[i], ! 295: psurf); ! 296: } ! 297: } ! 298: } ! 299: } ! 300: } ! 301: ! 302: ! 303: /* ! 304: ================ ! 305: R_DrawSolidClippedSubmodelPolygons ! 306: ================ ! 307: */ ! 308: void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) ! 309: { ! 310: int i, j, lindex; ! 311: vec_t dot; ! 312: msurface_t *psurf; ! 313: int numsurfaces; ! 314: mplane_t *pplane; ! 315: mvertex_t bverts[MAX_BMODEL_VERTS]; ! 316: bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; ! 317: medge_t *pedge, *pedges; ! 318: ! 319: // FIXME: use bounding-box-based frustum clipping info? ! 320: ! 321: psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; ! 322: numsurfaces = pmodel->nummodelsurfaces; ! 323: pedges = pmodel->edges; ! 324: ! 325: for (i=0 ; i<numsurfaces ; i++, psurf++) ! 326: { ! 327: // find which side of the node we are on ! 328: pplane = psurf->plane; ! 329: ! 330: dot = DotProduct (modelorg, pplane->normal) - pplane->dist; ! 331: ! 332: // draw the polygon ! 333: if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || ! 334: (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) ! 335: { ! 336: // FIXME: use bounding-box-based frustum clipping info? ! 337: ! 338: // copy the edges to bedges, flipping if necessary so always ! 339: // clockwise winding ! 340: // FIXME: if edges and vertices get caches, these assignments must move ! 341: // outside the loop, and overflow checking must be done here ! 342: pbverts = bverts; ! 343: pbedges = bedges; ! 344: numbverts = numbedges = 0; ! 345: ! 346: if (psurf->numedges > 0) ! 347: { ! 348: pbedge = &bedges[numbedges]; ! 349: numbedges += psurf->numedges; ! 350: ! 351: for (j=0 ; j<psurf->numedges ; j++) ! 352: { ! 353: lindex = pmodel->surfedges[psurf->firstedge+j]; ! 354: ! 355: if (lindex > 0) ! 356: { ! 357: pedge = &pedges[lindex]; ! 358: pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; ! 359: pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; ! 360: } ! 361: else ! 362: { ! 363: lindex = -lindex; ! 364: pedge = &pedges[lindex]; ! 365: pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; ! 366: pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; ! 367: } ! 368: ! 369: pbedge[j].pnext = &pbedge[j+1]; ! 370: } ! 371: ! 372: pbedge[j-1].pnext = NULL; // mark end of edges ! 373: ! 374: R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf); ! 375: } ! 376: else ! 377: { ! 378: Sys_Error ("no edges in bmodel"); ! 379: } ! 380: } ! 381: } ! 382: } ! 383: ! 384: ! 385: /* ! 386: ================ ! 387: R_DrawSubmodelPolygons ! 388: ================ ! 389: */ ! 390: void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) ! 391: { ! 392: int i; ! 393: vec_t dot; ! 394: msurface_t *psurf; ! 395: int numsurfaces; ! 396: mplane_t *pplane; ! 397: ! 398: // FIXME: use bounding-box-based frustum clipping info? ! 399: ! 400: psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; ! 401: numsurfaces = pmodel->nummodelsurfaces; ! 402: ! 403: for (i=0 ; i<numsurfaces ; i++, psurf++) ! 404: { ! 405: // find which side of the node we are on ! 406: pplane = psurf->plane; ! 407: ! 408: dot = DotProduct (modelorg, pplane->normal) - pplane->dist; ! 409: ! 410: // draw the polygon ! 411: if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || ! 412: (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) ! 413: { ! 414: r_currentkey = ((mleaf_t *)currententity->topnode)->key; ! 415: ! 416: // FIXME: use bounding-box-based frustum clipping info? ! 417: R_RenderFace (psurf, clipflags); ! 418: } ! 419: } ! 420: } ! 421: ! 422: ! 423: /* ! 424: ================ ! 425: R_RecursiveWorldNode ! 426: ================ ! 427: */ ! 428: void R_RecursiveWorldNode (mnode_t *node, int clipflags) ! 429: { ! 430: int i, c, side, *pindex; ! 431: vec3_t acceptpt, rejectpt; ! 432: mplane_t *plane; ! 433: msurface_t *surf, **mark; ! 434: mleaf_t *pleaf; ! 435: double d, dot; ! 436: ! 437: if (node->contents == CONTENTS_SOLID) ! 438: return; // solid ! 439: ! 440: if (node->visframe != r_visframecount) ! 441: return; ! 442: ! 443: // cull the clipping planes if not trivial accept ! 444: // FIXME: the compiler is doing a lousy job of optimizing here; it could be ! 445: // twice as fast in ASM ! 446: if (clipflags) ! 447: { ! 448: for (i=0 ; i<4 ; i++) ! 449: { ! 450: if (! (clipflags & (1<<i)) ) ! 451: continue; // don't need to clip against it ! 452: ! 453: // generate accept and reject points ! 454: // FIXME: do with fast look-ups or integer tests based on the sign bit ! 455: // of the floating point values ! 456: ! 457: pindex = pfrustum_indexes[i]; ! 458: ! 459: rejectpt[0] = (float)node->minmaxs[pindex[0]]; ! 460: rejectpt[1] = (float)node->minmaxs[pindex[1]]; ! 461: rejectpt[2] = (float)node->minmaxs[pindex[2]]; ! 462: ! 463: d = DotProduct (rejectpt, view_clipplanes[i].normal); ! 464: d -= view_clipplanes[i].dist; ! 465: ! 466: if (d <= 0) ! 467: return; ! 468: ! 469: acceptpt[0] = (float)node->minmaxs[pindex[3+0]]; ! 470: acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; ! 471: acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; ! 472: ! 473: d = DotProduct (acceptpt, view_clipplanes[i].normal); ! 474: d -= view_clipplanes[i].dist; ! 475: ! 476: if (d >= 0) ! 477: clipflags &= ~(1<<i); // node is entirely on screen ! 478: } ! 479: } ! 480: ! 481: // if a leaf node, draw stuff ! 482: if (node->contents < 0) ! 483: { ! 484: pleaf = (mleaf_t *)node; ! 485: ! 486: mark = pleaf->firstmarksurface; ! 487: c = pleaf->nummarksurfaces; ! 488: ! 489: if (c) ! 490: { ! 491: do ! 492: { ! 493: (*mark)->visframe = r_framecount; ! 494: mark++; ! 495: } while (--c); ! 496: } ! 497: ! 498: // deal with model fragments in this leaf ! 499: if (pleaf->efrags) ! 500: { ! 501: R_StoreEfrags (&pleaf->efrags); ! 502: } ! 503: ! 504: pleaf->key = r_currentkey; ! 505: r_currentkey++; // all bmodels in a leaf share the same key ! 506: } ! 507: else ! 508: { ! 509: // node is just a decision point, so go down the apropriate sides ! 510: ! 511: // find which side of the node we are on ! 512: plane = node->plane; ! 513: ! 514: switch (plane->type) ! 515: { ! 516: case PLANE_X: ! 517: dot = modelorg[0] - plane->dist; ! 518: break; ! 519: case PLANE_Y: ! 520: dot = modelorg[1] - plane->dist; ! 521: break; ! 522: case PLANE_Z: ! 523: dot = modelorg[2] - plane->dist; ! 524: break; ! 525: default: ! 526: dot = DotProduct (modelorg, plane->normal) - plane->dist; ! 527: break; ! 528: } ! 529: ! 530: if (dot >= 0) ! 531: side = 0; ! 532: else ! 533: side = 1; ! 534: ! 535: // recurse down the children, front side first ! 536: R_RecursiveWorldNode (node->children[side], clipflags); ! 537: ! 538: // draw stuff ! 539: c = node->numsurfaces; ! 540: ! 541: if (c) ! 542: { ! 543: surf = cl.worldmodel->surfaces + node->firstsurface; ! 544: ! 545: if (dot < -BACKFACE_EPSILON) ! 546: { ! 547: do ! 548: { ! 549: if ((surf->flags & SURF_PLANEBACK) && ! 550: (surf->visframe == r_framecount)) ! 551: { ! 552: if (r_drawpolys) ! 553: { ! 554: if (r_worldpolysbacktofront) ! 555: { ! 556: if (numbtofpolys < MAX_BTOFPOLYS) ! 557: { ! 558: pbtofpolys[numbtofpolys].clipflags = ! 559: clipflags; ! 560: pbtofpolys[numbtofpolys].psurf = surf; ! 561: numbtofpolys++; ! 562: } ! 563: } ! 564: else ! 565: { ! 566: R_RenderPoly (surf, clipflags); ! 567: } ! 568: } ! 569: else ! 570: { ! 571: R_RenderFace (surf, clipflags); ! 572: } ! 573: } ! 574: ! 575: surf++; ! 576: } while (--c); ! 577: } ! 578: else if (dot > BACKFACE_EPSILON) ! 579: { ! 580: do ! 581: { ! 582: if (!(surf->flags & SURF_PLANEBACK) && ! 583: (surf->visframe == r_framecount)) ! 584: { ! 585: if (r_drawpolys) ! 586: { ! 587: if (r_worldpolysbacktofront) ! 588: { ! 589: if (numbtofpolys < MAX_BTOFPOLYS) ! 590: { ! 591: pbtofpolys[numbtofpolys].clipflags = ! 592: clipflags; ! 593: pbtofpolys[numbtofpolys].psurf = surf; ! 594: numbtofpolys++; ! 595: } ! 596: } ! 597: else ! 598: { ! 599: R_RenderPoly (surf, clipflags); ! 600: } ! 601: } ! 602: else ! 603: { ! 604: R_RenderFace (surf, clipflags); ! 605: } ! 606: } ! 607: ! 608: surf++; ! 609: } while (--c); ! 610: } ! 611: ! 612: // all surfaces on the same node share the same sequence number ! 613: r_currentkey++; ! 614: } ! 615: ! 616: // recurse down the back side ! 617: R_RecursiveWorldNode (node->children[!side], clipflags); ! 618: } ! 619: } ! 620: ! 621: ! 622: ! 623: /* ! 624: ================ ! 625: R_RenderWorld ! 626: ================ ! 627: */ ! 628: void R_RenderWorld (void) ! 629: { ! 630: int i; ! 631: model_t *clmodel; ! 632: btofpoly_t btofpolys[MAX_BTOFPOLYS]; ! 633: ! 634: pbtofpolys = btofpolys; ! 635: ! 636: currententity = &cl_entities[0]; ! 637: VectorCopy (r_origin, modelorg); ! 638: clmodel = currententity->model; ! 639: r_pcurrentvertbase = clmodel->vertexes; ! 640: ! 641: R_RecursiveWorldNode (clmodel->nodes, 15); ! 642: ! 643: // if the driver wants the polygons back to front, play the visible ones back ! 644: // in that order ! 645: if (r_worldpolysbacktofront) ! 646: { ! 647: for (i=numbtofpolys-1 ; i>=0 ; i--) ! 648: { ! 649: R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); ! 650: } ! 651: } ! 652: } ! 653: ! 654:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.