map.c 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "qbsp.h"
  19. extern qboolean onlyents;
  20. int nummapbrushes;
  21. mapbrush_t mapbrushes[MAX_MAP_BRUSHES];
  22. int nummapbrushsides;
  23. side_t brushsides[MAX_MAP_SIDES];
  24. brush_texture_t side_brushtextures[MAX_MAP_SIDES];
  25. int nummapplanes;
  26. plane_t mapplanes[MAX_MAP_PLANES];
  27. #define PLANE_HASHES 1024
  28. plane_t *planehash[PLANE_HASHES];
  29. vec3_t map_mins, map_maxs;
  30. // undefine to make plane finding use linear sort
  31. #define USE_HASHING
  32. void TestExpandBrushes (void);
  33. int c_boxbevels;
  34. int c_edgebevels;
  35. int c_areaportals;
  36. int c_clipbrushes;
  37. /*
  38. =============================================================================
  39. PLANE FINDING
  40. =============================================================================
  41. */
  42. /*
  43. =================
  44. PlaneTypeForNormal
  45. =================
  46. */
  47. int PlaneTypeForNormal (vec3_t normal)
  48. {
  49. vec_t ax, ay, az;
  50. // NOTE: should these have an epsilon around 1.0?
  51. if (normal[0] == 1.0 || normal[0] == -1.0)
  52. return PLANE_X;
  53. if (normal[1] == 1.0 || normal[1] == -1.0)
  54. return PLANE_Y;
  55. if (normal[2] == 1.0 || normal[2] == -1.0)
  56. return PLANE_Z;
  57. ax = fabs(normal[0]);
  58. ay = fabs(normal[1]);
  59. az = fabs(normal[2]);
  60. if (ax >= ay && ax >= az)
  61. return PLANE_ANYX;
  62. if (ay >= ax && ay >= az)
  63. return PLANE_ANYY;
  64. return PLANE_ANYZ;
  65. }
  66. /*
  67. ================
  68. PlaneEqual
  69. ================
  70. */
  71. #define NORMAL_EPSILON 0.00001
  72. #define DIST_EPSILON 0.01
  73. qboolean PlaneEqual (plane_t *p, vec3_t normal, vec_t dist)
  74. {
  75. #if 1
  76. if (
  77. fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
  78. && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
  79. && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
  80. && fabs(p->dist - dist) < DIST_EPSILON )
  81. return true;
  82. #else
  83. if (p->normal[0] == normal[0]
  84. && p->normal[1] == normal[1]
  85. && p->normal[2] == normal[2]
  86. && p->dist == dist)
  87. return true;
  88. #endif
  89. return false;
  90. }
  91. /*
  92. ================
  93. AddPlaneToHash
  94. ================
  95. */
  96. void AddPlaneToHash (plane_t *p)
  97. {
  98. int hash;
  99. hash = (int)fabs(p->dist) / 8;
  100. hash &= (PLANE_HASHES-1);
  101. p->hash_chain = planehash[hash];
  102. planehash[hash] = p;
  103. }
  104. /*
  105. ================
  106. CreateNewFloatPlane
  107. ================
  108. */
  109. int CreateNewFloatPlane (vec3_t normal, vec_t dist)
  110. {
  111. plane_t *p, temp;
  112. if (VectorLength(normal) < 0.5)
  113. Error ("FloatPlane: bad normal");
  114. // create a new plane
  115. if (nummapplanes+2 > MAX_MAP_PLANES)
  116. Error ("MAX_MAP_PLANES");
  117. p = &mapplanes[nummapplanes];
  118. VectorCopy (normal, p->normal);
  119. p->dist = dist;
  120. p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
  121. VectorSubtract (vec3_origin, normal, (p+1)->normal);
  122. (p+1)->dist = -dist;
  123. nummapplanes += 2;
  124. // allways put axial planes facing positive first
  125. if (p->type < 3)
  126. {
  127. if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
  128. {
  129. // flip order
  130. temp = *p;
  131. *p = *(p+1);
  132. *(p+1) = temp;
  133. AddPlaneToHash (p);
  134. AddPlaneToHash (p+1);
  135. return nummapplanes - 1;
  136. }
  137. }
  138. AddPlaneToHash (p);
  139. AddPlaneToHash (p+1);
  140. return nummapplanes - 2;
  141. }
  142. /*
  143. ==============
  144. SnapVector
  145. ==============
  146. */
  147. void SnapVector (vec3_t normal)
  148. {
  149. int i;
  150. for (i=0 ; i<3 ; i++)
  151. {
  152. if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
  153. {
  154. VectorClear (normal);
  155. normal[i] = 1;
  156. break;
  157. }
  158. if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
  159. {
  160. VectorClear (normal);
  161. normal[i] = -1;
  162. break;
  163. }
  164. }
  165. }
  166. /*
  167. ==============
  168. SnapPlane
  169. ==============
  170. */
  171. void SnapPlane (vec3_t normal, vec_t *dist)
  172. {
  173. SnapVector (normal);
  174. if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON)
  175. *dist = Q_rint(*dist);
  176. }
  177. /*
  178. =============
  179. FindFloatPlane
  180. =============
  181. */
  182. #ifndef USE_HASHING
  183. int FindFloatPlane (vec3_t normal, vec_t dist)
  184. {
  185. int i;
  186. plane_t *p;
  187. SnapPlane (normal, &dist);
  188. for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++)
  189. {
  190. if (PlaneEqual (p, normal, dist))
  191. return i;
  192. }
  193. return CreateNewFloatPlane (normal, dist);
  194. }
  195. #else
  196. int FindFloatPlane (vec3_t normal, vec_t dist)
  197. {
  198. int i;
  199. plane_t *p;
  200. int hash, h;
  201. SnapPlane (normal, &dist);
  202. hash = (int)fabs(dist) / 8;
  203. hash &= (PLANE_HASHES-1);
  204. // search the border bins as well
  205. for (i=-1 ; i<=1 ; i++)
  206. {
  207. h = (hash+i)&(PLANE_HASHES-1);
  208. for (p = planehash[h] ; p ; p=p->hash_chain)
  209. {
  210. if (PlaneEqual (p, normal, dist))
  211. return p-mapplanes;
  212. }
  213. }
  214. return CreateNewFloatPlane (normal, dist);
  215. }
  216. #endif
  217. /*
  218. ================
  219. PlaneFromPoints
  220. ================
  221. */
  222. int PlaneFromPoints (int *p0, int *p1, int *p2)
  223. {
  224. vec3_t t1, t2, normal;
  225. vec_t dist;
  226. VectorSubtract (p0, p1, t1);
  227. VectorSubtract (p2, p1, t2);
  228. CrossProduct (t1, t2, normal);
  229. VectorNormalize (normal, normal);
  230. dist = DotProduct (p0, normal);
  231. return FindFloatPlane (normal, dist);
  232. }
  233. //====================================================================
  234. /*
  235. ===========
  236. BrushContents
  237. ===========
  238. */
  239. int BrushContents (mapbrush_t *b)
  240. {
  241. int contents;
  242. side_t *s;
  243. int i;
  244. int trans;
  245. s = &b->original_sides[0];
  246. contents = s->contents;
  247. trans = texinfo[s->texinfo].flags;
  248. for (i=1 ; i<b->numsides ; i++, s++)
  249. {
  250. s = &b->original_sides[i];
  251. trans |= texinfo[s->texinfo].flags;
  252. if (s->contents != contents)
  253. {
  254. printf ("Entity %i, Brush %i: mixed face contents\n"
  255. , b->entitynum, b->brushnum);
  256. break;
  257. }
  258. }
  259. // if any side is translucent, mark the contents
  260. // and change solid to window
  261. if ( trans & (SURF_TRANS33|SURF_TRANS66) )
  262. {
  263. contents |= CONTENTS_TRANSLUCENT;
  264. if (contents & CONTENTS_SOLID)
  265. {
  266. contents &= ~CONTENTS_SOLID;
  267. contents |= CONTENTS_WINDOW;
  268. }
  269. }
  270. return contents;
  271. }
  272. //============================================================================
  273. /*
  274. =================
  275. AddBrushBevels
  276. Adds any additional planes necessary to allow the brush to be expanded
  277. against axial bounding boxes
  278. =================
  279. */
  280. void AddBrushBevels (mapbrush_t *b)
  281. {
  282. int axis, dir;
  283. int i, j, k, l, order;
  284. side_t sidetemp;
  285. brush_texture_t tdtemp;
  286. side_t *s, *s2;
  287. vec3_t normal;
  288. float dist;
  289. winding_t *w, *w2;
  290. vec3_t vec, vec2;
  291. float d;
  292. //
  293. // add the axial planes
  294. //
  295. order = 0;
  296. for (axis=0 ; axis <3 ; axis++)
  297. {
  298. for (dir=-1 ; dir <= 1 ; dir+=2, order++)
  299. {
  300. // see if the plane is allready present
  301. for (i=0, s=b->original_sides ; i<b->numsides ; i++,s++)
  302. {
  303. if (mapplanes[s->planenum].normal[axis] == dir)
  304. break;
  305. }
  306. if (i == b->numsides)
  307. { // add a new side
  308. if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
  309. Error ("MAX_MAP_BRUSHSIDES");
  310. nummapbrushsides++;
  311. b->numsides++;
  312. VectorClear (normal);
  313. normal[axis] = dir;
  314. if (dir == 1)
  315. dist = b->maxs[axis];
  316. else
  317. dist = -b->mins[axis];
  318. s->planenum = FindFloatPlane (normal, dist);
  319. s->texinfo = b->original_sides[0].texinfo;
  320. s->contents = b->original_sides[0].contents;
  321. s->bevel = true;
  322. c_boxbevels++;
  323. }
  324. // if the plane is not in it canonical order, swap it
  325. if (i != order)
  326. {
  327. sidetemp = b->original_sides[order];
  328. b->original_sides[order] = b->original_sides[i];
  329. b->original_sides[i] = sidetemp;
  330. j = b->original_sides - brushsides;
  331. tdtemp = side_brushtextures[j+order];
  332. side_brushtextures[j+order] = side_brushtextures[j+i];
  333. side_brushtextures[j+i] = tdtemp;
  334. }
  335. }
  336. }
  337. //
  338. // add the edge bevels
  339. //
  340. if (b->numsides == 6)
  341. return; // pure axial
  342. // test the non-axial plane edges
  343. for (i=6 ; i<b->numsides ; i++)
  344. {
  345. s = b->original_sides + i;
  346. w = s->winding;
  347. if (!w)
  348. continue;
  349. for (j=0 ; j<w->numpoints ; j++)
  350. {
  351. k = (j+1)%w->numpoints;
  352. VectorSubtract (w->p[j], w->p[k], vec);
  353. if (VectorNormalize (vec, vec) < 0.5)
  354. continue;
  355. SnapVector (vec);
  356. for (k=0 ; k<3 ; k++)
  357. if ( vec[k] == -1 || vec[k] == 1)
  358. break; // axial
  359. if (k != 3)
  360. continue; // only test non-axial edges
  361. // try the six possible slanted axials from this edge
  362. for (axis=0 ; axis <3 ; axis++)
  363. {
  364. for (dir=-1 ; dir <= 1 ; dir+=2)
  365. {
  366. // construct a plane
  367. VectorClear (vec2);
  368. vec2[axis] = dir;
  369. CrossProduct (vec, vec2, normal);
  370. if (VectorNormalize (normal, normal) < 0.5)
  371. continue;
  372. dist = DotProduct (w->p[j], normal);
  373. // if all the points on all the sides are
  374. // behind this plane, it is a proper edge bevel
  375. for (k=0 ; k<b->numsides ; k++)
  376. {
  377. // if this plane has allready been used, skip it
  378. if (PlaneEqual (&mapplanes[b->original_sides[k].planenum]
  379. , normal, dist) )
  380. break;
  381. w2 = b->original_sides[k].winding;
  382. if (!w2)
  383. continue;
  384. for (l=0 ; l<w2->numpoints ; l++)
  385. {
  386. d = DotProduct (w2->p[l], normal) - dist;
  387. if (d > 0.1)
  388. break; // point in front
  389. }
  390. if (l != w2->numpoints)
  391. break;
  392. }
  393. if (k != b->numsides)
  394. continue; // wasn't part of the outer hull
  395. // add this plane
  396. if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
  397. Error ("MAX_MAP_BRUSHSIDES");
  398. nummapbrushsides++;
  399. s2 = &b->original_sides[b->numsides];
  400. s2->planenum = FindFloatPlane (normal, dist);
  401. s2->texinfo = b->original_sides[0].texinfo;
  402. s2->contents = b->original_sides[0].contents;
  403. s2->bevel = true;
  404. c_edgebevels++;
  405. b->numsides++;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. /*
  412. ================
  413. MakeBrushWindings
  414. makes basewindigs for sides and mins / maxs for the brush
  415. ================
  416. */
  417. qboolean MakeBrushWindings (mapbrush_t *ob)
  418. {
  419. int i, j;
  420. winding_t *w;
  421. side_t *side;
  422. plane_t *plane;
  423. ClearBounds (ob->mins, ob->maxs);
  424. for (i=0 ; i<ob->numsides ; i++)
  425. {
  426. plane = &mapplanes[ob->original_sides[i].planenum];
  427. w = BaseWindingForPlane (plane->normal, plane->dist);
  428. for (j=0 ; j<ob->numsides && w; j++)
  429. {
  430. if (i == j)
  431. continue;
  432. if (ob->original_sides[j].bevel)
  433. continue;
  434. plane = &mapplanes[ob->original_sides[j].planenum^1];
  435. ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
  436. }
  437. side = &ob->original_sides[i];
  438. side->winding = w;
  439. if (w)
  440. {
  441. side->visible = true;
  442. for (j=0 ; j<w->numpoints ; j++)
  443. AddPointToBounds (w->p[j], ob->mins, ob->maxs);
  444. }
  445. }
  446. for (i=0 ; i<3 ; i++)
  447. {
  448. if (ob->mins[0] < -4096 || ob->maxs[0] > 4096)
  449. printf ("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
  450. if (ob->mins[0] > 4096 || ob->maxs[0] < -4096)
  451. printf ("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
  452. }
  453. return true;
  454. }
  455. /*
  456. =================
  457. ParseBrush
  458. =================
  459. */
  460. void ParseBrush (entity_t *mapent)
  461. {
  462. mapbrush_t *b;
  463. int i,j, k;
  464. int mt;
  465. side_t *side, *s2;
  466. int planenum;
  467. brush_texture_t td;
  468. int planepts[3][3];
  469. if (nummapbrushes == MAX_MAP_BRUSHES)
  470. Error ("nummapbrushes == MAX_MAP_BRUSHES");
  471. b = &mapbrushes[nummapbrushes];
  472. b->original_sides = &brushsides[nummapbrushsides];
  473. b->entitynum = num_entities-1;
  474. b->brushnum = nummapbrushes - mapent->firstbrush;
  475. do
  476. {
  477. if (!GetToken (true))
  478. break;
  479. if (!strcmp (token, "}") )
  480. break;
  481. if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
  482. Error ("MAX_MAP_BRUSHSIDES");
  483. side = &brushsides[nummapbrushsides];
  484. // read the three point plane definition
  485. for (i=0 ; i<3 ; i++)
  486. {
  487. if (i != 0)
  488. GetToken (true);
  489. if (strcmp (token, "(") )
  490. Error ("parsing brush");
  491. for (j=0 ; j<3 ; j++)
  492. {
  493. GetToken (false);
  494. planepts[i][j] = atoi(token);
  495. }
  496. GetToken (false);
  497. if (strcmp (token, ")") )
  498. Error ("parsing brush");
  499. }
  500. //
  501. // read the texturedef
  502. //
  503. GetToken (false);
  504. strcpy (td.name, token);
  505. GetToken (false);
  506. td.shift[0] = atoi(token);
  507. GetToken (false);
  508. td.shift[1] = atoi(token);
  509. GetToken (false);
  510. td.rotate = atoi(token);
  511. GetToken (false);
  512. td.scale[0] = atof(token);
  513. GetToken (false);
  514. td.scale[1] = atof(token);
  515. // find default flags and values
  516. mt = FindMiptex (td.name);
  517. td.flags = textureref[mt].flags;
  518. td.value = textureref[mt].value;
  519. side->contents = textureref[mt].contents;
  520. side->surf = td.flags = textureref[mt].flags;
  521. if (TokenAvailable())
  522. {
  523. GetToken (false);
  524. side->contents = atoi(token);
  525. GetToken (false);
  526. side->surf = td.flags = atoi(token);
  527. GetToken (false);
  528. td.value = atoi(token);
  529. }
  530. // translucent objects are automatically classified as detail
  531. if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
  532. side->contents |= CONTENTS_DETAIL;
  533. if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  534. side->contents |= CONTENTS_DETAIL;
  535. if (fulldetail)
  536. side->contents &= ~CONTENTS_DETAIL;
  537. if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1)
  538. | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) )
  539. side->contents |= CONTENTS_SOLID;
  540. // hints and skips are never detail, and have no content
  541. if (side->surf & (SURF_HINT|SURF_SKIP) )
  542. {
  543. side->contents = 0;
  544. side->surf &= ~CONTENTS_DETAIL;
  545. }
  546. //
  547. // find the plane number
  548. //
  549. planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
  550. if (planenum == -1)
  551. {
  552. printf ("Entity %i, Brush %i: plane with no normal\n"
  553. , b->entitynum, b->brushnum);
  554. continue;
  555. }
  556. //
  557. // see if the plane has been used already
  558. //
  559. for (k=0 ; k<b->numsides ; k++)
  560. {
  561. s2 = b->original_sides + k;
  562. if (s2->planenum == planenum)
  563. {
  564. printf ("Entity %i, Brush %i: duplicate plane\n"
  565. , b->entitynum, b->brushnum);
  566. break;
  567. }
  568. if ( s2->planenum == (planenum^1) )
  569. {
  570. printf ("Entity %i, Brush %i: mirrored plane\n"
  571. , b->entitynum, b->brushnum);
  572. break;
  573. }
  574. }
  575. if (k != b->numsides)
  576. continue; // duplicated
  577. //
  578. // keep this side
  579. //
  580. side = b->original_sides + b->numsides;
  581. side->planenum = planenum;
  582. side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
  583. &td, vec3_origin);
  584. // save the td off in case there is an origin brush and we
  585. // have to recalculate the texinfo
  586. side_brushtextures[nummapbrushsides] = td;
  587. nummapbrushsides++;
  588. b->numsides++;
  589. } while (1);
  590. // get the content for the entire brush
  591. b->contents = BrushContents (b);
  592. // allow detail brushes to be removed
  593. if (nodetail && (b->contents & CONTENTS_DETAIL) )
  594. {
  595. b->numsides = 0;
  596. return;
  597. }
  598. // allow water brushes to be removed
  599. if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
  600. {
  601. b->numsides = 0;
  602. return;
  603. }
  604. // create windings for sides and bounds for brush
  605. MakeBrushWindings (b);
  606. // brushes that will not be visible at all will never be
  607. // used as bsp splitters
  608. if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  609. {
  610. c_clipbrushes++;
  611. for (i=0 ; i<b->numsides ; i++)
  612. b->original_sides[i].texinfo = TEXINFO_NODE;
  613. }
  614. //
  615. // origin brushes are removed, but they set
  616. // the rotation origin for the rest of the brushes
  617. // in the entity. After the entire entity is parsed,
  618. // the planenums and texinfos will be adjusted for
  619. // the origin brush
  620. //
  621. if (b->contents & CONTENTS_ORIGIN)
  622. {
  623. char string[32];
  624. vec3_t origin;
  625. if (num_entities == 1)
  626. {
  627. Error ("Entity %i, Brush %i: origin brushes not allowed in world"
  628. , b->entitynum, b->brushnum);
  629. return;
  630. }
  631. VectorAdd (b->mins, b->maxs, origin);
  632. VectorScale (origin, 0.5, origin);
  633. sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  634. SetKeyValue (&entities[b->entitynum], "origin", string);
  635. VectorCopy (origin, entities[b->entitynum].origin);
  636. // don't keep this brush
  637. b->numsides = 0;
  638. return;
  639. }
  640. AddBrushBevels (b);
  641. nummapbrushes++;
  642. mapent->numbrushes++;
  643. }
  644. /*
  645. ================
  646. MoveBrushesToWorld
  647. Takes all of the brushes from the current entity and
  648. adds them to the world's brush list.
  649. Used by func_group and func_areaportal
  650. ================
  651. */
  652. void MoveBrushesToWorld (entity_t *mapent)
  653. {
  654. int newbrushes;
  655. int worldbrushes;
  656. mapbrush_t *temp;
  657. int i;
  658. // this is pretty gross, because the brushes are expected to be
  659. // in linear order for each entity
  660. newbrushes = mapent->numbrushes;
  661. worldbrushes = entities[0].numbrushes;
  662. temp = malloc(newbrushes*sizeof(mapbrush_t));
  663. memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
  664. #if 0 // let them keep their original brush numbers
  665. for (i=0 ; i<newbrushes ; i++)
  666. temp[i].entitynum = 0;
  667. #endif
  668. // make space to move the brushes (overlapped copy)
  669. memmove (mapbrushes + worldbrushes + newbrushes,
  670. mapbrushes + worldbrushes,
  671. sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
  672. // copy the new brushes down
  673. memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
  674. // fix up indexes
  675. entities[0].numbrushes += newbrushes;
  676. for (i=1 ; i<num_entities ; i++)
  677. entities[i].firstbrush += newbrushes;
  678. free (temp);
  679. mapent->numbrushes = 0;
  680. }
  681. /*
  682. ================
  683. ParseMapEntity
  684. ================
  685. */
  686. qboolean ParseMapEntity (void)
  687. {
  688. entity_t *mapent;
  689. epair_t *e;
  690. side_t *s;
  691. int i, j;
  692. int startbrush, startsides;
  693. vec_t newdist;
  694. mapbrush_t *b;
  695. if (!GetToken (true))
  696. return false;
  697. if (strcmp (token, "{") )
  698. Error ("ParseEntity: { not found");
  699. if (num_entities == MAX_MAP_ENTITIES)
  700. Error ("num_entities == MAX_MAP_ENTITIES");
  701. startbrush = nummapbrushes;
  702. startsides = nummapbrushsides;
  703. mapent = &entities[num_entities];
  704. num_entities++;
  705. memset (mapent, 0, sizeof(*mapent));
  706. mapent->firstbrush = nummapbrushes;
  707. mapent->numbrushes = 0;
  708. // mapent->portalareas[0] = -1;
  709. // mapent->portalareas[1] = -1;
  710. do
  711. {
  712. if (!GetToken (true))
  713. Error ("ParseEntity: EOF without closing brace");
  714. if (!strcmp (token, "}") )
  715. break;
  716. if (!strcmp (token, "{") )
  717. ParseBrush (mapent);
  718. else
  719. {
  720. e = ParseEpair ();
  721. e->next = mapent->epairs;
  722. mapent->epairs = e;
  723. }
  724. } while (1);
  725. GetVectorForKey (mapent, "origin", mapent->origin);
  726. //
  727. // if there was an origin brush, offset all of the planes and texinfo
  728. //
  729. if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
  730. {
  731. for (i=0 ; i<mapent->numbrushes ; i++)
  732. {
  733. b = &mapbrushes[mapent->firstbrush + i];
  734. for (j=0 ; j<b->numsides ; j++)
  735. {
  736. s = &b->original_sides[j];
  737. newdist = mapplanes[s->planenum].dist -
  738. DotProduct (mapplanes[s->planenum].normal, mapent->origin);
  739. s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
  740. s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
  741. &side_brushtextures[s-brushsides], mapent->origin);
  742. }
  743. MakeBrushWindings (b);
  744. }
  745. }
  746. // group entities are just for editor convenience
  747. // toss all brushes into the world entity
  748. if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
  749. {
  750. MoveBrushesToWorld (mapent);
  751. mapent->numbrushes = 0;
  752. return true;
  753. }
  754. // areaportal entities move their brushes, but don't eliminate
  755. // the entity
  756. if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
  757. {
  758. char str[128];
  759. if (mapent->numbrushes != 1)
  760. Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
  761. b = &mapbrushes[nummapbrushes-1];
  762. b->contents = CONTENTS_AREAPORTAL;
  763. c_areaportals++;
  764. mapent->areaportalnum = c_areaportals;
  765. // set the portal number as "style"
  766. sprintf (str, "%i", c_areaportals);
  767. SetKeyValue (mapent, "style", str);
  768. MoveBrushesToWorld (mapent);
  769. return true;
  770. }
  771. return true;
  772. }
  773. //===================================================================
  774. /*
  775. ================
  776. LoadMapFile
  777. ================
  778. */
  779. void LoadMapFile (char *filename)
  780. {
  781. int i;
  782. qprintf ("--- LoadMapFile ---\n");
  783. LoadScriptFile (filename);
  784. nummapbrushsides = 0;
  785. num_entities = 0;
  786. while (ParseMapEntity ())
  787. {
  788. }
  789. ClearBounds (map_mins, map_maxs);
  790. for (i=0 ; i<entities[0].numbrushes ; i++)
  791. {
  792. if (mapbrushes[i].mins[0] > 4096)
  793. continue; // no valid points
  794. AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
  795. AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
  796. }
  797. qprintf ("%5i brushes\n", nummapbrushes);
  798. qprintf ("%5i clipbrushes\n", c_clipbrushes);
  799. qprintf ("%5i total sides\n", nummapbrushsides);
  800. qprintf ("%5i boxbevels\n", c_boxbevels);
  801. qprintf ("%5i edgebevels\n", c_edgebevels);
  802. qprintf ("%5i entities\n", num_entities);
  803. qprintf ("%5i planes\n", nummapplanes);
  804. qprintf ("%5i areaportals\n", c_areaportals);
  805. qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
  806. map_maxs[0],map_maxs[1],map_maxs[2]);
  807. // TestExpandBrushes ();
  808. }
  809. //====================================================================
  810. /*
  811. ================
  812. TestExpandBrushes
  813. Expands all the brush planes and saves a new map out
  814. ================
  815. */
  816. void TestExpandBrushes (void)
  817. {
  818. FILE *f;
  819. side_t *s;
  820. int i, j, bn;
  821. winding_t *w;
  822. char *name = "expanded.map";
  823. mapbrush_t *brush;
  824. vec_t dist;
  825. printf ("writing %s\n", name);
  826. f = fopen (name, "wb");
  827. if (!f)
  828. Error ("Can't write %s\b", name);
  829. fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
  830. for (bn=0 ; bn<nummapbrushes ; bn++)
  831. {
  832. brush = &mapbrushes[bn];
  833. fprintf (f, "{\n");
  834. for (i=0 ; i<brush->numsides ; i++)
  835. {
  836. s = brush->original_sides + i;
  837. dist = mapplanes[s->planenum].dist;
  838. for (j=0 ; j<3 ; j++)
  839. dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
  840. w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
  841. fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
  842. fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
  843. fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
  844. fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
  845. FreeWinding (w);
  846. }
  847. fprintf (f, "}\n");
  848. }
  849. fprintf (f, "}\n");
  850. fclose (f);
  851. Error ("can't proceed after expanding brushes");
  852. }