1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "Brush.h" 21 22 #include "CollectionUtils.h" 23 #include "Model/BrushContentTypeBuilder.h" 24 #include "Model/BrushFace.h" 25 #include "Model/BrushGeometry.h" 26 #include "Model/BrushSnapshot.h" 27 #include "Model/Entity.h" 28 #include "Model/FindContainerVisitor.h" 29 #include "Model/FindGroupVisitor.h" 30 #include "Model/FindLayerVisitor.h" 31 #include "Model/Group.h" 32 #include "Model/IssueGenerator.h" 33 #include "Model/NodeVisitor.h" 34 #include "Model/PickResult.h" 35 #include "Model/World.h" 36 37 namespace TrenchBroom { 38 namespace Model { 39 const Hit::HitType Brush::BrushHit = Hit::freeHitType(); 40 project(BrushVertex * & vertex)41 BrushVertex*& Brush::ProjectToVertex::project(BrushVertex*& vertex) { 42 return vertex; 43 } 44 project(BrushEdge * & edge)45 BrushEdge*& Brush::ProjectToEdge::project(BrushEdge*& edge) { 46 return edge; 47 } 48 49 class Brush::AddFaceToGeometryCallback : public BrushGeometry::Callback { 50 private: 51 BrushFace* m_addedFace; 52 public: AddFaceToGeometryCallback(BrushFace * addedFace)53 AddFaceToGeometryCallback(BrushFace* addedFace) : 54 m_addedFace(addedFace) { 55 assert(m_addedFace != NULL); 56 } 57 faceWasCreated(BrushFaceGeometry * face)58 void faceWasCreated(BrushFaceGeometry* face) { 59 face->setPayload(m_addedFace); 60 m_addedFace->setGeometry(face); 61 } 62 faceWillBeDeleted(BrushFaceGeometry * face)63 void faceWillBeDeleted(BrushFaceGeometry* face) { 64 BrushFace* brushFace = face->payload(); 65 if (brushFace != NULL) { 66 assert(!brushFace->selected()); 67 68 delete brushFace; 69 face->setPayload(NULL); 70 } 71 } 72 }; 73 74 class Brush::HealEdgesCallback : public BrushGeometry::Callback { 75 public: facesWillBeMerged(BrushFaceGeometry * remainingGeometry,BrushFaceGeometry * geometryToDelete)76 void facesWillBeMerged(BrushFaceGeometry* remainingGeometry, BrushFaceGeometry* geometryToDelete) { 77 BrushFace* remainingFace = remainingGeometry->payload(); 78 assert(remainingFace != NULL); 79 remainingFace->invalidate(); 80 81 BrushFace* faceToDelete = geometryToDelete->payload(); 82 assert(faceToDelete != NULL); 83 assert(!faceToDelete->selected()); 84 85 delete faceToDelete; 86 geometryToDelete->setPayload(NULL); 87 } 88 faceWillBeDeleted(BrushFaceGeometry * face)89 void faceWillBeDeleted(BrushFaceGeometry* face) { 90 BrushFace* brushFace = face->payload(); 91 assert(brushFace != NULL); 92 assert(!brushFace->selected()); 93 94 delete brushFace; 95 face->setPayload(NULL); 96 } 97 }; 98 99 class Brush::AddFacesToGeometry { 100 private: 101 BrushGeometry& m_geometry; 102 bool m_brushEmpty; 103 bool m_brushValid; 104 public: AddFacesToGeometry(BrushGeometry & geometry,const BrushFaceList & facesToAdd)105 AddFacesToGeometry(BrushGeometry& geometry, const BrushFaceList& facesToAdd) : 106 m_geometry(geometry), 107 m_brushEmpty(false), 108 m_brushValid(false) { 109 BrushFaceList::const_iterator it, end; 110 for (it = facesToAdd.begin(), end = facesToAdd.end(); it != end && !m_brushEmpty; ++it) { 111 BrushFace* face = *it; 112 AddFaceToGeometryCallback callback(face); 113 const BrushGeometry::ClipResult result = m_geometry.clip(face->boundary(), callback); 114 if (result.empty()) 115 m_brushEmpty = true; 116 } 117 m_geometry.correctVertexPositions(); 118 119 HealEdgesCallback callback; 120 m_brushValid = m_geometry.healEdges(callback); 121 } 122 brushEmpty() const123 bool brushEmpty() const { 124 return m_brushEmpty; 125 } 126 brushValid() const127 bool brushValid() const { 128 return m_brushValid; 129 } 130 }; 131 132 class Brush::CanMoveBoundaryCallback : public BrushGeometry::Callback { 133 private: 134 BrushFace* m_addedFace; 135 bool m_hasDroppedFaces; 136 public: CanMoveBoundaryCallback(BrushFace * addedFace)137 CanMoveBoundaryCallback(BrushFace* addedFace) : 138 m_addedFace(addedFace), 139 m_hasDroppedFaces(false) { 140 assert(m_addedFace != NULL); 141 } 142 faceWasCreated(BrushFaceGeometry * face)143 void faceWasCreated(BrushFaceGeometry* face) { 144 face->setPayload(m_addedFace); 145 m_addedFace->setGeometry(face); 146 } 147 faceWillBeDeleted(BrushFaceGeometry * face)148 void faceWillBeDeleted(BrushFaceGeometry* face) { 149 if (face->payload() != NULL) 150 m_hasDroppedFaces = true; 151 } 152 hasDroppedFaces() const153 bool hasDroppedFaces() const { 154 return m_hasDroppedFaces; 155 } 156 }; 157 158 class Brush::CanMoveBoundary { 159 private: 160 BrushGeometry& m_geometry; 161 bool m_hasDroppedFaces; 162 bool m_hasRedundandFaces; 163 bool m_brushEmpty; 164 public: CanMoveBoundary(BrushGeometry & geometry,const BrushFaceList & facesToAdd)165 CanMoveBoundary(BrushGeometry& geometry, const BrushFaceList& facesToAdd) : 166 m_geometry(geometry), 167 m_hasDroppedFaces(false), 168 m_hasRedundandFaces(false), 169 m_brushEmpty(false) { 170 BrushFaceList::const_iterator it, end; 171 for (it = facesToAdd.begin(), end = facesToAdd.end(); it != end && !m_brushEmpty; ++it) { 172 BrushFace* face = *it; 173 CanMoveBoundaryCallback callback(face); 174 const BrushGeometry::ClipResult result = m_geometry.clip(face->boundary(), callback); 175 if (result.unchanged()) 176 m_hasRedundandFaces = true; 177 else if (result.empty()) 178 m_brushEmpty = true; 179 else 180 m_hasDroppedFaces |= callback.hasDroppedFaces(); 181 } 182 } 183 hasDroppedFaces() const184 bool hasDroppedFaces() const { 185 return m_hasDroppedFaces; 186 } 187 hasRedundandFaces() const188 bool hasRedundandFaces() const { 189 return m_hasRedundandFaces; 190 } 191 brushEmpty() const192 bool brushEmpty() const { 193 return m_brushEmpty; 194 } 195 }; 196 197 class Brush::MoveVerticesCallback : public BrushGeometry::Callback { 198 public: faceWillBeDeleted(BrushFaceGeometry * faceGeometry)199 void faceWillBeDeleted(BrushFaceGeometry* faceGeometry) { 200 BrushFace* face = faceGeometry->payload(); 201 assert(!face->selected()); 202 delete face; 203 faceGeometry->setPayload(NULL); 204 } 205 faceDidChange(BrushFaceGeometry * faceGeometry)206 void faceDidChange(BrushFaceGeometry* faceGeometry) { 207 BrushFace* face = faceGeometry->payload(); 208 face->updatePointsFromVertices(); 209 } 210 faceWasSplit(BrushFaceGeometry * originalGeometry,BrushFaceGeometry * cloneGeometry)211 void faceWasSplit(BrushFaceGeometry* originalGeometry, BrushFaceGeometry* cloneGeometry) { 212 BrushFace* originalFace = originalGeometry->payload(); 213 assert(originalFace != NULL); 214 assert(cloneGeometry->payload() == NULL); 215 216 BrushFace* clonedFace = originalFace->clone(); 217 cloneGeometry->setPayload(clonedFace); 218 clonedFace->setGeometry(cloneGeometry); 219 220 originalFace->invalidate(); 221 clonedFace->invalidate(); 222 } 223 facesWillBeMerged(BrushFaceGeometry * remainingGeometry,BrushFaceGeometry * geometryToDelete)224 void facesWillBeMerged(BrushFaceGeometry* remainingGeometry, BrushFaceGeometry* geometryToDelete) { 225 BrushFace* remainingFace = remainingGeometry->payload(); 226 assert(remainingFace != NULL); 227 remainingFace->invalidate(); 228 229 BrushFace* faceToDelete = geometryToDelete->payload(); 230 assert(faceToDelete != NULL); 231 assert(!faceToDelete->selected()); 232 233 delete faceToDelete; 234 geometryToDelete->setPayload(NULL); 235 } 236 }; 237 238 class Brush::QueryCallback : public BrushGeometry::Callback { 239 public: plane(const BrushFaceGeometry * face) const240 Plane3 plane(const BrushFaceGeometry* face) const { 241 return face->payload()->boundary(); 242 } 243 }; 244 Brush(const BBox3 & worldBounds,const BrushFaceList & faces)245 Brush::Brush(const BBox3& worldBounds, const BrushFaceList& faces) : 246 m_geometry(NULL), 247 m_contentTypeBuilder(NULL), 248 m_contentType(0), 249 m_transparent(false), 250 m_contentTypeValid(true) { 251 addFaces(faces); 252 try { 253 rebuildGeometry(worldBounds); 254 } catch (const GeometryException&) { 255 cleanup(); 256 throw; 257 } 258 } 259 ~Brush()260 Brush::~Brush() { 261 cleanup(); 262 } 263 cleanup()264 void Brush::cleanup() { 265 delete m_geometry; 266 m_geometry = NULL; 267 VectorUtils::clearAndDelete(m_faces); 268 m_contentTypeBuilder = NULL; 269 } 270 clone(const BBox3 & worldBounds) const271 Brush* Brush::clone(const BBox3& worldBounds) const { 272 return static_cast<Brush*>(Node::clone(worldBounds)); 273 } 274 doTakeSnapshot()275 NodeSnapshot* Brush::doTakeSnapshot() { 276 return new BrushSnapshot(this); 277 } 278 279 class FindBrushOwner : public NodeVisitor, public NodeQuery<AttributableNode*> { 280 private: doVisit(World * world)281 void doVisit(World* world) { setResult(world); cancel(); } doVisit(Layer * layer)282 void doVisit(Layer* layer) {} doVisit(Group * group)283 void doVisit(Group* group) {} doVisit(Entity * entity)284 void doVisit(Entity* entity) { setResult(entity); cancel(); } doVisit(Brush * brush)285 void doVisit(Brush* brush) {} 286 }; 287 entity() const288 AttributableNode* Brush::entity() const { 289 if (parent() == NULL) 290 return NULL; 291 FindBrushOwner visitor; 292 parent()->acceptAndEscalate(visitor); 293 if (!visitor.hasResult()) 294 return NULL; 295 return visitor.result(); 296 } 297 faces() const298 const BrushFaceList& Brush::faces() const { 299 return m_faces; 300 } 301 setFaces(const BBox3 & worldBounds,const BrushFaceList & faces)302 void Brush::setFaces(const BBox3& worldBounds, const BrushFaceList& faces) { 303 const NotifyNodeChange nodeChange(this); 304 detachFaces(m_faces); 305 VectorUtils::clearAndDelete(m_faces); 306 addFaces(faces); 307 rebuildGeometry(worldBounds); 308 } 309 findFaceByNormal(const Vec3 & normal) const310 BrushFace* Brush::findFaceByNormal(const Vec3& normal) const { 311 BrushFaceList::const_iterator it, end; 312 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 313 BrushFace* face = *it; 314 if (face->boundary().normal.equals(normal)) 315 return face; 316 } 317 return NULL; 318 } 319 fullySpecified() const320 bool Brush::fullySpecified() const { 321 assert(m_geometry != NULL); 322 323 BrushFaceGeometry* first = m_geometry->faces().front(); 324 BrushFaceGeometry* current = first; 325 do { 326 if (current->payload() == NULL) 327 return false; 328 current = current->next(); 329 } while (current != first); 330 return true; 331 } 332 faceDidChange()333 void Brush::faceDidChange() { 334 invalidateContentType(); 335 } 336 addFaces(const BrushFaceList & faces)337 void Brush::addFaces(const BrushFaceList& faces) { 338 addFaces(faces.begin(), faces.end(), faces.size()); 339 } 340 addFace(BrushFace * face)341 void Brush::addFace(BrushFace* face) { 342 assert(face != NULL); 343 assert(face->brush() == NULL); 344 assert(!VectorUtils::contains(m_faces, face)); 345 346 m_faces.push_back(face); 347 face->setBrush(this); 348 invalidateContentType(); 349 if (face->selected()) 350 incChildSelectionCount(1); 351 } 352 removeFace(BrushFace * face)353 void Brush::removeFace(BrushFace* face) { 354 m_faces.erase(doRemoveFace(m_faces.begin(), m_faces.end(), face), m_faces.end()); 355 } 356 doRemoveFace(BrushFaceList::iterator begin,BrushFaceList::iterator end,BrushFace * face)357 BrushFaceList::iterator Brush::doRemoveFace(BrushFaceList::iterator begin, BrushFaceList::iterator end, BrushFace* face) { 358 assert(face != NULL); 359 360 BrushFaceList::iterator it = std::remove(begin, end, face); 361 assert(it != m_faces.end()); 362 detachFace(face); 363 return it; 364 } 365 detachFaces(const BrushFaceList & faces)366 void Brush::detachFaces(const BrushFaceList& faces) { 367 BrushFaceList::const_iterator it, end; 368 for (it = faces.begin(), end = faces.end(); it != end; ++it) 369 detachFace(*it); 370 } 371 detachFace(BrushFace * face)372 void Brush::detachFace(BrushFace* face) { 373 assert(face != NULL); 374 assert(face->brush() == this); 375 376 if (face->selected()) 377 decChildSelectionCount(1); 378 face->setBrush(NULL); 379 invalidateContentType(); 380 } 381 cloneFaceAttributesFrom(const BrushList & brushes)382 void Brush::cloneFaceAttributesFrom(const BrushList& brushes) { 383 BrushList::const_iterator bIt, bEnd; 384 for (bIt = brushes.begin(), bEnd = brushes.end(); bIt != bEnd; ++bIt) { 385 const Brush* brush = *bIt; 386 cloneFaceAttributesFrom(brush); 387 } 388 } 389 cloneFaceAttributesFrom(const Brush * brush)390 void Brush::cloneFaceAttributesFrom(const Brush* brush) { 391 BrushFaceList::iterator fIt, fEnd; 392 for (fIt = m_faces.begin(), fEnd = m_faces.end(); fIt != fEnd; ++fIt) { 393 BrushFace* destination = *fIt; 394 const BrushFace* source = brush->findFaceWithBoundary(destination->boundary()); 395 if (source != NULL) { 396 destination->setAttribs(source->attribs()); 397 } 398 } 399 } 400 cloneInvertedFaceAttributesFrom(const BrushList & brushes)401 void Brush::cloneInvertedFaceAttributesFrom(const BrushList& brushes) { 402 BrushList::const_iterator bIt, bEnd; 403 for (bIt = brushes.begin(), bEnd = brushes.end(); bIt != bEnd; ++bIt) { 404 const Brush* brush = *bIt; 405 cloneInvertedFaceAttributesFrom(brush); 406 } 407 } 408 cloneInvertedFaceAttributesFrom(const Brush * brush)409 void Brush::cloneInvertedFaceAttributesFrom(const Brush* brush) { 410 BrushFaceList::iterator fIt, fEnd; 411 for (fIt = m_faces.begin(), fEnd = m_faces.end(); fIt != fEnd; ++fIt) { 412 BrushFace* destination = *fIt; 413 const BrushFace* source = brush->findFaceWithBoundary(destination->boundary().flipped()); 414 if (source != NULL) { 415 // Todo: invert the face attributes? 416 destination->setAttribs(source->attribs()); 417 } 418 } 419 } 420 findFaceWithBoundary(const Plane3 & boundary) const421 BrushFace* Brush::findFaceWithBoundary(const Plane3& boundary) const { 422 BrushFaceList::const_iterator it, end; 423 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 424 BrushFace* face = *it; 425 if (face->boundary().equals(boundary)) 426 return face; 427 } 428 return NULL; 429 } 430 clip(const BBox3 & worldBounds,BrushFace * face)431 bool Brush::clip(const BBox3& worldBounds, BrushFace* face) { 432 const NotifyNodeChange nodeChange(this); 433 try { 434 addFace(face); 435 rebuildGeometry(worldBounds); 436 return !m_faces.empty(); 437 } catch (GeometryException&) { 438 return false; 439 } 440 } 441 canMoveBoundary(const BBox3 & worldBounds,const BrushFace * face,const Vec3 & delta) const442 bool Brush::canMoveBoundary(const BBox3& worldBounds, const BrushFace* face, const Vec3& delta) const { 443 BrushFace* testFace = face->clone(); 444 testFace->transform(translationMatrix(delta), false); 445 446 BrushFaceList testFaces; 447 testFaces.push_back(testFace); 448 449 BrushFaceList::const_iterator it, end; 450 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 451 BrushFace* brushFace = *it; 452 if (brushFace != face) 453 testFaces.push_back(brushFace); 454 } 455 456 BrushGeometry testGeometry(worldBounds); 457 CanMoveBoundary canMove(testGeometry, testFaces); 458 const bool inWorldBounds = worldBounds.contains(testGeometry.bounds()) && testGeometry.closed(); 459 460 restoreFaceLinks(m_geometry); 461 delete testFace; 462 463 return (inWorldBounds && 464 !canMove.brushEmpty() && 465 !canMove.hasRedundandFaces() && 466 !canMove.hasDroppedFaces()); 467 } 468 moveBoundary(const BBox3 & worldBounds,BrushFace * face,const Vec3 & delta,const bool lockTexture)469 void Brush::moveBoundary(const BBox3& worldBounds, BrushFace* face, const Vec3& delta, const bool lockTexture) { 470 assert(canMoveBoundary(worldBounds, face, delta)); 471 472 const NotifyNodeChange nodeChange(this); 473 face->transform(translationMatrix(delta), lockTexture); 474 rebuildGeometry(worldBounds); 475 } 476 vertexCount() const477 size_t Brush::vertexCount() const { 478 assert(m_geometry != NULL); 479 return m_geometry->vertexCount(); 480 } 481 vertices() const482 Brush::VertexList Brush::vertices() const { 483 assert(m_geometry != NULL); 484 return VertexList(m_geometry->vertices()); 485 } 486 edgeCount() const487 size_t Brush::edgeCount() const { 488 assert(m_geometry != NULL); 489 return m_geometry->edgeCount(); 490 } 491 edges() const492 Brush::EdgeList Brush::edges() const { 493 assert(m_geometry != NULL); 494 return EdgeList(m_geometry->edges()); 495 } 496 containsPoint(const Vec3 & point) const497 bool Brush::containsPoint(const Vec3& point) const { 498 if (!bounds().contains(point)) 499 return false; 500 501 BrushFaceList::const_iterator it, end; 502 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 503 const BrushFace* face = *it; 504 if (face->boundary().pointStatus(point) == Math::PointStatus::PSAbove) 505 return false; 506 } 507 return true; 508 } 509 incidentFaces(const BrushVertex * vertex) const510 BrushFaceList Brush::incidentFaces(const BrushVertex* vertex) const { 511 BrushFaceList result; 512 result.reserve(m_faces.size()); 513 514 BrushHalfEdge* first = vertex->leaving(); 515 BrushHalfEdge* current = first; 516 do { 517 result.push_back(current->face()->payload()); 518 current = current->nextIncident(); 519 } while (current != first); 520 521 return result; 522 } 523 canMoveVertices(const BBox3 & worldBounds,const Vec3::List & vertexPositions,const Vec3 & delta)524 bool Brush::canMoveVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, const Vec3& delta) { 525 assert(m_geometry != NULL); 526 assert(!vertexPositions.empty()); 527 if (delta.null()) 528 return false; 529 530 BrushGeometry testGeometry(*m_geometry); 531 const SetTempFaceLinks setFaceLinks(this, testGeometry); 532 533 const BrushGeometry::MoveVerticesResult result = testGeometry.moveVertices(vertexPositions, delta, true); 534 return !result.hasUnchangedVertices() && !result.hasUnknownVertices() && worldBounds.contains(testGeometry.bounds()); 535 } 536 moveVertices(const BBox3 & worldBounds,const Vec3::List & vertexPositions,const Vec3 & delta)537 Vec3::List Brush::moveVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, const Vec3& delta) { 538 assert(m_geometry != NULL); 539 assert(!vertexPositions.empty()); 540 assert(canMoveVertices(worldBounds, vertexPositions, delta)); 541 542 const NotifyNodeChange nodeChange(this); 543 MoveVerticesCallback callback; 544 const BrushGeometry::MoveVerticesResult result = m_geometry->moveVertices(vertexPositions, delta, true, callback); 545 updateFacesFromGeometry(worldBounds); 546 nodeBoundsDidChange(); 547 548 return result.newVertexPositions; 549 } 550 canSnapVertices(const BBox3 & worldBounds,const Vec3::List & vertexPositions,const size_t snapTo)551 bool Brush::canSnapVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, const size_t snapTo) { 552 assert(m_geometry != NULL); 553 assert(!vertexPositions.empty()); 554 555 const FloatType snapToF = static_cast<FloatType>(snapTo); 556 557 BrushGeometry testGeometry(*m_geometry); 558 const SetTempFaceLinks setFaceLinks(this, testGeometry); 559 560 Vec3::List::const_iterator it, end; 561 for (it = vertexPositions.begin(), end = vertexPositions.end(); it != end; ++it) { 562 const Vec3 origin = *it; 563 const Vec3 destination = snapToF * origin.rounded() / snapToF; 564 if (!origin.equals(destination)) { 565 const Vec3 delta = destination - origin; 566 const BrushGeometry::MoveVerticesResult result = testGeometry.moveVertices(Vec3::List(1, origin), delta, true); 567 if (result.hasUnchangedVertices()) 568 return false; 569 } 570 } 571 572 return true; 573 } 574 snapVertices(const BBox3 & worldBounds,const Vec3::List & vertexPositions,const size_t snapTo)575 Vec3::List Brush::snapVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, const size_t snapTo) { 576 assert(m_geometry != NULL); 577 assert(!vertexPositions.empty()); 578 assert(canSnapVertices(worldBounds, vertexPositions, snapTo)); 579 580 const FloatType snapToF = static_cast<FloatType>(snapTo); 581 Vec3::Set newVertexPositions; 582 583 const NotifyNodeChange nodeChange(this); 584 MoveVerticesCallback callback; 585 586 Vec3::List::const_iterator it, end; 587 for (it = vertexPositions.begin(), end = vertexPositions.end(); it != end; ++it) { 588 const Vec3 origin = *it; 589 const Vec3 destination = snapToF * (origin / snapToF).rounded(); 590 if (!origin.equals(destination)) { 591 const Vec3 delta = destination - origin; 592 const BrushGeometry::MoveVerticesResult result = m_geometry->moveVertices(Vec3::List(1, origin), delta, true, callback); 593 if (!result.hasUnknownVertices() && !result.hasDeletedVertices()) 594 newVertexPositions.insert(result.newVertexPositions.front()); 595 } 596 } 597 598 updateFacesFromGeometry(worldBounds); 599 updatePointsFromVertices(worldBounds); 600 nodeBoundsDidChange(); 601 602 return Vec3::List(newVertexPositions.begin(), newVertexPositions.end()); 603 } 604 canMoveEdges(const BBox3 & worldBounds,const Edge3::List & edgePositions,const Vec3 & delta)605 bool Brush::canMoveEdges(const BBox3& worldBounds, const Edge3::List& edgePositions, const Vec3& delta) { 606 assert(m_geometry != NULL); 607 assert(!edgePositions.empty()); 608 if (delta.null()) 609 return true; 610 611 BrushGeometry testGeometry(*m_geometry); 612 const SetTempFaceLinks setFaceLinks(this, testGeometry); 613 614 const Vec3::List vertexPositions = Edge3::asVertexList(edgePositions); 615 const BrushGeometry::MoveVerticesResult result = testGeometry.moveVertices(vertexPositions, delta, false); 616 if (!result.allVerticesMoved() || !worldBounds.contains(testGeometry.bounds())) 617 return false; 618 619 Edge3::List::const_iterator it, end; 620 for (it = edgePositions.begin(), end = edgePositions.end(); it != end; ++it) { 621 const Edge3& edge = *it; 622 const Edge3 newEdge(edge.start() + delta, edge.end() + delta); 623 if (!testGeometry.hasEdge(newEdge.start(), newEdge.end())) 624 return false; 625 } 626 627 return true; 628 } 629 moveEdges(const BBox3 & worldBounds,const Edge3::List & edgePositions,const Vec3 & delta)630 Edge3::List Brush::moveEdges(const BBox3& worldBounds, const Edge3::List& edgePositions, const Vec3& delta) { 631 assert(m_geometry != NULL); 632 assert(!edgePositions.empty()); 633 assert(canMoveEdges(worldBounds, edgePositions, delta)); 634 635 const NotifyNodeChange nodeChange(this); 636 MoveVerticesCallback callback; 637 const Vec3::List vertexPositions = Edge3::asVertexList(edgePositions); 638 m_geometry->moveVertices(vertexPositions, delta, false, callback); 639 updateFacesFromGeometry(worldBounds); 640 nodeBoundsDidChange(); 641 642 Edge3::List result; 643 result.reserve(edgePositions.size()); 644 645 Edge3::List::const_iterator it, end; 646 for (it = edgePositions.begin(), end = edgePositions.end(); it != end; ++it) { 647 const Edge3& edge = *it; 648 const Edge3 newEdge(edge.start() + delta, edge.end() + delta); 649 assert(m_geometry->hasEdge(newEdge.start(), newEdge.end())); 650 result.push_back(newEdge); 651 } 652 653 return result; 654 } 655 canSplitEdge(const BBox3 & worldBounds,const Edge3 & edgePosition,const Vec3 & delta)656 bool Brush::canSplitEdge(const BBox3& worldBounds, const Edge3& edgePosition, const Vec3& delta) { 657 assert(m_geometry != NULL); 658 if (delta.null()) 659 return false; 660 661 BrushGeometry testGeometry(*m_geometry); 662 const SetTempFaceLinks setFaceLinks(this, testGeometry); 663 664 const BrushGeometry::MoveVerticesResult result = testGeometry.splitEdge(edgePosition.start(), edgePosition.end(), delta); 665 return result.allVerticesMoved() && worldBounds.contains(testGeometry.bounds()); 666 } 667 splitEdge(const BBox3 & worldBounds,const Edge3 & edgePosition,const Vec3 & delta)668 Vec3 Brush::splitEdge(const BBox3& worldBounds, const Edge3& edgePosition, const Vec3& delta) { 669 assert(m_geometry != NULL); 670 assert(canSplitEdge(worldBounds, edgePosition, delta)); 671 672 const NotifyNodeChange nodeChange(this); 673 674 MoveVerticesCallback callback; 675 const BrushGeometry::MoveVerticesResult result = m_geometry->splitEdge(edgePosition.start(), edgePosition.end(), delta, callback); 676 677 assert(result.allVerticesMoved()); 678 updateFacesFromGeometry(worldBounds); 679 nodeBoundsDidChange(); 680 681 return result.newVertexPositions.front(); 682 } 683 canMoveFaces(const BBox3 & worldBounds,const Polygon3::List & facePositions,const Vec3 & delta)684 bool Brush::canMoveFaces(const BBox3& worldBounds, const Polygon3::List& facePositions, const Vec3& delta) { 685 assert(m_geometry != NULL); 686 assert(!facePositions.empty()); 687 if (delta.null()) 688 return false; 689 690 BrushGeometry testGeometry(*m_geometry); 691 const SetTempFaceLinks setFaceLinks(this, testGeometry); 692 693 const Vec3::List vertexPositions = Polygon3::asVertexList(facePositions); 694 const BrushGeometry::MoveVerticesResult result = testGeometry.moveVertices(vertexPositions, delta, false); 695 696 if (!result.allVerticesMoved() || !worldBounds.contains(testGeometry.bounds())) 697 return false; 698 699 Polygon3::List::const_iterator fIt, fEnd; 700 for (fIt = facePositions.begin(), fEnd = facePositions.end(); fIt != fEnd; ++fIt) { 701 const Polygon3& face = *fIt; 702 const Polygon3 newFace(face.vertices() + delta); 703 if (!testGeometry.hasFace(newFace.vertices())) 704 return false; 705 } 706 707 return true; 708 } 709 moveFaces(const BBox3 & worldBounds,const Polygon3::List & facePositions,const Vec3 & delta)710 Polygon3::List Brush::moveFaces(const BBox3& worldBounds, const Polygon3::List& facePositions, const Vec3& delta) { 711 assert(m_geometry != NULL); 712 assert(!facePositions.empty()); 713 assert(canMoveFaces(worldBounds, facePositions, delta)); 714 715 const NotifyNodeChange nodeChange(this); 716 MoveVerticesCallback callback; 717 const Vec3::List vertexPositions = Polygon3::asVertexList(facePositions); 718 m_geometry->moveVertices(vertexPositions, delta, false, callback); 719 updateFacesFromGeometry(worldBounds); 720 nodeBoundsDidChange(); 721 722 Polygon3::List result; 723 result.reserve(facePositions.size()); 724 725 Polygon3::List::const_iterator fIt, fEnd; 726 for (fIt = facePositions.begin(), fEnd = facePositions.end(); fIt != fEnd; ++fIt) { 727 const Polygon3& face = *fIt; 728 const Polygon3 newFace(face.vertices() + delta); 729 assert(m_geometry->hasFace(newFace.vertices())); 730 result.push_back(newFace); 731 } 732 733 return result; 734 } 735 canSplitFace(const BBox3 & worldBounds,const Polygon3 & facePosition,const Vec3 & delta)736 bool Brush::canSplitFace(const BBox3& worldBounds, const Polygon3& facePosition, const Vec3& delta) { 737 assert(m_geometry != NULL); 738 if (delta.null()) 739 return false; 740 741 BrushGeometry testGeometry(*m_geometry); 742 const SetTempFaceLinks setFaceLinks(this, testGeometry); 743 const BrushGeometry::MoveVerticesResult result = testGeometry.splitFace(facePosition.vertices(), delta); 744 return result.allVerticesMoved() && worldBounds.contains(testGeometry.bounds()); 745 } 746 splitFace(const BBox3 & worldBounds,const Polygon3 & facePosition,const Vec3 & delta)747 Vec3 Brush::splitFace(const BBox3& worldBounds, const Polygon3& facePosition, const Vec3& delta) { 748 assert(m_geometry != NULL); 749 assert(canSplitFace(worldBounds, facePosition, delta)); 750 751 const NotifyNodeChange nodeChange(this); 752 753 MoveVerticesCallback callback; 754 const BrushGeometry::MoveVerticesResult result = m_geometry->splitFace(facePosition.vertices(), delta, callback); 755 assert(result.allVerticesMoved()); 756 updateFacesFromGeometry(worldBounds); 757 nodeBoundsDidChange(); 758 759 return result.newVertexPositions.front(); 760 } 761 subtract(const ModelFactory & factory,const BBox3 & worldBounds,const String & defaultTextureName,const Brush * subtrahend) const762 BrushList Brush::subtract(const ModelFactory& factory, const BBox3& worldBounds, const String& defaultTextureName, const Brush* subtrahend) const { 763 const BrushGeometry::SubtractResult result = m_geometry->subtract(*subtrahend->m_geometry); 764 765 BrushList brushes(0); 766 brushes.reserve(result.size()); 767 768 BrushGeometry::SubtractResult::const_iterator it, end; 769 for (it = result.begin(), end = result.end(); it != end; ++it) { 770 const BrushGeometry& geometry = *it; 771 Brush* brush = createBrush(factory, worldBounds, defaultTextureName, geometry, subtrahend); 772 brushes.push_back(brush); 773 } 774 775 return brushes; 776 } 777 intersect(const BBox3 & worldBounds,const Brush * brush)778 void Brush::intersect(const BBox3& worldBounds, const Brush* brush) { 779 const BrushFaceList& theirFaces = brush->faces(); 780 781 BrushFaceList::const_iterator it, end; 782 for (it = theirFaces.begin(), end = theirFaces.end(); it != end; ++it) { 783 const BrushFace* theirFace = *it; 784 addFace(theirFace->clone()); 785 } 786 787 rebuildGeometry(worldBounds); 788 } 789 createBrush(const ModelFactory & factory,const BBox3 & worldBounds,const String & defaultTextureName,const BrushGeometry & geometry,const Brush * subtrahend) const790 Brush* Brush::createBrush(const ModelFactory& factory, const BBox3& worldBounds, const String& defaultTextureName, const BrushGeometry& geometry, const Brush* subtrahend) const { 791 BrushFaceList faces(0); 792 faces.reserve(geometry.faceCount()); 793 794 BrushFaceGeometry* firstFace = geometry.faces().front(); 795 BrushFaceGeometry* currentFace = firstFace; 796 do { 797 const BrushGeometry::HalfEdge* h1 = currentFace->boundary().front(); 798 const BrushGeometry::HalfEdge* h0 = h1->next(); 799 const BrushGeometry::HalfEdge* h2 = h0->next(); 800 801 const Vec3& p0 = h0->origin()->position(); 802 const Vec3& p1 = h1->origin()->position(); 803 const Vec3& p2 = h2->origin()->position(); 804 805 BrushFaceAttributes attribs(defaultTextureName); 806 faces.push_back(factory.createFace(p0, p1, p2, attribs)); 807 808 currentFace = currentFace->next(); 809 } while (currentFace != firstFace); 810 811 Brush* brush = factory.createBrush(worldBounds, faces); 812 brush->cloneFaceAttributesFrom(this); 813 brush->cloneInvertedFaceAttributesFrom(subtrahend); 814 return brush; 815 } 816 updateFacesFromGeometry(const BBox3 & worldBounds)817 void Brush::updateFacesFromGeometry(const BBox3& worldBounds) { 818 m_faces.clear(); 819 820 BrushFaceGeometry* first = m_geometry->faces().front(); 821 BrushFaceGeometry* current = first; 822 do { 823 BrushFace* face = current->payload(); 824 if (face != NULL) { // could happen if the brush isn't fully specified 825 if (face->brush() == NULL) 826 addFace(face); 827 else 828 m_faces.push_back(face); 829 } 830 current = current->next(); 831 } while (current != first); 832 833 invalidateContentType(); 834 } 835 updatePointsFromVertices(const BBox3 & worldBounds)836 void Brush::updatePointsFromVertices(const BBox3& worldBounds) { 837 BrushFaceGeometry* first = m_geometry->faces().front(); 838 BrushFaceGeometry* current = first; 839 do { 840 BrushFace* face = current->payload(); 841 face->updatePointsFromVertices(); 842 current = current->next(); 843 } while (current != first); 844 845 rebuildGeometry(worldBounds); 846 } 847 rebuildGeometry(const BBox3 & worldBounds)848 void Brush::rebuildGeometry(const BBox3& worldBounds) { 849 delete m_geometry; 850 m_geometry = new BrushGeometry(worldBounds.expanded(1.0)); 851 852 AddFacesToGeometry addFacesToGeometry(*m_geometry, m_faces); 853 updateFacesFromGeometry(worldBounds); 854 if (addFacesToGeometry.brushEmpty()) 855 throw GeometryException("Brush is empty"); 856 if (!addFacesToGeometry.brushValid()) 857 throw GeometryException("Brush is invalid"); 858 if (!fullySpecified()) 859 throw GeometryException("Brush is not fully specified"); 860 nodeBoundsDidChange(); 861 } 862 findIntegerPlanePoints(const BBox3 & worldBounds)863 void Brush::findIntegerPlanePoints(const BBox3& worldBounds) { 864 const NotifyNodeChange nodeChange(this); 865 866 BrushFaceList::const_iterator it, end; 867 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 868 BrushFace* brushFace = *it; 869 brushFace->findIntegerPlanePoints(); 870 } 871 rebuildGeometry(worldBounds); 872 } 873 checkGeometry() const874 bool Brush::checkGeometry() const { 875 BrushFaceList::const_iterator fIt, fEnd; 876 for (fIt = m_faces.begin(), fEnd = m_faces.end(); fIt != fEnd; ++fIt) { 877 const BrushFace* face = *fIt; 878 if (face->geometry() == NULL) 879 return false; 880 if (!m_geometry->faces().contains(face->geometry())) 881 return false; 882 } 883 884 const BrushGeometry::FaceList& faceGeometries = m_geometry->faces(); 885 BrushGeometry::FaceList::const_iterator gIt, gEnd; 886 for (gIt = faceGeometries.begin(), gEnd = faceGeometries.end(); gIt != gEnd; ++gIt) { 887 const BrushFaceGeometry* geometry = *gIt; 888 if (geometry->payload() == NULL) 889 return false; 890 if (!VectorUtils::contains(m_faces, geometry->payload())) 891 return false; 892 } 893 894 return true; 895 } 896 transparent() const897 bool Brush::transparent() const { 898 if (!m_contentTypeValid) 899 validateContentType(); 900 return m_transparent; 901 } 902 hasContentType(const BrushContentType & contentType) const903 bool Brush::hasContentType(const BrushContentType& contentType) const { 904 return hasContentType(contentType.flagValue()); 905 } 906 hasContentType(const BrushContentType::FlagType contentTypeMask) const907 bool Brush::hasContentType(const BrushContentType::FlagType contentTypeMask) const { 908 return (contentTypeFlags() & contentTypeMask) != 0; 909 } 910 setContentTypeBuilder(const BrushContentTypeBuilder * contentTypeBuilder)911 void Brush::setContentTypeBuilder(const BrushContentTypeBuilder* contentTypeBuilder) { 912 m_contentTypeBuilder = contentTypeBuilder; 913 invalidateContentType(); 914 } 915 contentTypeFlags() const916 BrushContentType::FlagType Brush::contentTypeFlags() const { 917 if (!m_contentTypeValid) 918 validateContentType(); 919 return m_contentType; 920 } 921 invalidateContentType()922 void Brush::invalidateContentType() { 923 m_contentTypeValid = false; 924 } 925 validateContentType() const926 void Brush::validateContentType() const { 927 assert(!m_contentTypeValid); 928 if (m_contentTypeBuilder != NULL) { 929 const BrushContentTypeBuilder::Result result = m_contentTypeBuilder->buildContentType(this); 930 m_contentType = result.contentType; 931 m_transparent = result.transparent; 932 m_contentTypeValid = true; 933 } 934 } 935 doGetName() const936 const String& Brush::doGetName() const { 937 static const String name("brush"); 938 return name; 939 } 940 doGetBounds() const941 const BBox3& Brush::doGetBounds() const { 942 assert(m_geometry != NULL); 943 return m_geometry->bounds(); 944 } 945 doClone(const BBox3 & worldBounds) const946 Node* Brush::doClone(const BBox3& worldBounds) const { 947 BrushFaceList faceClones; 948 faceClones.reserve(m_faces.size()); 949 950 BrushFaceList::const_iterator it, end; 951 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 952 const BrushFace* face = *it; 953 faceClones.push_back(face->clone()); 954 } 955 956 Brush* brush = new Brush(worldBounds, faceClones); 957 brush->setContentTypeBuilder(m_contentTypeBuilder); 958 cloneAttributes(brush); 959 return brush; 960 } 961 doCanAddChild(const Node * child) const962 bool Brush::doCanAddChild(const Node* child) const { 963 return false; 964 } 965 doCanRemoveChild(const Node * child) const966 bool Brush::doCanRemoveChild(const Node* child) const { 967 return false; 968 } 969 doRemoveIfEmpty() const970 bool Brush::doRemoveIfEmpty() const { 971 return false; 972 } 973 doParentDidChange()974 void Brush::doParentDidChange() { 975 invalidateContentType(); 976 } 977 doSelectable() const978 bool Brush::doSelectable() const { 979 return true; 980 } 981 doGenerateIssues(const IssueGenerator * generator,IssueList & issues)982 void Brush::doGenerateIssues(const IssueGenerator* generator, IssueList& issues) { 983 generator->generate(this, issues); 984 } 985 doAccept(NodeVisitor & visitor)986 void Brush::doAccept(NodeVisitor& visitor) { 987 visitor.visit(this); 988 } 989 doAccept(ConstNodeVisitor & visitor) const990 void Brush::doAccept(ConstNodeVisitor& visitor) const { 991 visitor.visit(this); 992 } 993 doPick(const Ray3 & ray,PickResult & pickResult) const994 void Brush::doPick(const Ray3& ray, PickResult& pickResult) const { 995 const BrushFaceHit hit = findFaceHit(ray); 996 if (hit.face != NULL) { 997 assert(!Math::isnan(hit.distance)); 998 const Vec3 hitPoint = ray.pointAtDistance(hit.distance); 999 pickResult.addHit(Hit(BrushHit, hit.distance, hitPoint, hit.face)); 1000 } 1001 } 1002 doFindNodesContaining(const Vec3 & point,NodeList & result)1003 void Brush::doFindNodesContaining(const Vec3& point, NodeList& result) { 1004 if (containsPoint(point)) 1005 result.push_back(this); 1006 } 1007 doIntersectWithRay(const Ray3 & ray) const1008 FloatType Brush::doIntersectWithRay(const Ray3& ray) const { 1009 const BrushFaceHit hit = findFaceHit(ray); 1010 return hit.distance; 1011 } 1012 BrushFaceHit()1013 Brush::BrushFaceHit::BrushFaceHit() : face(NULL), distance(Math::nan<FloatType>()) {} 1014 BrushFaceHit(BrushFace * i_face,const FloatType i_distance)1015 Brush::BrushFaceHit::BrushFaceHit(BrushFace* i_face, const FloatType i_distance) : face(i_face), distance(i_distance) {} 1016 findFaceHit(const Ray3 & ray) const1017 Brush::BrushFaceHit Brush::findFaceHit(const Ray3& ray) const { 1018 if (Math::isnan(bounds().intersectWithRay(ray))) 1019 return BrushFaceHit(); 1020 1021 BrushFaceList::const_iterator it, end; 1022 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 1023 BrushFace* face = *it; 1024 const FloatType distance = face->intersectWithRay(ray); 1025 if (!Math::isnan(distance)) 1026 return BrushFaceHit(face, distance); 1027 } 1028 return BrushFaceHit(); 1029 } 1030 doGetContainer() const1031 Node* Brush::doGetContainer() const { 1032 FindContainerVisitor visitor; 1033 escalate(visitor); 1034 return visitor.hasResult() ? visitor.result() : NULL; 1035 } 1036 doGetLayer() const1037 Layer* Brush::doGetLayer() const { 1038 FindLayerVisitor visitor; 1039 escalate(visitor); 1040 return visitor.hasResult() ? visitor.result() : NULL; 1041 } 1042 doGetGroup() const1043 Group* Brush::doGetGroup() const { 1044 FindGroupVisitor visitor(false); 1045 escalate(visitor); 1046 return visitor.hasResult() ? visitor.result() : NULL; 1047 } 1048 doTransform(const Mat4x4 & transformation,bool lockTextures,const BBox3 & worldBounds)1049 void Brush::doTransform(const Mat4x4& transformation, bool lockTextures, const BBox3& worldBounds) { 1050 const NotifyNodeChange nodeChange(this); 1051 1052 BrushFaceList::const_iterator it, end; 1053 for (it = m_faces.begin(), end = m_faces.end(); it != end; ++it) { 1054 BrushFace* face = *it; 1055 face->transform(transformation, lockTextures); 1056 } 1057 rebuildGeometry(worldBounds); 1058 } 1059 1060 class Brush::Contains : public ConstNodeVisitor, public NodeQuery<bool> { 1061 private: 1062 const Brush* m_this; 1063 public: Contains(const Brush * i_this)1064 Contains(const Brush* i_this) : 1065 m_this(i_this) {} 1066 private: doVisit(const World * world)1067 void doVisit(const World* world) { setResult(false); } doVisit(const Layer * layer)1068 void doVisit(const Layer* layer) { setResult(false); } doVisit(const Group * group)1069 void doVisit(const Group* group) { setResult(contains(group->bounds())); } doVisit(const Entity * entity)1070 void doVisit(const Entity* entity) { setResult(contains(entity->bounds())); } doVisit(const Brush * brush)1071 void doVisit(const Brush* brush) { setResult(contains(brush)); } 1072 contains(const BBox3 & bounds) const1073 bool contains(const BBox3& bounds) const { 1074 if (m_this->bounds().contains(bounds)) 1075 return true; 1076 const Vec3::List vertices = bBoxVertices(bounds); 1077 for (size_t i = 0; i < vertices.size(); ++i) { 1078 if (!m_this->containsPoint(vertices[i])) 1079 return false; 1080 } 1081 return true; 1082 } 1083 contains(const Brush * brush) const1084 bool contains(const Brush* brush) const { 1085 return m_this->m_geometry->contains(*brush->m_geometry, QueryCallback()); 1086 } 1087 }; 1088 doContains(const Node * node) const1089 bool Brush::doContains(const Node* node) const { 1090 Contains contains(this); 1091 node->accept(contains); 1092 assert(contains.hasResult()); 1093 return contains.result(); 1094 } 1095 1096 class Brush::Intersects : public ConstNodeVisitor, public NodeQuery<bool> { 1097 private: 1098 const Brush* m_this; 1099 public: Intersects(const Brush * i_this)1100 Intersects(const Brush* i_this) : 1101 m_this(i_this) {} 1102 private: doVisit(const World * world)1103 void doVisit(const World* world) { setResult(false); } doVisit(const Layer * layer)1104 void doVisit(const Layer* layer) { setResult(false); } doVisit(const Group * group)1105 void doVisit(const Group* group) { setResult(intersects(group->bounds())); } doVisit(const Entity * entity)1106 void doVisit(const Entity* entity) { setResult(intersects(entity->bounds())); } doVisit(const Brush * brush)1107 void doVisit(const Brush* brush) { setResult(intersects(brush)); } 1108 intersects(const BBox3 & bounds) const1109 bool intersects(const BBox3& bounds) const { 1110 return m_this->bounds().intersects(bounds); 1111 } 1112 intersects(const Brush * brush)1113 bool intersects(const Brush* brush) { 1114 return m_this->m_geometry->intersects(*brush->m_geometry, QueryCallback()); 1115 } 1116 }; 1117 doIntersects(const Node * node) const1118 bool Brush::doIntersects(const Node* node) const { 1119 Intersects intersects(this); 1120 node->accept(intersects); 1121 assert(intersects.hasResult()); 1122 return intersects.result(); 1123 } 1124 } 1125 } 1126