r_bsp.c 14 KB

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