r_bsp.c 15 KB

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