#include "stdafx.h"
#include "qe3.h"
#include "winding.h"
Include dependency graph for CSG.CPP:

Go to the source code of this file.
Functions | |
| brush_t * | Brush_Merge (brush_t *brush1, brush_t *brush2, int onlyshape) |
| brush_t * | Brush_MergeList (brush_t *brushlist, int onlyshape) |
| brush_t * | Brush_MergeListPairs (brush_t *brushlist, int onlyshape) |
| void | Brush_Scale (brush_t *b) |
| brush_t * | Brush_Subtract (brush_t *a, brush_t *b) |
| void | CSG_MakeHollow (void) |
| void | CSG_Merge (void) |
| void | CSG_Subtract (void) |
|
||||||||||||||||
|
Definition at line 91 of file CSG.CPP. References Brush_Alloc(), Brush_BuildWindings(), brush_s::brush_faces, brush_t, plane_t::dist, Entity_LinkBrush(), f, Face_Alloc(), face_t, face_s::face_winding, i, brush_s::maxs, brush_s::mins, texdef_t::name, face_s::next, plane_t::normal, ON_EPSILON, brush_s::owner, face_s::plane, Plane_Equal(), face_s::planepts, face_s::texdef, VectorCopy, and Winding_PlanesConcave(). Referenced by Brush_MergeListPairs(). 00092 {
00093 int i, shared;
00094 brush_t *newbrush;
00095 face_t *face1, *face2, *newface, *f;
00096
00097 // check for bounding box overlapp
00098 for (i = 0; i < 3; i++)
00099 {
00100 if (brush1->mins[i] > brush2->maxs[i] + ON_EPSILON
00101 || brush1->maxs[i] < brush2->mins[i] - ON_EPSILON)
00102 {
00103 // never merge if the brushes overlap
00104 return NULL;
00105 }
00106 }
00107 //
00108 shared = 0;
00109 // check if the new brush would be convex... flipped planes make a brush non-convex
00110 for (face1 = brush1->brush_faces; face1; face1 = face1->next)
00111 {
00112 // don't check the faces of brush 1 and 2 touching each other
00113 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00114 {
00115 if (Plane_Equal(&face1->plane, &face2->plane, true))
00116 {
00117 shared++;
00118 // there may only be ONE shared side
00119 if (shared > 1)
00120 return NULL;
00121 break;
00122 }
00123 }
00124 // if this face plane is shared
00125 if (face2) continue;
00126 //
00127 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00128 {
00129 // don't check the faces of brush 1 and 2 touching each other
00130 for (f = brush1->brush_faces; f; f = f->next)
00131 {
00132 if (Plane_Equal(&face2->plane, &f->plane, true)) break;
00133 }
00134 if (f)
00135 continue;
00136 //
00137 if (Plane_Equal(&face1->plane, &face2->plane, false))
00138 {
00139 //if the texture/shader references should be the same but are not
00140 if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL;
00141 continue;
00142 }
00143 //
00144 if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
00145 face1->plane.normal, face2->plane.normal,
00146 face1->plane.dist, face2->plane.dist))
00147 {
00148 return NULL;
00149 } //end if
00150 } //end for
00151 } //end for
00152 //
00153 newbrush = Brush_Alloc();
00154 //
00155 for (face1 = brush1->brush_faces; face1; face1 = face1->next)
00156 {
00157 // don't add the faces of brush 1 and 2 touching each other
00158 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00159 {
00160 if (Plane_Equal(&face1->plane, &face2->plane, true))
00161 break;
00162 }
00163 if (face2)
00164 continue;
00165 // don't add faces with the same plane twice
00166 for (f = newbrush->brush_faces; f; f = f->next)
00167 {
00168 if (Plane_Equal(&face1->plane, &f->plane, false))
00169 break;
00170 if (Plane_Equal(&face1->plane, &f->plane, true))
00171 break;
00172 }
00173 if (f)
00174 continue;
00175 //
00176 newface = Face_Alloc();
00177 newface->texdef = face1->texdef;
00178 VectorCopy(face1->planepts[0], newface->planepts[0]);
00179 VectorCopy(face1->planepts[1], newface->planepts[1]);
00180 VectorCopy(face1->planepts[2], newface->planepts[2]);
00181 newface->plane = face1->plane;
00182 newface->next = newbrush->brush_faces;
00183 newbrush->brush_faces = newface;
00184 }
00185 //
00186 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00187 {
00188 // don't add the faces of brush 1 and 2 touching each other
00189 for (face1 = brush1->brush_faces; face1; face1 = face1->next)
00190 {
00191 if (Plane_Equal(&face2->plane, &face1->plane, true))
00192 break;
00193 }
00194 if (face1)
00195 continue;
00196 // don't add faces with the same plane twice
00197 for (f = newbrush->brush_faces; f; f = f->next)
00198 {
00199 if (Plane_Equal(&face2->plane, &f->plane, false))
00200 break;
00201 if (Plane_Equal(&face2->plane, &f->plane, true))
00202 break;
00203 }
00204 if (f)
00205 continue;
00206 //
00207 newface = Face_Alloc();
00208 newface->texdef = face2->texdef;
00209 VectorCopy(face2->planepts[0], newface->planepts[0]);
00210 VectorCopy(face2->planepts[1], newface->planepts[1]);
00211 VectorCopy(face2->planepts[2], newface->planepts[2]);
00212 newface->plane = face2->plane;
00213 newface->next = newbrush->brush_faces;
00214 newbrush->brush_faces = newface;
00215 }
00216 // link the new brush to an entity
00217 Entity_LinkBrush (brush1->owner, newbrush);
00218 // build windings for the faces
00219 Brush_BuildWindings( newbrush, false);
00220 return newbrush;
00221 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 304 of file CSG.CPP. References Brush_Alloc(), Brush_BuildWindings(), brush_s::brush_faces, brush_t, plane_t::dist, Entity_LinkBrush(), f, Face_Alloc(), face_t, face_s::face_winding, texdef_t::name, face_s::next, brush_s::next, plane_t::normal, brush_s::owner, face_s::plane, Plane_Equal(), face_s::planepts, face_s::texdef, VectorCopy, and Winding_PlanesConcave(). Referenced by CSG_Merge(). 00305 {
00306 brush_t *brush1, *brush2, *brush3, *newbrush;
00307 face_t *face1, *face2, *face3, *newface, *f;
00308
00309 if (!brushlist) return NULL;
00310 for (brush1 = brushlist; brush1; brush1 = brush1->next)
00311 {
00312 // check if the new brush would be convex... flipped planes make a brush concave
00313 for (face1 = brush1->brush_faces; face1; face1 = face1->next)
00314 {
00315 // don't check face1 if it touches another brush
00316 for (brush2 = brushlist; brush2; brush2 = brush2->next)
00317 {
00318 if (brush2 == brush1) continue;
00319 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00320 {
00321 if (Plane_Equal(&face1->plane, &face2->plane, true))
00322 {
00323 break;
00324 }
00325 }
00326 if (face2) break;
00327 }
00328 // if face1 touches another brush
00329 if (brush2) continue;
00330 //
00331 for (brush2 = brush1->next; brush2; brush2 = brush2->next)
00332 {
00333 // don't check the faces of brush 2 touching another brush
00334 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00335 {
00336 for (brush3 = brushlist; brush3; brush3 = brush3->next)
00337 {
00338 if (brush3 == brush2) continue;
00339 for (face3 = brush3->brush_faces; face3; face3 = face3->next)
00340 {
00341 if (Plane_Equal(&face2->plane, &face3->plane, true)) break;
00342 }
00343 if (face3) break;
00344 }
00345 // if face2 touches another brush
00346 if (brush3) continue;
00347 //
00348 if (Plane_Equal(&face1->plane, &face2->plane, false))
00349 {
00350 //if the texture/shader references should be the same but are not
00351 if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL;
00352 continue;
00353 }
00354 //
00355 if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
00356 face1->plane.normal, face2->plane.normal,
00357 face1->plane.dist, face2->plane.dist))
00358 {
00359 return NULL;
00360 }
00361 }
00362 }
00363 }
00364 }
00365 //
00366 newbrush = Brush_Alloc();
00367 //
00368 for (brush1 = brushlist; brush1; brush1 = brush1->next)
00369 {
00370 for (face1 = brush1->brush_faces; face1; face1 = face1->next)
00371 {
00372 // don't add face1 to the new brush if it touches another brush
00373 for (brush2 = brushlist; brush2; brush2 = brush2->next)
00374 {
00375 if (brush2 == brush1) continue;
00376 for (face2 = brush2->brush_faces; face2; face2 = face2->next)
00377 {
00378 if (Plane_Equal(&face1->plane, &face2->plane, true))
00379 {
00380 break;
00381 }
00382 }
00383 if (face2) break;
00384 }
00385 if (brush2) continue;
00386 // don't add faces with the same plane twice
00387 for (f = newbrush->brush_faces; f; f = f->next)
00388 {
00389 if (Plane_Equal(&face1->plane, &f->plane, false))
00390 break;
00391 if (Plane_Equal(&face1->plane, &f->plane, true))
00392 break;
00393 }
00394 if (f)
00395 continue;
00396 //
00397 newface = Face_Alloc();
00398 newface->texdef = face1->texdef;
00399 VectorCopy(face1->planepts[0], newface->planepts[0]);
00400 VectorCopy(face1->planepts[1], newface->planepts[1]);
00401 VectorCopy(face1->planepts[2], newface->planepts[2]);
00402 newface->plane = face1->plane;
00403 newface->next = newbrush->brush_faces;
00404 newbrush->brush_faces = newface;
00405 }
00406 }
00407 // link the new brush to an entity
00408 Entity_LinkBrush (brushlist->owner, newbrush);
00409 // build windings for the faces
00410 Brush_BuildWindings( newbrush, false);
00411 return newbrush;
00412 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 233 of file CSG.CPP. References Brush_Free(), Brush_Merge(), brush_t, brush_s::next, and brush_s::prev. Referenced by CSG_Subtract(). 00234 {
00235 int nummerges, merged;
00236 brush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
00237 brush_t *lastb2;
00238
00239 if (!brushlist) return NULL;
00240
00241 nummerges = 0;
00242 do
00243 {
00244 for (tail = brushlist; tail; tail = tail->next)
00245 {
00246 if (!tail->next) break;
00247 }
00248 merged = 0;
00249 newbrushlist = NULL;
00250 for (b1 = brushlist; b1; b1 = brushlist)
00251 {
00252 lastb2 = b1;
00253 for (b2 = b1->next; b2; b2 = b2->next)
00254 {
00255 newbrush = Brush_Merge(b1, b2, onlyshape);
00256 if (newbrush)
00257 {
00258 tail->next = newbrush;
00259 lastb2->next = b2->next;
00260 brushlist = brushlist->next;
00261 b1->next = b1->prev = NULL;
00262 b2->next = b2->prev = NULL;
00263 Brush_Free(b1);
00264 Brush_Free(b2);
00265 for (tail = brushlist; tail; tail = tail->next)
00266 {
00267 if (!tail->next) break;
00268 } //end for
00269 merged++;
00270 nummerges++;
00271 break;
00272 }
00273 lastb2 = b2;
00274 }
00275 //if b1 can't be merged with any of the other brushes
00276 if (!b2)
00277 {
00278 brushlist = brushlist->next;
00279 //keep b1
00280 b1->next = newbrushlist;
00281 newbrushlist = b1;
00282 }
00283 }
00284 brushlist = newbrushlist;
00285 } while(merged);
00286 return newbrushlist;
00287 }
|
Here is the call graph for this function:

