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 #ifndef TrenchBroom_Brush
21 #define TrenchBroom_Brush
22 
23 #include "TrenchBroom.h"
24 #include "VecMath.h"
25 #include "Hit.h"
26 #include "ProjectingSequence.h"
27 #include "Model/BrushContentType.h"
28 #include "Model/BrushGeometry.h"
29 #include "Model/Node.h"
30 #include "Model/Object.h"
31 
32 namespace TrenchBroom {
33     namespace Model {
34         struct BrushAlgorithmResult;
35         class BrushContentTypeBuilder;
36         class ModelFactory;
37         class PickResult;
38 
39         class Brush : public Node, public Object {
40         private:
41             friend class SetTempFaceLinks;
42         public:
43             static const Hit::HitType BrushHit;
44         private:
45             struct ProjectToVertex : public ProjectingSequenceProjector<BrushVertex*, BrushVertex*> {
46                 static BrushVertex*& project(BrushVertex*& vertex);
47             };
48 
49             struct ProjectToEdge : public ProjectingSequenceProjector<BrushEdge*, BrushEdge*> {
50                 static BrushEdge*& project(BrushEdge*& edge);
51             };
52 
53             class AddFaceToGeometryCallback;
54             class HealEdgesCallback;
55             class AddFacesToGeometry;
56             class CanMoveBoundaryCallback;
57             class CanMoveBoundary;
58             class MoveVerticesCallback;
59             class QueryCallback;
60         public:
61             typedef ConstProjectingSequence<BrushVertexList, ProjectToVertex> VertexList;
62             typedef ConstProjectingSequence<BrushEdgeList, ProjectToEdge> EdgeList;
63         private:
64             BrushFaceList m_faces;
65             BrushGeometry* m_geometry;
66 
67             const BrushContentTypeBuilder* m_contentTypeBuilder;
68             mutable BrushContentType::FlagType m_contentType;
69             mutable bool m_transparent;
70             mutable bool m_contentTypeValid;
71         public:
72             Brush(const BBox3& worldBounds, const BrushFaceList& faces);
73             ~Brush();
74         private:
75             void cleanup();
76         public:
77             Brush* clone(const BBox3& worldBounds) const;
78 
79             AttributableNode* entity() const;
80         public: // face management:
81             const BrushFaceList& faces() const;
82             void setFaces(const BBox3& worldBounds, const BrushFaceList& faces);
83 
84             BrushFace* findFaceByNormal(const Vec3& normal) const;
85 
86             bool fullySpecified() const;
87 
88             void faceDidChange();
89         private:
90             void addFaces(const BrushFaceList& faces);
91             template <typename I>
addFaces(I cur,I end,size_t count)92             void addFaces(I cur, I end, size_t count) {
93                 m_faces.reserve(m_faces.size() + count);
94                 while (cur != end) {
95                     addFace(*cur);
96                     ++cur;
97                 }
98             }
99             void addFace(BrushFace* face);
100 
101             template <typename I>
removeFaces(I cur,I end)102             void removeFaces(I cur, I end) {
103                 BrushFaceList::iterator rem = m_faces.end();
104                 while (cur != end) {
105                     rem = doRemoveFace(m_faces.begin(), rem, *cur);
106                     ++cur;
107                 }
108 
109                 m_faces.erase(rem, m_faces.end());
110             }
111 
112             void removeFace(BrushFace* face);
113             BrushFaceList::iterator doRemoveFace(BrushFaceList::iterator begin, BrushFaceList::iterator end, BrushFace* face);
114 
115             void detachFaces(const BrushFaceList& faces);
116             void detachFace(BrushFace* face);
117         public: // clone face attributes from matching faces of other brushes
118             void cloneFaceAttributesFrom(const BrushList& brushes);
119             void cloneFaceAttributesFrom(const Brush* brush);
120             void cloneInvertedFaceAttributesFrom(const BrushList& brushes);
121             void cloneInvertedFaceAttributesFrom(const Brush* brush);
122             BrushFace* findFaceWithBoundary(const Plane3& boundary) const;
123         public: // clipping
124             bool clip(const BBox3& worldBounds, BrushFace* face);
125         public: // move face along normal
126             bool canMoveBoundary(const BBox3& worldBounds, const BrushFace* face, const Vec3& delta) const;
127             void moveBoundary(const BBox3& worldBounds, BrushFace* face, const Vec3& delta, const bool lockTexture);
128         public:
129             // geometry access
130             size_t vertexCount() const;
131             VertexList vertices() const;
132 
133             size_t edgeCount() const;
134             EdgeList edges() const;
135 
136             bool containsPoint(const Vec3& point) const;
137 
138             BrushFaceList incidentFaces(const BrushVertex* vertex) const;
139 
140             // vertex operations
141             bool canMoveVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, const Vec3& delta);
142             Vec3::List moveVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, const Vec3& delta);
143 
144             bool canSnapVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, size_t snapTo);
145             Vec3::List snapVertices(const BBox3& worldBounds, const Vec3::List& vertexPositions, size_t snapTo);
146 
147             // edge operations
148             bool canMoveEdges(const BBox3& worldBounds, const Edge3::List& edgePositions, const Vec3& delta);
149             Edge3::List moveEdges(const BBox3& worldBounds, const Edge3::List& edgePositions, const Vec3& delta);
150             bool canSplitEdge(const BBox3& worldBounds, const Edge3& edgePosition, const Vec3& delta);
151             Vec3 splitEdge(const BBox3& worldBounds, const Edge3& edgePosition, const Vec3& delta);
152 
153             // face operations
154             bool canMoveFaces(const BBox3& worldBounds, const Polygon3::List& facePositions, const Vec3& delta);
155             Polygon3::List moveFaces(const BBox3& worldBounds, const Polygon3::List& facePositions, const Vec3& delta);
156             bool canSplitFace(const BBox3& worldBounds, const Polygon3& facePosition, const Vec3& delta);
157             Vec3 splitFace(const BBox3& worldBounds, const Polygon3& facePosition, const Vec3& delta);
158 
159             // CSG operations
160             BrushList subtract(const ModelFactory& factory, const BBox3& worldBounds, const String& defaultTextureName, const Brush* subtrahend) const;
161             void intersect(const BBox3& worldBounds, const Brush* brush);
162         private:
163             Brush* createBrush(const ModelFactory& factory, const BBox3& worldBounds, const String& defaultTextureName, const BrushGeometry& geometry, const Brush* subtrahend) const;
164         private:
165             void updateFacesFromGeometry(const BBox3& worldBounds);
166             void updatePointsFromVertices(const BBox3& worldBounds);
167         public: // brush geometry
168             void rebuildGeometry(const BBox3& worldBounds);
169             void findIntegerPlanePoints(const BBox3& worldBounds);
170         private:
171             bool checkGeometry() const;
172         public: // content type
173             bool transparent() const;
174             bool hasContentType(const BrushContentType& contentType) const;
175             bool hasContentType(BrushContentType::FlagType contentTypeMask) const;
176             void setContentTypeBuilder(const BrushContentTypeBuilder* contentTypeBuilder);
177         private:
178             BrushContentType::FlagType contentTypeFlags() const;
179             void invalidateContentType();
180             void validateContentType() const;
181         private: // implement Node interface
182             const String& doGetName() const;
183             const BBox3& doGetBounds() const;
184 
185             Node* doClone(const BBox3& worldBounds) const;
186             NodeSnapshot* doTakeSnapshot();
187 
188             bool doCanAddChild(const Node* child) const;
189             bool doCanRemoveChild(const Node* child) const;
190             bool doRemoveIfEmpty() const;
191 
192             void doParentDidChange();
193 
194             bool doSelectable() const;
195 
196             void doGenerateIssues(const IssueGenerator* generator, IssueList& issues);
197             void doAccept(NodeVisitor& visitor);
198             void doAccept(ConstNodeVisitor& visitor) const;
199         private: // implement Object interface
200             void doPick(const Ray3& ray, PickResult& pickResult) const;
201             void doFindNodesContaining(const Vec3& point, NodeList& result);
202             FloatType doIntersectWithRay(const Ray3& ray) const;
203 
204             struct BrushFaceHit {
205                 BrushFace* face;
206                 FloatType distance;
207 				BrushFaceHit();
208                 BrushFaceHit(BrushFace* i_face, FloatType i_distance);
209             };
210 
211             BrushFaceHit findFaceHit(const Ray3& ray) const;
212 
213             Node* doGetContainer() const;
214             Layer* doGetLayer() const;
215             Group* doGetGroup() const;
216 
217             void doTransform(const Mat4x4& transformation, bool lockTextures, const BBox3& worldBounds);
218 
219             class Contains;
220             bool doContains(const Node* node) const;
221 
222             class Intersects;
223             bool doIntersects(const Node* node) const;
224         private:
225             Brush(const Brush&);
226             Brush& operator=(const Brush&);
227         };
228     }
229 }
230 
231 #endif /* defined(TrenchBroom_Brush) */
232