]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brush.cpp
added install.py; updated COMPILING; fixed q3 shader transparency rendering; jedi...
[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
24 std::set<Callback> g_brushTextureChangedCallbacks;
25
26 void Brush_addTextureChangedCallback(const Callback& callback)
27 {
28   g_brushTextureChangedCallbacks.insert(callback);
29 }
30
31 void Brush_textureChanged()
32 {
33   std::for_each(g_brushTextureChangedCallbacks.begin(), g_brushTextureChangedCallbacks.end(), CallbackInvoke());
34 }
35
36 QuantiseFunc Face::m_quantise;
37 EBrushType Face::m_type;
38 EBrushType FacePlane::m_type;
39 bool g_brush_texturelock_enabled = false;
40
41 EBrushType Brush::m_type;
42 double Brush::m_maxWorldCoord = 0;
43 Shader* Brush::m_state_point;
44 Shader* BrushClipPlane::m_state = 0;
45 Shader* BrushInstance::m_state_selpoint;
46 Counter* BrushInstance::m_counter = 0;
47
48 FaceInstanceSet g_SelectedFaceInstances;
49
50
51 struct SListNode
52 {
53   SListNode* m_next;
54 };
55
56 class ProximalVertex
57 {
58 public:
59   const SListNode* m_vertices;
60
61   ProximalVertex(const SListNode* next)
62     : m_vertices(next)
63   {
64   }
65
66   bool operator<(const ProximalVertex& other) const
67   {
68     if(!(operator==(other)))
69     {
70       return m_vertices < other.m_vertices;
71     }
72     return false;
73   }
74   bool operator==(const ProximalVertex& other) const
75   {
76     const SListNode* v = m_vertices;
77     std::size_t DEBUG_LOOP = 0;
78     do
79     {
80       if(v == other.m_vertices)
81         return true;
82       v = v->m_next;
83       //ASSERT_MESSAGE(DEBUG_LOOP < c_brush_maxFaces, "infinite loop");
84       if(!(DEBUG_LOOP < c_brush_maxFaces))
85       {
86         break;
87       }
88       ++DEBUG_LOOP;
89     }
90     while(v != m_vertices);
91     return false;
92   }
93 };
94
95 typedef Array<SListNode> ProximalVertexArray;
96 std::size_t ProximalVertexArray_index(const ProximalVertexArray& array, const ProximalVertex& vertex)
97 {
98   return vertex.m_vertices - array.data();
99 }
100
101
102
103 inline bool Brush_isBounded(const Brush& brush)
104 {
105   for(Brush::const_iterator i = brush.begin(); i != brush.end(); ++i)
106   {
107     if(!(*i)->is_bounded())
108     {
109       return false;
110     }
111   }
112   return true;
113 }
114
115 void Brush::buildBRep()
116 {
117   bool degenerate = buildWindings();
118
119   std::size_t faces_size = 0;
120   std::size_t faceVerticesCount = 0;
121   for(Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i)
122   {
123     if((*i)->contributes())
124     {
125       ++faces_size;
126     }
127     faceVerticesCount += (*i)->getWinding().numpoints;
128   }
129
130   if(degenerate || faces_size < 4 || faceVerticesCount != (faceVerticesCount>>1)<<1) // sum of vertices for each face of a valid polyhedron is always even
131   {
132     m_uniqueVertexPoints.resize(0);
133
134     vertex_clear();
135     edge_clear();
136
137     m_edge_indices.resize(0);
138     m_edge_faces.resize(0);
139
140     m_faceCentroidPoints.resize(0);
141     m_uniqueEdgePoints.resize(0);
142     m_uniqueVertexPoints.resize(0);
143
144     for(Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i)
145     {
146       (*i)->getWinding().resize(0);
147     }
148   }
149   else
150   {
151     {
152       typedef std::vector<FaceVertexId> FaceVertices;
153       FaceVertices faceVertices;
154       faceVertices.reserve(faceVerticesCount);
155
156       {
157         for(std::size_t i = 0; i != m_faces.size(); ++i)
158         {
159           for(std::size_t j = 0; j < m_faces[i]->getWinding().numpoints; ++j)
160           {
161             faceVertices.push_back(FaceVertexId(i, j));
162           }
163         }
164       }
165
166       IndexBuffer uniqueEdgeIndices;
167       typedef VertexBuffer<ProximalVertex> UniqueEdges;
168       UniqueEdges uniqueEdges;
169
170       uniqueEdgeIndices.reserve(faceVertices.size());
171       uniqueEdges.reserve(faceVertices.size());
172
173       {
174         ProximalVertexArray edgePairs;
175         edgePairs.resize(faceVertices.size());
176
177         {
178           for(std::size_t i=0; i<faceVertices.size(); ++i)
179           {
180             edgePairs[i].m_next = edgePairs.data() + absoluteIndex(next_edge(m_faces, faceVertices[i]));
181           }
182         }
183
184         {
185           UniqueVertexBuffer<ProximalVertex> inserter(uniqueEdges);
186           for(ProximalVertexArray::iterator i = edgePairs.begin(); i != edgePairs.end(); ++i)
187           {
188             uniqueEdgeIndices.insert(inserter.insert(ProximalVertex(&(*i))));
189           }
190         }
191
192         {
193           edge_clear();
194           m_select_edges.reserve(uniqueEdges.size());
195           for(UniqueEdges::iterator i = uniqueEdges.begin(); i != uniqueEdges.end(); ++i)
196           {
197             edge_push_back(faceVertices[ProximalVertexArray_index(edgePairs, *i)]);
198           }
199         }
200
201         {
202           m_edge_faces.resize(uniqueEdges.size());
203           for(std::size_t i=0; i<uniqueEdges.size(); ++i)
204           {
205             FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(edgePairs, uniqueEdges[i])];
206             m_edge_faces[i] = EdgeFaces(faceVertex.getFace(), m_faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent);
207           }
208         }
209
210         {
211           m_uniqueEdgePoints.resize(uniqueEdges.size());
212           for(std::size_t i=0; i<uniqueEdges.size(); ++i)
213           {
214             FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(edgePairs, uniqueEdges[i])];
215
216             const Winding& w = m_faces[faceVertex.getFace()]->getWinding();
217             Vector3 edge = vector3_mid(w[faceVertex.getVertex()].vertex, w[Winding_next(w, faceVertex.getVertex())].vertex);
218             m_uniqueEdgePoints[i] = pointvertex_for_windingpoint(edge, colour_vertex);
219           }
220         }
221
222       }
223     
224
225       IndexBuffer uniqueVertexIndices;
226       typedef VertexBuffer<ProximalVertex> UniqueVertices;
227       UniqueVertices uniqueVertices;
228
229       uniqueVertexIndices.reserve(faceVertices.size());
230       uniqueVertices.reserve(faceVertices.size());
231
232       {
233         ProximalVertexArray vertexRings;
234         vertexRings.resize(faceVertices.size());
235
236         {
237           for(std::size_t i=0; i<faceVertices.size(); ++i)
238           {
239             vertexRings[i].m_next = vertexRings.data() + absoluteIndex(next_vertex(m_faces, faceVertices[i]));
240           }
241         }
242
243         {
244           UniqueVertexBuffer<ProximalVertex> inserter(uniqueVertices);
245           for(ProximalVertexArray::iterator i = vertexRings.begin(); i != vertexRings.end(); ++i)
246           {
247             uniqueVertexIndices.insert(inserter.insert(ProximalVertex(&(*i))));
248           }
249         }
250
251         {
252           vertex_clear();
253           m_select_vertices.reserve(uniqueVertices.size());  
254           for(UniqueVertices::iterator i = uniqueVertices.begin(); i != uniqueVertices.end(); ++i)
255           {
256             vertex_push_back(faceVertices[ProximalVertexArray_index(vertexRings, (*i))]);
257           }
258         }
259
260         {
261           m_uniqueVertexPoints.resize(uniqueVertices.size());
262           for(std::size_t i=0; i<uniqueVertices.size(); ++i)
263           {
264             FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(vertexRings, uniqueVertices[i])];
265
266             const Winding& winding = m_faces[faceVertex.getFace()]->getWinding();
267             m_uniqueVertexPoints[i] = pointvertex_for_windingpoint(winding[faceVertex.getVertex()].vertex, colour_vertex);
268           }
269         }
270       }
271
272       ASSERT_MESSAGE((uniqueVertices.size() + faces_size) - uniqueEdges.size() == 2, "Final B-Rep: inconsistent vertex count");
273
274 #if BRUSH_CONNECTIVITY_DEBUG
275       if((uniqueVertices.size() + faces_size) - uniqueEdges.size() != 2)
276       {
277         for(Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i)
278         {
279                   std::size_t faceIndex = std::distance(m_faces.begin(), i);
280
281           if(!(*i)->contributes())
282           {
283             globalOutputStream() << "face: " << Unsigned(faceIndex) << " does not contribute\n";
284           }
285
286           Winding_printConnectivity((*i)->getWinding());
287         }
288       }
289 #endif
290
291       // edge-index list for wireframe rendering
292       {
293         m_edge_indices.resize(uniqueEdgeIndices.size());
294
295         for(std::size_t i=0, count=0; i<m_faces.size(); ++i)
296         {
297           const Winding& winding = m_faces[i]->getWinding();
298           for(std::size_t j = 0; j < winding.numpoints; ++j)
299           {
300             const RenderIndex edge_index = uniqueEdgeIndices[count+j];
301
302             m_edge_indices[edge_index].first = uniqueVertexIndices[count + j];
303             m_edge_indices[edge_index].second = uniqueVertexIndices[count + Winding_next(winding, j)];
304           }
305           count += winding.numpoints;
306         }
307       }
308     }
309
310     {
311       m_faceCentroidPoints.resize(m_faces.size());
312       for(std::size_t i=0; i<m_faces.size(); ++i)
313       {
314         m_faces[i]->construct_centroid();
315         m_faceCentroidPoints[i] = pointvertex_for_windingpoint(m_faces[i]->centroid(), colour_vertex);
316       }
317     }
318   }
319 }
320
321
322 class FaceFilterWrapper : public Filter
323 {
324   FaceFilter& m_filter;
325   bool m_active;
326   bool m_invert;
327 public:
328   FaceFilterWrapper(FaceFilter& filter, bool invert) :
329     m_filter(filter),
330     m_invert(invert)
331   {
332   }
333   void setActive(bool active)
334   {
335     m_active = active;
336   }
337   bool active()
338   {
339     return m_active;
340   }
341   bool filter(const Face& face)
342   {
343     return m_invert ^ m_filter.filter(face);
344   }
345 };
346
347
348 typedef std::list<FaceFilterWrapper> FaceFilters;
349 FaceFilters g_faceFilters;
350
351 void add_face_filter(FaceFilter& filter, int mask, bool invert)
352 {
353   g_faceFilters.push_back(FaceFilterWrapper(filter, invert));
354   GlobalFilterSystem().addFilter(g_faceFilters.back(), mask);
355 }
356
357 bool face_filtered(Face& face)
358 {
359   for(FaceFilters::iterator i = g_faceFilters.begin(); i != g_faceFilters.end(); ++i)
360   {
361     if((*i).active() && (*i).filter(face))
362     {
363       return true;
364     }
365   }
366   return false;
367 }
368
369
370 class BrushFilterWrapper : public Filter
371 {
372   bool m_active;
373   bool m_invert;
374   BrushFilter& m_filter;
375 public:
376   BrushFilterWrapper(BrushFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
377   {
378   }
379   void setActive(bool active)
380   {
381     m_active = active;
382   }
383   bool active()
384   {
385     return m_active;
386   }
387   bool filter(const Brush& brush)
388   {
389     return m_invert ^ m_filter.filter(brush);
390   }
391 };
392
393
394 typedef std::list<BrushFilterWrapper> BrushFilters;
395 BrushFilters g_brushFilters;
396
397 void add_brush_filter(BrushFilter& filter, int mask, bool invert)
398 {
399   g_brushFilters.push_back(BrushFilterWrapper(filter, invert));
400   GlobalFilterSystem().addFilter(g_brushFilters.back(), mask);
401 }
402
403 bool brush_filtered(Brush& brush)
404 {
405   for(BrushFilters::iterator i = g_brushFilters.begin(); i != g_brushFilters.end(); ++i)
406   {
407     if((*i).active() && (*i).filter(brush))
408     {
409       return true;
410     }
411   }
412   return false;
413 }
414
415