]> git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brush.cpp
gcc: appease the hardening warnings
[xonotic/netradiant.git] / radiant / brush.cpp
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "brush.h"
23 #include "signal/signal.h"
24
25 Signal0 g_brushTextureChangedCallbacks;
26
27 void Brush_addTextureChangedCallback(const SignalHandler &handler)
28 {
29     g_brushTextureChangedCallbacks.connectLast(handler);
30 }
31
32 void Brush_textureChanged()
33 {
34     g_brushTextureChangedCallbacks();
35 }
36
37 QuantiseFunc Face::m_quantise;
38 EBrushType Face::m_type;
39 EBrushType FacePlane::m_type;
40 bool g_brush_texturelock_enabled = true;
41
42 EBrushType Brush::m_type;
43 double Brush::m_maxWorldCoord = 0;
44 Shader *Brush::m_state_point;
45 Shader *BrushClipPlane::m_state = 0;
46 Shader *BrushInstance::m_state_selpoint;
47 Counter *BrushInstance::m_counter = 0;
48
49 FaceInstanceSet g_SelectedFaceInstances;
50
51
52 struct SListNode {
53     SListNode *m_next;
54 };
55
56 class ProximalVertex {
57 public:
58     const SListNode *m_vertices;
59
60     ProximalVertex(const SListNode *next)
61             : m_vertices(next)
62     {
63     }
64
65     bool operator<(const ProximalVertex &other) const
66     {
67         if (!(operator==(other))) {
68             return m_vertices < other.m_vertices;
69         }
70         return false;
71     }
72
73     bool operator==(const ProximalVertex &other) const
74     {
75         const SListNode *v = m_vertices;
76         std::size_t DEBUG_LOOP = 0;
77         do {
78             if (v == other.m_vertices) {
79                 return true;
80             }
81             v = v->m_next;
82             //ASSERT_MESSAGE(DEBUG_LOOP < c_brush_maxFaces, "infinite loop");
83             if (!(DEBUG_LOOP < c_brush_maxFaces)) {
84                 break;
85             }
86             ++DEBUG_LOOP;
87         } while (v != m_vertices);
88         return false;
89     }
90 };
91
92 typedef Array<SListNode> ProximalVertexArray;
93
94 std::size_t ProximalVertexArray_index(const ProximalVertexArray &array, const ProximalVertex &vertex)
95 {
96     return vertex.m_vertices - array.data();
97 }
98
99
100 inline bool Brush_isBounded(const Brush &brush)
101 {
102     for (Brush::const_iterator i = brush.begin(); i != brush.end(); ++i) {
103         if (!(*i)->is_bounded()) {
104             return false;
105         }
106     }
107     return true;
108 }
109
110 void Brush::buildBRep()
111 {
112     bool degenerate = buildWindings();
113
114     std::size_t faces_size = 0;
115     std::size_t faceVerticesCount = 0;
116     for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) {
117         if ((*i)->contributes()) {
118             ++faces_size;
119         }
120         faceVerticesCount += (*i)->getWinding().numpoints;
121     }
122
123     if (degenerate || faces_size < 4 || faceVerticesCount != (faceVerticesCount >> 1)
124             << 1) { // sum of vertices for each face of a valid polyhedron is always even
125         m_uniqueVertexPoints.resize(0);
126
127         vertex_clear();
128         edge_clear();
129
130         m_edge_indices.resize(0);
131         m_edge_faces.resize(0);
132
133         m_faceCentroidPoints.resize(0);
134         m_uniqueEdgePoints.resize(0);
135         m_uniqueVertexPoints.resize(0);
136
137         for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) {
138             (*i)->getWinding().resize(0);
139         }
140     } else {
141         {
142             typedef std::vector<FaceVertexId> FaceVertices;
143             FaceVertices faceVertices;
144             faceVertices.reserve(faceVerticesCount);
145
146             {
147                 for (std::size_t i = 0; i != m_faces.size(); ++i) {
148                     for (std::size_t j = 0; j < m_faces[i]->getWinding().numpoints; ++j) {
149                         faceVertices.push_back(FaceVertexId(i, j));
150                     }
151                 }
152             }
153
154             IndexBuffer uniqueEdgeIndices;
155             typedef VertexBuffer<ProximalVertex> UniqueEdges;
156             UniqueEdges uniqueEdges;
157
158             uniqueEdgeIndices.reserve(faceVertices.size());
159             uniqueEdges.reserve(faceVertices.size());
160
161             {
162                 ProximalVertexArray edgePairs;
163                 edgePairs.resize(faceVertices.size());
164
165                 {
166                     for (std::size_t i = 0; i < faceVertices.size(); ++i) {
167                         edgePairs[i].m_next = edgePairs.data() + absoluteIndex(next_edge(m_faces, faceVertices[i]));
168                     }
169                 }
170
171                 {
172                     UniqueVertexBuffer<ProximalVertex> inserter(uniqueEdges);
173                     for (ProximalVertexArray::iterator i = edgePairs.begin(); i != edgePairs.end(); ++i) {
174                         uniqueEdgeIndices.insert(inserter.insert(ProximalVertex(&(*i))));
175                     }
176                 }
177
178                 {
179                     edge_clear();
180                     m_select_edges.reserve(uniqueEdges.size());
181                     for (UniqueEdges::iterator i = uniqueEdges.begin(); i != uniqueEdges.end(); ++i) {
182                         edge_push_back(faceVertices[ProximalVertexArray_index(edgePairs, *i)]);
183                     }
184                 }
185
186                 {
187                     m_edge_faces.resize(uniqueEdges.size());
188                     for (std::size_t i = 0; i < uniqueEdges.size(); ++i) {
189                         FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(edgePairs, uniqueEdges[i])];
190                         m_edge_faces[i] = EdgeFaces(faceVertex.getFace(),
191                                                     m_faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent);
192                     }
193                 }
194
195                 {
196                     m_uniqueEdgePoints.resize(uniqueEdges.size());
197                     for (std::size_t i = 0; i < uniqueEdges.size(); ++i) {
198                         FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(edgePairs, uniqueEdges[i])];
199
200                         const Winding &w = m_faces[faceVertex.getFace()]->getWinding();
201                         Vector3 edge = vector3_mid(w[faceVertex.getVertex()].vertex,
202                                                    w[Winding_next(w, faceVertex.getVertex())].vertex);
203                         m_uniqueEdgePoints[i] = pointvertex_for_windingpoint(edge, colour_vertex);
204                     }
205                 }
206
207             }
208
209
210             IndexBuffer uniqueVertexIndices;
211             typedef VertexBuffer<ProximalVertex> UniqueVertices;
212             UniqueVertices uniqueVertices;
213
214             uniqueVertexIndices.reserve(faceVertices.size());
215             uniqueVertices.reserve(faceVertices.size());
216
217             {
218                 ProximalVertexArray vertexRings;
219                 vertexRings.resize(faceVertices.size());
220
221                 {
222                     for (std::size_t i = 0; i < faceVertices.size(); ++i) {
223                         vertexRings[i].m_next =
224                                 vertexRings.data() + absoluteIndex(next_vertex(m_faces, faceVertices[i]));
225                     }
226                 }
227
228                 {
229                     UniqueVertexBuffer<ProximalVertex> inserter(uniqueVertices);
230                     for (ProximalVertexArray::iterator i = vertexRings.begin(); i != vertexRings.end(); ++i) {
231                         uniqueVertexIndices.insert(inserter.insert(ProximalVertex(&(*i))));
232                     }
233                 }
234
235                 {
236                     vertex_clear();
237                     m_select_vertices.reserve(uniqueVertices.size());
238                     for (UniqueVertices::iterator i = uniqueVertices.begin(); i != uniqueVertices.end(); ++i) {
239                         vertex_push_back(faceVertices[ProximalVertexArray_index(vertexRings, (*i))]);
240                     }
241                 }
242
243                 {
244                     m_uniqueVertexPoints.resize(uniqueVertices.size());
245                     for (std::size_t i = 0; i < uniqueVertices.size(); ++i) {
246                         FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(vertexRings,
247                                                                                          uniqueVertices[i])];
248
249                         const Winding &winding = m_faces[faceVertex.getFace()]->getWinding();
250                         m_uniqueVertexPoints[i] = pointvertex_for_windingpoint(winding[faceVertex.getVertex()].vertex,
251                                                                                colour_vertex);
252                     }
253                 }
254             }
255
256             if ((uniqueVertices.size() + faces_size) - uniqueEdges.size() != 2) {
257                 globalErrorStream() << "Final B-Rep: inconsistent vertex count\n";
258             }
259
260 #if BRUSH_CONNECTIVITY_DEBUG
261             if ( ( uniqueVertices.size() + faces_size ) - uniqueEdges.size() != 2 ) {
262                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
263                 {
264                     std::size_t faceIndex = std::distance( m_faces.begin(), i );
265
266                     if ( !( *i )->contributes() ) {
267                         globalOutputStream() << "face: " << Unsigned( faceIndex ) << " does not contribute\n";
268                     }
269
270                     Winding_printConnectivity( ( *i )->getWinding() );
271                 }
272             }
273 #endif
274
275             // edge-index list for wireframe rendering
276             {
277                 m_edge_indices.resize(uniqueEdgeIndices.size());
278
279                 for (std::size_t i = 0, count = 0; i < m_faces.size(); ++i) {
280                     const Winding &winding = m_faces[i]->getWinding();
281                     for (std::size_t j = 0; j < winding.numpoints; ++j) {
282                         const RenderIndex edge_index = uniqueEdgeIndices[count + j];
283
284                         m_edge_indices[edge_index].first = uniqueVertexIndices[count + j];
285                         m_edge_indices[edge_index].second = uniqueVertexIndices[count + Winding_next(winding, j)];
286                     }
287                     count += winding.numpoints;
288                 }
289             }
290         }
291
292         {
293             m_faceCentroidPoints.resize(m_faces.size());
294             for (std::size_t i = 0; i < m_faces.size(); ++i) {
295                 m_faces[i]->construct_centroid();
296                 m_faceCentroidPoints[i] = pointvertex_for_windingpoint(m_faces[i]->centroid(), colour_vertex);
297             }
298         }
299     }
300 }
301
302
303 class FaceFilterWrapper : public Filter {
304     FaceFilter &m_filter;
305     bool m_active = false;
306     bool m_invert;
307 public:
308     FaceFilterWrapper(FaceFilter &filter, bool invert) :
309             m_filter(filter),
310             m_invert(invert)
311     {
312     }
313
314     void setActive(bool active)
315     {
316         m_active = active;
317     }
318
319     bool active()
320     {
321         return m_active;
322     }
323
324     bool filter(const Face &face)
325     {
326         return m_invert ^ m_filter.filter(face);
327     }
328 };
329
330
331 typedef std::list<FaceFilterWrapper> FaceFilters;
332 FaceFilters g_faceFilters;
333
334 void add_face_filter(FaceFilter &filter, int mask, bool invert)
335 {
336     g_faceFilters.push_back(FaceFilterWrapper(filter, invert));
337     GlobalFilterSystem().addFilter(g_faceFilters.back(), mask);
338 }
339
340 bool face_filtered(Face &face)
341 {
342     for (FaceFilters::iterator i = g_faceFilters.begin(); i != g_faceFilters.end(); ++i) {
343         if ((*i).active() && (*i).filter(face)) {
344             return true;
345         }
346     }
347     return false;
348 }
349
350
351 class BrushFilterWrapper : public Filter {
352     bool m_active = false;
353     bool m_invert;
354     BrushFilter &m_filter;
355 public:
356     BrushFilterWrapper(BrushFilter &filter, bool invert) : m_invert(invert), m_filter(filter)
357     {
358     }
359
360     void setActive(bool active)
361     {
362         m_active = active;
363     }
364
365     bool active()
366     {
367         return m_active;
368     }
369
370     bool filter(const Brush &brush)
371     {
372         return m_invert ^ m_filter.filter(brush);
373     }
374 };
375
376
377 typedef std::list<BrushFilterWrapper> BrushFilters;
378 BrushFilters g_brushFilters;
379
380 void add_brush_filter(BrushFilter &filter, int mask, bool invert)
381 {
382     g_brushFilters.push_back(BrushFilterWrapper(filter, invert));
383     GlobalFilterSystem().addFilter(g_brushFilters.back(), mask);
384 }
385
386 bool brush_filtered(Brush &brush)
387 {
388     for (BrushFilters::iterator i = g_brushFilters.begin(); i != g_brushFilters.end(); ++i) {
389         if ((*i).active() && (*i).filter(brush)) {
390             return true;
391         }
392     }
393     return false;
394 }