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