Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1469 lines
27 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "vbsp.h"
  9. int c_nodes;
  10. int c_nonvis;
  11. int c_active_brushes;
  12. // if a brush just barely pokes onto the other side,
  13. // let it slide by without chopping
  14. #define PLANESIDE_EPSILON 0.001
  15. //0.1
  16. void FindBrushInTree (node_t *node, int brushnum)
  17. {
  18. bspbrush_t *b;
  19. if (node->planenum == PLANENUM_LEAF)
  20. {
  21. for (b=node->brushlist ; b ; b=b->next)
  22. if (b->original->brushnum == brushnum)
  23. Msg("here\n");
  24. return;
  25. }
  26. FindBrushInTree (node->children[0], brushnum);
  27. FindBrushInTree (node->children[1], brushnum);
  28. }
  29. //==================================================
  30. /*
  31. ================
  32. DrawBrushList
  33. ================
  34. */
  35. void DrawBrushList (bspbrush_t *brush, node_t *node)
  36. {
  37. int i;
  38. side_t *s;
  39. GLS_BeginScene ();
  40. for ( ; brush ; brush=brush->next)
  41. {
  42. for (i=0 ; i<brush->numsides ; i++)
  43. {
  44. s = &brush->sides[i];
  45. if (!s->winding)
  46. continue;
  47. if (s->texinfo == TEXINFO_NODE)
  48. GLS_Winding (s->winding, 1);
  49. else if (!s->visible)
  50. GLS_Winding (s->winding, 2);
  51. else
  52. GLS_Winding (s->winding, 0);
  53. }
  54. }
  55. GLS_EndScene ();
  56. }
  57. /*
  58. ================
  59. WriteBrushList
  60. ================
  61. */
  62. void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis)
  63. {
  64. int i;
  65. side_t *s;
  66. qprintf ("writing %s\n", name);
  67. FileHandle_t f = g_pFileSystem->Open(name, "w");
  68. for ( ; brush ; brush=brush->next)
  69. {
  70. for (i=0 ; i<brush->numsides ; i++)
  71. {
  72. s = &brush->sides[i];
  73. if (!s->winding)
  74. continue;
  75. if (onlyvis && !s->visible)
  76. continue;
  77. OutputWinding (brush->sides[i].winding, f);
  78. }
  79. }
  80. g_pFileSystem->Close (f);
  81. }
  82. void PrintBrush (bspbrush_t *brush)
  83. {
  84. int i;
  85. Msg("brush: %p\n", brush);
  86. for (i=0;i<brush->numsides ; i++)
  87. {
  88. pw(brush->sides[i].winding);
  89. Msg("\n");
  90. }
  91. }
  92. /*
  93. ==================
  94. BoundBrush
  95. Sets the mins/maxs based on the windings
  96. ==================
  97. */
  98. void BoundBrush (bspbrush_t *brush)
  99. {
  100. int i, j;
  101. winding_t *w;
  102. ClearBounds (brush->mins, brush->maxs);
  103. for (i=0 ; i<brush->numsides ; i++)
  104. {
  105. w = brush->sides[i].winding;
  106. if (!w)
  107. continue;
  108. for (j=0 ; j<w->numpoints ; j++)
  109. AddPointToBounds (w->p[j], brush->mins, brush->maxs);
  110. }
  111. }
  112. Vector PointInsideBrush( bspbrush_t *brush )
  113. {
  114. Vector insidePoint = vec3_origin;
  115. bool bInside = false;
  116. for ( int k = 0; k < 4 && !bInside; k++ )
  117. {
  118. bInside = true;
  119. for (int i = 0; i < brush->numsides; i++)
  120. {
  121. side_t *side = &brush->sides[i];
  122. plane_t *plane = &g_MainMap->mapplanes[side->planenum];
  123. float d = DotProduct( plane->normal, insidePoint ) - plane->dist;
  124. if ( d < 0 )
  125. {
  126. bInside = false;
  127. insidePoint -= d * plane->normal;
  128. }
  129. }
  130. }
  131. return insidePoint;
  132. }
  133. /*
  134. ==================
  135. CreateBrushWindings
  136. ==================
  137. */
  138. void CreateBrushWindings (bspbrush_t *brush)
  139. {
  140. int i, j;
  141. winding_t *w;
  142. side_t *side;
  143. plane_t *plane;
  144. // translate the CSG problem to improve precision
  145. Vector insidePoint = PointInsideBrush( brush );
  146. Vector offset = -insidePoint;
  147. for (i=0 ; i<brush->numsides ; i++)
  148. {
  149. side = &brush->sides[i];
  150. plane = &g_MainMap->mapplanes[side->planenum];
  151. w = BaseWindingForPlane (plane->normal, plane->dist + DotProduct(plane->normal, offset));
  152. for (j=0 ; j<brush->numsides && w; j++)
  153. {
  154. if (i == j)
  155. continue;
  156. if (brush->sides[j].bevel)
  157. continue;
  158. plane = &g_MainMap->mapplanes[brush->sides[j].planenum^1];
  159. ChopWindingInPlace (&w, plane->normal, plane->dist + DotProduct(plane->normal, offset), 0); //CLIP_EPSILON);
  160. }
  161. TranslateWinding( w, -offset );
  162. side->winding = w;
  163. }
  164. BoundBrush (brush);
  165. }
  166. /*
  167. ==================
  168. BrushFromBounds
  169. Creates a new axial brush
  170. ==================
  171. */
  172. bspbrush_t *BrushFromBounds (Vector& mins, Vector& maxs)
  173. {
  174. bspbrush_t *b;
  175. int i;
  176. Vector normal;
  177. vec_t dist;
  178. b = AllocBrush (6);
  179. b->numsides = 6;
  180. for (i=0 ; i<3 ; i++)
  181. {
  182. VectorClear (normal);
  183. normal[i] = 1;
  184. dist = maxs[i];
  185. b->sides[i].planenum = g_MainMap->FindFloatPlane (normal, dist);
  186. normal[i] = -1;
  187. dist = -mins[i];
  188. b->sides[3+i].planenum = g_MainMap->FindFloatPlane (normal, dist);
  189. }
  190. CreateBrushWindings (b);
  191. return b;
  192. }
  193. /*
  194. ==================
  195. BrushVolume
  196. ==================
  197. */
  198. vec_t BrushVolume (bspbrush_t *brush)
  199. {
  200. int i;
  201. winding_t *w;
  202. Vector corner;
  203. vec_t d, area, volume;
  204. plane_t *plane;
  205. if (!brush)
  206. return 0;
  207. // grab the first valid point as the corner
  208. w = NULL;
  209. for (i=0 ; i<brush->numsides ; i++)
  210. {
  211. w = brush->sides[i].winding;
  212. if (w)
  213. break;
  214. }
  215. if (!w)
  216. return 0;
  217. VectorCopy (w->p[0], corner);
  218. // make tetrahedrons to all other faces
  219. volume = 0;
  220. for ( ; i<brush->numsides ; i++)
  221. {
  222. w = brush->sides[i].winding;
  223. if (!w)
  224. continue;
  225. plane = &g_MainMap->mapplanes[brush->sides[i].planenum];
  226. d = -(DotProduct (corner, plane->normal) - plane->dist);
  227. area = WindingArea (w);
  228. volume += d*area;
  229. }
  230. volume /= 3;
  231. return volume;
  232. }
  233. /*
  234. ================
  235. CountBrushList
  236. ================
  237. */
  238. int CountBrushList (bspbrush_t *brushes)
  239. {
  240. int c;
  241. c = 0;
  242. for ( ; brushes ; brushes = brushes->next)
  243. c++;
  244. return c;
  245. }
  246. /*
  247. ================
  248. AllocTree
  249. ================
  250. */
  251. tree_t *AllocTree (void)
  252. {
  253. tree_t *tree;
  254. tree = (tree_t*)malloc(sizeof(*tree));
  255. memset (tree, 0, sizeof(*tree));
  256. ClearBounds (tree->mins, tree->maxs);
  257. return tree;
  258. }
  259. /*
  260. ================
  261. AllocNode
  262. ================
  263. */
  264. node_t *AllocNode (void)
  265. {
  266. static int s_NodeCount = 0;
  267. node_t *node;
  268. node = (node_t*)malloc(sizeof(*node));
  269. memset (node, 0, sizeof(*node));
  270. node->id = s_NodeCount;
  271. node->diskId = -1;
  272. s_NodeCount++;
  273. return node;
  274. }
  275. /*
  276. ================
  277. AllocBrush
  278. ================
  279. */
  280. bspbrush_t *AllocBrush (int numsides)
  281. {
  282. static int s_BrushId = 0;
  283. bspbrush_t *bb;
  284. int c;
  285. c = (int)&(((bspbrush_t *)0)->sides[numsides]);
  286. bb = (bspbrush_t*)malloc(c);
  287. memset (bb, 0, c);
  288. bb->id = s_BrushId++;
  289. if (numthreads == 1)
  290. c_active_brushes++;
  291. return bb;
  292. }
  293. /*
  294. ================
  295. FreeBrush
  296. ================
  297. */
  298. void FreeBrush (bspbrush_t *brushes)
  299. {
  300. int i;
  301. for (i=0 ; i<brushes->numsides ; i++)
  302. if (brushes->sides[i].winding)
  303. FreeWinding(brushes->sides[i].winding);
  304. free (brushes);
  305. if (numthreads == 1)
  306. c_active_brushes--;
  307. }
  308. /*
  309. ================
  310. FreeBrushList
  311. ================
  312. */
  313. void FreeBrushList (bspbrush_t *brushes)
  314. {
  315. bspbrush_t *next;
  316. for ( ; brushes ; brushes = next)
  317. {
  318. next = brushes->next;
  319. FreeBrush (brushes);
  320. }
  321. }
  322. /*
  323. ==================
  324. CopyBrush
  325. Duplicates the brush, the sides, and the windings
  326. ==================
  327. */
  328. bspbrush_t *CopyBrush (bspbrush_t *brush)
  329. {
  330. bspbrush_t *newbrush;
  331. int size;
  332. int i;
  333. size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);
  334. newbrush = AllocBrush (brush->numsides);
  335. memcpy (newbrush, brush, size);
  336. for (i=0 ; i<brush->numsides ; i++)
  337. {
  338. if (brush->sides[i].winding)
  339. newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
  340. }
  341. return newbrush;
  342. }
  343. /*
  344. ==================
  345. PointInLeaf
  346. ==================
  347. */
  348. node_t *PointInLeaf (node_t *node, Vector& point)
  349. {
  350. vec_t d;
  351. plane_t *plane;
  352. while (node->planenum != PLANENUM_LEAF)
  353. {
  354. plane = &g_MainMap->mapplanes[node->planenum];
  355. if (plane->type < 3)
  356. {
  357. d = point[plane->type] - plane->dist;
  358. }
  359. else
  360. {
  361. d = DotProduct (point, plane->normal) - plane->dist;
  362. }
  363. if (d >= 0)
  364. node = node->children[0];
  365. else
  366. node = node->children[1];
  367. }
  368. return node;
  369. }
  370. //========================================================
  371. /*
  372. ==============
  373. BoxOnPlaneSide
  374. Returns PSIDE_FRONT, PSIDE_BACK, or PSIDE_BOTH
  375. ==============
  376. */
  377. int BrushBspBoxOnPlaneSide (const Vector& mins, const Vector& maxs, dplane_t *plane)
  378. {
  379. int side;
  380. int i;
  381. Vector corners[2];
  382. vec_t dist1, dist2;
  383. // axial planes are easy
  384. if (plane->type < 3)
  385. {
  386. side = 0;
  387. if (maxs[plane->type] > plane->dist+PLANESIDE_EPSILON)
  388. side |= PSIDE_FRONT;
  389. if (mins[plane->type] < plane->dist-PLANESIDE_EPSILON)
  390. side |= PSIDE_BACK;
  391. return side;
  392. }
  393. // create the proper leading and trailing verts for the box
  394. for (i=0 ; i<3 ; i++)
  395. {
  396. if (plane->normal[i] < 0)
  397. {
  398. corners[0][i] = mins[i];
  399. corners[1][i] = maxs[i];
  400. }
  401. else
  402. {
  403. corners[1][i] = mins[i];
  404. corners[0][i] = maxs[i];
  405. }
  406. }
  407. dist1 = DotProduct (plane->normal, corners[0]) - plane->dist;
  408. dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
  409. side = 0;
  410. if (dist1 >= PLANESIDE_EPSILON)
  411. side = PSIDE_FRONT;
  412. if (dist2 < PLANESIDE_EPSILON)
  413. side |= PSIDE_BACK;
  414. return side;
  415. }
  416. /*
  417. ============
  418. QuickTestBrushToPlanenum
  419. ============
  420. */
  421. int QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
  422. {
  423. int i, num;
  424. plane_t *plane;
  425. int s;
  426. *numsplits = 0;
  427. // if the brush actually uses the planenum,
  428. // we can tell the side for sure
  429. for (i=0 ; i<brush->numsides ; i++)
  430. {
  431. num = brush->sides[i].planenum;
  432. if (num >= 0x10000)
  433. Error ("bad planenum");
  434. if (num == planenum)
  435. return PSIDE_BACK|PSIDE_FACING;
  436. if (num == (planenum ^ 1) )
  437. return PSIDE_FRONT|PSIDE_FACING;
  438. }
  439. // box on plane side
  440. plane = &g_MainMap->mapplanes[planenum];
  441. s = BrushBspBoxOnPlaneSide (brush->mins, brush->maxs, plane);
  442. // if both sides, count the visible faces split
  443. if (s == PSIDE_BOTH)
  444. {
  445. *numsplits += 3;
  446. }
  447. return s;
  448. }
  449. /*
  450. ============
  451. TestBrushToPlanenum
  452. ============
  453. */
  454. int TestBrushToPlanenum (bspbrush_t *brush, int planenum,
  455. int *numsplits, qboolean *hintsplit, int *epsilonbrush)
  456. {
  457. int i, j, num;
  458. plane_t *plane;
  459. int s;
  460. winding_t *w;
  461. vec_t d, d_front, d_back;
  462. int front, back;
  463. *numsplits = 0;
  464. *hintsplit = false;
  465. // if the brush actually uses the planenum,
  466. // we can tell the side for sure
  467. for (i=0 ; i<brush->numsides ; i++)
  468. {
  469. num = brush->sides[i].planenum;
  470. if (num >= 0x10000)
  471. Error ("bad planenum");
  472. if (num == planenum)
  473. return PSIDE_BACK|PSIDE_FACING;
  474. if (num == (planenum ^ 1) )
  475. return PSIDE_FRONT|PSIDE_FACING;
  476. }
  477. // box on plane side
  478. plane = &g_MainMap->mapplanes[planenum];
  479. s = BrushBspBoxOnPlaneSide (brush->mins, brush->maxs, plane);
  480. if (s != PSIDE_BOTH)
  481. return s;
  482. // if both sides, count the visible faces split
  483. d_front = d_back = 0;
  484. for (i=0 ; i<brush->numsides ; i++)
  485. {
  486. if (brush->sides[i].texinfo == TEXINFO_NODE)
  487. continue; // on node, don't worry about splits
  488. if (!brush->sides[i].visible)
  489. continue; // we don't care about non-visible
  490. w = brush->sides[i].winding;
  491. if (!w)
  492. continue;
  493. front = back = 0;
  494. for (j=0 ; j<w->numpoints; j++)
  495. {
  496. d = DotProduct (w->p[j], plane->normal) - plane->dist;
  497. if (d > d_front)
  498. d_front = d;
  499. if (d < d_back)
  500. d_back = d;
  501. if (d > 0.1) // PLANESIDE_EPSILON)
  502. front = 1;
  503. if (d < -0.1) // PLANESIDE_EPSILON)
  504. back = 1;
  505. }
  506. if (front && back)
  507. {
  508. if ( !(brush->sides[i].surf & SURF_SKIP) )
  509. {
  510. (*numsplits)++;
  511. if (brush->sides[i].surf & SURF_HINT)
  512. *hintsplit = true;
  513. }
  514. }
  515. }
  516. if ( (d_front > 0.0 && d_front < 1.0)
  517. || (d_back < 0.0 && d_back > -1.0) )
  518. (*epsilonbrush)++;
  519. #if 0
  520. if (*numsplits == 0)
  521. { // didn't really need to be split
  522. if (front)
  523. s = PSIDE_FRONT;
  524. else if (back)
  525. s = PSIDE_BACK;
  526. else
  527. s = 0;
  528. }
  529. #endif
  530. return s;
  531. }
  532. //========================================================
  533. /*
  534. ================
  535. WindingIsTiny
  536. Returns true if the winding would be crunched out of
  537. existance by the vertex snapping.
  538. ================
  539. */
  540. #define EDGE_LENGTH 0.2
  541. qboolean WindingIsTiny (winding_t *w)
  542. {
  543. int i, j;
  544. vec_t len;
  545. Vector delta;
  546. int edges;
  547. edges = 0;
  548. for (i=0 ; i<w->numpoints ; i++)
  549. {
  550. j = i == w->numpoints - 1 ? 0 : i+1;
  551. VectorSubtract (w->p[j], w->p[i], delta);
  552. len = VectorLength (delta);
  553. if (len > EDGE_LENGTH)
  554. {
  555. if (++edges == 3)
  556. return false;
  557. }
  558. }
  559. return true;
  560. }
  561. // UNDONE: JAY: This should be a slightly better heuristic - it builds an OBB
  562. // around the winding and tests planar dimensions. NOTE: This can fail when a
  563. // winding normal cannot be constructed (or is degenerate), but that is probably
  564. // desired in this case.
  565. // UNDONE: Test & use this instead.
  566. #if 0
  567. qboolean WindingIsTiny2 (winding_t *w)
  568. {
  569. int i, j;
  570. vec_t len;
  571. Vector delta;
  572. int edges;
  573. vec_t maxLen = 0;
  574. Vector maxEdge = vec3_origin;
  575. edges = 0;
  576. for (i=0 ; i<w->numpoints ; i++)
  577. {
  578. j = i == w->numpoints - 1 ? 0 : i+1;
  579. VectorSubtract (w->p[j], w->p[i], delta);
  580. len = VectorLength (delta);
  581. if (len > maxLen)
  582. {
  583. maxEdge = delta;
  584. maxLen = len;
  585. }
  586. }
  587. Vector normal;
  588. vec_t dist;
  589. WindingPlane (w, normal, &dist); // normal can come back vec3_origin in some cases
  590. VectorNormalize(maxEdge);
  591. Vector cross = CrossProduct(normal, maxEdge);
  592. VectorNormalize(cross);
  593. Vector mins, maxs;
  594. ClearBounds( mins, maxs );
  595. for (i=0 ; i<w->numpoints ; i++)
  596. {
  597. Vector point;
  598. point.x = DotProduct( w->p[i], maxEdge );
  599. point.y = DotProduct( w->p[i], cross );
  600. point.z = DotProduct( w->p[i], normal );
  601. AddPointToBounds( point, mins, maxs );
  602. }
  603. // check to see if the size in the plane is too small in either dimension
  604. Vector size = maxs - mins;
  605. for ( i = 0; i < 2; i++ )
  606. {
  607. if ( size[i] < EDGE_LENGTH )
  608. return true;
  609. }
  610. return false;
  611. }
  612. #endif
  613. /*
  614. ================
  615. WindingIsHuge
  616. Returns true if the winding still has one of the points
  617. from basewinding for plane
  618. ================
  619. */
  620. qboolean WindingIsHuge (winding_t *w)
  621. {
  622. int i, j;
  623. for (i=0 ; i<w->numpoints ; i++)
  624. {
  625. for (j=0 ; j<3 ; j++)
  626. if (w->p[i][j] < MIN_COORD_INTEGER || w->p[i][j] > MAX_COORD_INTEGER)
  627. return true;
  628. }
  629. return false;
  630. }
  631. //============================================================
  632. /*
  633. ================
  634. Leafnode
  635. ================
  636. */
  637. void LeafNode (node_t *node, bspbrush_t *brushes)
  638. {
  639. bspbrush_t *b;
  640. int i;
  641. node->planenum = PLANENUM_LEAF;
  642. node->contents = 0;
  643. for (b=brushes ; b ; b=b->next)
  644. {
  645. // if the brush is solid and all of its sides are on nodes,
  646. // it eats everything
  647. if (b->original->contents & CONTENTS_SOLID)
  648. {
  649. for (i=0 ; i<b->numsides ; i++)
  650. if (b->sides[i].texinfo != TEXINFO_NODE)
  651. break;
  652. if (i == b->numsides)
  653. {
  654. node->contents = CONTENTS_SOLID;
  655. break;
  656. }
  657. }
  658. node->contents |= b->original->contents;
  659. }
  660. node->brushlist = brushes;
  661. }
  662. void RemoveAreaPortalBrushes_R( node_t *node )
  663. {
  664. if( node->planenum == PLANENUM_LEAF )
  665. {
  666. // Remove any CONTENTS_AREAPORTAL brushes we added. We don't want them in the engine
  667. // at runtime but we do want their flags in the leaves.
  668. bspbrush_t **pPrev = &node->brushlist;
  669. for( bspbrush_t *b=node->brushlist; b; b=b->next )
  670. {
  671. if( b->original->contents == CONTENTS_AREAPORTAL )
  672. {
  673. *pPrev = b->next;
  674. }
  675. else
  676. {
  677. pPrev = &b->next;
  678. }
  679. }
  680. }
  681. else
  682. {
  683. RemoveAreaPortalBrushes_R( node->children[0] );
  684. RemoveAreaPortalBrushes_R( node->children[1] );
  685. }
  686. }
  687. //============================================================
  688. void CheckPlaneAgainstParents (int pnum, node_t *node)
  689. {
  690. node_t *p;
  691. for (p=node->parent ; p ; p=p->parent)
  692. {
  693. if (p->planenum == pnum)
  694. Error ("Tried parent");
  695. }
  696. }
  697. qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
  698. {
  699. bspbrush_t *front, *back;
  700. qboolean good;
  701. SplitBrush (node->volume, pnum, &front, &back);
  702. good = (front && back);
  703. if (front)
  704. FreeBrush (front);
  705. if (back)
  706. FreeBrush (back);
  707. return good;
  708. }
  709. /*
  710. ================
  711. SelectSplitSide
  712. Using a hueristic, choses one of the sides out of the brushlist
  713. to partition the brushes with.
  714. Returns NULL if there are no valid planes to split with..
  715. ================
  716. */
  717. side_t *SelectSplitSide (bspbrush_t *brushes, node_t *node)
  718. {
  719. int value, bestvalue;
  720. bspbrush_t *brush, *test;
  721. side_t *side, *bestside;
  722. int i, j, pass, numpasses;
  723. int pnum;
  724. int s;
  725. int front, back, both, facing, splits;
  726. int bsplits;
  727. int bestsplits;
  728. int epsilonbrush;
  729. qboolean hintsplit = false;
  730. bestside = NULL;
  731. bestvalue = -99999;
  732. bestsplits = 0;
  733. // the search order goes: visible-structural, nonvisible-structural
  734. // If any valid plane is available in a pass, no further
  735. // passes will be tried.
  736. numpasses = 2;
  737. for (pass = 0 ; pass < numpasses ; pass++)
  738. {
  739. for (brush = brushes ; brush ; brush=brush->next)
  740. {
  741. for (i=0 ; i<brush->numsides ; i++)
  742. {
  743. side = brush->sides + i;
  744. if (side->bevel)
  745. continue; // never use a bevel as a spliter
  746. if (!side->winding)
  747. continue; // nothing visible, so it can't split
  748. if (side->texinfo == TEXINFO_NODE)
  749. continue; // allready a node splitter
  750. if (side->tested)
  751. continue; // we allready have metrics for this plane
  752. if (side->surf & SURF_SKIP)
  753. continue; // skip surfaces are never chosen
  754. if ( side->visible ^ (pass<1) )
  755. continue; // only check visible faces on first pass
  756. pnum = side->planenum;
  757. pnum &= ~1; // allways use positive facing plane
  758. CheckPlaneAgainstParents (pnum, node);
  759. if (!CheckPlaneAgainstVolume (pnum, node))
  760. continue; // would produce a tiny volume
  761. front = 0;
  762. back = 0;
  763. both = 0;
  764. facing = 0;
  765. splits = 0;
  766. epsilonbrush = 0;
  767. for (test = brushes ; test ; test=test->next)
  768. {
  769. s = TestBrushToPlanenum (test, pnum, &bsplits, &hintsplit, &epsilonbrush);
  770. splits += bsplits;
  771. if (bsplits && (s&PSIDE_FACING) )
  772. Error ("PSIDE_FACING with splits");
  773. test->testside = s;
  774. // if the brush shares this face, don't bother
  775. // testing that facenum as a splitter again
  776. if (s & PSIDE_FACING)
  777. {
  778. facing++;
  779. for (j=0 ; j<test->numsides ; j++)
  780. {
  781. if ( (test->sides[j].planenum&~1) == pnum)
  782. test->sides[j].tested = true;
  783. }
  784. }
  785. if (s & PSIDE_FRONT)
  786. front++;
  787. if (s & PSIDE_BACK)
  788. back++;
  789. if (s == PSIDE_BOTH)
  790. both++;
  791. }
  792. // give a value estimate for using this plane
  793. value = 5*facing - 5*splits - abs(front-back);
  794. // value = -5*splits;
  795. // value = 5*facing - 5*splits;
  796. if (g_MainMap->mapplanes[pnum].type < 3)
  797. value+=5; // axial is better
  798. value -= epsilonbrush*1000; // avoid!
  799. // trans should split last
  800. if ( side->surf & SURF_TRANS )
  801. {
  802. value -= 500;
  803. }
  804. // never split a hint side except with another hint
  805. if (hintsplit && !(side->surf & SURF_HINT) )
  806. value = -9999999;
  807. // water should split first
  808. if (side->contents & (CONTENTS_WATER | CONTENTS_SLIME))
  809. value = 9999999;
  810. // save off the side test so we don't need
  811. // to recalculate it when we actually seperate
  812. // the brushes
  813. if (value > bestvalue)
  814. {
  815. bestvalue = value;
  816. bestside = side;
  817. bestsplits = splits;
  818. for (test = brushes ; test ; test=test->next)
  819. test->side = test->testside;
  820. }
  821. }
  822. }
  823. // if we found a good plane, don't bother trying any
  824. // other passes
  825. if (bestside)
  826. {
  827. if (pass > 0)
  828. {
  829. if (numthreads == 1)
  830. c_nonvis++;
  831. }
  832. break;
  833. }
  834. }
  835. //
  836. // clear all the tested flags we set
  837. //
  838. for (brush = brushes ; brush ; brush=brush->next)
  839. {
  840. for (i=0 ; i<brush->numsides ; i++)
  841. brush->sides[i].tested = false;
  842. }
  843. return bestside;
  844. }
  845. /*
  846. ==================
  847. BrushMostlyOnSide
  848. ==================
  849. */
  850. int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane)
  851. {
  852. int i, j;
  853. winding_t *w;
  854. vec_t d, max;
  855. int side;
  856. max = 0;
  857. side = PSIDE_FRONT;
  858. for (i=0 ; i<brush->numsides ; i++)
  859. {
  860. w = brush->sides[i].winding;
  861. if (!w)
  862. continue;
  863. for (j=0 ; j<w->numpoints ; j++)
  864. {
  865. d = DotProduct (w->p[j], plane->normal) - plane->dist;
  866. if (d > max)
  867. {
  868. max = d;
  869. side = PSIDE_FRONT;
  870. }
  871. if (-d > max)
  872. {
  873. max = -d;
  874. side = PSIDE_BACK;
  875. }
  876. }
  877. }
  878. return side;
  879. }
  880. /*
  881. ================
  882. SplitBrush
  883. Generates two new brushes, leaving the original
  884. unchanged
  885. ================
  886. */
  887. void SplitBrush( bspbrush_t *brush, int planenum, bspbrush_t **front, bspbrush_t **back )
  888. {
  889. bspbrush_t *b[2];
  890. int i, j;
  891. winding_t *w, *cw[2], *midwinding;
  892. plane_t *plane, *plane2;
  893. side_t *s, *cs;
  894. float d, d_front, d_back;
  895. *front = *back = NULL;
  896. plane = &g_MainMap->mapplanes[planenum];
  897. // check all points
  898. d_front = d_back = 0;
  899. for (i=0 ; i<brush->numsides ; i++)
  900. {
  901. w = brush->sides[i].winding;
  902. if (!w)
  903. continue;
  904. for (j=0 ; j<w->numpoints ; j++)
  905. {
  906. d = DotProduct (w->p[j], plane->normal) - plane->dist;
  907. if (d > 0 && d > d_front)
  908. d_front = d;
  909. if (d < 0 && d < d_back)
  910. d_back = d;
  911. }
  912. }
  913. if (d_front < 0.1) // PLANESIDE_EPSILON)
  914. { // only on back
  915. *back = CopyBrush (brush);
  916. return;
  917. }
  918. if (d_back > -0.1) // PLANESIDE_EPSILON)
  919. { // only on front
  920. *front = CopyBrush (brush);
  921. return;
  922. }
  923. // Move the CSG problem so that offset is at the origin
  924. // This gives us much better floating point precision in the clipping operations
  925. Vector offset = -0.5f * (brush->mins + brush->maxs);
  926. // create a new winding from the split plane
  927. w = BaseWindingForPlane (plane->normal, plane->dist + DotProduct(plane->normal,offset));
  928. for (i=0 ; i<brush->numsides && w ; i++)
  929. {
  930. plane2 = &g_MainMap->mapplanes[brush->sides[i].planenum ^ 1];
  931. ChopWindingInPlace (&w, plane2->normal, plane2->dist+DotProduct(plane2->normal,offset), 0); // PLANESIDE_EPSILON);
  932. }
  933. if (!w || WindingIsTiny (w) )
  934. { // the brush isn't really split
  935. int side;
  936. side = BrushMostlyOnSide (brush, plane);
  937. if (side == PSIDE_FRONT)
  938. *front = CopyBrush (brush);
  939. if (side == PSIDE_BACK)
  940. *back = CopyBrush (brush);
  941. return;
  942. }
  943. if (WindingIsHuge (w))
  944. {
  945. qprintf ("WARNING: huge winding\n");
  946. }
  947. TranslateWinding( w, -offset );
  948. midwinding = w;
  949. //
  950. //
  951. // split it for real
  952. //
  953. //
  954. //
  955. // allocate two new brushes referencing the original
  956. //
  957. for( i = 0; i < 2; i++ )
  958. {
  959. b[i] = AllocBrush( brush->numsides + 1 );
  960. b[i]->original = brush->original;
  961. }
  962. //
  963. // split all the current windings
  964. //
  965. for( i = 0; i < brush->numsides; i++ )
  966. {
  967. // get the current side
  968. s = &brush->sides[i];
  969. // get the sides winding
  970. w = s->winding;
  971. if( !w )
  972. continue;
  973. // clip the winding
  974. ClipWindingEpsilon_Offset( w, plane->normal, plane->dist, 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1], offset );
  975. for( j = 0; j < 2; j++ )
  976. {
  977. // does winding exist?
  978. if( !cw[j] )
  979. continue;
  980. #if 0
  981. if (WindingIsTiny (cw[j]))
  982. {
  983. FreeWinding (cw[j]);
  984. continue;
  985. }
  986. #endif
  987. //
  988. // create a clipped "side" with the new winding
  989. //
  990. cs = &b[j]->sides[b[j]->numsides];
  991. b[j]->numsides++;
  992. *cs = *s;
  993. cs->winding = cw[j];
  994. cs->tested = false;
  995. // save the original side information
  996. //cs->original = s->original;
  997. }
  998. }
  999. // see if we have valid polygons on both sides
  1000. for (i=0 ; i<2 ; i++)
  1001. {
  1002. BoundBrush (b[i]);
  1003. for (j=0 ; j<3 ; j++)
  1004. {
  1005. if (b[i]->mins[j] < MIN_COORD_INTEGER || b[i]->maxs[j] > MAX_COORD_INTEGER)
  1006. {
  1007. qprintf ("bogus brush after clip\n");
  1008. break;
  1009. }
  1010. }
  1011. if (b[i]->numsides < 3 || j < 3)
  1012. {
  1013. FreeBrush (b[i]);
  1014. b[i] = NULL;
  1015. }
  1016. }
  1017. if ( !(b[0] && b[1]) )
  1018. {
  1019. if (!b[0] && !b[1])
  1020. qprintf ("split removed brush\n");
  1021. else
  1022. qprintf ("split not on both sides\n");
  1023. if (b[0])
  1024. {
  1025. FreeBrush (b[0]);
  1026. *front = CopyBrush (brush);
  1027. }
  1028. if (b[1])
  1029. {
  1030. FreeBrush (b[1]);
  1031. *back = CopyBrush (brush);
  1032. }
  1033. return;
  1034. }
  1035. // add the midwinding to both sides
  1036. for (i=0 ; i<2 ; i++)
  1037. {
  1038. cs = &b[i]->sides[b[i]->numsides];
  1039. b[i]->numsides++;
  1040. cs->planenum = planenum^i^1;
  1041. cs->texinfo = TEXINFO_NODE;
  1042. // initialize the displacement map index
  1043. cs->pMapDisp = NULL;
  1044. cs->visible = false;
  1045. cs->tested = false;
  1046. if (i==0)
  1047. cs->winding = CopyWinding (midwinding);
  1048. else
  1049. cs->winding = midwinding;
  1050. }
  1051. {
  1052. vec_t v1;
  1053. int i;
  1054. for (i=0 ; i<2 ; i++)
  1055. {
  1056. v1 = BrushVolume (b[i]);
  1057. if (v1 < 1.0)
  1058. {
  1059. FreeBrush (b[i]);
  1060. b[i] = NULL;
  1061. // qprintf ("tiny volume after clip\n");
  1062. }
  1063. }
  1064. }
  1065. *front = b[0];
  1066. *back = b[1];
  1067. }
  1068. /*
  1069. ================
  1070. SplitBrushList
  1071. ================
  1072. */
  1073. void SplitBrushList (bspbrush_t *brushes,
  1074. node_t *node, bspbrush_t **front, bspbrush_t **back)
  1075. {
  1076. bspbrush_t *brush, *newbrush, *newbrush2;
  1077. side_t *side;
  1078. int sides;
  1079. int i;
  1080. *front = *back = NULL;
  1081. for (brush = brushes ; brush ; brush=brush->next)
  1082. {
  1083. sides = brush->side;
  1084. if (sides == PSIDE_BOTH)
  1085. { // split into two brushes
  1086. SplitBrush (brush, node->planenum, &newbrush, &newbrush2);
  1087. if (newbrush)
  1088. {
  1089. newbrush->next = *front;
  1090. *front = newbrush;
  1091. }
  1092. if (newbrush2)
  1093. {
  1094. newbrush2->next = *back;
  1095. *back = newbrush2;
  1096. }
  1097. continue;
  1098. }
  1099. newbrush = CopyBrush (brush);
  1100. // if the planenum is actualy a part of the brush
  1101. // find the plane and flag it as used so it won't be tried
  1102. // as a splitter again
  1103. if (sides & PSIDE_FACING)
  1104. {
  1105. for (i=0 ; i<newbrush->numsides ; i++)
  1106. {
  1107. side = newbrush->sides + i;
  1108. if ( (side->planenum& ~1) == node->planenum)
  1109. side->texinfo = TEXINFO_NODE;
  1110. }
  1111. }
  1112. if (sides & PSIDE_FRONT)
  1113. {
  1114. newbrush->next = *front;
  1115. *front = newbrush;
  1116. continue;
  1117. }
  1118. if (sides & PSIDE_BACK)
  1119. {
  1120. newbrush->next = *back;
  1121. *back = newbrush;
  1122. continue;
  1123. }
  1124. }
  1125. }
  1126. /*
  1127. ================
  1128. BuildTree_r
  1129. ================
  1130. */
  1131. node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
  1132. {
  1133. node_t *newnode;
  1134. side_t *bestside;
  1135. int i;
  1136. bspbrush_t *children[2];
  1137. if (numthreads == 1)
  1138. c_nodes++;
  1139. // find the best plane to use as a splitter
  1140. bestside = SelectSplitSide (brushes, node);
  1141. if (!bestside)
  1142. {
  1143. // leaf node
  1144. node->side = NULL;
  1145. node->planenum = -1;
  1146. LeafNode (node, brushes);
  1147. return node;
  1148. }
  1149. // this is a splitplane node
  1150. node->side = bestside;
  1151. node->planenum = bestside->planenum & ~1; // always use front facing
  1152. SplitBrushList (brushes, node, &children[0], &children[1]);
  1153. FreeBrushList (brushes);
  1154. // allocate children before recursing
  1155. for (i=0 ; i<2 ; i++)
  1156. {
  1157. newnode = AllocNode ();
  1158. newnode->parent = node;
  1159. node->children[i] = newnode;
  1160. }
  1161. SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
  1162. &node->children[1]->volume);
  1163. // recursively process children
  1164. for (i=0 ; i<2 ; i++)
  1165. {
  1166. node->children[i] = BuildTree_r (node->children[i], children[i]);
  1167. }
  1168. return node;
  1169. }
  1170. //===========================================================
  1171. /*
  1172. =================
  1173. BrushBSP
  1174. The incoming list will be freed before exiting
  1175. =================
  1176. */
  1177. tree_t *BrushBSP (bspbrush_t *brushlist, Vector& mins, Vector& maxs)
  1178. {
  1179. node_t *node;
  1180. bspbrush_t *b;
  1181. int c_faces, c_nonvisfaces;
  1182. int c_brushes;
  1183. tree_t *tree;
  1184. int i;
  1185. vec_t volume;
  1186. qprintf ("--- BrushBSP ---\n");
  1187. tree = AllocTree ();
  1188. c_faces = 0;
  1189. c_nonvisfaces = 0;
  1190. c_brushes = 0;
  1191. for (b=brushlist ; b ; b=b->next)
  1192. {
  1193. c_brushes++;
  1194. volume = BrushVolume (b);
  1195. if (volume < microvolume)
  1196. {
  1197. Warning("Brush %i: WARNING, microbrush\n", b->original->id);
  1198. }
  1199. for (i=0 ; i<b->numsides ; i++)
  1200. {
  1201. if (b->sides[i].bevel)
  1202. continue;
  1203. if (!b->sides[i].winding)
  1204. continue;
  1205. if (b->sides[i].texinfo == TEXINFO_NODE)
  1206. continue;
  1207. if (b->sides[i].visible)
  1208. c_faces++;
  1209. else
  1210. c_nonvisfaces++;
  1211. }
  1212. AddPointToBounds (b->mins, tree->mins, tree->maxs);
  1213. AddPointToBounds (b->maxs, tree->mins, tree->maxs);
  1214. }
  1215. qprintf ("%5i brushes\n", c_brushes);
  1216. qprintf ("%5i visible faces\n", c_faces);
  1217. qprintf ("%5i nonvisible faces\n", c_nonvisfaces);
  1218. c_nodes = 0;
  1219. c_nonvis = 0;
  1220. node = AllocNode ();
  1221. node->volume = BrushFromBounds (mins, maxs);
  1222. tree->headnode = node;
  1223. node = BuildTree_r (node, brushlist);
  1224. qprintf ("%5i visible nodes\n", c_nodes/2 - c_nonvis);
  1225. qprintf ("%5i nonvis nodes\n", c_nonvis);
  1226. qprintf ("%5i leafs\n", (c_nodes+1)/2);
  1227. #if 0
  1228. { // debug code
  1229. static node_t *tnode;
  1230. Vector p;
  1231. p[0] = -1469;
  1232. p[1] = -118;
  1233. p[2] = 119;
  1234. tnode = PointInLeaf (tree->headnode, p);
  1235. Msg("contents: %i\n", tnode->contents);
  1236. p[0] = 0;
  1237. }
  1238. #endif
  1239. return tree;
  1240. }