|
|
Definition at line 34 of file CSG.CPP. References b, brush_s::brush_faces, brush_t, QEGlobals_t::d_gridsize, f, face_t, g_qeglobals, i, face_s::next, face_s::planepts, and VectorScale. 00035 {
00036 for (face_t* f = b->brush_faces ; f ; f=f->next)
00037 {
00038 for (int i=0 ; i<3 ; i++)
00039 {
00040 VectorScale (f->planepts[i], g_qeglobals.d_gridsize, f->planepts[i]);
00041 }
00042 }
00043 }
|
|
||||||||||||
|
Definition at line 423 of file CSG.CPP. References b, brush_s::brush_faces, Brush_Free(), Brush_SplitBrushByFace(), brush_t, f, face_t, in, next, brush_s::next, face_s::next, and brush_s::prev. Referenced by CSG_Subtract(). 00424 {
00425 // a - b = out (list)
00426 brush_t *front, *back;
00427 brush_t *in, *out, *next;
00428 face_t *f;
00429
00430 in = a;
00431 out = NULL;
00432 for (f = b->brush_faces; f && in; f = f->next)
00433 {
00434 Brush_SplitBrushByFace(in, f, &front, &back);
00435 if (in != a) Brush_Free(in);
00436 if (front)
00437 { // add to list
00438 front->next = out;
00439 out = front;
00440 }
00441 in = back;
00442 }
00443 //NOTE: in != a just in case brush b has no faces
00444 if (in && in != a)
00445 {
00446 Brush_Free(in);
00447 }
00448 else
00449 { //didn't really intersect
00450 for (b = out; b; b = next)
00451 {
00452 next = b->next;
00453 b->next = b->prev = NULL;
00454 Brush_Free(b);
00455 }
00456 return a;
00457 }
00458 return out;
00459 }
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
|
Definition at line 591 of file CSG.CPP. References b, qtexture_s::bFromShader, Brush_AddToList(), brush_s::brush_faces, Brush_Free(), Brush_MergeList(), Brush_RemoveFromList(), brush_t, face_s::d_texture, entity_s::eclass, eclass_s::fixedsize, brush_s::next, next, qtexture_s::nShaderFlags, brush_s::owner, brush_s::patchBrush, brush_s::prev, selected_brushes, Sys_Printf(), Sys_UpdateWindows(), brush_s::terrainBrush, and W_ALL. Referenced by CMainFrame::OnSelectionCsgmerge(). 00592 {
00593 brush_t *b, *next, *newlist, *newbrush;
00594 struct entity_s *owner;
00595
00596 Sys_Printf ("Merging...\n");
00597
00598 if (selected_brushes.next == &selected_brushes)
00599 {
00600 Sys_Printf("No brushes selected.\n");
00601 return;
00602 }
00603
00604 if (selected_brushes.next->next == &selected_brushes)
00605 {
00606 Sys_Printf("At least two brushes have to be selected.\n");
00607 return;
00608 }
00609
00610 owner = selected_brushes.next->owner;
00611
00612 for (b = selected_brushes.next; b != &selected_brushes; b = next)
00613 {
00614 next = b->next;
00615
00616 if (b->owner->eclass->fixedsize)
00617 {
00618 // can't use texture from a fixed entity, so don't subtract
00619 Sys_Printf("Cannot add fixed size entities.\n");
00620 return;
00621 }
00622
00623 if (b->patchBrush)
00624 {
00625 Sys_Printf("Cannot add patches.\n");
00626 return;
00627 }
00628 if (b->terrainBrush)
00629 {
00630 Sys_Printf("Cannot add terrains.\n");
00631 return;
00632 }
00633
00634 if (b->brush_faces->d_texture->bFromShader && (b->brush_faces->d_texture->nShaderFlags & QER_NOCARVE))
00635 {
00636 Sys_Printf("Cannot add brushes using shaders that don't allows CSG operations.\n");
00637 return;
00638 }
00639
00640 if (b->owner != owner)
00641 {
00642 Sys_Printf("Cannot add brushes from different entities.\n");
00643 return;
00644 }
00645
00646 }
00647
00648 newlist = NULL;
00649 for (b = selected_brushes.next; b != &selected_brushes; b = next)
00650 {
00651 next = b->next;
00652
00653 Brush_RemoveFromList(b);
00654 b->next = newlist;
00655 b->prev = NULL;
00656 newlist = b;
00657 }
00658
00659 newbrush = Brush_MergeList(newlist, true);
00660 // if the new brush would not be convex
00661 if (!newbrush)
00662 {
00663 // add the brushes back into the selection
00664 for (b = newlist; b; b = next)
00665 {
00666 next = b->next;
00667 b->next = NULL;
00668 b->prev = NULL;
00669 Brush_AddToList(b, &selected_brushes);
00670 }
00671 Sys_Printf("Cannot add a set of brushes with a concave hull.\n");
00672 return;
00673 }
00674 // free the original brushes
00675 for (b = newlist; b; b = next)
00676 {
00677 next = b->next;
00678 b->next = NULL;
00679 b->prev = NULL;
00680 Brush_Free(b);
00681 }
00682 Brush_AddToList(newbrush, &selected_brushes);
00683
00684 Sys_Printf ("done.\n");
00685 Sys_UpdateWindows (W_ALL);
00686 }
|
Here is the call graph for this function:

