CSG.CPP 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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 "stdafx.h"
  19. #include "qe3.h"
  20. #include "winding.h"
  21. /*
  22. =============
  23. CSG_MakeHollow
  24. =============
  25. */
  26. void Brush_Scale(brush_t* b)
  27. {
  28. for (face_t* f = b->brush_faces ; f ; f=f->next)
  29. {
  30. for (int i=0 ; i<3 ; i++)
  31. {
  32. VectorScale (f->planepts[i], g_qeglobals.d_gridsize, f->planepts[i]);
  33. }
  34. }
  35. }
  36. void CSG_MakeHollow (void)
  37. {
  38. brush_t *b, *front, *back, *next;
  39. face_t *f;
  40. face_t split;
  41. vec3_t move;
  42. int i;
  43. for (b = selected_brushes.next ; b != &selected_brushes ; b=next)
  44. {
  45. next = b->next;
  46. if (b->owner->eclass->fixedsize || b->patchBrush || b->terrainBrush || b->hiddenBrush)
  47. continue;
  48. for (f = b->brush_faces ; f ; f=f->next)
  49. {
  50. split = *f;
  51. VectorScale (f->plane.normal, g_qeglobals.d_gridsize, move);
  52. for (i=0 ; i<3 ; i++)
  53. VectorSubtract (split.planepts[i], move, split.planepts[i]);
  54. Brush_SplitBrushByFace (b, &split, &front, &back);
  55. if (back)
  56. Brush_Free (back);
  57. if (front)
  58. Brush_AddToList (front, &selected_brushes);
  59. }
  60. Brush_Free (b);
  61. }
  62. Sys_UpdateWindows (W_ALL);
  63. }
  64. /*
  65. =============
  66. Brush_Merge
  67. Returns a new brush that is created by merging brush1 and brush2.
  68. May return NULL if brush1 and brush2 do not create a convex brush when merged.
  69. The input brushes brush1 and brush2 stay intact.
  70. if onlyshape is true then the merge is allowed based on the shape only
  71. otherwise the texture/shader references of faces in the same plane have to
  72. be the same as well.
  73. =============
  74. */
  75. brush_t *Brush_Merge(brush_t *brush1, brush_t *brush2, int onlyshape)
  76. {
  77. int i, shared;
  78. brush_t *newbrush;
  79. face_t *face1, *face2, *newface, *f;
  80. // check for bounding box overlapp
  81. for (i = 0; i < 3; i++)
  82. {
  83. if (brush1->mins[i] > brush2->maxs[i] + ON_EPSILON
  84. || brush1->maxs[i] < brush2->mins[i] - ON_EPSILON)
  85. {
  86. // never merge if the brushes overlap
  87. return NULL;
  88. }
  89. }
  90. //
  91. shared = 0;
  92. // check if the new brush would be convex... flipped planes make a brush non-convex
  93. for (face1 = brush1->brush_faces; face1; face1 = face1->next)
  94. {
  95. // don't check the faces of brush 1 and 2 touching each other
  96. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  97. {
  98. if (Plane_Equal(&face1->plane, &face2->plane, true))
  99. {
  100. shared++;
  101. // there may only be ONE shared side
  102. if (shared > 1)
  103. return NULL;
  104. break;
  105. }
  106. }
  107. // if this face plane is shared
  108. if (face2) continue;
  109. //
  110. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  111. {
  112. // don't check the faces of brush 1 and 2 touching each other
  113. for (f = brush1->brush_faces; f; f = f->next)
  114. {
  115. if (Plane_Equal(&face2->plane, &f->plane, true)) break;
  116. }
  117. if (f)
  118. continue;
  119. //
  120. if (Plane_Equal(&face1->plane, &face2->plane, false))
  121. {
  122. //if the texture/shader references should be the same but are not
  123. if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL;
  124. continue;
  125. }
  126. //
  127. if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
  128. face1->plane.normal, face2->plane.normal,
  129. face1->plane.dist, face2->plane.dist))
  130. {
  131. return NULL;
  132. } //end if
  133. } //end for
  134. } //end for
  135. //
  136. newbrush = Brush_Alloc();
  137. //
  138. for (face1 = brush1->brush_faces; face1; face1 = face1->next)
  139. {
  140. // don't add the faces of brush 1 and 2 touching each other
  141. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  142. {
  143. if (Plane_Equal(&face1->plane, &face2->plane, true))
  144. break;
  145. }
  146. if (face2)
  147. continue;
  148. // don't add faces with the same plane twice
  149. for (f = newbrush->brush_faces; f; f = f->next)
  150. {
  151. if (Plane_Equal(&face1->plane, &f->plane, false))
  152. break;
  153. if (Plane_Equal(&face1->plane, &f->plane, true))
  154. break;
  155. }
  156. if (f)
  157. continue;
  158. //
  159. newface = Face_Alloc();
  160. newface->texdef = face1->texdef;
  161. VectorCopy(face1->planepts[0], newface->planepts[0]);
  162. VectorCopy(face1->planepts[1], newface->planepts[1]);
  163. VectorCopy(face1->planepts[2], newface->planepts[2]);
  164. newface->plane = face1->plane;
  165. newface->next = newbrush->brush_faces;
  166. newbrush->brush_faces = newface;
  167. }
  168. //
  169. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  170. {
  171. // don't add the faces of brush 1 and 2 touching each other
  172. for (face1 = brush1->brush_faces; face1; face1 = face1->next)
  173. {
  174. if (Plane_Equal(&face2->plane, &face1->plane, true))
  175. break;
  176. }
  177. if (face1)
  178. continue;
  179. // don't add faces with the same plane twice
  180. for (f = newbrush->brush_faces; f; f = f->next)
  181. {
  182. if (Plane_Equal(&face2->plane, &f->plane, false))
  183. break;
  184. if (Plane_Equal(&face2->plane, &f->plane, true))
  185. break;
  186. }
  187. if (f)
  188. continue;
  189. //
  190. newface = Face_Alloc();
  191. newface->texdef = face2->texdef;
  192. VectorCopy(face2->planepts[0], newface->planepts[0]);
  193. VectorCopy(face2->planepts[1], newface->planepts[1]);
  194. VectorCopy(face2->planepts[2], newface->planepts[2]);
  195. newface->plane = face2->plane;
  196. newface->next = newbrush->brush_faces;
  197. newbrush->brush_faces = newface;
  198. }
  199. // link the new brush to an entity
  200. Entity_LinkBrush (brush1->owner, newbrush);
  201. // build windings for the faces
  202. Brush_BuildWindings( newbrush, false);
  203. return newbrush;
  204. }
  205. /*
  206. =============
  207. Brush_MergeListPairs
  208. Returns a list with merged brushes.
  209. Tries to merge brushes pair wise.
  210. The input list is destroyed.
  211. Input and output should be a single linked list using .next
  212. =============
  213. */
  214. brush_t *Brush_MergeListPairs(brush_t *brushlist, int onlyshape)
  215. {
  216. int nummerges, merged;
  217. brush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
  218. brush_t *lastb2;
  219. if (!brushlist) return NULL;
  220. nummerges = 0;
  221. do
  222. {
  223. for (tail = brushlist; tail; tail = tail->next)
  224. {
  225. if (!tail->next) break;
  226. }
  227. merged = 0;
  228. newbrushlist = NULL;
  229. for (b1 = brushlist; b1; b1 = brushlist)
  230. {
  231. lastb2 = b1;
  232. for (b2 = b1->next; b2; b2 = b2->next)
  233. {
  234. newbrush = Brush_Merge(b1, b2, onlyshape);
  235. if (newbrush)
  236. {
  237. tail->next = newbrush;
  238. lastb2->next = b2->next;
  239. brushlist = brushlist->next;
  240. b1->next = b1->prev = NULL;
  241. b2->next = b2->prev = NULL;
  242. Brush_Free(b1);
  243. Brush_Free(b2);
  244. for (tail = brushlist; tail; tail = tail->next)
  245. {
  246. if (!tail->next) break;
  247. } //end for
  248. merged++;
  249. nummerges++;
  250. break;
  251. }
  252. lastb2 = b2;
  253. }
  254. //if b1 can't be merged with any of the other brushes
  255. if (!b2)
  256. {
  257. brushlist = brushlist->next;
  258. //keep b1
  259. b1->next = newbrushlist;
  260. newbrushlist = b1;
  261. }
  262. }
  263. brushlist = newbrushlist;
  264. } while(merged);
  265. return newbrushlist;
  266. }
  267. /*
  268. =============
  269. Brush_MergeList
  270. Tries to merge all brushes in the list into one new brush.
  271. The input brush list stays intact.
  272. Returns NULL if no merged brush can be created.
  273. To create a new brush the brushes in the list may not overlap and
  274. the outer faces of the brushes together should make a new convex brush.
  275. if onlyshape is true then the merge is allowed based on the shape only
  276. otherwise the texture/shader references of faces in the same plane have to
  277. be the same as well.
  278. =============
  279. */
  280. brush_t *Brush_MergeList(brush_t *brushlist, int onlyshape)
  281. {
  282. brush_t *brush1, *brush2, *brush3, *newbrush;
  283. face_t *face1, *face2, *face3, *newface, *f;
  284. if (!brushlist) return NULL;
  285. for (brush1 = brushlist; brush1; brush1 = brush1->next)
  286. {
  287. // check if the new brush would be convex... flipped planes make a brush concave
  288. for (face1 = brush1->brush_faces; face1; face1 = face1->next)
  289. {
  290. // don't check face1 if it touches another brush
  291. for (brush2 = brushlist; brush2; brush2 = brush2->next)
  292. {
  293. if (brush2 == brush1) continue;
  294. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  295. {
  296. if (Plane_Equal(&face1->plane, &face2->plane, true))
  297. {
  298. break;
  299. }
  300. }
  301. if (face2) break;
  302. }
  303. // if face1 touches another brush
  304. if (brush2) continue;
  305. //
  306. for (brush2 = brush1->next; brush2; brush2 = brush2->next)
  307. {
  308. // don't check the faces of brush 2 touching another brush
  309. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  310. {
  311. for (brush3 = brushlist; brush3; brush3 = brush3->next)
  312. {
  313. if (brush3 == brush2) continue;
  314. for (face3 = brush3->brush_faces; face3; face3 = face3->next)
  315. {
  316. if (Plane_Equal(&face2->plane, &face3->plane, true)) break;
  317. }
  318. if (face3) break;
  319. }
  320. // if face2 touches another brush
  321. if (brush3) continue;
  322. //
  323. if (Plane_Equal(&face1->plane, &face2->plane, false))
  324. {
  325. //if the texture/shader references should be the same but are not
  326. if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL;
  327. continue;
  328. }
  329. //
  330. if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
  331. face1->plane.normal, face2->plane.normal,
  332. face1->plane.dist, face2->plane.dist))
  333. {
  334. return NULL;
  335. }
  336. }
  337. }
  338. }
  339. }
  340. //
  341. newbrush = Brush_Alloc();
  342. //
  343. for (brush1 = brushlist; brush1; brush1 = brush1->next)
  344. {
  345. for (face1 = brush1->brush_faces; face1; face1 = face1->next)
  346. {
  347. // don't add face1 to the new brush if it touches another brush
  348. for (brush2 = brushlist; brush2; brush2 = brush2->next)
  349. {
  350. if (brush2 == brush1) continue;
  351. for (face2 = brush2->brush_faces; face2; face2 = face2->next)
  352. {
  353. if (Plane_Equal(&face1->plane, &face2->plane, true))
  354. {
  355. break;
  356. }
  357. }
  358. if (face2) break;
  359. }
  360. if (brush2) continue;
  361. // don't add faces with the same plane twice
  362. for (f = newbrush->brush_faces; f; f = f->next)
  363. {
  364. if (Plane_Equal(&face1->plane, &f->plane, false))
  365. break;
  366. if (Plane_Equal(&face1->plane, &f->plane, true))
  367. break;
  368. }
  369. if (f)
  370. continue;
  371. //
  372. newface = Face_Alloc();
  373. newface->texdef = face1->texdef;
  374. VectorCopy(face1->planepts[0], newface->planepts[0]);
  375. VectorCopy(face1->planepts[1], newface->planepts[1]);
  376. VectorCopy(face1->planepts[2], newface->planepts[2]);
  377. newface->plane = face1->plane;
  378. newface->next = newbrush->brush_faces;
  379. newbrush->brush_faces = newface;
  380. }
  381. }
  382. // link the new brush to an entity
  383. Entity_LinkBrush (brushlist->owner, newbrush);
  384. // build windings for the faces
  385. Brush_BuildWindings( newbrush, false);
  386. return newbrush;
  387. }
  388. /*
  389. =============
  390. Brush_Subtract
  391. Returns a list of brushes that remain after B is subtracted from A.
  392. May by empty if A is contained inside B.
  393. The originals are undisturbed.
  394. =============
  395. */
  396. brush_t *Brush_Subtract(brush_t *a, brush_t *b)
  397. {
  398. // a - b = out (list)
  399. brush_t *front, *back;
  400. brush_t *in, *out, *next;
  401. face_t *f;
  402. in = a;
  403. out = NULL;
  404. for (f = b->brush_faces; f && in; f = f->next)
  405. {
  406. Brush_SplitBrushByFace(in, f, &front, &back);
  407. if (in != a) Brush_Free(in);
  408. if (front)
  409. { // add to list
  410. front->next = out;
  411. out = front;
  412. }
  413. in = back;
  414. }
  415. //NOTE: in != a just in case brush b has no faces
  416. if (in && in != a)
  417. {
  418. Brush_Free(in);
  419. }
  420. else
  421. { //didn't really intersect
  422. for (b = out; b; b = next)
  423. {
  424. next = b->next;
  425. b->next = b->prev = NULL;
  426. Brush_Free(b);
  427. }
  428. return a;
  429. }
  430. return out;
  431. }
  432. /*
  433. =============
  434. CSG_Subtract
  435. =============
  436. */
  437. void CSG_Subtract (void)
  438. {
  439. brush_t *b, *s, *fragments, *nextfragment, *frag, *next, *snext;
  440. brush_t fragmentlist;
  441. int i, numfragments, numbrushes;
  442. Sys_Printf ("Subtracting...\n");
  443. if (selected_brushes.next == &selected_brushes)
  444. {
  445. Sys_Printf("No brushes selected.\n");
  446. return;
  447. }
  448. fragmentlist.next = &fragmentlist;
  449. fragmentlist.prev = &fragmentlist;
  450. numfragments = 0;
  451. numbrushes = 0;
  452. for (b = selected_brushes.next ; b != &selected_brushes ; b=next)
  453. {
  454. next = b->next;
  455. if (b->owner->eclass->fixedsize)
  456. continue; // can't use texture from a fixed entity, so don't subtract
  457. // chop all fragments further up
  458. for (s = fragmentlist.next; s != &fragmentlist; s = snext)
  459. {
  460. snext = s->next;
  461. for (i=0 ; i<3 ; i++)
  462. if (b->mins[i] >= s->maxs[i] - ON_EPSILON
  463. || b->maxs[i] <= s->mins[i] + ON_EPSILON)
  464. break;
  465. if (i != 3)
  466. continue; // definately don't touch
  467. fragments = Brush_Subtract(s, b);
  468. // if the brushes did not really intersect
  469. if (fragments == s)
  470. continue;
  471. // try to merge fragments
  472. fragments = Brush_MergeListPairs(fragments, true);
  473. // add the fragments to the list
  474. for (frag = fragments; frag; frag = nextfragment)
  475. {
  476. nextfragment = frag->next;
  477. frag->next = NULL;
  478. frag->owner = s->owner;
  479. Brush_AddToList(frag, &fragmentlist);
  480. }
  481. // free the original brush
  482. Brush_Free(s);
  483. }
  484. // chop any active brushes up
  485. for (s = active_brushes.next; s != &active_brushes; s = snext)
  486. {
  487. snext = s->next;
  488. if (s->owner->eclass->fixedsize || s->patchBrush || s->terrainBrush || s->hiddenBrush)
  489. continue;
  490. //face_t *pFace = s->brush_faces;
  491. if (s->brush_faces->d_texture->bFromShader && (s->brush_faces->d_texture->nShaderFlags & QER_NOCARVE))
  492. {
  493. continue;
  494. }
  495. for (i=0 ; i<3 ; i++)
  496. if (b->mins[i] >= s->maxs[i] - ON_EPSILON
  497. || b->maxs[i] <= s->mins[i] + ON_EPSILON)
  498. break;
  499. if (i != 3)
  500. continue; // definately don't touch
  501. fragments = Brush_Subtract(s, b);
  502. // if the brushes did not really intersect
  503. if (fragments == s)
  504. continue;
  505. //
  506. Undo_AddBrush(s);
  507. // one extra brush chopped up
  508. numbrushes++;
  509. // try to merge fragments
  510. fragments = Brush_MergeListPairs(fragments, true);
  511. // add the fragments to the list
  512. for (frag = fragments; frag; frag = nextfragment)
  513. {
  514. nextfragment = frag->next;
  515. frag->next = NULL;
  516. frag->owner = s->owner;
  517. Brush_AddToList(frag, &fragmentlist);
  518. }
  519. // free the original brush
  520. Brush_Free(s);
  521. }
  522. }
  523. // move all fragments to the active brush list
  524. for (frag = fragmentlist.next; frag != &fragmentlist; frag = nextfragment)
  525. {
  526. nextfragment = frag->next;
  527. numfragments++;
  528. Brush_RemoveFromList(frag);
  529. Brush_AddToList(frag, &active_brushes);
  530. Undo_EndBrush(frag);
  531. }
  532. if (numfragments == 0)
  533. {
  534. Sys_Printf("Selected brush%s did not intersect with any other brushes.\n",
  535. (selected_brushes.next->next == &selected_brushes) ? "":"es");
  536. return;
  537. }
  538. Sys_Printf("done. (created %d fragment%s out of %d brush%s)\n", numfragments, (numfragments == 1)?"":"s",
  539. numbrushes, (numbrushes == 1)?"":"es");
  540. Sys_UpdateWindows(W_ALL);
  541. }
  542. /*
  543. =============
  544. CSG_Merge
  545. =============
  546. */
  547. void CSG_Merge(void)
  548. {
  549. brush_t *b, *next, *newlist, *newbrush;
  550. struct entity_s *owner;
  551. Sys_Printf ("Merging...\n");
  552. if (selected_brushes.next == &selected_brushes)
  553. {
  554. Sys_Printf("No brushes selected.\n");
  555. return;
  556. }
  557. if (selected_brushes.next->next == &selected_brushes)
  558. {
  559. Sys_Printf("At least two brushes have to be selected.\n");
  560. return;
  561. }
  562. owner = selected_brushes.next->owner;
  563. for (b = selected_brushes.next; b != &selected_brushes; b = next)
  564. {
  565. next = b->next;
  566. if (b->owner->eclass->fixedsize)
  567. {
  568. // can't use texture from a fixed entity, so don't subtract
  569. Sys_Printf("Cannot add fixed size entities.\n");
  570. return;
  571. }
  572. if (b->patchBrush)
  573. {
  574. Sys_Printf("Cannot add patches.\n");
  575. return;
  576. }
  577. if (b->terrainBrush)
  578. {
  579. Sys_Printf("Cannot add terrains.\n");
  580. return;
  581. }
  582. if (b->brush_faces->d_texture->bFromShader && (b->brush_faces->d_texture->nShaderFlags & QER_NOCARVE))
  583. {
  584. Sys_Printf("Cannot add brushes using shaders that don't allows CSG operations.\n");
  585. return;
  586. }
  587. if (b->owner != owner)
  588. {
  589. Sys_Printf("Cannot add brushes from different entities.\n");
  590. return;
  591. }
  592. }
  593. newlist = NULL;
  594. for (b = selected_brushes.next; b != &selected_brushes; b = next)
  595. {
  596. next = b->next;
  597. Brush_RemoveFromList(b);
  598. b->next = newlist;
  599. b->prev = NULL;
  600. newlist = b;
  601. }
  602. newbrush = Brush_MergeList(newlist, true);
  603. // if the new brush would not be convex
  604. if (!newbrush)
  605. {
  606. // add the brushes back into the selection
  607. for (b = newlist; b; b = next)
  608. {
  609. next = b->next;
  610. b->next = NULL;
  611. b->prev = NULL;
  612. Brush_AddToList(b, &selected_brushes);
  613. }
  614. Sys_Printf("Cannot add a set of brushes with a concave hull.\n");
  615. return;
  616. }
  617. // free the original brushes
  618. for (b = newlist; b; b = next)
  619. {
  620. next = b->next;
  621. b->next = NULL;
  622. b->prev = NULL;
  623. Brush_Free(b);
  624. }
  625. Brush_AddToList(newbrush, &selected_brushes);
  626. Sys_Printf ("done.\n");
  627. Sys_UpdateWindows (W_ALL);
  628. }