brushbsp.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena 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 III Arena 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 Foobar; 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. #include "l_mem.h"
  20. #include "../botlib/aasfile.h"
  21. #include "aas_store.h"
  22. #include "aas_cfg.h"
  23. #include <assert.h>
  24. /*
  25. each side has a count of the other sides it splits
  26. the best split will be the one that minimizes the total split counts
  27. of all remaining sides
  28. precalc side on plane table
  29. evaluate split side
  30. {
  31. cost = 0
  32. for all sides
  33. for all sides
  34. get
  35. if side splits side and splitside is on same child
  36. cost++;
  37. }
  38. */
  39. int c_nodes;
  40. int c_nonvis;
  41. int c_active_brushes;
  42. int c_solidleafnodes;
  43. int c_totalsides;
  44. int c_brushmemory;
  45. int c_peak_brushmemory;
  46. int c_nodememory;
  47. int c_peak_totalbspmemory;
  48. // if a brush just barely pokes onto the other side,
  49. // let it slide by without chopping
  50. #define PLANESIDE_EPSILON 0.001
  51. //0.1
  52. //#ifdef DEBUG
  53. typedef struct cname_s
  54. {
  55. int value;
  56. char *name;
  57. } cname_t;
  58. cname_t contentnames[] =
  59. {
  60. {CONTENTS_SOLID,"CONTENTS_SOLID"},
  61. {CONTENTS_WINDOW,"CONTENTS_WINDOW"},
  62. {CONTENTS_AUX,"CONTENTS_AUX"},
  63. {CONTENTS_LAVA,"CONTENTS_LAVA"},
  64. {CONTENTS_SLIME,"CONTENTS_SLIME"},
  65. {CONTENTS_WATER,"CONTENTS_WATER"},
  66. {CONTENTS_MIST,"CONTENTS_MIST"},
  67. {LAST_VISIBLE_CONTENTS,"LAST_VISIBLE_CONTENTS"},
  68. {CONTENTS_AREAPORTAL,"CONTENTS_AREAPORTAL"},
  69. {CONTENTS_PLAYERCLIP,"CONTENTS_PLAYERCLIP"},
  70. {CONTENTS_MONSTERCLIP,"CONTENTS_MONSTERCLIP"},
  71. {CONTENTS_CURRENT_0,"CONTENTS_CURRENT_0"},
  72. {CONTENTS_CURRENT_90,"CONTENTS_CURRENT_90"},
  73. {CONTENTS_CURRENT_180,"CONTENTS_CURRENT_180"},
  74. {CONTENTS_CURRENT_270,"CONTENTS_CURRENT_270"},
  75. {CONTENTS_CURRENT_UP,"CONTENTS_CURRENT_UP"},
  76. {CONTENTS_CURRENT_DOWN,"CONTENTS_CURRENT_DOWN"},
  77. {CONTENTS_ORIGIN,"CONTENTS_ORIGIN"},
  78. {CONTENTS_MONSTER,"CONTENTS_MONSTER"},
  79. {CONTENTS_DEADMONSTER,"CONTENTS_DEADMONSTER"},
  80. {CONTENTS_DETAIL,"CONTENTS_DETAIL"},
  81. {CONTENTS_Q2TRANSLUCENT,"CONTENTS_TRANSLUCENT"},
  82. {CONTENTS_LADDER,"CONTENTS_LADDER"},
  83. {0, 0}
  84. };
  85. void PrintContents(int contents)
  86. {
  87. int i;
  88. for (i = 0; contentnames[i].value; i++)
  89. {
  90. if (contents & contentnames[i].value)
  91. {
  92. Log_Write("%s,", contentnames[i].name);
  93. } //end if
  94. } //end for
  95. } //end of the function PrintContents
  96. //#endif DEBUG
  97. //===========================================================================
  98. //
  99. // Parameter: -
  100. // Returns: -
  101. // Changes Globals: -
  102. //===========================================================================
  103. void ResetBrushBSP(void)
  104. {
  105. c_nodes = 0;
  106. c_nonvis = 0;
  107. c_active_brushes = 0;
  108. c_solidleafnodes = 0;
  109. c_totalsides = 0;
  110. c_brushmemory = 0;
  111. c_peak_brushmemory = 0;
  112. c_nodememory = 0;
  113. c_peak_totalbspmemory = 0;
  114. } //end of the function ResetBrushBSP
  115. //===========================================================================
  116. //
  117. // Parameter: -
  118. // Returns: -
  119. // Changes Globals: -
  120. //===========================================================================
  121. void FindBrushInTree (node_t *node, int brushnum)
  122. {
  123. bspbrush_t *b;
  124. if (node->planenum == PLANENUM_LEAF)
  125. {
  126. for (b=node->brushlist ; b ; b=b->next)
  127. if (b->original->brushnum == brushnum)
  128. Log_Print ("here\n");
  129. return;
  130. }
  131. FindBrushInTree(node->children[0], brushnum);
  132. FindBrushInTree(node->children[1], brushnum);
  133. } //end of the function FindBrushInTree
  134. //===========================================================================
  135. //
  136. // Parameter: -
  137. // Returns: -
  138. // Changes Globals: -
  139. //===========================================================================
  140. void DrawBrushList (bspbrush_t *brush, node_t *node)
  141. {
  142. int i;
  143. side_t *s;
  144. GLS_BeginScene ();
  145. for ( ; brush ; brush=brush->next)
  146. {
  147. for (i=0 ; i<brush->numsides ; i++)
  148. {
  149. s = &brush->sides[i];
  150. if (!s->winding)
  151. continue;
  152. if (s->texinfo == TEXINFO_NODE)
  153. GLS_Winding (s->winding, 1);
  154. else if (!(s->flags & SFL_VISIBLE))
  155. GLS_Winding (s->winding, 2);
  156. else
  157. GLS_Winding (s->winding, 0);
  158. }
  159. }
  160. GLS_EndScene ();
  161. } //end of the function DrawBrushList
  162. //===========================================================================
  163. //
  164. // Parameter: -
  165. // Returns: -
  166. // Changes Globals: -
  167. //===========================================================================
  168. void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis)
  169. {
  170. int i;
  171. side_t *s;
  172. FILE *f;
  173. qprintf ("writing %s\n", name);
  174. f = SafeOpenWrite (name);
  175. for ( ; brush ; brush=brush->next)
  176. {
  177. for (i=0 ; i<brush->numsides ; i++)
  178. {
  179. s = &brush->sides[i];
  180. if (!s->winding)
  181. continue;
  182. if (onlyvis && !(s->flags & SFL_VISIBLE))
  183. continue;
  184. OutputWinding (brush->sides[i].winding, f);
  185. }
  186. }
  187. fclose (f);
  188. } //end of the function WriteBrushList
  189. //===========================================================================
  190. //
  191. // Parameter: -
  192. // Returns: -
  193. // Changes Globals: -
  194. //===========================================================================
  195. void PrintBrush (bspbrush_t *brush)
  196. {
  197. int i;
  198. printf ("brush: %p\n", brush);
  199. for (i=0;i<brush->numsides ; i++)
  200. {
  201. pw(brush->sides[i].winding);
  202. printf ("\n");
  203. } //end for
  204. } //end of the function PrintBrush
  205. //===========================================================================
  206. // Sets the mins/maxs based on the windings
  207. //
  208. // Parameter: -
  209. // Returns: -
  210. // Changes Globals: -
  211. //===========================================================================
  212. void BoundBrush (bspbrush_t *brush)
  213. {
  214. int i, j;
  215. winding_t *w;
  216. ClearBounds (brush->mins, brush->maxs);
  217. for (i=0 ; i<brush->numsides ; i++)
  218. {
  219. w = brush->sides[i].winding;
  220. if (!w)
  221. continue;
  222. for (j=0 ; j<w->numpoints ; j++)
  223. AddPointToBounds (w->p[j], brush->mins, brush->maxs);
  224. }
  225. } //end of the function BoundBrush
  226. //===========================================================================
  227. //
  228. // Parameter: -
  229. // Returns: -
  230. // Changes Globals: -
  231. //===========================================================================
  232. void CreateBrushWindings (bspbrush_t *brush)
  233. {
  234. int i, j;
  235. winding_t *w;
  236. side_t *side;
  237. plane_t *plane;
  238. for (i=0 ; i<brush->numsides ; i++)
  239. {
  240. side = &brush->sides[i];
  241. plane = &mapplanes[side->planenum];
  242. w = BaseWindingForPlane (plane->normal, plane->dist);
  243. for (j=0 ; j<brush->numsides && w; j++)
  244. {
  245. if (i == j)
  246. continue;
  247. if (brush->sides[j].flags & SFL_BEVEL)
  248. continue;
  249. plane = &mapplanes[brush->sides[j].planenum^1];
  250. ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
  251. }
  252. side->winding = w;
  253. }
  254. BoundBrush (brush);
  255. } //end of the function CreateBrushWindings
  256. //===========================================================================
  257. // Creates a new axial brush
  258. //
  259. // Parameter: -
  260. // Returns: -
  261. // Changes Globals: -
  262. //===========================================================================
  263. bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs)
  264. {
  265. bspbrush_t *b;
  266. int i;
  267. vec3_t normal;
  268. vec_t dist;
  269. b = AllocBrush (6);
  270. b->numsides = 6;
  271. for (i=0 ; i<3 ; i++)
  272. {
  273. VectorClear (normal);
  274. normal[i] = 1;
  275. dist = maxs[i];
  276. b->sides[i].planenum = FindFloatPlane (normal, dist);
  277. normal[i] = -1;
  278. dist = -mins[i];
  279. b->sides[3+i].planenum = FindFloatPlane (normal, dist);
  280. }
  281. CreateBrushWindings (b);
  282. return b;
  283. } //end of the function BrushFromBounds
  284. //===========================================================================
  285. //
  286. // Parameter: -
  287. // Returns: -
  288. // Changes Globals: -
  289. //===========================================================================
  290. int BrushOutOfBounds(bspbrush_t *brush, vec3_t mins, vec3_t maxs, float epsilon)
  291. {
  292. int i, j, n;
  293. winding_t *w;
  294. side_t *side;
  295. for (i = 0; i < brush->numsides; i++)
  296. {
  297. side = &brush->sides[i];
  298. w = side->winding;
  299. for (j = 0; j < w->numpoints; j++)
  300. {
  301. for (n = 0; n < 3; n++)
  302. {
  303. if (w->p[j][n] < (mins[n] + epsilon) || w->p[j][n] > (maxs[n] - epsilon)) return true;
  304. } //end for
  305. } //end for
  306. } //end for
  307. return false;
  308. } //end of the function BrushOutOfBounds
  309. //===========================================================================
  310. //
  311. // Parameter: -
  312. // Returns: -
  313. // Changes Globals: -
  314. //===========================================================================
  315. vec_t BrushVolume (bspbrush_t *brush)
  316. {
  317. int i;
  318. winding_t *w;
  319. vec3_t corner;
  320. vec_t d, area, volume;
  321. plane_t *plane;
  322. if (!brush) return 0;
  323. // grab the first valid point as the corner
  324. w = NULL;
  325. for (i = 0; i < brush->numsides; i++)
  326. {
  327. w = brush->sides[i].winding;
  328. if (w) break;
  329. } //end for
  330. if (!w) return 0;
  331. VectorCopy (w->p[0], corner);
  332. // make tetrahedrons to all other faces
  333. volume = 0;
  334. for ( ; i < brush->numsides; i++)
  335. {
  336. w = brush->sides[i].winding;
  337. if (!w) continue;
  338. plane = &mapplanes[brush->sides[i].planenum];
  339. d = -(DotProduct (corner, plane->normal) - plane->dist);
  340. area = WindingArea(w);
  341. volume += d * area;
  342. } //end for
  343. volume /= 3;
  344. return volume;
  345. } //end of the function BrushVolume
  346. //===========================================================================
  347. //
  348. // Parameter: -
  349. // Returns: -
  350. // Changes Globals: -
  351. //===========================================================================
  352. int CountBrushList (bspbrush_t *brushes)
  353. {
  354. int c;
  355. c = 0;
  356. for ( ; brushes; brushes = brushes->next) c++;
  357. return c;
  358. } //end of the function CountBrushList
  359. //===========================================================================
  360. //
  361. // Parameter: -
  362. // Returns: -
  363. // Changes Globals: -
  364. //===========================================================================
  365. node_t *AllocNode (void)
  366. {
  367. node_t *node;
  368. node = GetMemory(sizeof(*node));
  369. memset (node, 0, sizeof(*node));
  370. if (numthreads == 1)
  371. {
  372. c_nodememory += MemorySize(node);
  373. } //end if
  374. return node;
  375. } //end of the function AllocNode
  376. //===========================================================================
  377. //
  378. // Parameter: -
  379. // Returns: -
  380. // Changes Globals: -
  381. //===========================================================================
  382. bspbrush_t *AllocBrush (int numsides)
  383. {
  384. bspbrush_t *bb;
  385. int c;
  386. c = (int)&(((bspbrush_t *)0)->sides[numsides]);
  387. bb = GetMemory(c);
  388. memset (bb, 0, c);
  389. if (numthreads == 1)
  390. {
  391. c_active_brushes++;
  392. c_brushmemory += MemorySize(bb);
  393. if (c_brushmemory > c_peak_brushmemory)
  394. c_peak_brushmemory = c_brushmemory;
  395. } //end if
  396. return bb;
  397. } //end of the function AllocBrush
  398. //===========================================================================
  399. //
  400. // Parameter: -
  401. // Returns: -
  402. // Changes Globals: -
  403. //===========================================================================
  404. void FreeBrush (bspbrush_t *brushes)
  405. {
  406. int i;
  407. for (i=0 ; i<brushes->numsides ; i++)
  408. if (brushes->sides[i].winding)
  409. FreeWinding(brushes->sides[i].winding);
  410. if (numthreads == 1)
  411. {
  412. c_active_brushes--;
  413. c_brushmemory -= MemorySize(brushes);
  414. if (c_brushmemory < 0) c_brushmemory = 0;
  415. } //end if
  416. FreeMemory(brushes);
  417. } //end of the function FreeBrush
  418. //===========================================================================
  419. //
  420. // Parameter: -
  421. // Returns: -
  422. // Changes Globals: -
  423. //===========================================================================
  424. void FreeBrushList (bspbrush_t *brushes)
  425. {
  426. bspbrush_t *next;
  427. for ( ; brushes; brushes = next)
  428. {
  429. next = brushes->next;
  430. FreeBrush(brushes);
  431. } //end for
  432. } //end of the function FreeBrushList
  433. //===========================================================================
  434. // Duplicates the brush, the sides, and the windings
  435. //
  436. // Parameter: -
  437. // Returns: -
  438. // Changes Globals: -
  439. //===========================================================================
  440. bspbrush_t *CopyBrush (bspbrush_t *brush)
  441. {
  442. bspbrush_t *newbrush;
  443. int size;
  444. int i;
  445. size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);
  446. newbrush = AllocBrush (brush->numsides);
  447. memcpy (newbrush, brush, size);
  448. for (i=0 ; i<brush->numsides ; i++)
  449. {
  450. if (brush->sides[i].winding)
  451. newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
  452. }
  453. return newbrush;
  454. } //end of the function CopyBrush
  455. //===========================================================================
  456. //
  457. // Parameter: -
  458. // Returns: -
  459. // Changes Globals: -
  460. //===========================================================================
  461. node_t *PointInLeaf (node_t *node, vec3_t point)
  462. {
  463. vec_t d;
  464. plane_t *plane;
  465. while (node->planenum != PLANENUM_LEAF)
  466. {
  467. plane = &mapplanes[node->planenum];
  468. d = DotProduct (point, plane->normal) - plane->dist;
  469. if (d > 0)
  470. node = node->children[0];
  471. else
  472. node = node->children[1];
  473. }
  474. return node;
  475. } //end of the function PointInLeaf
  476. //===========================================================================
  477. // Returns PSIDE_FRONT, PSIDE_BACK, or PSIDE_BOTH
  478. //
  479. // Parameter: -
  480. // Returns: -
  481. // Changes Globals: -
  482. //===========================================================================
  483. #if 0
  484. int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane)
  485. {
  486. int side;
  487. int i;
  488. vec3_t corners[2];
  489. vec_t dist1, dist2;
  490. // axial planes are easy
  491. if (plane->type < 3)
  492. {
  493. side = 0;
  494. if (maxs[plane->type] > plane->dist+PLANESIDE_EPSILON)
  495. side |= PSIDE_FRONT;
  496. if (mins[plane->type] < plane->dist-PLANESIDE_EPSILON)
  497. side |= PSIDE_BACK;
  498. return side;
  499. }
  500. // create the proper leading and trailing verts for the box
  501. for (i=0 ; i<3 ; i++)
  502. {
  503. if (plane->normal[i] < 0)
  504. {
  505. corners[0][i] = mins[i];
  506. corners[1][i] = maxs[i];
  507. }
  508. else
  509. {
  510. corners[1][i] = mins[i];
  511. corners[0][i] = maxs[i];
  512. }
  513. }
  514. dist1 = DotProduct (plane->normal, corners[0]) - plane->dist;
  515. dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
  516. side = 0;
  517. if (dist1 >= PLANESIDE_EPSILON)
  518. side = PSIDE_FRONT;
  519. if (dist2 < PLANESIDE_EPSILON)
  520. side |= PSIDE_BACK;
  521. return side;
  522. }
  523. #else
  524. int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, plane_t *p)
  525. {
  526. float dist1, dist2;
  527. int sides;
  528. // axial planes are easy
  529. if (p->type < 3)
  530. {
  531. sides = 0;
  532. if (emaxs[p->type] > p->dist+PLANESIDE_EPSILON) sides |= PSIDE_FRONT;
  533. if (emins[p->type] < p->dist-PLANESIDE_EPSILON) sides |= PSIDE_BACK;
  534. return sides;
  535. } //end if
  536. // general case
  537. switch (p->signbits)
  538. {
  539. case 0:
  540. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  541. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  542. break;
  543. case 1:
  544. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  545. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  546. break;
  547. case 2:
  548. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  549. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  550. break;
  551. case 3:
  552. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  553. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  554. break;
  555. case 4:
  556. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  557. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  558. break;
  559. case 5:
  560. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  561. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  562. break;
  563. case 6:
  564. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  565. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  566. break;
  567. case 7:
  568. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  569. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  570. break;
  571. default:
  572. dist1 = dist2 = 0; // shut up compiler
  573. // assert( 0 );
  574. break;
  575. }
  576. sides = 0;
  577. if (dist1 - p->dist >= PLANESIDE_EPSILON) sides = PSIDE_FRONT;
  578. if (dist2 - p->dist < PLANESIDE_EPSILON) sides |= PSIDE_BACK;
  579. // assert(sides != 0);
  580. return sides;
  581. }
  582. #endif
  583. //===========================================================================
  584. //
  585. // Parameter: -
  586. // Returns: -
  587. // Changes Globals: -
  588. //===========================================================================
  589. int QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
  590. {
  591. int i, num;
  592. plane_t *plane;
  593. int s;
  594. *numsplits = 0;
  595. plane = &mapplanes[planenum];
  596. #ifdef ME
  597. //fast axial cases
  598. if (plane->type < 3)
  599. {
  600. if (plane->dist + PLANESIDE_EPSILON < brush->mins[plane->type])
  601. return PSIDE_FRONT;
  602. if (plane->dist - PLANESIDE_EPSILON > brush->maxs[plane->type])
  603. return PSIDE_BACK;
  604. } //end if
  605. #endif //ME*/
  606. // if the brush actually uses the planenum,
  607. // we can tell the side for sure
  608. for (i = 0; i < brush->numsides; i++)
  609. {
  610. num = brush->sides[i].planenum;
  611. if (num >= MAX_MAPFILE_PLANES)
  612. Error ("bad planenum");
  613. if (num == planenum)
  614. return PSIDE_BACK|PSIDE_FACING;
  615. if (num == (planenum ^ 1) )
  616. return PSIDE_FRONT|PSIDE_FACING;
  617. }
  618. // box on plane side
  619. s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
  620. // if both sides, count the visible faces split
  621. if (s == PSIDE_BOTH)
  622. {
  623. *numsplits += 3;
  624. }
  625. return s;
  626. } //end of the function QuickTestBrushToPlanenum
  627. //===========================================================================
  628. //
  629. // Parameter: -
  630. // Returns: -
  631. // Changes Globals: -
  632. //===========================================================================
  633. int TestBrushToPlanenum (bspbrush_t *brush, int planenum,
  634. int *numsplits, qboolean *hintsplit, int *epsilonbrush)
  635. {
  636. int i, j, num;
  637. plane_t *plane;
  638. int s = 0;
  639. winding_t *w;
  640. vec_t d, d_front, d_back;
  641. int front, back;
  642. int type;
  643. float dist;
  644. *numsplits = 0;
  645. *hintsplit = false;
  646. plane = &mapplanes[planenum];
  647. #ifdef ME
  648. //fast axial cases
  649. type = plane->type;
  650. if (type < 3)
  651. {
  652. dist = plane->dist;
  653. if (dist + PLANESIDE_EPSILON < brush->mins[type]) return PSIDE_FRONT;
  654. if (dist - PLANESIDE_EPSILON > brush->maxs[type]) return PSIDE_BACK;
  655. if (brush->mins[type] < dist - PLANESIDE_EPSILON &&
  656. brush->maxs[type] > dist + PLANESIDE_EPSILON) s = PSIDE_BOTH;
  657. } //end if
  658. if (s != PSIDE_BOTH)
  659. #endif //ME
  660. {
  661. // if the brush actually uses the planenum,
  662. // we can tell the side for sure
  663. for (i = 0; i < brush->numsides; i++)
  664. {
  665. num = brush->sides[i].planenum;
  666. if (num >= MAX_MAPFILE_PLANES) Error ("bad planenum");
  667. if (num == planenum)
  668. {
  669. //we don't need to test this side plane again
  670. brush->sides[i].flags |= SFL_TESTED;
  671. return PSIDE_BACK|PSIDE_FACING;
  672. } //end if
  673. if (num == (planenum ^ 1) )
  674. {
  675. //we don't need to test this side plane again
  676. brush->sides[i].flags |= SFL_TESTED;
  677. return PSIDE_FRONT|PSIDE_FACING;
  678. } //end if
  679. } //end for
  680. // box on plane side
  681. s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
  682. if (s != PSIDE_BOTH) return s;
  683. } //end if
  684. // if both sides, count the visible faces split
  685. d_front = d_back = 0;
  686. for (i = 0; i < brush->numsides; i++)
  687. {
  688. if (brush->sides[i].texinfo == TEXINFO_NODE)
  689. continue; // on node, don't worry about splits
  690. if (!(brush->sides[i].flags & SFL_VISIBLE))
  691. continue; // we don't care about non-visible
  692. w = brush->sides[i].winding;
  693. if (!w) continue;
  694. front = back = 0;
  695. for (j = 0; j < w->numpoints; j++)
  696. {
  697. d = DotProduct(w->p[j], plane->normal) - plane->dist;
  698. if (d > d_front) d_front = d;
  699. if (d < d_back) d_back = d;
  700. if (d > 0.1) // PLANESIDE_EPSILON)
  701. front = 1;
  702. if (d < -0.1) // PLANESIDE_EPSILON)
  703. back = 1;
  704. } //end for
  705. if (front && back)
  706. {
  707. if ( !(brush->sides[i].surf & SURF_SKIP) )
  708. {
  709. (*numsplits)++;
  710. if (brush->sides[i].surf & SURF_HINT)
  711. {
  712. *hintsplit = true;
  713. } //end if
  714. } //end if
  715. } //end if
  716. } //end for
  717. if ( (d_front > 0.0 && d_front < 1.0)
  718. || (d_back < 0.0 && d_back > -1.0) )
  719. (*epsilonbrush)++;
  720. #if 0
  721. if (*numsplits == 0)
  722. { // didn't really need to be split
  723. if (front) s = PSIDE_FRONT;
  724. else if (back) s = PSIDE_BACK;
  725. else s = 0;
  726. }
  727. #endif
  728. return s;
  729. } //end of the function TestBrushToPlanenum
  730. //===========================================================================
  731. // Returns true if the winding would be crunched out of
  732. // existance by the vertex snapping.
  733. //
  734. // Parameter: -
  735. // Returns: -
  736. // Changes Globals: -
  737. //===========================================================================
  738. #define EDGE_LENGTH 0.2
  739. qboolean WindingIsTiny (winding_t *w)
  740. {
  741. #if 0
  742. if (WindingArea (w) < 1)
  743. return true;
  744. return false;
  745. #else
  746. int i, j;
  747. vec_t len;
  748. vec3_t delta;
  749. int edges;
  750. edges = 0;
  751. for (i=0 ; i<w->numpoints ; i++)
  752. {
  753. j = i == w->numpoints - 1 ? 0 : i+1;
  754. VectorSubtract (w->p[j], w->p[i], delta);
  755. len = VectorLength (delta);
  756. if (len > EDGE_LENGTH)
  757. {
  758. if (++edges == 3)
  759. return false;
  760. }
  761. }
  762. return true;
  763. #endif
  764. } //end of the function WindingIsTiny
  765. //===========================================================================
  766. // Returns true if the winding still has one of the points
  767. // from basewinding for plane
  768. //
  769. // Parameter: -
  770. // Returns: -
  771. // Changes Globals: -
  772. //===========================================================================
  773. qboolean WindingIsHuge (winding_t *w)
  774. {
  775. int i, j;
  776. for (i=0 ; i<w->numpoints ; i++)
  777. {
  778. for (j=0 ; j<3 ; j++)
  779. if (w->p[i][j] < -BOGUS_RANGE+1 || w->p[i][j] > BOGUS_RANGE-1)
  780. return true;
  781. }
  782. return false;
  783. } //end of the function WindingIsHuge
  784. //===========================================================================
  785. // creates a leaf out of the given nodes with the given brushes
  786. //
  787. // Parameter: -
  788. // Returns: -
  789. // Changes Globals: -
  790. //===========================================================================
  791. void LeafNode(node_t *node, bspbrush_t *brushes)
  792. {
  793. bspbrush_t *b;
  794. int i;
  795. node->side = NULL;
  796. node->planenum = PLANENUM_LEAF;
  797. node->contents = 0;
  798. for (b = brushes; b; b = b->next)
  799. {
  800. // if the brush is solid and all of its sides are on nodes,
  801. // it eats everything
  802. if (b->original->contents & CONTENTS_SOLID)
  803. {
  804. for (i=0 ; i<b->numsides ; i++)
  805. if (b->sides[i].texinfo != TEXINFO_NODE)
  806. break;
  807. if (i == b->numsides)
  808. {
  809. node->contents = CONTENTS_SOLID;
  810. break;
  811. } //end if
  812. } //end if
  813. node->contents |= b->original->contents;
  814. } //end for
  815. if (create_aas)
  816. {
  817. node->expansionbboxes = 0;
  818. node->contents = 0;
  819. for (b = brushes; b; b = b->next)
  820. {
  821. node->expansionbboxes |= b->original->expansionbbox;
  822. node->contents |= b->original->contents;
  823. if (b->original->modelnum)
  824. node->modelnum = b->original->modelnum;
  825. } //end for
  826. if (node->contents & CONTENTS_SOLID)
  827. {
  828. if (node->expansionbboxes != cfg.allpresencetypes)
  829. {
  830. node->contents &= ~CONTENTS_SOLID;
  831. } //end if
  832. } //end if
  833. } //end if
  834. node->brushlist = brushes;
  835. } //end of the function LeafNode
  836. //===========================================================================
  837. //
  838. // Parameter: -
  839. // Returns: -
  840. // Changes Globals: -
  841. //===========================================================================
  842. void CheckPlaneAgainstParents (int pnum, node_t *node)
  843. {
  844. node_t *p;
  845. for (p = node->parent; p; p = p->parent)
  846. {
  847. if (p->planenum == pnum) Error("Tried parent");
  848. } //end for
  849. } //end of the function CheckPlaneAgainstParants
  850. //===========================================================================
  851. //
  852. // Parameter: -
  853. // Returns: -
  854. // Changes Globals: -
  855. //===========================================================================
  856. qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
  857. {
  858. bspbrush_t *front, *back;
  859. qboolean good;
  860. SplitBrush (node->volume, pnum, &front, &back);
  861. good = (front && back);
  862. if (front) FreeBrush (front);
  863. if (back) FreeBrush (back);
  864. return good;
  865. } //end of the function CheckPlaneAgaintsVolume
  866. //===========================================================================
  867. // Using a hueristic, choses one of the sides out of the brushlist
  868. // to partition the brushes with.
  869. // Returns NULL if there are no valid planes to split with..
  870. //
  871. // Parameter: -
  872. // Returns: -
  873. // Changes Globals: -
  874. //===========================================================================
  875. side_t *SelectSplitSide (bspbrush_t *brushes, node_t *node)
  876. {
  877. int value, bestvalue;
  878. bspbrush_t *brush, *test;
  879. side_t *side, *bestside;
  880. int i, pass, numpasses;
  881. int pnum;
  882. int s;
  883. int front, back, both, facing, splits;
  884. int bsplits;
  885. int bestsplits;
  886. int epsilonbrush;
  887. qboolean hintsplit = false;
  888. bestside = NULL;
  889. bestvalue = -99999;
  890. bestsplits = 0;
  891. // the search order goes: visible-structural, visible-detail,
  892. // nonvisible-structural, nonvisible-detail.
  893. // If any valid plane is available in a pass, no further
  894. // passes will be tried.
  895. numpasses = 2;
  896. for (pass = 0; pass < numpasses; pass++)
  897. {
  898. for (brush = brushes; brush; brush = brush->next)
  899. {
  900. // only check detail the second pass
  901. // if ( (pass & 1) && !(brush->original->contents & CONTENTS_DETAIL) )
  902. // continue;
  903. // if ( !(pass & 1) && (brush->original->contents & CONTENTS_DETAIL) )
  904. // continue;
  905. for (i = 0; i < brush->numsides; i++)
  906. {
  907. side = brush->sides + i;
  908. // if (side->flags & SFL_BEVEL)
  909. // continue; // never use a bevel as a spliter
  910. if (!side->winding)
  911. continue; // nothing visible, so it can't split
  912. if (side->texinfo == TEXINFO_NODE)
  913. continue; // allready a node splitter
  914. if (side->flags & SFL_TESTED)
  915. continue; // we allready have metrics for this plane
  916. // if (side->surf & SURF_SKIP)
  917. // continue; // skip surfaces are never chosen
  918. // if (!(side->flags & SFL_VISIBLE) && (pass < 2))
  919. // continue; // only check visible faces on first pass
  920. if ((side->flags & SFL_CURVE) && (pass < 1))
  921. continue; // only check curves the second pass
  922. pnum = side->planenum;
  923. pnum &= ~1; // allways use positive facing plane
  924. CheckPlaneAgainstParents (pnum, node);
  925. if (!CheckPlaneAgainstVolume (pnum, node))
  926. continue; // would produce a tiny volume
  927. front = 0;
  928. back = 0;
  929. both = 0;
  930. facing = 0;
  931. splits = 0;
  932. epsilonbrush = 0;
  933. //inner loop: optimize
  934. for (test = brushes; test; test = test->next)
  935. {
  936. s = TestBrushToPlanenum (test, pnum, &bsplits, &hintsplit, &epsilonbrush);
  937. splits += bsplits;
  938. // if (bsplits && (s&PSIDE_FACING) )
  939. // Error ("PSIDE_FACING with splits");
  940. test->testside = s;
  941. //
  942. if (s & PSIDE_FACING) facing++;
  943. if (s & PSIDE_FRONT) front++;
  944. if (s & PSIDE_BACK) back++;
  945. if (s == PSIDE_BOTH) both++;
  946. } //end for
  947. // give a value estimate for using this plane
  948. value = 5*facing - 5*splits - abs(front-back);
  949. // value = -5*splits;
  950. // value = 5*facing - 5*splits;
  951. if (mapplanes[pnum].type < 3)
  952. value+=5; // axial is better
  953. value -= epsilonbrush * 1000; // avoid!
  954. // never split a hint side except with another hint
  955. if (hintsplit && !(side->surf & SURF_HINT) )
  956. value = -9999999;
  957. // save off the side test so we don't need
  958. // to recalculate it when we actually seperate
  959. // the brushes
  960. if (value > bestvalue)
  961. {
  962. bestvalue = value;
  963. bestside = side;
  964. bestsplits = splits;
  965. for (test = brushes; test ; test = test->next)
  966. test->side = test->testside;
  967. } //end if
  968. } //end for
  969. } //end for (brush = brushes;
  970. // if we found a good plane, don't bother trying any
  971. // other passes
  972. if (bestside)
  973. {
  974. if (pass > 1)
  975. {
  976. if (numthreads == 1) c_nonvis++;
  977. }
  978. if (pass > 0) node->detail_seperator = true; // not needed for vis
  979. break;
  980. } //end if
  981. } //end for (pass = 0;
  982. //
  983. // clear all the tested flags we set
  984. //
  985. for (brush = brushes ; brush ; brush=brush->next)
  986. {
  987. for (i = 0; i < brush->numsides; i++)
  988. {
  989. brush->sides[i].flags &= ~SFL_TESTED;
  990. } //end for
  991. } //end for
  992. return bestside;
  993. } //end of the function SelectSplitSide
  994. //===========================================================================
  995. //
  996. // Parameter: -
  997. // Returns: -
  998. // Changes Globals: -
  999. //===========================================================================
  1000. int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane)
  1001. {
  1002. int i, j;
  1003. winding_t *w;
  1004. vec_t d, max;
  1005. int side;
  1006. max = 0;
  1007. side = PSIDE_FRONT;
  1008. for (i=0 ; i<brush->numsides ; i++)
  1009. {
  1010. w = brush->sides[i].winding;
  1011. if (!w)
  1012. continue;
  1013. for (j=0 ; j<w->numpoints ; j++)
  1014. {
  1015. d = DotProduct (w->p[j], plane->normal) - plane->dist;
  1016. if (d > max)
  1017. {
  1018. max = d;
  1019. side = PSIDE_FRONT;
  1020. }
  1021. if (-d > max)
  1022. {
  1023. max = -d;
  1024. side = PSIDE_BACK;
  1025. }
  1026. }
  1027. }
  1028. return side;
  1029. } //end of the function BrushMostlyOnSide
  1030. //===========================================================================
  1031. // Generates two new brushes, leaving the original
  1032. // unchanged
  1033. //
  1034. // Parameter: -
  1035. // Returns: -
  1036. // Changes Globals: -
  1037. //===========================================================================
  1038. void SplitBrush (bspbrush_t *brush, int planenum,
  1039. bspbrush_t **front, bspbrush_t **back)
  1040. {
  1041. bspbrush_t *b[2];
  1042. int i, j;
  1043. winding_t *w, *cw[2], *midwinding;
  1044. plane_t *plane, *plane2;
  1045. side_t *s, *cs;
  1046. float d, d_front, d_back;
  1047. *front = *back = NULL;
  1048. plane = &mapplanes[planenum];
  1049. // check all points
  1050. d_front = d_back = 0;
  1051. for (i=0 ; i<brush->numsides ; i++)
  1052. {
  1053. w = brush->sides[i].winding;
  1054. if (!w)
  1055. continue;
  1056. for (j=0 ; j<w->numpoints ; j++)
  1057. {
  1058. d = DotProduct (w->p[j], plane->normal) - plane->dist;
  1059. if (d > 0 && d > d_front)
  1060. d_front = d;
  1061. if (d < 0 && d < d_back)
  1062. d_back = d;
  1063. }
  1064. }
  1065. if (d_front < 0.2) // PLANESIDE_EPSILON)
  1066. { // only on back
  1067. *back = CopyBrush (brush);
  1068. return;
  1069. }
  1070. if (d_back > -0.2) // PLANESIDE_EPSILON)
  1071. { // only on front
  1072. *front = CopyBrush (brush);
  1073. return;
  1074. }
  1075. // create a new winding from the split plane
  1076. w = BaseWindingForPlane (plane->normal, plane->dist);
  1077. for (i=0 ; i<brush->numsides && w ; i++)
  1078. {
  1079. plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
  1080. ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
  1081. }
  1082. if (!w || WindingIsTiny(w))
  1083. { // the brush isn't really split
  1084. int side;
  1085. side = BrushMostlyOnSide (brush, plane);
  1086. if (side == PSIDE_FRONT)
  1087. *front = CopyBrush (brush);
  1088. if (side == PSIDE_BACK)
  1089. *back = CopyBrush (brush);
  1090. //free a possible winding
  1091. if (w) FreeWinding(w);
  1092. return;
  1093. }
  1094. if (WindingIsHuge (w))
  1095. {
  1096. Log_Write("WARNING: huge winding\n");
  1097. }
  1098. midwinding = w;
  1099. // split it for real
  1100. for (i=0 ; i<2 ; i++)
  1101. {
  1102. b[i] = AllocBrush (brush->numsides+1);
  1103. b[i]->original = brush->original;
  1104. }
  1105. // split all the current windings
  1106. for (i=0 ; i<brush->numsides ; i++)
  1107. {
  1108. s = &brush->sides[i];
  1109. w = s->winding;
  1110. if (!w)
  1111. continue;
  1112. ClipWindingEpsilon (w, plane->normal, plane->dist,
  1113. 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
  1114. for (j=0 ; j<2 ; j++)
  1115. {
  1116. if (!cw[j])
  1117. continue;
  1118. #if 0
  1119. if (WindingIsTiny (cw[j]))
  1120. {
  1121. FreeWinding (cw[j]);
  1122. continue;
  1123. }
  1124. #endif
  1125. cs = &b[j]->sides[b[j]->numsides];
  1126. b[j]->numsides++;
  1127. *cs = *s;
  1128. // cs->planenum = s->planenum;
  1129. // cs->texinfo = s->texinfo;
  1130. // cs->original = s->original;
  1131. cs->winding = cw[j];
  1132. cs->flags &= ~SFL_TESTED;
  1133. }
  1134. }
  1135. // see if we have valid polygons on both sides
  1136. for (i=0 ; i<2 ; i++)
  1137. {
  1138. BoundBrush (b[i]);
  1139. for (j=0 ; j<3 ; j++)
  1140. {
  1141. if (b[i]->mins[j] < -MAX_MAP_BOUNDS || b[i]->maxs[j] > MAX_MAP_BOUNDS)
  1142. {
  1143. Log_Write("bogus brush after clip");
  1144. break;
  1145. }
  1146. }
  1147. if (b[i]->numsides < 3 || j < 3)
  1148. {
  1149. FreeBrush (b[i]);
  1150. b[i] = NULL;
  1151. }
  1152. }
  1153. if ( !(b[0] && b[1]) )
  1154. {
  1155. if (!b[0] && !b[1])
  1156. Log_Write("split removed brush\r\n");
  1157. else
  1158. Log_Write("split not on both sides\r\n");
  1159. if (b[0])
  1160. {
  1161. FreeBrush (b[0]);
  1162. *front = CopyBrush (brush);
  1163. }
  1164. if (b[1])
  1165. {
  1166. FreeBrush (b[1]);
  1167. *back = CopyBrush (brush);
  1168. }
  1169. return;
  1170. }
  1171. // add the midwinding to both sides
  1172. for (i=0 ; i<2 ; i++)
  1173. {
  1174. cs = &b[i]->sides[b[i]->numsides];
  1175. b[i]->numsides++;
  1176. cs->planenum = planenum^i^1;
  1177. cs->texinfo = TEXINFO_NODE; //never use these sides as splitters
  1178. cs->flags &= ~SFL_VISIBLE;
  1179. cs->flags &= ~SFL_TESTED;
  1180. if (i==0)
  1181. cs->winding = CopyWinding (midwinding);
  1182. else
  1183. cs->winding = midwinding;
  1184. }
  1185. {
  1186. vec_t v1;
  1187. int i;
  1188. for (i = 0; i < 2; i++)
  1189. {
  1190. v1 = BrushVolume (b[i]);
  1191. if (v1 < 1.0)
  1192. {
  1193. FreeBrush(b[i]);
  1194. b[i] = NULL;
  1195. //Log_Write("tiny volume after clip");
  1196. }
  1197. }
  1198. if (!b[0] && !b[1])
  1199. {
  1200. Log_Write("two tiny brushes\r\n");
  1201. } //end if
  1202. }
  1203. *front = b[0];
  1204. *back = b[1];
  1205. } //end of the function SplitBrush
  1206. //===========================================================================
  1207. //
  1208. // Parameter: -
  1209. // Returns: -
  1210. // Changes Globals: -
  1211. //===========================================================================
  1212. void SplitBrushList (bspbrush_t *brushes,
  1213. node_t *node, bspbrush_t **front, bspbrush_t **back)
  1214. {
  1215. bspbrush_t *brush, *newbrush, *newbrush2;
  1216. side_t *side;
  1217. int sides;
  1218. int i;
  1219. *front = *back = NULL;
  1220. for (brush = brushes; brush; brush = brush->next)
  1221. {
  1222. sides = brush->side;
  1223. if (sides == PSIDE_BOTH)
  1224. { // split into two brushes
  1225. SplitBrush (brush, node->planenum, &newbrush, &newbrush2);
  1226. if (newbrush)
  1227. {
  1228. newbrush->next = *front;
  1229. *front = newbrush;
  1230. } //end if
  1231. if (newbrush2)
  1232. {
  1233. newbrush2->next = *back;
  1234. *back = newbrush2;
  1235. } //end if
  1236. continue;
  1237. } //end if
  1238. newbrush = CopyBrush (brush);
  1239. // if the planenum is actualy a part of the brush
  1240. // find the plane and flag it as used so it won't be tried
  1241. // as a splitter again
  1242. if (sides & PSIDE_FACING)
  1243. {
  1244. for (i=0 ; i<newbrush->numsides ; i++)
  1245. {
  1246. side = newbrush->sides + i;
  1247. if ( (side->planenum& ~1) == node->planenum)
  1248. side->texinfo = TEXINFO_NODE;
  1249. } //end for
  1250. } //end if
  1251. if (sides & PSIDE_FRONT)
  1252. {
  1253. newbrush->next = *front;
  1254. *front = newbrush;
  1255. continue;
  1256. } //end if
  1257. if (sides & PSIDE_BACK)
  1258. {
  1259. newbrush->next = *back;
  1260. *back = newbrush;
  1261. continue;
  1262. } //end if
  1263. } //end for
  1264. } //end of the function SplitBrushList
  1265. //===========================================================================
  1266. //
  1267. // Parameter: -
  1268. // Returns: -
  1269. // Changes Globals: -
  1270. //===========================================================================
  1271. void CheckBrushLists(bspbrush_t *brushlist1, bspbrush_t *brushlist2)
  1272. {
  1273. bspbrush_t *brush1, *brush2;
  1274. for (brush1 = brushlist1; brush1; brush1 = brush1->next)
  1275. {
  1276. for (brush2 = brushlist2; brush2; brush2 = brush2->next)
  1277. {
  1278. assert(brush1 != brush2);
  1279. } //end for
  1280. } //end for
  1281. } //end of the function CheckBrushLists
  1282. //===========================================================================
  1283. //
  1284. // Parameter: -
  1285. // Returns: -
  1286. // Changes Globals: -
  1287. //===========================================================================
  1288. int numrecurse = 0;
  1289. node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
  1290. {
  1291. node_t *newnode;
  1292. side_t *bestside;
  1293. int i, totalmem;
  1294. bspbrush_t *children[2];
  1295. qprintf("\r%6d", numrecurse);
  1296. numrecurse++;
  1297. if (numthreads == 1)
  1298. {
  1299. totalmem = WindingMemory() + c_nodememory + c_brushmemory;
  1300. if (totalmem > c_peak_totalbspmemory)
  1301. c_peak_totalbspmemory = totalmem;
  1302. c_nodes++;
  1303. } //endif
  1304. if (drawflag)
  1305. DrawBrushList(brushes, node);
  1306. // find the best plane to use as a splitter
  1307. bestside = SelectSplitSide (brushes, node);
  1308. if (!bestside)
  1309. {
  1310. // leaf node
  1311. node->side = NULL;
  1312. node->planenum = -1;
  1313. LeafNode(node, brushes);
  1314. if (node->contents & CONTENTS_SOLID) c_solidleafnodes++;
  1315. if (create_aas)
  1316. {
  1317. //free up memory!!!
  1318. FreeBrushList(node->brushlist);
  1319. node->brushlist = NULL;
  1320. //free the node volume brush
  1321. if (node->volume)
  1322. {
  1323. FreeBrush(node->volume);
  1324. node->volume = NULL;
  1325. } //end if
  1326. } //end if
  1327. return node;
  1328. } //end if
  1329. // this is a splitplane node
  1330. node->side = bestside;
  1331. node->planenum = bestside->planenum & ~1; // always use front facing
  1332. //split the brush list in two for both children
  1333. SplitBrushList (brushes, node, &children[0], &children[1]);
  1334. //free the old brush list
  1335. FreeBrushList (brushes);
  1336. // allocate children before recursing
  1337. for (i = 0; i < 2; i++)
  1338. {
  1339. newnode = AllocNode ();
  1340. newnode->parent = node;
  1341. node->children[i] = newnode;
  1342. } //end for
  1343. //split the volume brush of the node for the children
  1344. SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
  1345. &node->children[1]->volume);
  1346. if (create_aas)
  1347. {
  1348. //free the volume brush
  1349. if (node->volume)
  1350. {
  1351. FreeBrush(node->volume);
  1352. node->volume = NULL;
  1353. } //end if
  1354. } //end if
  1355. // recursively process children
  1356. for (i = 0; i < 2; i++)
  1357. {
  1358. node->children[i] = BuildTree_r(node->children[i], children[i]);
  1359. } //end for
  1360. return node;
  1361. } //end of the function BuildTree_r
  1362. //===========================================================================
  1363. //
  1364. // Parameter: -
  1365. // Returns: -
  1366. // Changes Globals: -
  1367. //===========================================================================
  1368. node_t *firstnode; //first node in the list
  1369. node_t *lastnode; //last node in the list
  1370. int nodelistsize; //number of nodes in the list
  1371. int use_nodequeue = 0; //use nodequeue, otherwise a node stack is used
  1372. int numwaiting = 0;
  1373. void (*AddNodeToList)(node_t *node);
  1374. //add the node to the front of the node list
  1375. //(effectively using a node stack)
  1376. void AddNodeToStack(node_t *node)
  1377. {
  1378. ThreadLock();
  1379. node->next = firstnode;
  1380. firstnode = node;
  1381. if (!lastnode) lastnode = node;
  1382. nodelistsize++;
  1383. ThreadUnlock();
  1384. //
  1385. ThreadSemaphoreIncrease(1);
  1386. } //end of the function AddNodeToStack
  1387. //add the node to the end of the node list
  1388. //(effectively using a node queue)
  1389. void AddNodeToQueue(node_t *node)
  1390. {
  1391. ThreadLock();
  1392. node->next = NULL;
  1393. if (lastnode) lastnode->next = node;
  1394. else firstnode = node;
  1395. lastnode = node;
  1396. nodelistsize++;
  1397. ThreadUnlock();
  1398. //
  1399. ThreadSemaphoreIncrease(1);
  1400. } //end of the function AddNodeToQueue
  1401. //get the first node from the front of the node list
  1402. node_t *NextNodeFromList(void)
  1403. {
  1404. node_t *node;
  1405. ThreadLock();
  1406. numwaiting++;
  1407. if (!firstnode)
  1408. {
  1409. if (numwaiting >= GetNumThreads()) ThreadSemaphoreIncrease(GetNumThreads());
  1410. } //end if
  1411. ThreadUnlock();
  1412. ThreadSemaphoreWait();
  1413. ThreadLock();
  1414. numwaiting--;
  1415. node = firstnode;
  1416. if (firstnode)
  1417. {
  1418. firstnode = firstnode->next;
  1419. nodelistsize--;
  1420. } //end if
  1421. if (!firstnode) lastnode = NULL;
  1422. ThreadUnlock();
  1423. return node;
  1424. } //end of the function NextNodeFromList
  1425. //returns the size of the node list
  1426. int NodeListSize(void)
  1427. {
  1428. int size;
  1429. ThreadLock();
  1430. size = nodelistsize;
  1431. ThreadUnlock();
  1432. return size;
  1433. } //end of the function NodeListSize
  1434. //
  1435. void IncreaseNodeCounter(void)
  1436. {
  1437. ThreadLock();
  1438. //if (verbose) printf("\r%6d", numrecurse++);
  1439. qprintf("\r%6d", numrecurse++);
  1440. //qprintf("\r%6d %d, %5d ", numrecurse++, GetNumThreads(), nodelistsize);
  1441. ThreadUnlock();
  1442. } //end of the function IncreaseNodeCounter
  1443. //thread function, gets nodes from the nodelist and processes them
  1444. void BuildTreeThread(int threadid)
  1445. {
  1446. node_t *newnode, *node;
  1447. side_t *bestside;
  1448. int i, totalmem;
  1449. bspbrush_t *brushes;
  1450. for (node = NextNodeFromList(); node; )
  1451. {
  1452. //if the nodelist isn't empty try to add another thread
  1453. //if (NodeListSize() > 10) AddThread(BuildTreeThread);
  1454. //display the number of nodes processed so far
  1455. if (numthreads == 1)
  1456. IncreaseNodeCounter();
  1457. brushes = node->brushlist;
  1458. if (numthreads == 1)
  1459. {
  1460. totalmem = WindingMemory() + c_nodememory + c_brushmemory;
  1461. if (totalmem > c_peak_totalbspmemory)
  1462. {
  1463. c_peak_totalbspmemory = totalmem;
  1464. } //end if
  1465. c_nodes++;
  1466. } //endif
  1467. if (drawflag)
  1468. {
  1469. DrawBrushList(brushes, node);
  1470. } //end if
  1471. if (cancelconversion)
  1472. {
  1473. bestside = NULL;
  1474. } //end if
  1475. else
  1476. {
  1477. // find the best plane to use as a splitter
  1478. bestside = SelectSplitSide(brushes, node);
  1479. } //end else
  1480. //if there's no split side left
  1481. if (!bestside)
  1482. {
  1483. //create a leaf out of the node
  1484. LeafNode(node, brushes);
  1485. if (node->contents & CONTENTS_SOLID) c_solidleafnodes++;
  1486. if (create_aas)
  1487. {
  1488. //free up memory!!!
  1489. FreeBrushList(node->brushlist);
  1490. node->brushlist = NULL;
  1491. } //end if
  1492. //free the node volume brush (it is not used anymore)
  1493. if (node->volume)
  1494. {
  1495. FreeBrush(node->volume);
  1496. node->volume = NULL;
  1497. } //end if
  1498. node = NextNodeFromList();
  1499. continue;
  1500. } //end if
  1501. // this is a splitplane node
  1502. node->side = bestside;
  1503. node->planenum = bestside->planenum & ~1; //always use front facing
  1504. //allocate children
  1505. for (i = 0; i < 2; i++)
  1506. {
  1507. newnode = AllocNode();
  1508. newnode->parent = node;
  1509. node->children[i] = newnode;
  1510. } //end for
  1511. //split the brush list in two for both children
  1512. SplitBrushList(brushes, node, &node->children[0]->brushlist, &node->children[1]->brushlist);
  1513. CheckBrushLists(node->children[0]->brushlist, node->children[1]->brushlist);
  1514. //free the old brush list
  1515. FreeBrushList(brushes);
  1516. node->brushlist = NULL;
  1517. //split the volume brush of the node for the children
  1518. SplitBrush(node->volume, node->planenum, &node->children[0]->volume,
  1519. &node->children[1]->volume);
  1520. if (!node->children[0]->volume || !node->children[1]->volume)
  1521. {
  1522. Error("child without volume brush");
  1523. } //end if
  1524. //free the volume brush
  1525. if (node->volume)
  1526. {
  1527. FreeBrush(node->volume);
  1528. node->volume = NULL;
  1529. } //end if
  1530. //add both children to the node list
  1531. //AddNodeToList(node->children[0]);
  1532. AddNodeToList(node->children[1]);
  1533. node = node->children[0];
  1534. } //end while
  1535. RemoveThread(threadid);
  1536. } //end of the function BuildTreeThread
  1537. //===========================================================================
  1538. // build the bsp tree using a node list
  1539. //
  1540. // Parameter: -
  1541. // Returns: -
  1542. // Changes Globals: -
  1543. //===========================================================================
  1544. void BuildTree(tree_t *tree)
  1545. {
  1546. int i;
  1547. firstnode = NULL;
  1548. lastnode = NULL;
  1549. //use a node queue or node stack
  1550. if (use_nodequeue) AddNodeToList = AddNodeToQueue;
  1551. else AddNodeToList = AddNodeToStack;
  1552. //setup thread locking
  1553. ThreadSetupLock();
  1554. ThreadSetupSemaphore();
  1555. numwaiting = 0;
  1556. //
  1557. Log_Print("%6d threads max\n", numthreads);
  1558. if (use_nodequeue) Log_Print("breadth first bsp building\n");
  1559. else Log_Print("depth first bsp building\n");
  1560. qprintf("%6d splits", 0);
  1561. //add the first node to the list
  1562. AddNodeToList(tree->headnode);
  1563. //start the threads
  1564. for (i = 0; i < numthreads; i++)
  1565. AddThread(BuildTreeThread);
  1566. //wait for all added threads to be finished
  1567. WaitForAllThreadsFinished();
  1568. //shutdown the thread locking
  1569. ThreadShutdownLock();
  1570. ThreadShutdownSemaphore();
  1571. } //end of the function BuildTree
  1572. //===========================================================================
  1573. // The incoming brush list will be freed before exiting
  1574. //
  1575. // Parameter: -
  1576. // Returns: -
  1577. // Changes Globals: -
  1578. //===========================================================================
  1579. tree_t *BrushBSP(bspbrush_t *brushlist, vec3_t mins, vec3_t maxs)
  1580. {
  1581. int i, c_faces, c_nonvisfaces, c_brushes;
  1582. bspbrush_t *b;
  1583. node_t *node;
  1584. tree_t *tree;
  1585. vec_t volume;
  1586. // vec3_t point;
  1587. Log_Print("-------- Brush BSP ---------\n");
  1588. tree = Tree_Alloc();
  1589. c_faces = 0;
  1590. c_nonvisfaces = 0;
  1591. c_brushes = 0;
  1592. c_totalsides = 0;
  1593. for (b = brushlist; b; b = b->next)
  1594. {
  1595. c_brushes++;
  1596. volume = BrushVolume(b);
  1597. if (volume < microvolume)
  1598. {
  1599. Log_Print("WARNING: entity %i, brush %i: microbrush\n",
  1600. b->original->entitynum, b->original->brushnum);
  1601. } //end if
  1602. for (i=0 ; i<b->numsides ; i++)
  1603. {
  1604. if (b->sides[i].flags & SFL_BEVEL)
  1605. continue;
  1606. if (!b->sides[i].winding)
  1607. continue;
  1608. if (b->sides[i].texinfo == TEXINFO_NODE)
  1609. continue;
  1610. if (b->sides[i].flags & SFL_VISIBLE)
  1611. {
  1612. c_faces++;
  1613. } //end if
  1614. else
  1615. {
  1616. c_nonvisfaces++;
  1617. //if (create_aas) b->sides[i].texinfo = TEXINFO_NODE;
  1618. } //end if
  1619. } //end for
  1620. c_totalsides += b->numsides;
  1621. AddPointToBounds (b->mins, tree->mins, tree->maxs);
  1622. AddPointToBounds (b->maxs, tree->mins, tree->maxs);
  1623. } //end for
  1624. Log_Print("%6i brushes\n", c_brushes);
  1625. Log_Print("%6i visible faces\n", c_faces);
  1626. Log_Print("%6i nonvisible faces\n", c_nonvisfaces);
  1627. Log_Print("%6i total sides\n", c_totalsides);
  1628. c_active_brushes = c_brushes;
  1629. c_nodememory = 0;
  1630. c_brushmemory = 0;
  1631. c_peak_brushmemory = 0;
  1632. c_nodes = 0;
  1633. c_nonvis = 0;
  1634. node = AllocNode ();
  1635. //volume of first node (head node)
  1636. node->volume = BrushFromBounds (mins, maxs);
  1637. //
  1638. tree->headnode = node;
  1639. //just get some statistics and the mins/maxs of the node
  1640. numrecurse = 0;
  1641. // qprintf("%6d splits", numrecurse);
  1642. tree->headnode->brushlist = brushlist;
  1643. BuildTree(tree);
  1644. //build the bsp tree with the start node from the brushlist
  1645. // node = BuildTree_r(node, brushlist);
  1646. //if the conversion is cancelled
  1647. if (cancelconversion) return tree;
  1648. qprintf("\n");
  1649. Log_Write("%6d splits\r\n", numrecurse);
  1650. // Log_Print("%6i visible nodes\n", c_nodes/2 - c_nonvis);
  1651. // Log_Print("%6i nonvis nodes\n", c_nonvis);
  1652. // Log_Print("%6i leaves\n", (c_nodes+1)/2);
  1653. // Log_Print("%6i solid leaf nodes\n", c_solidleafnodes);
  1654. // Log_Print("%6i active brushes\n", c_active_brushes);
  1655. if (numthreads == 1)
  1656. {
  1657. // Log_Print("%6i KB of node memory\n", c_nodememory >> 10);
  1658. // Log_Print("%6i KB of brush memory\n", c_brushmemory >> 10);
  1659. // Log_Print("%6i KB of peak brush memory\n", c_peak_brushmemory >> 10);
  1660. // Log_Print("%6i KB of winding memory\n", WindingMemory() >> 10);
  1661. // Log_Print("%6i KB of peak winding memory\n", WindingPeakMemory() >> 10);
  1662. Log_Print("%6i KB of peak total bsp memory\n", c_peak_totalbspmemory >> 10);
  1663. } //end if
  1664. /*
  1665. point[0] = 1485;
  1666. point[1] = 956.125;
  1667. point[2] = 352.125;
  1668. node = PointInLeaf(tree->headnode, point);
  1669. if (node->planenum != PLANENUM_LEAF)
  1670. {
  1671. Log_Print("node not a leaf\n");
  1672. } //end if
  1673. Log_Print("at %f %f %f:\n", point[0], point[1], point[2]);
  1674. PrintContents(node->contents);
  1675. Log_Print("node->expansionbboxes = %d\n", node->expansionbboxes);
  1676. //*/
  1677. return tree;
  1678. } //end of the function BrushBSP