|
|
Definition at line 466 of file CSG.CPP. References active_brushes, b, qtexture_s::bFromShader, Brush_AddToList(), brush_s::brush_faces, Brush_Free(), Brush_MergeListPairs(), Brush_RemoveFromList(), Brush_Subtract(), brush_t, face_s::d_texture, entity_s::eclass, eclass_s::fixedsize, brush_s::hiddenBrush, i, brush_s::maxs, brush_s::mins, brush_s::next, next, qtexture_s::nShaderFlags, numbrushes, ON_EPSILON, brush_s::owner, brush_s::patchBrush, brush_s::prev, s, selected_brushes, Sys_Printf(), Sys_UpdateWindows(), brush_s::terrainBrush, Undo_AddBrush(), Undo_EndBrush(), and W_ALL. Referenced by CMainFrame::OnSelectionCsgsubtract(), and Spherize(). 00467 {
00468 brush_t *b, *s, *fragments, *nextfragment, *frag, *next, *snext;
00469 brush_t fragmentlist;
00470 int i, numfragments, numbrushes;
00471
00472 Sys_Printf ("Subtracting...\n");
00473
00474 if (selected_brushes.next == &selected_brushes)
00475 {
00476 Sys_Printf("No brushes selected.\n");
00477 return;
00478 }
00479
00480 fragmentlist.next = &fragmentlist;
00481 fragmentlist.prev = &fragmentlist;
00482
00483 numfragments = 0;
00484 numbrushes = 0;
00485 for (b = selected_brushes.next ; b != &selected_brushes ; b=next)
00486 {
00487 next = b->next;
00488
00489 if (b->owner->eclass->fixedsize)
00490 continue; // can't use texture from a fixed entity, so don't subtract
00491
00492 // chop all fragments further up
00493 for (s = fragmentlist.next; s != &fragmentlist; s = snext)
00494 {
00495 snext = s->next;
00496
00497 for (i=0 ; i<3 ; i++)
00498 if (b->mins[i] >= s->maxs[i] - ON_EPSILON
00499 || b->maxs[i] <= s->mins[i] + ON_EPSILON)
00500 break;
00501 if (i != 3)
00502 continue; // definately don't touch
00503 fragments = Brush_Subtract(s, b);
00504 // if the brushes did not really intersect
00505 if (fragments == s)
00506 continue;
00507 // try to merge fragments
00508 fragments = Brush_MergeListPairs(fragments, true);
00509 // add the fragments to the list
00510 for (frag = fragments; frag; frag = nextfragment)
00511 {
00512 nextfragment = frag->next;
00513 frag->next = NULL;
00514 frag->owner = s->owner;
00515 Brush_AddToList(frag, &fragmentlist);
00516 }
00517 // free the original brush
00518 Brush_Free(s);
00519 }
00520
00521 // chop any active brushes up
00522 for (s = active_brushes.next; s != &active_brushes; s = snext)
00523 {
00524 snext = s->next;
00525
00526 if (s->owner->eclass->fixedsize || s->patchBrush || s->terrainBrush || s->hiddenBrush)
00527 continue;
00528
00529 //face_t *pFace = s->brush_faces;
00530 if (s->brush_faces->d_texture->bFromShader && (s->brush_faces->d_texture->nShaderFlags & QER_NOCARVE))
00531 {
00532 continue;
00533 }
00534
00535 for (i=0 ; i<3 ; i++)
00536 if (b->mins[i] >= s->maxs[i] - ON_EPSILON
00537 || b->maxs[i] <= s->mins[i] + ON_EPSILON)
00538 break;
00539 if (i != 3)
00540 continue; // definately don't touch
00541
00542 fragments = Brush_Subtract(s, b);
00543 // if the brushes did not really intersect
00544 if (fragments == s)
00545 continue;
00546 //
00547 Undo_AddBrush(s);
00548 // one extra brush chopped up
00549 numbrushes++;
00550 // try to merge fragments
00551 fragments = Brush_MergeListPairs(fragments, true);
00552 // add the fragments to the list
00553 for (frag = fragments; frag; frag = nextfragment)
00554 {
00555 nextfragment = frag->next;
00556 frag->next = NULL;
00557 frag->owner = s->owner;
00558 Brush_AddToList(frag, &fragmentlist);
00559 }
00560 // free the original brush
00561 Brush_Free(s);
00562 }
00563 }
00564
00565 // move all fragments to the active brush list
00566 for (frag = fragmentlist.next; frag != &fragmentlist; frag = nextfragment)
00567 {
00568 nextfragment = frag->next;
00569 numfragments++;
00570 Brush_RemoveFromList(frag);
00571 Brush_AddToList(frag, &active_brushes);
00572 Undo_EndBrush(frag);
00573 }
00574
00575 if (numfragments == 0)
00576 {
00577 Sys_Printf("Selected brush%s did not intersect with any other brushes.\n",
00578 (selected_brushes.next->next == &selected_brushes) ? "":"es");
00579 return;
00580 }
00581 Sys_Printf("done. (created %d fragment%s out of %d brush%s)\n", numfragments, (numfragments == 1)?"":"s",
00582 numbrushes, (numbrushes == 1)?"":"es");
00583 Sys_UpdateWindows(W_ALL);
00584 }
|
Here is the call graph for this function:

1.3.9.1