BRUSH.C 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. // brush.c
  2. #include "bsp5.h"
  3. int numbrushplanes;
  4. plane_t planes[MAX_MAP_PLANES];
  5. int numbrushfaces;
  6. mface_t faces[128]; // beveled clipping hull can generate many extra
  7. /*
  8. =================
  9. CheckFace
  10. Note: this will not catch 0 area polygons
  11. =================
  12. */
  13. void CheckFace (face_t *f)
  14. {
  15. int i, j;
  16. vec_t *p1, *p2;
  17. vec_t d, edgedist;
  18. vec3_t dir, edgenormal, facenormal;
  19. if (f->numpoints < 3)
  20. Error ("CheckFace: %i points",f->numpoints);
  21. VectorCopy (planes[f->planenum].normal, facenormal);
  22. if (f->planeside)
  23. {
  24. VectorSubtract (vec3_origin, facenormal, facenormal);
  25. }
  26. for (i=0 ; i<f->numpoints ; i++)
  27. {
  28. p1 = f->pts[i];
  29. for (j=0 ; j<3 ; j++)
  30. if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
  31. Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
  32. j = i+1 == f->numpoints ? 0 : i+1;
  33. // check the point is on the face plane
  34. d = DotProduct (p1, planes[f->planenum].normal) - planes[f->planenum].dist;
  35. if (d < -ON_EPSILON || d > ON_EPSILON)
  36. Error ("CheckFace: point off plane");
  37. // check the edge isn't degenerate
  38. p2 = f->pts[j];
  39. VectorSubtract (p2, p1, dir);
  40. if (VectorLength (dir) < ON_EPSILON)
  41. Error ("CheckFace: degenerate edge");
  42. CrossProduct (facenormal, dir, edgenormal);
  43. VectorNormalize (edgenormal);
  44. edgedist = DotProduct (p1, edgenormal);
  45. edgedist += ON_EPSILON;
  46. // all other points must be on front side
  47. for (j=0 ; j<f->numpoints ; j++)
  48. {
  49. if (j == i)
  50. continue;
  51. d = DotProduct (f->pts[j], edgenormal);
  52. if (d > edgedist)
  53. Error ("CheckFace: non-convex");
  54. }
  55. }
  56. }
  57. //===========================================================================
  58. /*
  59. =================
  60. ClearBounds
  61. =================
  62. */
  63. void ClearBounds (brushset_t *bs)
  64. {
  65. int i, j;
  66. for (j=0 ; j<NUM_HULLS ; j++)
  67. for (i=0 ; i<3 ; i++)
  68. {
  69. bs->mins[i] = 99999;
  70. bs->maxs[i] = -99999;
  71. }
  72. }
  73. /*
  74. =================
  75. AddToBounds
  76. =================
  77. */
  78. void AddToBounds (brushset_t *bs, vec3_t v)
  79. {
  80. int i;
  81. for (i=0 ; i<3 ; i++)
  82. {
  83. if (v[i] < bs->mins[i])
  84. bs->mins[i] = v[i];
  85. if (v[i] > bs->maxs[i])
  86. bs->maxs[i] = v[i];
  87. }
  88. }
  89. //===========================================================================
  90. int PlaneTypeForNormal (vec3_t normal)
  91. {
  92. float ax, ay, az;
  93. // NOTE: should these have an epsilon around 1.0?
  94. if (normal[0] == 1.0)
  95. return PLANE_X;
  96. if (normal[1] == 1.0)
  97. return PLANE_Y;
  98. if (normal[2] == 1.0)
  99. return PLANE_Z;
  100. if (normal[0] == -1.0 ||
  101. normal[1] == -1.0 ||
  102. normal[2] == -1.0)
  103. Error ("PlaneTypeForNormal: not a canonical vector");
  104. ax = fabs(normal[0]);
  105. ay = fabs(normal[1]);
  106. az = fabs(normal[2]);
  107. if (ax >= ay && ax >= az)
  108. return PLANE_ANYX;
  109. if (ay >= ax && ay >= az)
  110. return PLANE_ANYY;
  111. return PLANE_ANYZ;
  112. }
  113. #define DISTEPSILON 0.01
  114. #define ANGLEEPSILON 0.00001
  115. void NormalizePlane (plane_t *dp)
  116. {
  117. vec_t ax, ay, az;
  118. if (dp->normal[0] == -1.0)
  119. {
  120. dp->normal[0] = 1.0;
  121. dp->dist = -dp->dist;
  122. }
  123. if (dp->normal[1] == -1.0)
  124. {
  125. dp->normal[1] = 1.0;
  126. dp->dist = -dp->dist;
  127. }
  128. if (dp->normal[2] == -1.0)
  129. {
  130. dp->normal[2] = 1.0;
  131. dp->dist = -dp->dist;
  132. }
  133. if (dp->normal[0] == 1.0)
  134. {
  135. dp->type = PLANE_X;
  136. return;
  137. }
  138. if (dp->normal[1] == 1.0)
  139. {
  140. dp->type = PLANE_Y;
  141. return;
  142. }
  143. if (dp->normal[2] == 1.0)
  144. {
  145. dp->type = PLANE_Z;
  146. return;
  147. }
  148. ax = fabs(dp->normal[0]);
  149. ay = fabs(dp->normal[1]);
  150. az = fabs(dp->normal[2]);
  151. if (ax >= ay && ax >= az)
  152. dp->type = PLANE_ANYX;
  153. else if (ay >= ax && ay >= az)
  154. dp->type = PLANE_ANYY;
  155. else
  156. dp->type = PLANE_ANYZ;
  157. if (dp->normal[dp->type-PLANE_ANYX] < 0)
  158. {
  159. VectorSubtract (vec3_origin, dp->normal, dp->normal);
  160. dp->dist = -dp->dist;
  161. }
  162. }
  163. /*
  164. ===============
  165. FindPlane
  166. Returns a global plane number and the side that will be the front
  167. ===============
  168. */
  169. int FindPlane (plane_t *dplane, int *side)
  170. {
  171. int i;
  172. plane_t *dp, pl;
  173. vec_t dot;
  174. dot = VectorLength(dplane->normal);
  175. if (dot < 1.0 - ANGLEEPSILON || dot > 1.0 + ANGLEEPSILON)
  176. Error ("FindPlane: normalization error");
  177. pl = *dplane;
  178. NormalizePlane (&pl);
  179. if (DotProduct(pl.normal, dplane->normal) > 0)
  180. *side = 0;
  181. else
  182. *side = 1;
  183. dp = planes;
  184. for (i=0 ; i<numbrushplanes;i++, dp++)
  185. {
  186. dot = DotProduct (dp->normal, pl.normal);
  187. if (dot > 1.0 - ANGLEEPSILON
  188. && fabs(dp->dist - pl.dist) < DISTEPSILON )
  189. { // regular match
  190. return i;
  191. }
  192. }
  193. if (numbrushplanes == MAX_MAP_PLANES)
  194. Error ("numbrushplanes == MAX_MAP_PLANES");
  195. planes[numbrushplanes] = pl;
  196. numbrushplanes++;
  197. return numbrushplanes-1;
  198. }
  199. /*
  200. ===============
  201. FindPlane_old
  202. Returns a global plane number and the side that will be the front
  203. ===============
  204. */
  205. int FindPlane_old (plane_t *dplane, int *side)
  206. {
  207. int i;
  208. plane_t *dp;
  209. vec_t dot, ax, ay, az;
  210. dot = VectorLength(dplane->normal);
  211. if (dot < 1.0 - ANGLEEPSILON || dot > 1.0 + ANGLEEPSILON)
  212. Error ("FindPlane: normalization error");
  213. dp = planes;
  214. for (i=0 ; i<numbrushplanes;i++, dp++)
  215. {
  216. dot = DotProduct (dplane->normal, dp->normal);
  217. if (dot > 1.0 - ANGLEEPSILON
  218. && fabs(dplane->dist - dp->dist) < DISTEPSILON )
  219. { // regular match
  220. *side = 0;
  221. return i;
  222. }
  223. if (dot < -1.0+ANGLEEPSILON
  224. && fabs(dplane->dist + dp->dist) < DISTEPSILON )
  225. { // inverse of vector
  226. *side = 1;
  227. return i;
  228. }
  229. }
  230. // allocate a new plane, flipping normal to a consistant direction
  231. // if needed
  232. *dp = *dplane;
  233. if (numbrushplanes == MAX_MAP_PLANES)
  234. Error ("numbrushplanes == MAX_MAP_PLANES");
  235. numbrushplanes++;
  236. *side = 0;
  237. // NOTE: should these have an epsilon around 1.0?
  238. if (dplane->normal[0] == 1.0)
  239. dp->type = PLANE_X;
  240. else if (dplane->normal[1] == 1.0)
  241. dp->type = PLANE_Y;
  242. else if (dplane->normal[2] == 1.0)
  243. dp->type = PLANE_Z;
  244. else if (dplane->normal[0] == -1.0)
  245. {
  246. dp->type = PLANE_X;
  247. dp->normal[0] = 1.0;
  248. dp->dist = -dp->dist;
  249. *side = 1;
  250. }
  251. else if (dplane->normal[1] == -1.0)
  252. {
  253. dp->type = PLANE_Y;
  254. dp->normal[1] = 1.0;
  255. dp->dist = -dp->dist;
  256. *side = 1;
  257. }
  258. else if (dplane->normal[2] == -1.0)
  259. {
  260. dp->type = PLANE_Z;
  261. dp->normal[2] = 1.0;
  262. dp->dist = -dp->dist;
  263. *side = 1;
  264. }
  265. else
  266. {
  267. ax = fabs(dplane->normal[0]);
  268. ay = fabs(dplane->normal[1]);
  269. az = fabs(dplane->normal[2]);
  270. if (ax >= ay && ax >= az)
  271. dp->type = PLANE_ANYX;
  272. else if (ay >= ax && ay >= az)
  273. dp->type = PLANE_ANYY;
  274. else
  275. dp->type = PLANE_ANYZ;
  276. if (dplane->normal[dp->type-PLANE_ANYX] < 0)
  277. {
  278. VectorSubtract (vec3_origin, dp->normal, dp->normal);
  279. dp->dist = -dp->dist;
  280. *side = 1;
  281. }
  282. }
  283. return i;
  284. }
  285. /*
  286. =============================================================================
  287. TURN BRUSHES INTO GROUPS OF FACES
  288. =============================================================================
  289. */
  290. vec3_t brush_mins, brush_maxs;
  291. face_t *brush_faces;
  292. /*
  293. =================
  294. CreateBrushFaces
  295. =================
  296. */
  297. #define ZERO_EPSILON 0.001
  298. void CreateBrushFaces (void)
  299. {
  300. int i,j, k;
  301. vec_t r;
  302. face_t *f;
  303. winding_t *w;
  304. plane_t plane;
  305. mface_t *mf;
  306. brush_mins[0] = brush_mins[1] = brush_mins[2] = 99999;
  307. brush_maxs[0] = brush_maxs[1] = brush_maxs[2] = -99999;
  308. brush_faces = NULL;
  309. for (i=0 ; i<numbrushfaces ; i++)
  310. {
  311. mf = &faces[i];
  312. w = BaseWindingForPlane (&mf->plane);
  313. for (j=0 ; j<numbrushfaces && w ; j++)
  314. {
  315. if (j == i)
  316. continue;
  317. // flip the plane, because we want to keep the back side
  318. VectorSubtract (vec3_origin,faces[j].plane.normal, plane.normal);
  319. plane.dist = -faces[j].plane.dist;
  320. w = ClipWinding (w, &plane, false);
  321. }
  322. if (!w)
  323. continue; // overcontrained plane
  324. // this face is a keeper
  325. f = AllocFace ();
  326. f->numpoints = w->numpoints;
  327. if (f->numpoints > MAXEDGES)
  328. Error ("f->numpoints > MAXEDGES");
  329. for (j=0 ; j<w->numpoints ; j++)
  330. {
  331. for (k=0 ; k<3 ; k++)
  332. {
  333. r = Q_rint (w->points[j][k]);
  334. if ( fabs(w->points[j][k] - r) < ZERO_EPSILON)
  335. f->pts[j][k] = r;
  336. else
  337. f->pts[j][k] = w->points[j][k];
  338. if (f->pts[j][k] < brush_mins[k])
  339. brush_mins[k] = f->pts[j][k];
  340. if (f->pts[j][k] > brush_maxs[k])
  341. brush_maxs[k] = f->pts[j][k];
  342. }
  343. }
  344. FreeWinding (w);
  345. f->texturenum = mf->texinfo;
  346. f->planenum = FindPlane (&mf->plane, &f->planeside);
  347. f->next = brush_faces;
  348. brush_faces = f;
  349. CheckFace (f);
  350. }
  351. }
  352. /*
  353. ==============================================================================
  354. BEVELED CLIPPING HULL GENERATION
  355. This is done by brute force, and could easily get a lot faster if anyone cares.
  356. ==============================================================================
  357. */
  358. vec3_t hull_size[3][2] = {
  359. { {0, 0, 0}, {0, 0, 0} },
  360. { {-16,-16,-32}, {16,16,24} },
  361. { {-32,-32,-64}, {32,32,24} }
  362. };
  363. #define MAX_HULL_POINTS 32
  364. #define MAX_HULL_EDGES 64
  365. int num_hull_points;
  366. vec3_t hull_points[MAX_HULL_POINTS];
  367. vec3_t hull_corners[MAX_HULL_POINTS*8];
  368. int num_hull_edges;
  369. int hull_edges[MAX_HULL_EDGES][2];
  370. /*
  371. ============
  372. AddBrushPlane
  373. =============
  374. */
  375. void AddBrushPlane (plane_t *plane)
  376. {
  377. int i;
  378. plane_t *pl;
  379. float l;
  380. if (numbrushfaces == MAX_FACES)
  381. Error ("AddBrushPlane: numbrushfaces == MAX_FACES");
  382. l = VectorLength (plane->normal);
  383. if (l < 0.999 || l > 1.001)
  384. Error ("AddBrushPlane: bad normal");
  385. for (i=0 ; i<numbrushfaces ; i++)
  386. {
  387. pl = &faces[i].plane;
  388. if (VectorCompare (pl->normal, plane->normal)
  389. && fabs(pl->dist - plane->dist) < ON_EPSILON )
  390. return;
  391. }
  392. faces[i].plane = *plane;
  393. faces[i].texinfo = faces[0].texinfo;
  394. numbrushfaces++;
  395. }
  396. /*
  397. ============
  398. TestAddPlane
  399. Adds the given plane to the brush description if all of the original brush
  400. vertexes can be put on the front side
  401. =============
  402. */
  403. void TestAddPlane (plane_t *plane)
  404. {
  405. int i, c;
  406. vec_t d;
  407. vec_t *corner;
  408. plane_t flip;
  409. vec3_t inv;
  410. int counts[3];
  411. plane_t *pl;
  412. // see if the plane has allready been added
  413. for (i=0 ; i<numbrushfaces ; i++)
  414. {
  415. pl = &faces[i].plane;
  416. if (VectorCompare (plane->normal, pl->normal) && fabs(plane->dist - pl->dist) < ON_EPSILON)
  417. return;
  418. VectorSubtract (vec3_origin, plane->normal, inv);
  419. if (VectorCompare (inv, pl->normal) && fabs(plane->dist + pl->dist) < ON_EPSILON)
  420. return;
  421. }
  422. // check all the corner points
  423. counts[0] = counts[1] = counts[2] = 0;
  424. c = num_hull_points * 8;
  425. corner = hull_corners[0];
  426. for (i=0 ; i<c ; i++, corner += 3)
  427. {
  428. d = DotProduct (corner, plane->normal) - plane->dist;
  429. if (d < -ON_EPSILON)
  430. {
  431. if (counts[0])
  432. return;
  433. counts[1]++;
  434. }
  435. else if (d > ON_EPSILON)
  436. {
  437. if (counts[1])
  438. return;
  439. counts[0]++;
  440. }
  441. else
  442. counts[2]++;
  443. }
  444. // the plane is a seperator
  445. if (counts[0])
  446. {
  447. VectorSubtract (vec3_origin, plane->normal, flip.normal);
  448. flip.dist = -plane->dist;
  449. plane = &flip;
  450. }
  451. AddBrushPlane (plane);
  452. }
  453. /*
  454. ============
  455. AddHullPoint
  456. Doesn't add if duplicated
  457. =============
  458. */
  459. int AddHullPoint (vec3_t p, int hullnum)
  460. {
  461. int i;
  462. vec_t *c;
  463. int x,y,z;
  464. for (i=0 ; i<num_hull_points ; i++)
  465. if (VectorCompare (p, hull_points[i]))
  466. return i;
  467. VectorCopy (p, hull_points[num_hull_points]);
  468. c = hull_corners[i*8];
  469. for (x=0 ; x<2 ; x++)
  470. for (y=0 ; y<2 ; y++)
  471. for (z=0; z<2 ; z++)
  472. {
  473. c[0] = p[0] + hull_size[hullnum][x][0];
  474. c[1] = p[1] + hull_size[hullnum][y][1];
  475. c[2] = p[2] + hull_size[hullnum][z][2];
  476. c += 3;
  477. }
  478. if (num_hull_points == MAX_HULL_POINTS)
  479. Error ("MAX_HULL_POINTS");
  480. num_hull_points++;
  481. return i;
  482. }
  483. /*
  484. ============
  485. AddHullEdge
  486. Creates all of the hull planes around the given edge, if not done allready
  487. =============
  488. */
  489. void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum)
  490. {
  491. int pt1, pt2;
  492. int i;
  493. int a, b, c, d, e;
  494. vec3_t edgevec, planeorg, planevec;
  495. plane_t plane;
  496. vec_t l;
  497. pt1 = AddHullPoint (p1, hullnum);
  498. pt2 = AddHullPoint (p2, hullnum);
  499. for (i=0 ; i<num_hull_edges ; i++)
  500. if ( (hull_edges[i][0] == pt1 && hull_edges[i][1] == pt2)
  501. || (hull_edges[i][0] == pt2 && hull_edges[i][1] == pt1) )
  502. return; // allread added
  503. if (num_hull_edges == MAX_HULL_EDGES)
  504. Error ("MAX_HULL_EDGES");
  505. hull_edges[i][0] = pt1;
  506. hull_edges[i][1] = pt2;
  507. num_hull_edges++;
  508. VectorSubtract (p1, p2, edgevec);
  509. VectorNormalize (edgevec);
  510. for (a=0 ; a<3 ; a++)
  511. {
  512. b = (a+1)%3;
  513. c = (a+2)%3;
  514. for (d=0 ; d<=1 ; d++)
  515. for (e=0 ; e<=1 ; e++)
  516. {
  517. VectorCopy (p1, planeorg);
  518. planeorg[b] += hull_size[hullnum][d][b];
  519. planeorg[c] += hull_size[hullnum][e][c];
  520. VectorCopy (vec3_origin, planevec);
  521. planevec[a] = 1;
  522. CrossProduct (planevec, edgevec, plane.normal);
  523. l = VectorLength (plane.normal);
  524. if (l < 1-ANGLEEPSILON || l > 1+ANGLEEPSILON)
  525. continue;
  526. plane.dist = DotProduct (planeorg, plane.normal);
  527. TestAddPlane (&plane);
  528. }
  529. }
  530. }
  531. /*
  532. ============
  533. ExpandBrush
  534. =============
  535. */
  536. void ExpandBrush (int hullnum)
  537. {
  538. int i, x, s;
  539. vec3_t corner;
  540. face_t *f;
  541. plane_t plane, *p;
  542. num_hull_points = 0;
  543. num_hull_edges = 0;
  544. // create all the hull points
  545. for (f=brush_faces ; f ; f=f->next)
  546. for (i=0 ; i<f->numpoints ; i++)
  547. AddHullPoint (f->pts[i], hullnum);
  548. // expand all of the planes
  549. for (i=0 ; i<numbrushfaces ; i++)
  550. {
  551. p = &faces[i].plane;
  552. VectorCopy (vec3_origin, corner);
  553. for (x=0 ; x<3 ; x++)
  554. {
  555. if (p->normal[x] > 0)
  556. corner[x] = hull_size[hullnum][1][x];
  557. else if (p->normal[x] < 0)
  558. corner[x] = hull_size[hullnum][0][x];
  559. }
  560. p->dist += DotProduct (corner, p->normal);
  561. }
  562. // add any axis planes not contained in the brush to bevel off corners
  563. for (x=0 ; x<3 ; x++)
  564. for (s=-1 ; s<=1 ; s+=2)
  565. {
  566. // add the plane
  567. VectorCopy (vec3_origin, plane.normal);
  568. plane.normal[x] = s;
  569. if (s == -1)
  570. plane.dist = -brush_mins[x] + -hull_size[hullnum][0][x];
  571. else
  572. plane.dist = brush_maxs[x] + hull_size[hullnum][1][x];
  573. AddBrushPlane (&plane);
  574. }
  575. // add all of the edge bevels
  576. for (f=brush_faces ; f ; f=f->next)
  577. for (i=0 ; i<f->numpoints ; i++)
  578. AddHullEdge (f->pts[i], f->pts[(i+1)%f->numpoints], hullnum);
  579. }
  580. //============================================================================
  581. /*
  582. ===============
  583. LoadBrush
  584. Converts a mapbrush to a bsp brush
  585. ===============
  586. */
  587. brush_t *LoadBrush (mbrush_t *mb, int hullnum)
  588. {
  589. brush_t *b;
  590. int contents;
  591. char *name;
  592. mface_t *f;
  593. //
  594. // check texture name for attributes
  595. //
  596. name = miptex[texinfo[mb->faces->texinfo].miptex];
  597. if (!Q_strcasecmp(name, "clip") && hullnum == 0)
  598. return NULL; // "clip" brushes don't show up in the draw hull
  599. if (name[0] == '*' && worldmodel) // entities never use water merging
  600. {
  601. if (!Q_strncasecmp(name+1,"lava",4))
  602. contents = CONTENTS_LAVA;
  603. else if (!Q_strncasecmp(name+1,"slime",5))
  604. contents = CONTENTS_SLIME;
  605. else
  606. contents = CONTENTS_WATER;
  607. }
  608. else if (!Q_strncasecmp (name, "sky",3) && worldmodel && hullnum == 0)
  609. contents = CONTENTS_SKY;
  610. else
  611. contents = CONTENTS_SOLID;
  612. if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY)
  613. return NULL; // water brushes don't show up in clipping hulls
  614. // no seperate textures on clip hull
  615. //
  616. // create the faces
  617. //
  618. brush_faces = NULL;
  619. numbrushfaces = 0;
  620. for (f=mb->faces ; f ; f=f->next)
  621. {
  622. faces[numbrushfaces] = *f;
  623. if (hullnum)
  624. faces[numbrushfaces].texinfo = 0;
  625. numbrushfaces++;
  626. }
  627. CreateBrushFaces ();
  628. if (!brush_faces)
  629. {
  630. printf ("WARNING: couldn't create brush faces\n");
  631. return NULL;
  632. }
  633. if (hullnum)
  634. {
  635. ExpandBrush (hullnum);
  636. CreateBrushFaces ();
  637. }
  638. //
  639. // create the brush
  640. //
  641. b = AllocBrush ();
  642. b->contents = contents;
  643. b->faces = brush_faces;
  644. VectorCopy (brush_mins, b->mins);
  645. VectorCopy (brush_maxs, b->maxs);
  646. return b;
  647. }
  648. //=============================================================================
  649. /*
  650. ============
  651. Brush_DrawAll
  652. ============
  653. */
  654. void Brush_DrawAll (brushset_t *bs)
  655. {
  656. brush_t *b;
  657. face_t *f;
  658. for (b=bs->brushes ; b ; b=b->next)
  659. for (f=b->faces ; f ; f=f->next)
  660. Draw_DrawFace (f);
  661. }
  662. /*
  663. ============
  664. Brush_LoadEntity
  665. ============
  666. */
  667. brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum)
  668. {
  669. brush_t *b, *next, *water, *other;
  670. mbrush_t *mbr;
  671. int numbrushes;
  672. brushset_t *bset;
  673. bset = malloc (sizeof(brushset_t));
  674. memset (bset, 0, sizeof(brushset_t));
  675. ClearBounds (bset);
  676. numbrushes = 0;
  677. other = water = NULL;
  678. qprintf ("--- Brush_LoadEntity ---\n");
  679. for (mbr = ent->brushes ; mbr ; mbr=mbr->next)
  680. {
  681. b = LoadBrush (mbr, hullnum);
  682. if (!b)
  683. continue;
  684. numbrushes++;
  685. if (b->contents != CONTENTS_SOLID)
  686. {
  687. b->next = water;
  688. water = b;
  689. }
  690. else
  691. {
  692. b->next = other;
  693. other = b;
  694. }
  695. AddToBounds (bset, b->mins);
  696. AddToBounds (bset, b->maxs);
  697. }
  698. // add all of the water textures at the start
  699. for (b=water ; b ; b=next)
  700. {
  701. next = b->next;
  702. b->next = other;
  703. other = b;
  704. }
  705. bset->brushes = other;
  706. brushset = bset;
  707. Brush_DrawAll (bset);
  708. qprintf ("%i brushes read\n",numbrushes);
  709. return bset;
  710. }