]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brush.h
gtkgl module: drop
[xonotic/netradiant.git] / radiant / brush.h
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 #if !defined( INCLUDED_BRUSH_H )
23 #define INCLUDED_BRUSH_H
24
25 /// \file
26 /// \brief The brush primitive.
27 ///
28 /// A collection of planes that define a convex polyhedron.
29 /// The Boundary-Representation of this primitive is a manifold polygonal mesh.
30 /// Each face polygon is represented by a list of vertices in a \c Winding.
31 /// Each vertex is associated with another face that is adjacent to the edge
32 /// formed by itself and the next vertex in the winding. This information can
33 /// be used to find edge-pairs and vertex-rings.
34
35
36 #include "debugging/debugging.h"
37
38 #include "itexdef.h"
39 #include "iundo.h"
40 #include "iselection.h"
41 #include "irender.h"
42 #include "imap.h"
43 #include "ibrush.h"
44 #include "igl.h"
45 #include "ifilter.h"
46 #include "nameable.h"
47 #include "moduleobserver.h"
48
49 #include <set>
50
51 #include "cullable.h"
52 #include "renderable.h"
53 #include "selectable.h"
54 #include "editable.h"
55 #include "mapfile.h"
56
57 #include "math/frustum.h"
58 #include "selectionlib.h"
59 #include "render.h"
60 #include "texturelib.h"
61 #include "container/container.h"
62 #include "generic/bitfield.h"
63 #include "signal/signalfwd.h"
64
65 #include "winding.h"
66 #include "brush_primit.h"
67
68 const unsigned int BRUSH_DETAIL_FLAG = 27;
69 const unsigned int BRUSH_DETAIL_MASK = ( 1 << BRUSH_DETAIL_FLAG );
70
71 enum EBrushType
72 {
73         eBrushTypeQuake,
74         eBrushTypeQuake2,
75         eBrushTypeQuake3,
76         eBrushTypeQuake3BP,
77         eBrushTypeDoom3,
78         eBrushTypeQuake4,
79         eBrushTypeHalfLife,
80 };
81
82
83 #define BRUSH_CONNECTIVITY_DEBUG 0
84 #define BRUSH_DEGENERATE_DEBUG 0
85
86 template<typename TextOuputStreamType>
87 inline TextOuputStreamType& ostream_write( TextOuputStreamType& ostream, const Matrix4& m ){
88         return ostream << "(" << m[0] << " " << m[1] << " " << m[2] << " " << m[3] << ", "
89                                    << m[4] << " " << m[5] << " " << m[6] << " " << m[7] << ", "
90                                    << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << ", "
91                                    << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << ")";
92 }
93
94 inline void print_vector3( const Vector3& v ){
95         globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n";
96 }
97
98 inline void print_3x3( const Matrix4& m ){
99         globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) "
100                                                  << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) "
101                                                  << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n";
102 }
103
104
105 inline bool texdef_sane( const texdef_t& texdef ){
106         return fabs( texdef.shift[0] ) < ( 1 << 16 )
107                    && fabs( texdef.shift[1] ) < ( 1 << 16 );
108 }
109
110 inline void Winding_DrawWireframe( const Winding& winding ){
111         glVertexPointer( 3, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->vertex );
112         glDrawArrays( GL_LINE_LOOP, 0, GLsizei( winding.numpoints ) );
113 }
114
115 inline void Winding_Draw( const Winding& winding, const Vector3& normal, RenderStateFlags state ){
116         glVertexPointer( 3, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->vertex );
117
118         if ( ( state & RENDER_BUMP ) != 0 ) {
119                 Vector3 normals[c_brush_maxFaces];
120                 typedef Vector3* Vector3Iter;
121                 for ( Vector3Iter i = normals, end = normals + winding.numpoints; i != end; ++i )
122                 {
123                         *i = normal;
124                 }
125                 if ( GlobalShaderCache().useShaderLanguage() ) {
126                         glNormalPointer( GL_FLOAT, sizeof( Vector3 ), normals );
127                         glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->texcoord );
128                         glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->tangent );
129                         glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->bitangent );
130                 }
131                 else
132                 {
133                         glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( Vector3 ), normals );
134                         glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->texcoord );
135                         glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->tangent );
136                         glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->bitangent );
137                 }
138         }
139         else
140         {
141                 if ( state & RENDER_LIGHTING ) {
142                         Vector3 normals[c_brush_maxFaces];
143                         typedef Vector3* Vector3Iter;
144                         for ( Vector3Iter i = normals, last = normals + winding.numpoints; i != last; ++i )
145                         {
146                                 *i = normal;
147                         }
148                         glNormalPointer( GL_FLOAT, sizeof( Vector3 ), normals );
149                 }
150
151                 if ( state & RENDER_TEXTURE ) {
152                         glTexCoordPointer( 2, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->texcoord );
153                 }
154         }
155 #if 0
156         if ( state & RENDER_FILL ) {
157                 glDrawArrays( GL_TRIANGLE_FAN, 0, GLsizei( winding.numpoints ) );
158         }
159         else
160         {
161                 glDrawArrays( GL_LINE_LOOP, 0, GLsizei( winding.numpoints ) );
162         }
163 #else
164         glDrawArrays( GL_POLYGON, 0, GLsizei( winding.numpoints ) );
165 #endif
166
167 #if 0
168         const Winding& winding = winding;
169
170         if ( state & RENDER_FILL ) {
171                 glBegin( GL_POLYGON );
172         }
173         else
174         {
175                 glBegin( GL_LINE_LOOP );
176         }
177
178         if ( state & RENDER_LIGHTING ) {
179                 glNormal3fv( normal );
180         }
181
182         for ( int i = 0; i < winding.numpoints; ++i )
183         {
184                 if ( state & RENDER_TEXTURE ) {
185                         glTexCoord2fv( &winding.points[i][3] );
186                 }
187                 glVertex3fv( winding.points[i] );
188         }
189         glEnd();
190 #endif
191 }
192
193
194 #include "shaderlib.h"
195
196 typedef DoubleVector3 PlanePoints[3];
197
198 inline bool planepts_equal( const PlanePoints planepts, const PlanePoints other ){
199         return planepts[0] == other[0] && planepts[1] == other[1] && planepts[2] == other[2];
200 }
201
202 inline void planepts_assign( PlanePoints planepts, const PlanePoints other ){
203         planepts[0] = other[0];
204         planepts[1] = other[1];
205         planepts[2] = other[2];
206 }
207
208 inline void planepts_quantise( PlanePoints planepts, double snap ){
209         vector3_snap( planepts[0], snap );
210         vector3_snap( planepts[1], snap );
211         vector3_snap( planepts[2], snap );
212 }
213
214 inline float vector3_max_component( const Vector3& vec3 ){
215         return std::max( fabsf( vec3[0] ), std::max( fabsf( vec3[1] ), fabsf( vec3[2] ) ) );
216 }
217
218 inline void edge_snap( Vector3& edge, double snap ){
219         float scale = static_cast<float>( ceil( fabs( snap / vector3_max_component( edge ) ) ) );
220         if ( scale > 0.0f ) {
221                 vector3_scale( edge, scale );
222         }
223         vector3_snap( edge, snap );
224 }
225
226 inline void planepts_snap( PlanePoints planepts, double snap ){
227         Vector3 edge01( vector3_subtracted( planepts[1], planepts[0] ) );
228         Vector3 edge12( vector3_subtracted( planepts[2], planepts[1] ) );
229         Vector3 edge20( vector3_subtracted( planepts[0], planepts[2] ) );
230
231         double length_squared_01 = vector3_dot( edge01, edge01 );
232         double length_squared_12 = vector3_dot( edge12, edge12 );
233         double length_squared_20 = vector3_dot( edge20, edge20 );
234
235         vector3_snap( planepts[0], snap );
236
237         if ( length_squared_01 < length_squared_12 ) {
238                 if ( length_squared_12 < length_squared_20 ) {
239                         edge_snap( edge01, snap );
240                         edge_snap( edge12, snap );
241                         planepts[1] = vector3_added( planepts[0], edge01 );
242                         planepts[2] = vector3_added( planepts[1], edge12 );
243                 }
244                 else
245                 {
246                         edge_snap( edge20, snap );
247                         edge_snap( edge01, snap );
248                         planepts[1] = vector3_added( planepts[0], edge20 );
249                         planepts[2] = vector3_added( planepts[1], edge01 );
250                 }
251         }
252         else
253         {
254                 if ( length_squared_01 < length_squared_20 ) {
255                         edge_snap( edge01, snap );
256                         edge_snap( edge12, snap );
257                         planepts[1] = vector3_added( planepts[0], edge01 );
258                         planepts[2] = vector3_added( planepts[1], edge12 );
259                 }
260                 else
261                 {
262                         edge_snap( edge12, snap );
263                         edge_snap( edge20, snap );
264                         planepts[1] = vector3_added( planepts[0], edge12 );
265                         planepts[2] = vector3_added( planepts[1], edge20 );
266                 }
267         }
268 }
269
270 inline PointVertex pointvertex_for_planept( const DoubleVector3& point, const Colour4b& colour ){
271         return PointVertex(
272                            Vertex3f(
273                                    static_cast<float>( point.x() ),
274                                    static_cast<float>( point.y() ),
275                                    static_cast<float>( point.z() )
276                                    ),
277                            colour
278                            );
279 }
280
281 inline PointVertex pointvertex_for_windingpoint( const Vector3& point, const Colour4b& colour ){
282         return PointVertex(
283                            vertex3f_for_vector3( point ),
284                            colour
285                            );
286 }
287
288 inline bool check_plane_is_integer( const PlanePoints& planePoints ){
289         return !float_is_integer( planePoints[0][0] )
290                    || !float_is_integer( planePoints[0][1] )
291                    || !float_is_integer( planePoints[0][2] )
292                    || !float_is_integer( planePoints[1][0] )
293                    || !float_is_integer( planePoints[1][1] )
294                    || !float_is_integer( planePoints[1][2] )
295                    || !float_is_integer( planePoints[2][0] )
296                    || !float_is_integer( planePoints[2][1] )
297                    || !float_is_integer( planePoints[2][2] );
298 }
299
300 inline void brush_check_shader( const char* name ){
301         if ( !shader_valid( name ) ) {
302                 globalErrorStream() << "brush face has invalid texture name: '" << name << "'\n";
303         }
304 }
305
306 class FaceShaderObserver
307 {
308 public:
309         virtual void realiseShader() = 0;
310         virtual void unrealiseShader() = 0;
311 };
312
313 typedef ReferencePair<FaceShaderObserver> FaceShaderObserverPair;
314
315
316 class ContentsFlagsValue
317 {
318 public:
319         ContentsFlagsValue(){
320         }
321
322         ContentsFlagsValue( int surfaceFlags, int contentFlags, int value, bool specified ) :
323                 m_surfaceFlags( surfaceFlags ),
324                 m_contentFlags( contentFlags ),
325                 m_value( value ),
326                 m_specified( specified ){
327         }
328
329         int m_surfaceFlags;
330         int m_contentFlags;
331         int m_value;
332         bool m_specified;
333 };
334
335 inline void ContentsFlagsValue_assignMasked( ContentsFlagsValue& flags, const ContentsFlagsValue& other ){
336         bool detail = bitfield_enabled( flags.m_contentFlags, BRUSH_DETAIL_MASK );
337         flags = other;
338         if ( detail ) {
339                 flags.m_contentFlags = bitfield_enable( flags.m_contentFlags, BRUSH_DETAIL_MASK );
340         }
341         else
342         {
343                 flags.m_contentFlags = bitfield_disable( flags.m_contentFlags, BRUSH_DETAIL_MASK );
344         }
345 }
346
347
348 class FaceShader : public ModuleObserver
349 {
350 public:
351         class SavedState
352         {
353         public:
354                 CopiedString m_shader;
355                 ContentsFlagsValue m_flags;
356
357                 SavedState( const FaceShader& faceShader ){
358                         m_shader = faceShader.getShader();
359                         m_flags = faceShader.m_flags;
360                 }
361
362                 void exportState( FaceShader& faceShader ) const {
363                         faceShader.setShader( m_shader.c_str() );
364                         faceShader.m_flags = m_flags;
365                 }
366         };
367
368         CopiedString m_shader;
369         Shader* m_state;
370         ContentsFlagsValue m_flags;
371         FaceShaderObserverPair m_observers;
372         bool m_instanced;
373         bool m_realised;
374
375         FaceShader( const char* shader, const ContentsFlagsValue& flags = ContentsFlagsValue( 0, 0, 0, false ) ) :
376                 m_shader( shader ),
377                 m_state( 0 ),
378                 m_flags( flags ),
379                 m_instanced( false ),
380                 m_realised( false ){
381                 captureShader();
382         }
383
384         ~FaceShader(){
385                 releaseShader();
386         }
387
388         // copy-construction not supported
389         FaceShader( const FaceShader& other );
390
391         void instanceAttach(){
392                 m_instanced = true;
393                 m_state->incrementUsed();
394         }
395
396         void instanceDetach(){
397                 m_state->decrementUsed();
398                 m_instanced = false;
399         }
400
401         void captureShader(){
402                 ASSERT_MESSAGE( m_state == 0, "shader cannot be captured" );
403                 brush_check_shader( m_shader.c_str() );
404                 m_state = GlobalShaderCache().capture( m_shader.c_str() );
405                 m_state->attach( *this );
406         }
407
408         void releaseShader(){
409                 ASSERT_MESSAGE( m_state != 0, "shader cannot be released" );
410                 m_state->detach( *this );
411                 GlobalShaderCache().release( m_shader.c_str() );
412                 m_state = 0;
413         }
414
415         void realise(){
416                 ASSERT_MESSAGE( !m_realised, "FaceTexdef::realise: already realised" );
417                 m_realised = true;
418                 m_observers.forEach([](FaceShaderObserver &observer) {
419                         observer.realiseShader();
420                 });
421         }
422
423         void unrealise(){
424                 ASSERT_MESSAGE( m_realised, "FaceTexdef::unrealise: already unrealised" );
425                 m_observers.forEach([](FaceShaderObserver &observer) {
426                         observer.unrealiseShader();
427                 });
428                 m_realised = false;
429         }
430
431         void attach( FaceShaderObserver& observer ){
432                 m_observers.attach( observer );
433                 if ( m_realised ) {
434                         observer.realiseShader();
435                 }
436         }
437
438         void detach( FaceShaderObserver& observer ){
439                 if ( m_realised ) {
440                         observer.unrealiseShader();
441                 }
442                 m_observers.detach( observer );
443         }
444
445         const char* getShader() const {
446                 return m_shader.c_str();
447         }
448         void setShader( const char* name ){
449                 if ( m_instanced ) {
450                         m_state->decrementUsed();
451                 }
452                 releaseShader();
453                 m_shader = name;
454                 captureShader();
455                 if ( m_instanced ) {
456                         m_state->incrementUsed();
457                 }
458         }
459
460         ContentsFlagsValue getFlags() const {
461                 ASSERT_MESSAGE( m_realised, "FaceShader::getFlags: flags not valid when unrealised" );
462                 if ( !m_flags.m_specified ) {
463                         return ContentsFlagsValue(
464                                            m_state->getTexture().surfaceFlags,
465                                            m_state->getTexture().contentFlags,
466                                            m_state->getTexture().value,
467                                            true
468                                            );
469                 }
470                 return m_flags;
471         }
472
473         void setFlags( const ContentsFlagsValue& flags ){
474                 ASSERT_MESSAGE( m_realised, "FaceShader::setFlags: flags not valid when unrealised" );
475                 ContentsFlagsValue_assignMasked( m_flags, flags );
476         }
477
478         Shader* state() const {
479                 return m_state;
480         }
481
482         std::size_t width() const {
483                 if ( m_realised ) {
484                         return m_state->getTexture().width;
485                 }
486                 return 1;
487         }
488
489         std::size_t height() const {
490                 if ( m_realised ) {
491                         return m_state->getTexture().height;
492                 }
493                 return 1;
494         }
495
496         unsigned int shaderFlags() const {
497                 if ( m_realised ) {
498                         return m_state->getFlags();
499                 }
500                 return 0;
501         }
502 };
503
504
505 class FaceTexdef : public FaceShaderObserver
506 {
507         // not copyable
508         FaceTexdef( const FaceTexdef& other );
509
510         // not assignable
511         FaceTexdef& operator=( const FaceTexdef& other );
512
513 public:
514         class SavedState
515         {
516         public:
517                 TextureProjection m_projection;
518
519                 SavedState( const FaceTexdef& faceTexdef ){
520                         m_projection = faceTexdef.m_projection;
521                 }
522
523                 void exportState( FaceTexdef& faceTexdef ) const {
524                         Texdef_Assign( faceTexdef.m_projection, m_projection );
525                 }
526         };
527
528         FaceShader& m_shader;
529         TextureProjection m_projection;
530         bool m_projectionInitialised;
531         bool m_scaleApplied;
532
533         FaceTexdef(
534                 FaceShader& shader,
535                 const TextureProjection& projection,
536                 bool projectionInitialised = true
537                 ) :
538                 m_shader( shader ),
539                 m_projection( projection ),
540                 m_projectionInitialised( projectionInitialised ),
541                 m_scaleApplied( false ){
542                 m_shader.attach( *this );
543         }
544
545         ~FaceTexdef(){
546                 m_shader.detach( *this );
547         }
548
549         void addScale(){
550                 ASSERT_MESSAGE( !m_scaleApplied, "texture scale aready added" );
551                 m_scaleApplied = true;
552                 m_projection.m_brushprimit_texdef.addScale( m_shader.width(), m_shader.height() );
553         }
554
555         void removeScale(){
556                 ASSERT_MESSAGE( m_scaleApplied, "texture scale aready removed" );
557                 m_scaleApplied = false;
558                 m_projection.m_brushprimit_texdef.removeScale( m_shader.width(), m_shader.height() );
559         }
560
561         void realiseShader(){
562                 if ( m_projectionInitialised && !m_scaleApplied ) {
563                         addScale();
564                 }
565         }
566
567         void unrealiseShader(){
568                 if ( m_projectionInitialised && m_scaleApplied ) {
569                         removeScale();
570                 }
571         }
572
573         void setTexdef( const TextureProjection& projection ){
574                 removeScale();
575                 Texdef_Assign( m_projection, projection );
576                 addScale();
577         }
578
579         void shift( float s, float t ){
580                 ASSERT_MESSAGE( texdef_sane( m_projection.m_texdef ), "FaceTexdef::shift: bad texdef" );
581                 removeScale();
582                 Texdef_Shift( m_projection, s, t );
583                 addScale();
584         }
585
586         void scale( float s, float t ){
587                 removeScale();
588                 Texdef_Scale( m_projection, s, t );
589                 addScale();
590         }
591
592         void rotate( float angle ){
593                 removeScale();
594                 Texdef_Rotate( m_projection, angle );
595                 addScale();
596         }
597
598         void fit( const Vector3& normal, const Winding& winding, float s_repeat, float t_repeat ){
599                 Texdef_FitTexture( m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat );
600         }
601
602         void emitTextureCoordinates( Winding& winding, const Vector3& normal, const Matrix4& localToWorld ){
603                 Texdef_EmitTextureCoordinates( m_projection, m_shader.width(), m_shader.height(), winding, normal, localToWorld );
604         }
605
606         void transform( const Plane3& plane, const Matrix4& matrix ){
607                 removeScale();
608                 Texdef_transformLocked( m_projection, m_shader.width(), m_shader.height(), plane, matrix );
609                 addScale();
610         }
611
612         TextureProjection normalised() const {
613                 brushprimit_texdef_t tmp( m_projection.m_brushprimit_texdef );
614                 tmp.removeScale( m_shader.width(), m_shader.height() );
615                 return TextureProjection( m_projection.m_texdef, tmp, m_projection.m_basis_s, m_projection.m_basis_t );
616         }
617
618         void setBasis( const Vector3& normal ){
619                 Matrix4 basis;
620                 Normal_GetTransform( normal, basis );
621                 m_projection.m_basis_s = Vector3( basis.xx(), basis.yx(), basis.zx() );
622                 m_projection.m_basis_t = Vector3( -basis.xy(), -basis.yy(), -basis.zy() );
623         }
624 };
625
626 inline void planepts_print( const PlanePoints& planePoints, TextOutputStream& ostream ){
627         ostream << "( " << planePoints[0][0] << " " << planePoints[0][1] << " " << planePoints[0][2] << " ) "
628                         << "( " << planePoints[1][0] << " " << planePoints[1][1] << " " << planePoints[1][2] << " ) "
629                         << "( " << planePoints[2][0] << " " << planePoints[2][1] << " " << planePoints[2][2] << " )";
630 }
631
632
633 inline Plane3 Plane3_applyTranslation( const Plane3& plane, const Vector3& translation ){
634         Plane3 tmp( plane3_translated( Plane3( plane.normal(), -plane.dist() ), translation ) );
635         return Plane3( tmp.normal(), -tmp.dist() );
636 }
637
638 inline Plane3 Plane3_applyTransform( const Plane3& plane, const Matrix4& matrix ){
639         Plane3 tmp( plane3_transformed( Plane3( plane.normal(), -plane.dist() ), matrix ) );
640         return Plane3( tmp.normal(), -tmp.dist() );
641 }
642
643 class FacePlane
644 {
645         PlanePoints m_planepts;
646         Plane3 m_planeCached;
647         Plane3 m_plane;
648 public:
649         Vector3 m_funcStaticOrigin;
650
651         static EBrushType m_type;
652
653         static bool isDoom3Plane(){
654                 return FacePlane::m_type == eBrushTypeDoom3 || FacePlane::m_type == eBrushTypeQuake4;
655         }
656
657         FacePlane& operator=(const FacePlane&) = default;
658
659         class SavedState
660         {
661         public:
662                 PlanePoints m_planepts;
663                 Plane3 m_plane;
664
665                 SavedState( const FacePlane& facePlane ){
666                         if ( facePlane.isDoom3Plane() ) {
667                                 m_plane = facePlane.m_plane;
668                         }
669                         else
670                         {
671                                 planepts_assign( m_planepts, facePlane.planePoints() );
672                         }
673                 }
674
675                 void exportState( FacePlane& facePlane ) const {
676                         if ( facePlane.isDoom3Plane() ) {
677                                 facePlane.m_plane = m_plane;
678                                 facePlane.updateTranslated();
679                         }
680                         else
681                         {
682                                 planepts_assign( facePlane.planePoints(), m_planepts );
683                                 facePlane.MakePlane();
684                         }
685                 }
686         };
687
688         FacePlane() : m_funcStaticOrigin( 0, 0, 0 ){
689         }
690
691         FacePlane( const FacePlane& other ) : m_funcStaticOrigin( 0, 0, 0 ){
692                 if ( !isDoom3Plane() ) {
693                         planepts_assign( m_planepts, other.m_planepts );
694                         MakePlane();
695                 }
696                 else
697                 {
698                         m_plane = other.m_plane;
699                         updateTranslated();
700                 }
701         }
702
703         void MakePlane(){
704                 if ( !isDoom3Plane() ) {
705 #if 0
706                         if ( check_plane_is_integer( m_planepts ) ) {
707                                 globalErrorStream() << "non-integer planepts: ";
708                                 planepts_print( m_planepts, globalErrorStream() );
709                                 globalErrorStream() << "\n";
710                         }
711 #endif
712                         m_planeCached = plane3_for_points( m_planepts );
713                 }
714         }
715
716         void reverse(){
717                 if ( !isDoom3Plane() ) {
718                         vector3_swap( m_planepts[0], m_planepts[2] );
719                         MakePlane();
720                 }
721                 else
722                 {
723                         m_planeCached = plane3_flipped( m_plane );
724                         updateSource();
725                 }
726         }
727
728         void transform( const Matrix4& matrix, bool mirror ){
729                 if ( !isDoom3Plane() ) {
730
731 #if 0
732                         bool off = check_plane_is_integer( planePoints() );
733 #endif
734
735                         matrix4_transform_point( matrix, m_planepts[0] );
736                         matrix4_transform_point( matrix, m_planepts[1] );
737                         matrix4_transform_point( matrix, m_planepts[2] );
738
739                         if ( mirror ) {
740                                 reverse();
741                         }
742
743 #if 0
744                         if ( check_plane_is_integer( planePoints() ) ) {
745                                 if ( !off ) {
746                                         globalErrorStream() << "caused by transform\n";
747                                 }
748                         }
749 #endif
750                         MakePlane();
751                 }
752                 else
753                 {
754                         m_planeCached = Plane3_applyTransform( m_planeCached, matrix );
755                         updateSource();
756                 }
757         }
758
759         void offset( float offset ){
760                 if ( !isDoom3Plane() ) {
761                         Vector3 move( vector3_scaled( m_planeCached.normal(), -offset ) );
762
763                         vector3_subtract( m_planepts[0], move );
764                         vector3_subtract( m_planepts[1], move );
765                         vector3_subtract( m_planepts[2], move );
766
767                         MakePlane();
768                 }
769                 else
770                 {
771                         m_planeCached.d += offset;
772                         updateSource();
773                 }
774         }
775
776         void updateTranslated(){
777                 m_planeCached = Plane3_applyTranslation( m_plane, m_funcStaticOrigin );
778         }
779
780         void updateSource(){
781                 m_plane = Plane3_applyTranslation( m_planeCached, vector3_negated( m_funcStaticOrigin ) );
782         }
783
784
785         PlanePoints& planePoints(){
786                 return m_planepts;
787         }
788
789         const PlanePoints& planePoints() const {
790                 return m_planepts;
791         }
792
793         const Plane3& plane3() const {
794                 return m_planeCached;
795         }
796
797         void setDoom3Plane( const Plane3& plane ){
798                 m_plane = plane;
799                 updateTranslated();
800         }
801
802         const Plane3& getDoom3Plane() const {
803                 return m_plane;
804         }
805
806         void copy( const FacePlane& other ){
807                 if ( !isDoom3Plane() ) {
808                         planepts_assign( m_planepts, other.m_planepts );
809                         MakePlane();
810                 }
811                 else
812                 {
813                         m_planeCached = other.m_plane;
814                         updateSource();
815                 }
816         }
817
818         void copy( const Vector3& p0, const Vector3& p1, const Vector3& p2 ){
819                 if ( !isDoom3Plane() ) {
820                         m_planepts[0] = p0;
821                         m_planepts[1] = p1;
822                         m_planepts[2] = p2;
823                         MakePlane();
824                 }
825                 else
826                 {
827                         m_planeCached = plane3_for_points( p2, p1, p0 );
828                         updateSource();
829                 }
830         }
831 };
832
833 inline void Winding_testSelect( Winding& winding, SelectionTest& test, SelectionIntersection& best ){
834         test.TestPolygon( VertexPointer( reinterpret_cast<VertexPointer::pointer>( &winding.points.data()->vertex ), sizeof( WindingVertex ) ), winding.numpoints, best );
835 }
836
837 const double GRID_MIN = 0.125;
838
839 inline double quantiseInteger( double f ){
840         return float_to_integer( f );
841 }
842
843 inline double quantiseFloating( double f ){
844         return float_snapped( f, 1.f / ( 1 << 16 ) );
845 }
846
847 typedef double ( *QuantiseFunc )( double f );
848
849 class Face;
850
851 class FaceFilter
852 {
853 public:
854         virtual bool filter( const Face& face ) const = 0;
855 };
856
857 bool face_filtered( Face& face );
858
859 void add_face_filter( FaceFilter& filter, int mask, bool invert = false );
860
861 void Brush_addTextureChangedCallback( const SignalHandler& callback );
862
863 void Brush_textureChanged();
864
865
866 extern bool g_brush_texturelock_enabled;
867
868 class FaceObserver
869 {
870 public:
871         virtual void planeChanged() = 0;
872         virtual void connectivityChanged() = 0;
873         virtual void shaderChanged() = 0;
874         virtual void evaluateTransform() = 0;
875 };
876
877 class Face :
878         public OpenGLRenderable,
879         public Filterable,
880         public Undoable,
881         public FaceShaderObserver
882 {
883 std::size_t m_refcount;
884
885 class SavedState : public UndoMemento
886 {
887 public:
888 FacePlane::SavedState m_planeState;
889 FaceTexdef::SavedState m_texdefState;
890 FaceShader::SavedState m_shaderState;
891
892 SavedState( const Face& face ) : m_planeState( face.getPlane() ), m_texdefState( face.getTexdef() ), m_shaderState( face.getShader() ){
893 }
894
895 void exportState( Face& face ) const {
896         m_planeState.exportState( face.getPlane() );
897         m_shaderState.exportState( face.getShader() );
898         m_texdefState.exportState( face.getTexdef() );
899 }
900
901 void release(){
902         delete this;
903 }
904 };
905
906 public:
907 static QuantiseFunc m_quantise;
908 static EBrushType m_type;
909
910 PlanePoints m_move_planepts;
911 PlanePoints m_move_planeptsTransformed;
912 private:
913 FacePlane m_plane;
914 FacePlane m_planeTransformed;
915 FaceShader m_shader;
916 FaceTexdef m_texdef;
917 TextureProjection m_texdefTransformed;
918
919 Winding m_winding;
920 Vector3 m_centroid;
921 bool m_filtered;
922
923 FaceObserver* m_observer;
924 UndoObserver* m_undoable_observer;
925 MapFile* m_map;
926
927 // assignment not supported
928 Face& operator=( const Face& other );
929
930 // copy-construction not supported
931 Face( const Face& other );
932
933 public:
934
935 Face( FaceObserver* observer ) :
936         m_refcount( 0 ),
937         m_shader( texdef_name_default() ),
938         m_texdef( m_shader, TextureProjection(), false ),
939         m_filtered( false ),
940         m_observer( observer ),
941         m_undoable_observer( 0 ),
942         m_map( 0 ){
943         m_shader.attach( *this );
944         m_plane.copy( Vector3( 0, 0, 0 ), Vector3( 64, 0, 0 ), Vector3( 0, 64, 0 ) );
945         m_texdef.setBasis( m_plane.plane3().normal() );
946         planeChanged();
947 }
948
949 Face(
950         const Vector3& p0,
951         const Vector3& p1,
952         const Vector3& p2,
953         const char* shader,
954         const TextureProjection& projection,
955         FaceObserver* observer
956         ) :
957         m_refcount( 0 ),
958         m_shader( shader ),
959         m_texdef( m_shader, projection ),
960         m_observer( observer ),
961         m_undoable_observer( 0 ),
962         m_map( 0 ){
963         m_shader.attach( *this );
964         m_plane.copy( p0, p1, p2 );
965         m_texdef.setBasis( m_plane.plane3().normal() );
966         planeChanged();
967         updateFiltered();
968 }
969
970 Face( const Face& other, FaceObserver* observer ) :
971         m_refcount( 0 ),
972         m_shader( other.m_shader.getShader(), other.m_shader.m_flags ),
973         m_texdef( m_shader, other.getTexdef().normalised() ),
974         m_observer( observer ),
975         m_undoable_observer( 0 ),
976         m_map( 0 ){
977         m_shader.attach( *this );
978         m_plane.copy( other.m_plane );
979         planepts_assign( m_move_planepts, other.m_move_planepts );
980         m_texdef.setBasis( m_plane.plane3().normal() );
981         planeChanged();
982         updateFiltered();
983 }
984
985 ~Face(){
986         m_shader.detach( *this );
987 }
988
989 void planeChanged(){
990         revertTransform();
991         m_observer->planeChanged();
992 }
993
994 void realiseShader(){
995         m_observer->shaderChanged();
996 }
997
998 void unrealiseShader(){
999 }
1000
1001 void instanceAttach( MapFile* map ){
1002         m_shader.instanceAttach();
1003         m_map = map;
1004         m_undoable_observer = GlobalUndoSystem().observer( this );
1005         GlobalFilterSystem().registerFilterable( *this );
1006 }
1007 void instanceDetach( MapFile* map ){
1008         GlobalFilterSystem().unregisterFilterable( *this );
1009         m_undoable_observer = 0;
1010         GlobalUndoSystem().release( this );
1011         m_map = 0;
1012         m_shader.instanceDetach();
1013 }
1014
1015 void render( RenderStateFlags state ) const {
1016         Winding_Draw( m_winding, m_planeTransformed.plane3().normal(), state );
1017 }
1018
1019 void updateFiltered(){
1020         m_filtered = face_filtered( *this );
1021 }
1022
1023 bool isFiltered() const {
1024         return m_filtered;
1025 }
1026
1027 void undoSave(){
1028         if ( m_map != 0 ) {
1029                 m_map->changed();
1030         }
1031         if ( m_undoable_observer != 0 ) {
1032                 m_undoable_observer->save( this );
1033         }
1034 }
1035
1036 // undoable
1037 UndoMemento* exportState() const {
1038         return new SavedState( *this );
1039 }
1040
1041 void importState( const UndoMemento* data ){
1042         undoSave();
1043
1044         static_cast<const SavedState*>( data )->exportState( *this );
1045
1046         planeChanged();
1047         m_observer->connectivityChanged();
1048         texdefChanged();
1049         m_observer->shaderChanged();
1050         updateFiltered();
1051 }
1052
1053 void IncRef(){
1054         ++m_refcount;
1055 }
1056
1057 void DecRef(){
1058         if ( --m_refcount == 0 ) {
1059                 delete this;
1060         }
1061 }
1062
1063 void flipWinding(){
1064         m_plane.reverse();
1065         planeChanged();
1066 }
1067
1068 bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const {
1069         return volume.TestPlane( Plane3( plane3().normal(), -plane3().dist() ), localToWorld );
1070 }
1071
1072 void render( Renderer& renderer, const Matrix4& localToWorld ) const {
1073         renderer.SetState( m_shader.state(), Renderer::eFullMaterials );
1074         renderer.addRenderable( *this, localToWorld );
1075 }
1076
1077 void transform( const Matrix4& matrix, bool mirror ){
1078         if ( g_brush_texturelock_enabled ) {
1079                 Texdef_transformLocked( m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix );
1080         }
1081
1082         m_planeTransformed.transform( matrix, mirror );
1083
1084 #if 0
1085         ASSERT_MESSAGE( projectionaxis_for_normal( normal ) == projectionaxis_for_normal( plane3().normal() ), "bleh" );
1086 #endif
1087         m_observer->planeChanged();
1088
1089         if ( g_brush_texturelock_enabled ) {
1090                 Brush_textureChanged();
1091         }
1092 }
1093
1094 void assign_planepts( const PlanePoints planepts ){
1095         m_planeTransformed.copy( planepts[0], planepts[1], planepts[2] );
1096         m_observer->planeChanged();
1097 }
1098
1099 /// \brief Reverts the transformable state of the brush to identity.
1100 void revertTransform(){
1101         m_planeTransformed = m_plane;
1102         planepts_assign( m_move_planeptsTransformed, m_move_planepts );
1103         m_texdefTransformed = m_texdef.m_projection;
1104 }
1105
1106 void freezeTransform(){
1107         undoSave();
1108         m_plane = m_planeTransformed;
1109         planepts_assign( m_move_planepts, m_move_planeptsTransformed );
1110         m_texdef.m_projection = m_texdefTransformed;
1111 }
1112
1113 void update_move_planepts_vertex( std::size_t index, PlanePoints planePoints ){
1114         std::size_t numpoints = getWinding().numpoints;
1115         ASSERT_MESSAGE( index < numpoints, "update_move_planepts_vertex: invalid index" );
1116
1117         std::size_t opposite = Winding_Opposite( getWinding(), index );
1118         std::size_t adjacent = Winding_wrap( getWinding(), opposite + numpoints - 1 );
1119         planePoints[0] = getWinding()[opposite].vertex;
1120         planePoints[1] = getWinding()[index].vertex;
1121         planePoints[2] = getWinding()[adjacent].vertex;
1122         // winding points are very inaccurate, so they must be quantised before using them to generate the face-plane
1123         planepts_quantise( planePoints, GRID_MIN );
1124 }
1125
1126 void snapto( float snap ){
1127         if ( contributes() ) {
1128 #if 0
1129                 ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane before snap to grid" );
1130                 planepts_snap( m_plane.planePoints(), snap );
1131                 ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane after snap to grid" );
1132 #else
1133                 PlanePoints planePoints;
1134                 update_move_planepts_vertex( 0, planePoints );
1135                 vector3_snap( planePoints[0], snap );
1136                 vector3_snap( planePoints[1], snap );
1137                 vector3_snap( planePoints[2], snap );
1138                 assign_planepts( planePoints );
1139                 freezeTransform();
1140 #endif
1141                 SceneChangeNotify();
1142                 if ( !plane3_valid( m_plane.plane3() ) ) {
1143                         globalErrorStream() << "WARNING: invalid plane after snap to grid\n";
1144                 }
1145         }
1146 }
1147
1148 void testSelect( SelectionTest& test, SelectionIntersection& best ){
1149         Winding_testSelect( m_winding, test, best );
1150 }
1151
1152 void testSelect_centroid( SelectionTest& test, SelectionIntersection& best ){
1153         test.TestPoint( m_centroid, best );
1154 }
1155
1156 void shaderChanged(){
1157         EmitTextureCoordinates();
1158         Brush_textureChanged();
1159         m_observer->shaderChanged();
1160         updateFiltered();
1161         planeChanged();
1162         SceneChangeNotify();
1163 }
1164
1165 const char* GetShader() const {
1166         return m_shader.getShader();
1167 }
1168
1169 void SetShader( const char* name ){
1170         undoSave();
1171         m_shader.setShader( name );
1172         shaderChanged();
1173 }
1174
1175 void revertTexdef(){
1176         m_texdefTransformed = m_texdef.m_projection;
1177 }
1178
1179 void texdefChanged(){
1180         revertTexdef();
1181         EmitTextureCoordinates();
1182         Brush_textureChanged();
1183 }
1184
1185 void GetTexdef( TextureProjection& projection ) const {
1186         projection = m_texdef.normalised();
1187 }
1188
1189 void SetTexdef( const TextureProjection& projection ){
1190         undoSave();
1191         m_texdef.setTexdef( projection );
1192         texdefChanged();
1193 }
1194
1195 void GetFlags( ContentsFlagsValue& flags ) const {
1196         flags = m_shader.getFlags();
1197 }
1198
1199 void SetFlags( const ContentsFlagsValue& flags ){
1200         undoSave();
1201         m_shader.setFlags( flags );
1202         m_observer->shaderChanged();
1203         updateFiltered();
1204 }
1205
1206 void ShiftTexdef( float s, float t ){
1207         undoSave();
1208         m_texdef.shift( s, t );
1209         texdefChanged();
1210 }
1211
1212 void ScaleTexdef( float s, float t ){
1213         undoSave();
1214         m_texdef.scale( s, t );
1215         texdefChanged();
1216 }
1217
1218 void RotateTexdef( float angle ){
1219         undoSave();
1220         m_texdef.rotate( angle );
1221         texdefChanged();
1222 }
1223
1224 void FitTexture( float s_repeat, float t_repeat ){
1225         undoSave();
1226         m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat );
1227         texdefChanged();
1228 }
1229
1230 void EmitTextureCoordinates(){
1231         Texdef_EmitTextureCoordinates( m_texdefTransformed, m_shader.width(), m_shader.height(), m_winding, plane3().normal(), g_matrix4_identity );
1232 }
1233
1234
1235 const Vector3& centroid() const {
1236         return m_centroid;
1237 }
1238
1239 void construct_centroid(){
1240         Winding_Centroid( m_winding, plane3(), m_centroid );
1241 }
1242
1243 const Winding& getWinding() const {
1244         return m_winding;
1245 }
1246
1247 Winding& getWinding(){
1248         return m_winding;
1249 }
1250
1251 const Plane3& plane3() const {
1252         m_observer->evaluateTransform();
1253         return m_planeTransformed.plane3();
1254 }
1255
1256 FacePlane& getPlane(){
1257         return m_plane;
1258 }
1259
1260 const FacePlane& getPlane() const {
1261         return m_plane;
1262 }
1263
1264 FaceTexdef& getTexdef(){
1265         return m_texdef;
1266 }
1267
1268 const FaceTexdef& getTexdef() const {
1269         return m_texdef;
1270 }
1271
1272 FaceShader& getShader(){
1273         return m_shader;
1274 }
1275
1276 const FaceShader& getShader() const {
1277         return m_shader;
1278 }
1279
1280 bool isDetail() const {
1281         return ( m_shader.m_flags.m_contentFlags & BRUSH_DETAIL_MASK ) != 0;
1282 }
1283
1284 void setDetail( bool detail ){
1285         undoSave();
1286         if ( detail && !isDetail() ) {
1287                 m_shader.m_flags.m_contentFlags |= BRUSH_DETAIL_MASK;
1288         }
1289         else if ( !detail && isDetail() ) {
1290                 m_shader.m_flags.m_contentFlags &= ~BRUSH_DETAIL_MASK;
1291         }
1292         m_observer->shaderChanged();
1293 }
1294
1295 bool contributes() const {
1296         return m_winding.numpoints > 2;
1297 }
1298
1299 bool is_bounded() const {
1300         for ( Winding::const_iterator i = m_winding.begin(); i != m_winding.end(); ++i )
1301         {
1302                 if ( ( *i ).adjacent == c_brush_maxFaces ) {
1303                         return false;
1304                 }
1305         }
1306         return true;
1307 }
1308 };
1309
1310
1311 class FaceVertexId
1312 {
1313         std::size_t m_face;
1314         std::size_t m_vertex;
1315
1316 public:
1317         FaceVertexId( std::size_t face, std::size_t vertex )
1318                 : m_face( face ), m_vertex( vertex ){
1319         }
1320
1321         std::size_t getFace() const {
1322                 return m_face;
1323         }
1324
1325         std::size_t getVertex() const {
1326                 return m_vertex;
1327         }
1328 };
1329
1330 typedef std::size_t faceIndex_t;
1331
1332 struct EdgeRenderIndices
1333 {
1334         RenderIndex first;
1335         RenderIndex second;
1336
1337         EdgeRenderIndices()
1338                 : first( 0 ), second( 0 ){
1339         }
1340
1341         EdgeRenderIndices( const RenderIndex _first, const RenderIndex _second )
1342                 : first( _first ), second( _second ){
1343         }
1344 };
1345
1346 struct EdgeFaces
1347 {
1348         faceIndex_t first;
1349         faceIndex_t second;
1350
1351         EdgeFaces()
1352                 : first( c_brush_maxFaces ), second( c_brush_maxFaces ){
1353         }
1354
1355         EdgeFaces( const faceIndex_t _first, const faceIndex_t _second )
1356                 : first( _first ), second( _second ){
1357         }
1358 };
1359
1360 class RenderableWireframe : public OpenGLRenderable
1361 {
1362 public:
1363 void render( RenderStateFlags state ) const {
1364 #if 1
1365         glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices->colour );
1366         glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices->vertex );
1367         glDrawElements( GL_LINES, GLsizei( m_size << 1 ), RenderIndexTypeID, m_faceVertex.data() );
1368 #else
1369         glBegin( GL_LINES );
1370         for ( std::size_t i = 0; i < m_size; ++i )
1371         {
1372                 glVertex3fv( &m_vertices[m_faceVertex[i].first].vertex.x );
1373                 glVertex3fv( &m_vertices[m_faceVertex[i].second].vertex.x );
1374         }
1375         glEnd();
1376 #endif
1377 }
1378
1379 Array<EdgeRenderIndices> m_faceVertex;
1380 std::size_t m_size;
1381 const PointVertex* m_vertices;
1382 };
1383
1384 class Brush;
1385
1386 typedef std::vector<Brush*> brush_vector_t;
1387
1388 class BrushFilter
1389 {
1390 public:
1391         virtual bool filter( const Brush& brush ) const = 0;
1392 };
1393
1394 bool brush_filtered( Brush& brush );
1395
1396 void add_brush_filter( BrushFilter& filter, int mask, bool invert = false );
1397
1398
1399 /// \brief Returns true if 'self' takes priority when building brush b-rep.
1400 inline bool plane3_inside( const Plane3& self, const Plane3& other, bool selfIsLater ){
1401         if ( vector3_equal_epsilon( self.normal(), other.normal(), 0.001 ) ) {
1402                 // same plane? prefer the one with smaller index
1403                 if ( self.dist() == other.dist() ) {
1404                         return selfIsLater;
1405                 }
1406                 return self.dist() < other.dist();
1407         }
1408         return true;
1409 }
1410
1411 typedef SmartPointer<Face> FaceSmartPointer;
1412 typedef std::vector<FaceSmartPointer> Faces;
1413
1414 /// \brief Returns the unique-id of the edge adjacent to \p faceVertex in the edge-pair for the set of \p faces.
1415 inline FaceVertexId next_edge( const Faces& faces, FaceVertexId faceVertex ){
1416         std::size_t adjacent_face = faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent;
1417         std::size_t adjacent_vertex = Winding_FindAdjacent( faces[adjacent_face]->getWinding(), faceVertex.getFace() );
1418
1419         ASSERT_MESSAGE( adjacent_vertex != c_brush_maxFaces, "connectivity data invalid" );
1420         if ( adjacent_vertex == c_brush_maxFaces ) {
1421                 return faceVertex;
1422         }
1423
1424         return FaceVertexId( adjacent_face, adjacent_vertex );
1425 }
1426
1427 /// \brief Returns the unique-id of the vertex adjacent to \p faceVertex in the vertex-ring for the set of \p faces.
1428 inline FaceVertexId next_vertex( const Faces& faces, FaceVertexId faceVertex ){
1429         FaceVertexId nextEdge = next_edge( faces, faceVertex );
1430         return FaceVertexId( nextEdge.getFace(), Winding_next( faces[nextEdge.getFace()]->getWinding(), nextEdge.getVertex() ) );
1431 }
1432
1433 class SelectableEdge
1434 {
1435         Vector3 getEdge() const {
1436                 const Winding& winding = getFace().getWinding();
1437                 return vector3_mid( winding[m_faceVertex.getVertex()].vertex, winding[Winding_next( winding, m_faceVertex.getVertex() )].vertex );
1438         }
1439
1440 public:
1441         Faces& m_faces;
1442         FaceVertexId m_faceVertex;
1443
1444         SelectableEdge( Faces& faces, FaceVertexId faceVertex )
1445                 : m_faces( faces ), m_faceVertex( faceVertex ){
1446         }
1447
1448         SelectableEdge& operator=( const SelectableEdge& other ){
1449                 m_faceVertex = other.m_faceVertex;
1450                 return *this;
1451         }
1452
1453         Face& getFace() const {
1454                 return *m_faces[m_faceVertex.getFace()];
1455         }
1456
1457         void testSelect( SelectionTest& test, SelectionIntersection& best ){
1458                 test.TestPoint( getEdge(), best );
1459         }
1460 };
1461
1462 class SelectableVertex
1463 {
1464         Vector3 getVertex() const {
1465                 return getFace().getWinding()[m_faceVertex.getVertex()].vertex;
1466         }
1467
1468 public:
1469         Faces& m_faces;
1470         FaceVertexId m_faceVertex;
1471
1472         SelectableVertex( Faces& faces, FaceVertexId faceVertex )
1473                 : m_faces( faces ), m_faceVertex( faceVertex ){
1474         }
1475
1476         SelectableVertex& operator=( const SelectableVertex& other ){
1477                 m_faceVertex = other.m_faceVertex;
1478                 return *this;
1479         }
1480
1481         Face& getFace() const {
1482                 return *m_faces[m_faceVertex.getFace()];
1483         }
1484
1485         void testSelect( SelectionTest& test, SelectionIntersection& best ){
1486                 test.TestPoint( getVertex(), best );
1487         }
1488 };
1489
1490 class BrushObserver
1491 {
1492 public:
1493         virtual void reserve( std::size_t size ) = 0;
1494         virtual void clear() = 0;
1495         virtual void push_back( Face& face ) = 0;
1496         virtual void pop_back() = 0;
1497         virtual void erase( std::size_t index ) = 0;
1498         virtual void connectivityChanged() = 0;
1499         virtual void edge_clear() = 0;
1500         virtual void edge_push_back( SelectableEdge& edge ) = 0;
1501         virtual void vertex_clear() = 0;
1502         virtual void vertex_push_back( SelectableVertex& vertex ) = 0;
1503         virtual void DEBUG_verify() const = 0;
1504 };
1505
1506 class BrushVisitor
1507 {
1508 public:
1509         virtual void visit( Face& face ) const = 0;
1510 };
1511
1512 class Brush :
1513         public TransformNode,
1514         public Bounded,
1515         public Cullable,
1516         public Snappable,
1517         public Undoable,
1518         public FaceObserver,
1519         public Filterable,
1520         public Nameable,
1521         public BrushDoom3
1522 {
1523 private:
1524         scene::Node* m_node;
1525         typedef UniqueSet<BrushObserver*> Observers;
1526         Observers m_observers;
1527         UndoObserver* m_undoable_observer;
1528         MapFile* m_map;
1529
1530         // state
1531         Faces m_faces;
1532         // ----
1533
1534         // cached data compiled from state
1535         Array<PointVertex> m_faceCentroidPoints;
1536         RenderablePointArray m_render_faces;
1537
1538         Array<PointVertex> m_uniqueVertexPoints;
1539         typedef std::vector<SelectableVertex> SelectableVertices;
1540         SelectableVertices m_select_vertices;
1541         RenderablePointArray m_render_vertices;
1542
1543         Array<PointVertex> m_uniqueEdgePoints;
1544         typedef std::vector<SelectableEdge> SelectableEdges;
1545         SelectableEdges m_select_edges;
1546         RenderablePointArray m_render_edges;
1547
1548         Array<EdgeRenderIndices> m_edge_indices;
1549         Array<EdgeFaces> m_edge_faces;
1550
1551         AABB m_aabb_local;
1552         // ----
1553
1554         Callback<void()> m_evaluateTransform;
1555         Callback<void()> m_boundsChanged;
1556
1557         mutable bool m_planeChanged;   // b-rep evaluation required
1558         mutable bool m_transformChanged;   // transform evaluation required
1559         // ----
1560
1561 public:
1562         STRING_CONSTANT( Name, "Brush" );
1563
1564         Callback<void()> m_lightsChanged;
1565
1566         // static data
1567         static Shader* m_state_point;
1568         // ----
1569
1570         static EBrushType m_type;
1571         static double m_maxWorldCoord;
1572
1573         Brush( scene::Node& node, const Callback<void()>& evaluateTransform, const Callback<void()>& boundsChanged ) :
1574                 m_node( &node ),
1575                 m_undoable_observer( 0 ),
1576                 m_map( 0 ),
1577                 m_render_faces( m_faceCentroidPoints, GL_POINTS ),
1578                 m_render_vertices( m_uniqueVertexPoints, GL_POINTS ),
1579                 m_render_edges( m_uniqueEdgePoints, GL_POINTS ),
1580                 m_evaluateTransform( evaluateTransform ),
1581                 m_boundsChanged( boundsChanged ),
1582                 m_planeChanged( false ),
1583                 m_transformChanged( false ){
1584                 planeChanged();
1585         }
1586         Brush( const Brush& other, scene::Node& node, const Callback<void()>& evaluateTransform, const Callback<void()>& boundsChanged ) :
1587                 m_node( &node ),
1588                 m_undoable_observer( 0 ),
1589                 m_map( 0 ),
1590                 m_render_faces( m_faceCentroidPoints, GL_POINTS ),
1591                 m_render_vertices( m_uniqueVertexPoints, GL_POINTS ),
1592                 m_render_edges( m_uniqueEdgePoints, GL_POINTS ),
1593                 m_evaluateTransform( evaluateTransform ),
1594                 m_boundsChanged( boundsChanged ),
1595                 m_planeChanged( false ),
1596                 m_transformChanged( false ){
1597                 copy( other );
1598         }
1599
1600         Brush( const Brush& other ) :
1601                 TransformNode( other ),
1602                 Bounded( other ),
1603                 Cullable( other ),
1604                 Snappable(),
1605                 Undoable( other ),
1606                 FaceObserver( other ),
1607                 Filterable( other ),
1608                 Nameable( other ),
1609                 BrushDoom3( other ),
1610                 m_node( 0 ),
1611                 m_undoable_observer( 0 ),
1612                 m_map( 0 ),
1613                 m_render_faces( m_faceCentroidPoints, GL_POINTS ),
1614                 m_render_vertices( m_uniqueVertexPoints, GL_POINTS ),
1615                 m_render_edges( m_uniqueEdgePoints, GL_POINTS ),
1616                 m_planeChanged( false ),
1617                 m_transformChanged( false ){
1618                 copy( other );
1619         }
1620
1621         ~Brush(){
1622                 ASSERT_MESSAGE( m_observers.empty(), "Brush::~Brush: observers still attached" );
1623         }
1624
1625         // assignment not supported
1626         Brush& operator=( const Brush& other );
1627
1628         void setDoom3GroupOrigin( const Vector3& origin ){
1629                 //globalOutputStream() << "func_static origin before: " << m_funcStaticOrigin << " after: " << origin << "\n";
1630                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1631                 {
1632                         ( *i )->getPlane().m_funcStaticOrigin = origin;
1633                         ( *i )->getPlane().updateTranslated();
1634                         ( *i )->planeChanged();
1635                 }
1636                 planeChanged();
1637         }
1638
1639         void attach( BrushObserver& observer ){
1640                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1641                 {
1642                         observer.push_back( *( *i ) );
1643                 }
1644
1645                 for ( SelectableEdges::iterator i = m_select_edges.begin(); i != m_select_edges.end(); ++i )
1646                 {
1647                         observer.edge_push_back( *i );
1648                 }
1649
1650                 for ( SelectableVertices::iterator i = m_select_vertices.begin(); i != m_select_vertices.end(); ++i )
1651                 {
1652                         observer.vertex_push_back( *i );
1653                 }
1654
1655                 m_observers.insert( &observer );
1656         }
1657
1658         void detach( BrushObserver& observer ){
1659                 m_observers.erase( &observer );
1660         }
1661
1662         void forEachFace( const BrushVisitor& visitor ) const {
1663                 for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1664                 {
1665                         visitor.visit( *( *i ) );
1666                 }
1667         }
1668
1669         void forEachFace_instanceAttach( MapFile* map ) const {
1670                 for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1671                 {
1672                         ( *i )->instanceAttach( map );
1673                 }
1674         }
1675
1676         void forEachFace_instanceDetach( MapFile* map ) const {
1677                 for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1678                 {
1679                         ( *i )->instanceDetach( map );
1680                 }
1681         }
1682
1683         InstanceCounter m_instanceCounter;
1684
1685         void instanceAttach( const scene::Path& path ){
1686                 if ( ++m_instanceCounter.m_count == 1 ) {
1687                         m_map = path_find_mapfile( path.begin(), path.end() );
1688                         m_undoable_observer = GlobalUndoSystem().observer( this );
1689                         GlobalFilterSystem().registerFilterable( *this );
1690                         forEachFace_instanceAttach( m_map );
1691                 }
1692                 else
1693                 {
1694                         ASSERT_MESSAGE( path_find_mapfile( path.begin(), path.end() ) == m_map, "node is instanced across more than one file" );
1695                 }
1696         }
1697
1698         void instanceDetach( const scene::Path& path ){
1699                 if ( --m_instanceCounter.m_count == 0 ) {
1700                         forEachFace_instanceDetach( m_map );
1701                         GlobalFilterSystem().unregisterFilterable( *this );
1702                         m_map = 0;
1703                         m_undoable_observer = 0;
1704                         GlobalUndoSystem().release( this );
1705                 }
1706         }
1707
1708         // nameable
1709         const char* name() const {
1710                 return "brush";
1711         }
1712
1713         void attach( const NameCallback& callback ){
1714         }
1715
1716         void detach( const NameCallback& callback ){
1717         }
1718
1719         // filterable
1720         void updateFiltered(){
1721                 if ( m_node != 0 ) {
1722                         if ( brush_filtered( *this ) ) {
1723                                 m_node->enable( scene::Node::eFiltered );
1724                         }
1725                         else
1726                         {
1727                                 m_node->disable( scene::Node::eFiltered );
1728                         }
1729                 }
1730         }
1731
1732         // observer
1733         void planeChanged(){
1734                 m_planeChanged = true;
1735                 aabbChanged();
1736                 m_lightsChanged();
1737         }
1738
1739         void shaderChanged(){
1740                 updateFiltered();
1741                 planeChanged();
1742         }
1743
1744         void evaluateBRep() const {
1745                 if ( m_planeChanged ) {
1746                         m_planeChanged = false;
1747                         const_cast<Brush*>( this )->buildBRep();
1748                 }
1749         }
1750
1751         void transformChanged(){
1752                 m_transformChanged = true;
1753                 planeChanged();
1754         }
1755
1756         typedef MemberCaller<Brush, void(), &Brush::transformChanged> TransformChangedCaller;
1757
1758         void evaluateTransform(){
1759                 if ( m_transformChanged ) {
1760                         m_transformChanged = false;
1761                         revertTransform();
1762                         m_evaluateTransform();
1763                 }
1764         }
1765
1766         const Matrix4& localToParent() const {
1767                 return g_matrix4_identity;
1768         }
1769
1770         void aabbChanged(){
1771                 m_boundsChanged();
1772         }
1773
1774         const AABB& localAABB() const {
1775                 evaluateBRep();
1776                 return m_aabb_local;
1777         }
1778
1779         VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const {
1780                 return test.TestAABB( m_aabb_local, localToWorld );
1781         }
1782
1783         void renderComponents( SelectionSystem::EComponentMode mode, Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
1784                 switch ( mode )
1785                 {
1786                 case SelectionSystem::eVertex:
1787                         renderer.addRenderable( m_render_vertices, localToWorld );
1788                         break;
1789                 case SelectionSystem::eEdge:
1790                         renderer.addRenderable( m_render_edges, localToWorld );
1791                         break;
1792                 case SelectionSystem::eFace:
1793                         renderer.addRenderable( m_render_faces, localToWorld );
1794                         break;
1795                 default:
1796                         break;
1797                 }
1798         }
1799
1800         void transform( const Matrix4& matrix ){
1801                 bool mirror = matrix4_handedness( matrix ) == MATRIX4_LEFTHANDED;
1802
1803                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1804                 {
1805                         ( *i )->transform( matrix, mirror );
1806                 }
1807         }
1808
1809         void snapto( float snap ){
1810                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1811                 {
1812                         ( *i )->snapto( snap );
1813                 }
1814         }
1815
1816         void revertTransform(){
1817                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1818                 {
1819                         ( *i )->revertTransform();
1820                 }
1821         }
1822
1823         void freezeTransform(){
1824                 for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
1825                 {
1826                         ( *i )->freezeTransform();
1827                 }
1828         }
1829
1830         /// \brief Returns the absolute index of the \p faceVertex.
1831         std::size_t absoluteIndex( FaceVertexId faceVertex ){
1832                 std::size_t index = 0;
1833                 for ( std::size_t i = 0; i < faceVertex.getFace(); ++i )
1834                 {
1835                         index += m_faces[i]->getWinding().numpoints;
1836                 }
1837                 return index + faceVertex.getVertex();
1838         }
1839
1840         void appendFaces( const Faces& other ){
1841                 clear();
1842                 for ( Faces::const_iterator i = other.begin(); i != other.end(); ++i )
1843                 {
1844                         push_back( *i );
1845                 }
1846         }
1847
1848         /// \brief The undo memento for a brush stores only the list of face references - the faces are not copied.
1849         class BrushUndoMemento : public UndoMemento
1850         {
1851         public:
1852                 BrushUndoMemento( const Faces& faces ) : m_faces( faces ){
1853         }
1854
1855         void release(){
1856                 delete this;
1857         }
1858
1859         Faces m_faces;
1860         };
1861
1862         void undoSave(){
1863                 if ( m_map != 0 ) {
1864                         m_map->changed();
1865                 }
1866                 if ( m_undoable_observer != 0 ) {
1867                         m_undoable_observer->save( this );
1868                 }
1869         }
1870
1871         UndoMemento* exportState() const {
1872                 return new BrushUndoMemento( m_faces );
1873         }
1874
1875         void importState( const UndoMemento* state ){
1876                 undoSave();
1877                 appendFaces( static_cast<const BrushUndoMemento*>( state )->m_faces );
1878                 planeChanged();
1879
1880                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
1881                 {
1882                         ( *i )->DEBUG_verify();
1883                 }
1884         }
1885
1886         bool isDetail(){
1887                 return !m_faces.empty() && m_faces.front()->isDetail();
1888         }
1889
1890         /// \brief Appends a copy of \p face to the end of the face list.
1891         Face* addFace( const Face& face ){
1892                 if ( m_faces.size() == c_brush_maxFaces ) {
1893                         return 0;
1894                 }
1895                 undoSave();
1896                 push_back( FaceSmartPointer( new Face( face, this ) ) );
1897                 m_faces.back()->setDetail( isDetail() );
1898                 planeChanged();
1899                 return m_faces.back();
1900         }
1901
1902         /// \brief Appends a new face constructed from the parameters to the end of the face list.
1903         Face* addPlane( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection ){
1904                 if ( m_faces.size() == c_brush_maxFaces ) {
1905                         return 0;
1906                 }
1907                 undoSave();
1908                 push_back( FaceSmartPointer( new Face( p0, p1, p2, shader, projection, this ) ) );
1909                 m_faces.back()->setDetail( isDetail() );
1910                 planeChanged();
1911                 return m_faces.back();
1912         }
1913
1914         static void constructStatic( EBrushType type ){
1915                 m_type = type;
1916                 Face::m_type = type;
1917                 FacePlane::m_type = type;
1918
1919                 g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE;
1920                 if ( m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4 ) {
1921                         g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES;
1922                         // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting
1923                 }
1924                 else if ( m_type == eBrushTypeHalfLife ) {
1925                         g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE;
1926                         // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting
1927                 }
1928
1929                 Face::m_quantise = ( m_type == eBrushTypeQuake ) ? quantiseInteger : quantiseFloating;
1930
1931                 m_state_point = GlobalShaderCache().capture( "$POINT" );
1932         }
1933
1934         static void destroyStatic(){
1935                 GlobalShaderCache().release( "$POINT" );
1936         }
1937
1938         std::size_t DEBUG_size(){
1939                 return m_faces.size();
1940         }
1941
1942         typedef Faces::const_iterator const_iterator;
1943
1944         const_iterator begin() const {
1945                 return m_faces.begin();
1946         }
1947
1948         const_iterator end() const {
1949                 return m_faces.end();
1950         }
1951
1952         Face* back(){
1953                 return m_faces.back();
1954         }
1955
1956         const Face* back() const {
1957                 return m_faces.back();
1958         }
1959
1960         void reserve( std::size_t count ){
1961                 m_faces.reserve( count );
1962                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
1963                 {
1964                         ( *i )->reserve( count );
1965                 }
1966         }
1967
1968         void push_back( Faces::value_type face ){
1969                 m_faces.push_back( face );
1970                 if ( m_instanceCounter.m_count != 0 ) {
1971                         m_faces.back()->instanceAttach( m_map );
1972                 }
1973                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
1974                 {
1975                         ( *i )->push_back( *face );
1976                         ( *i )->DEBUG_verify();
1977                 }
1978         }
1979
1980         void pop_back(){
1981                 if ( m_instanceCounter.m_count != 0 ) {
1982                         m_faces.back()->instanceDetach( m_map );
1983                 }
1984                 m_faces.pop_back();
1985                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
1986                 {
1987                         ( *i )->pop_back();
1988                         ( *i )->DEBUG_verify();
1989                 }
1990         }
1991
1992         void erase( std::size_t index ){
1993                 if ( m_instanceCounter.m_count != 0 ) {
1994                         m_faces[index]->instanceDetach( m_map );
1995                 }
1996                 m_faces.erase( m_faces.begin() + index );
1997                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
1998                 {
1999                         ( *i )->erase( index );
2000                         ( *i )->DEBUG_verify();
2001                 }
2002         }
2003
2004         void connectivityChanged(){
2005                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
2006                 {
2007                         ( *i )->connectivityChanged();
2008                 }
2009         }
2010
2011
2012         void clear(){
2013                 undoSave();
2014                 if ( m_instanceCounter.m_count != 0 ) {
2015                         forEachFace_instanceDetach( m_map );
2016                 }
2017                 m_faces.clear();
2018                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
2019                 {
2020                         ( *i )->clear();
2021                         ( *i )->DEBUG_verify();
2022                 }
2023         }
2024
2025         std::size_t size() const {
2026                 return m_faces.size();
2027         }
2028
2029         bool empty() const {
2030                 return m_faces.empty();
2031         }
2032
2033         /// \brief Returns true if any face of the brush contributes to the final B-Rep.
2034         bool hasContributingFaces() const {
2035                 for ( const_iterator i = begin(); i != end(); ++i )
2036                 {
2037                         if ( ( *i )->contributes() ) {
2038                                 return true;
2039                         }
2040                 }
2041                 return false;
2042         }
2043
2044         /// \brief Removes faces that do not contribute to the brush. This is useful for cleaning up after CSG operations on the brush.
2045         /// Note: removal of empty faces is not performed during direct brush manipulations, because it would make a manipulation irreversible if it created an empty face.
2046         void removeEmptyFaces(){
2047                 evaluateBRep();
2048
2049                 {
2050                         std::size_t i = 0;
2051                         while ( i < m_faces.size() )
2052                         {
2053                                 if ( !m_faces[i]->contributes() ) {
2054                                         erase( i );
2055                                         planeChanged();
2056                                 }
2057                                 else
2058                                 {
2059                                         ++i;
2060                                 }
2061                         }
2062                 }
2063         }
2064
2065         /// \brief Constructs \p winding from the intersection of \p plane with the other planes of the brush.
2066         void windingForClipPlane( Winding& winding, const Plane3& plane ) const {
2067                 FixedWinding buffer[2];
2068                 bool swap = false;
2069
2070                 // get a poly that covers an effectively infinite area
2071                 Winding_createInfinite( buffer[swap], plane, m_maxWorldCoord + 1 );
2072
2073                 // chop the poly by all of the other faces
2074                 {
2075                         for ( std::size_t i = 0; i < m_faces.size(); ++i )
2076                         {
2077                                 const Face& clip = *m_faces[i];
2078
2079                                 if ( plane3_equal( clip.plane3(), plane )
2080                                          || !plane3_valid( clip.plane3() ) || !plane_unique( i )
2081                                          || plane3_opposing( plane, clip.plane3() ) ) {
2082                                         continue;
2083                                 }
2084
2085                                 buffer[!swap].clear();
2086
2087 #if BRUSH_CONNECTIVITY_DEBUG
2088                                 globalOutputStream() << "clip vs face: " << i << "\n";
2089 #endif
2090
2091                                 {
2092                                         // flip the plane, because we want to keep the back side
2093                                         Plane3 clipPlane( vector3_negated( clip.plane3().normal() ), -clip.plane3().dist() );
2094                                         Winding_Clip( buffer[swap], plane, clipPlane, i, buffer[!swap] );
2095                                 }
2096
2097 #if BRUSH_CONNECTIVITY_DEBUG
2098                                 for ( FixedWinding::Points::iterator k = buffer[!swap].points.begin(), j = buffer[!swap].points.end() - 1; k != buffer[!swap].points.end(); j = k, ++k )
2099                                 {
2100                                         if ( vector3_length_squared( vector3_subtracted( ( *k ).vertex, ( *j ).vertex ) ) < 1 ) {
2101                                                 globalOutputStream() << "v: " << std::distance( buffer[!swap].points.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n";
2102                                         }
2103                                 }
2104 #endif
2105
2106                                 //ASSERT_MESSAGE(buffer[!swap].numpoints != 1, "created single-point winding");
2107
2108                                 swap = !swap;
2109                         }
2110                 }
2111
2112                 Winding_forFixedWinding( winding, buffer[swap] );
2113
2114 #if BRUSH_CONNECTIVITY_DEBUG
2115                 Winding_printConnectivity( winding );
2116
2117                 for ( Winding::iterator i = winding.begin(), j = winding.end() - 1; i != winding.end(); j = i, ++i )
2118                 {
2119                         if ( vector3_length_squared( vector3_subtracted( ( *i ).vertex, ( *j ).vertex ) ) < 1 ) {
2120                                 globalOutputStream() << "v: " << std::distance( winding.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n";
2121                         }
2122                 }
2123 #endif
2124         }
2125
2126         void update_wireframe( RenderableWireframe& wire, const bool* faces_visible ) const {
2127                 wire.m_faceVertex.resize( m_edge_indices.size() );
2128                 wire.m_vertices = m_uniqueVertexPoints.data();
2129                 wire.m_size = 0;
2130                 for ( std::size_t i = 0; i < m_edge_faces.size(); ++i )
2131                 {
2132                         if ( faces_visible[m_edge_faces[i].first]
2133                                  || faces_visible[m_edge_faces[i].second] ) {
2134                                 wire.m_faceVertex[wire.m_size++] = m_edge_indices[i];
2135                         }
2136                 }
2137         }
2138
2139
2140         void update_faces_wireframe( Array<PointVertex>& wire, const bool* faces_visible ) const {
2141                 std::size_t count = 0;
2142                 for ( std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i )
2143                 {
2144                         if ( faces_visible[i] ) {
2145                                 ++count;
2146                         }
2147                 }
2148
2149                 wire.resize( count );
2150                 Array<PointVertex>::iterator p = wire.begin();
2151                 for ( std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i )
2152                 {
2153                         if ( faces_visible[i] ) {
2154                                 *p++ = m_faceCentroidPoints[i];
2155                         }
2156                 }
2157         }
2158
2159         /// \brief Makes this brush a deep-copy of the \p other.
2160         void copy( const Brush& other ){
2161                 for ( Faces::const_iterator i = other.m_faces.begin(); i != other.m_faces.end(); ++i )
2162                 {
2163                         addFace( *( *i ) );
2164                 }
2165                 planeChanged();
2166         }
2167
2168         private:
2169         void edge_push_back( FaceVertexId faceVertex ){
2170                 m_select_edges.push_back( SelectableEdge( m_faces, faceVertex ) );
2171                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
2172                 {
2173                         ( *i )->edge_push_back( m_select_edges.back() );
2174                 }
2175         }
2176
2177         void edge_clear(){
2178                 m_select_edges.clear();
2179                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
2180                 {
2181                         ( *i )->edge_clear();
2182                 }
2183         }
2184
2185         void vertex_push_back( FaceVertexId faceVertex ){
2186                 m_select_vertices.push_back( SelectableVertex( m_faces, faceVertex ) );
2187                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
2188                 {
2189                         ( *i )->vertex_push_back( m_select_vertices.back() );
2190                 }
2191         }
2192
2193         void vertex_clear(){
2194                 m_select_vertices.clear();
2195                 for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
2196                 {
2197                         ( *i )->vertex_clear();
2198                 }
2199         }
2200
2201         /// \brief Returns true if the face identified by \p index is preceded by another plane that takes priority over it.
2202         bool plane_unique( std::size_t index ) const {
2203                 // duplicate plane
2204                 for ( std::size_t i = 0; i < m_faces.size(); ++i )
2205                 {
2206                         if ( index != i && !plane3_inside( m_faces[index]->plane3(), m_faces[i]->plane3(), index < i ) ) {
2207                                 return false;
2208                         }
2209                 }
2210                 return true;
2211         }
2212
2213         /// \brief Removes edges that are smaller than the tolerance used when generating brush windings.
2214         void removeDegenerateEdges(){
2215                 for ( std::size_t i = 0; i < m_faces.size(); ++i )
2216                 {
2217                         Winding& winding = m_faces[i]->getWinding();
2218                         for ( Winding::iterator j = winding.begin(); j != winding.end(); )
2219                         {
2220                                 std::size_t index = std::distance( winding.begin(), j );
2221                                 std::size_t next = Winding_next( winding, index );
2222                                 if ( Edge_isDegenerate( winding[index].vertex, winding[next].vertex ) ) {
2223 #if BRUSH_DEGENERATE_DEBUG
2224                                         globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate edge adjacent to " << winding[index].adjacent << "\n";
2225 #endif
2226                                         Winding& other = m_faces[winding[index].adjacent]->getWinding();
2227                                         std::size_t adjacent = Winding_FindAdjacent( other, i );
2228                                         if ( adjacent != c_brush_maxFaces ) {
2229                                                 other.erase( other.begin() + adjacent );
2230                                         }
2231                                         winding.erase( j );
2232                                 }
2233                                 else
2234                                 {
2235                                         ++j;
2236                                 }
2237                         }
2238                 }
2239         }
2240
2241         /// \brief Invalidates faces that have only two vertices in their winding, while preserving edge-connectivity information.
2242         void removeDegenerateFaces(){
2243                 // save adjacency info for degenerate faces
2244                 for ( std::size_t i = 0; i < m_faces.size(); ++i )
2245                 {
2246                         Winding& degen = m_faces[i]->getWinding();
2247
2248                         if ( degen.numpoints == 2 ) {
2249 #if BRUSH_DEGENERATE_DEBUG
2250                                 globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate winding adjacent to " << degen[0].adjacent << ", " << degen[1].adjacent << "\n";
2251 #endif
2252                                 // this is an "edge" face, where the plane touches the edge of the brush
2253                                 {
2254                                         Winding& winding = m_faces[degen[0].adjacent]->getWinding();
2255                                         std::size_t index = Winding_FindAdjacent( winding, i );
2256                                         if ( index != c_brush_maxFaces ) {
2257 #if BRUSH_DEGENERATE_DEBUG
2258                                                 globalOutputStream() << "Brush::buildWindings: face " << degen[0].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[1].adjacent << "\n";
2259 #endif
2260                                                 winding[index].adjacent = degen[1].adjacent;
2261                                         }
2262                                 }
2263
2264                                 {
2265                                         Winding& winding = m_faces[degen[1].adjacent]->getWinding();
2266                                         std::size_t index = Winding_FindAdjacent( winding, i );
2267                                         if ( index != c_brush_maxFaces ) {
2268 #if BRUSH_DEGENERATE_DEBUG
2269                                                 globalOutputStream() << "Brush::buildWindings: face " << degen[1].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[0].adjacent << "\n";
2270 #endif
2271                                                 winding[index].adjacent = degen[0].adjacent;
2272                                         }
2273                                 }
2274
2275                                 degen.resize( 0 );
2276                         }
2277                 }
2278         }
2279
2280         /// \brief Removes edges that have the same adjacent-face as their immediate neighbour.
2281         void removeDuplicateEdges(){
2282                 // verify face connectivity graph
2283                 for ( std::size_t i = 0; i < m_faces.size(); ++i )
2284                 {
2285                         //if(m_faces[i]->contributes())
2286                         {
2287                                 Winding& winding = m_faces[i]->getWinding();
2288                                 for ( std::size_t j = 0; j != winding.numpoints; )
2289                                 {
2290                                         std::size_t next = Winding_next( winding, j );
2291                                         if ( winding[j].adjacent == winding[next].adjacent ) {
2292 #if BRUSH_DEGENERATE_DEBUG
2293                                                 globalOutputStream() << "Brush::buildWindings: face " << i << ": removed duplicate edge adjacent to face " << winding[j].adjacent << "\n";
2294 #endif
2295                                                 winding.erase( winding.begin() + next );
2296                                         }
2297                                         else
2298                                         {
2299                                                 ++j;
2300                                         }
2301                                 }
2302                         }
2303                 }
2304         }
2305
2306         /// \brief Removes edges that do not have a matching pair in their adjacent-face.
2307         void verifyConnectivityGraph(){
2308                 // verify face connectivity graph
2309                 for ( std::size_t i = 0; i < m_faces.size(); ++i )
2310                 {
2311                         //if(m_faces[i]->contributes())
2312                         {
2313                                 Winding& winding = m_faces[i]->getWinding();
2314                                 for ( Winding::iterator j = winding.begin(); j != winding.end(); )
2315                                 {
2316 #if BRUSH_CONNECTIVITY_DEBUG
2317                                         globalOutputStream() << "Brush::buildWindings: face " << i << ": adjacent to face " << ( *j ).adjacent << "\n";
2318 #endif
2319                                         // remove unidirectional graph edges
2320                                         if ( ( *j ).adjacent == c_brush_maxFaces
2321                                                  || Winding_FindAdjacent( m_faces[( *j ).adjacent]->getWinding(), i ) == c_brush_maxFaces ) {
2322 #if BRUSH_CONNECTIVITY_DEBUG
2323                                                 globalOutputStream() << "Brush::buildWindings: face " << i << ": removing unidirectional connectivity graph edge adjacent to face " << ( *j ).adjacent << "\n";
2324 #endif
2325                                                 winding.erase( j );
2326                                         }
2327                                         else
2328                                         {
2329                                                 ++j;
2330                                         }
2331                                 }
2332                         }
2333                 }
2334         }
2335
2336         /// \brief Returns true if the brush is a finite volume. A brush without a finite volume extends past the maximum world bounds and is not valid.
2337         bool isBounded(){
2338                 for ( const_iterator i = begin(); i != end(); ++i )
2339                 {
2340                         if ( !( *i )->is_bounded() ) {
2341                                 return false;
2342                         }
2343                 }
2344                 return true;
2345         }
2346
2347         /// \brief Constructs the polygon windings for each face of the brush. Also updates the brush bounding-box and face texture-coordinates.
2348         bool buildWindings(){
2349
2350                 {
2351                         m_aabb_local = AABB();
2352
2353                         for ( std::size_t i = 0; i < m_faces.size(); ++i )
2354                         {
2355                                 Face& f = *m_faces[i];
2356
2357                                 if ( !plane3_valid( f.plane3() ) || !plane_unique( i ) ) {
2358                                         f.getWinding().resize( 0 );
2359                                 }
2360                                 else
2361                                 {
2362 #if BRUSH_CONNECTIVITY_DEBUG
2363                                         globalOutputStream() << "face: " << i << "\n";
2364 #endif
2365                                         windingForClipPlane( f.getWinding(), f.plane3() );
2366
2367                                         // update brush bounds
2368                                         const Winding& winding = f.getWinding();
2369                                         for ( Winding::const_iterator i = winding.begin(); i != winding.end(); ++i )
2370                                         {
2371                                                 aabb_extend_by_point_safe( m_aabb_local, ( *i ).vertex );
2372                                         }
2373
2374                                         // update texture coordinates
2375                                         f.EmitTextureCoordinates();
2376                                 }
2377                         }
2378                 }
2379
2380                 bool degenerate = !isBounded();
2381
2382                 if ( !degenerate ) {
2383                         // clean up connectivity information.
2384                         // these cleanups must be applied in a specific order.
2385                         removeDegenerateEdges();
2386                         removeDegenerateFaces();
2387                         removeDuplicateEdges();
2388                         verifyConnectivityGraph();
2389                 }
2390
2391                 return degenerate;
2392         }
2393
2394         /// \brief Constructs the face windings and updates anything that depends on them.
2395         void buildBRep();
2396 };
2397
2398
2399 class FaceInstance;
2400
2401 class FaceInstanceSet
2402 {
2403         typedef SelectionList<FaceInstance> FaceInstances;
2404         FaceInstances m_faceInstances;
2405 public:
2406         void insert( FaceInstance& faceInstance ){
2407                 m_faceInstances.append( faceInstance );
2408         }
2409
2410         void erase( FaceInstance& faceInstance ){
2411                 m_faceInstances.erase( faceInstance );
2412         }
2413
2414         template<typename Functor>
2415         void foreach( Functor functor ){
2416                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
2417                 {
2418                         functor( *( *i ) );
2419                 }
2420         }
2421
2422         bool empty() const {
2423                 return m_faceInstances.empty();
2424         }
2425
2426         FaceInstance& last() const {
2427                 return m_faceInstances.back();
2428         }
2429 };
2430
2431 extern FaceInstanceSet g_SelectedFaceInstances;
2432
2433 typedef std::list<std::size_t> VertexSelection;
2434
2435 inline VertexSelection::iterator VertexSelection_find( VertexSelection& self, std::size_t value ){
2436         return std::find( self.begin(), self.end(), value );
2437 }
2438
2439 inline VertexSelection::const_iterator VertexSelection_find( const VertexSelection& self, std::size_t value ){
2440         return std::find( self.begin(), self.end(), value );
2441 }
2442
2443 inline VertexSelection::iterator VertexSelection_insert( VertexSelection& self, std::size_t value ){
2444         VertexSelection::iterator i = VertexSelection_find( self, value );
2445         if ( i == self.end() ) {
2446                 self.push_back( value );
2447                 return --self.end();
2448         }
2449         return i;
2450 }
2451
2452 inline void VertexSelection_erase( VertexSelection& self, std::size_t value ){
2453         VertexSelection::iterator i = VertexSelection_find( self, value );
2454         if ( i != self.end() ) {
2455                 self.erase( i );
2456         }
2457 }
2458
2459 inline bool triangle_reversed( std::size_t x, std::size_t y, std::size_t z ){
2460         return !( ( x < y && y < z ) || ( z < x && x < y ) || ( y < z && z < x ) );
2461 }
2462
2463 template<typename Element>
2464 inline Vector3 triangle_cross( const BasicVector3<Element>& x, const BasicVector3<Element> y, const BasicVector3<Element>& z ){
2465         return vector3_cross( y - x, z - x );
2466 }
2467
2468 template<typename Element>
2469 inline bool triangles_same_winding( const BasicVector3<Element>& x1, const BasicVector3<Element> y1, const BasicVector3<Element>& z1, const BasicVector3<Element>& x2, const BasicVector3<Element> y2, const BasicVector3<Element>& z2 ){
2470         return vector3_dot( triangle_cross( x1, y1, z1 ), triangle_cross( x2, y2, z2 ) ) > 0;
2471 }
2472
2473
2474 typedef const Plane3* PlanePointer;
2475 typedef PlanePointer* PlanesIterator;
2476
2477 class VectorLightList : public LightList
2478 {
2479         typedef std::vector<const RendererLight*> Lights;
2480         Lights m_lights;
2481 public:
2482         void addLight( const RendererLight& light ){
2483                 m_lights.push_back( &light );
2484         }
2485
2486         void clear(){
2487                 m_lights.clear();
2488         }
2489
2490         void evaluateLights() const {
2491         }
2492
2493         void lightsChanged() const {
2494         }
2495
2496         void forEachLight( const RendererLightCallback& callback ) const {
2497                 for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i )
2498                 {
2499                         callback( *( *i ) );
2500                 }
2501         }
2502 };
2503
2504 class FaceInstance
2505 {
2506         Face* m_face;
2507         ObservedSelectable m_selectable;
2508         ObservedSelectable m_selectableVertices;
2509         ObservedSelectable m_selectableEdges;
2510         SelectionChangeCallback m_selectionChanged;
2511
2512         VertexSelection m_vertexSelection;
2513         VertexSelection m_edgeSelection;
2514
2515 public:
2516         mutable VectorLightList m_lights;
2517
2518         FaceInstance( Face& face, const SelectionChangeCallback& observer ) :
2519                 m_face( &face ),
2520                 m_selectable( SelectedChangedCaller( *this ) ),
2521                 m_selectableVertices( observer ),
2522                 m_selectableEdges( observer ),
2523                 m_selectionChanged( observer ){
2524         }
2525
2526         FaceInstance( const FaceInstance& other ) :
2527                 m_face( other.m_face ),
2528                 m_selectable( SelectedChangedCaller( *this ) ),
2529                 m_selectableVertices( other.m_selectableVertices ),
2530                 m_selectableEdges( other.m_selectableEdges ),
2531                 m_selectionChanged( other.m_selectionChanged ){
2532         }
2533
2534         FaceInstance& operator=( const FaceInstance& other ){
2535                 m_face = other.m_face;
2536                 return *this;
2537         }
2538
2539         Face& getFace(){
2540                 return *m_face;
2541         }
2542
2543         const Face& getFace() const {
2544                 return *m_face;
2545         }
2546
2547         void selectedChanged( const Selectable& selectable ){
2548                 if ( selectable.isSelected() ) {
2549                         g_SelectedFaceInstances.insert( *this );
2550                 }
2551                 else
2552                 {
2553                         g_SelectedFaceInstances.erase( *this );
2554                 }
2555                 m_selectionChanged( selectable );
2556         }
2557
2558         typedef MemberCaller<FaceInstance, void(const Selectable&), &FaceInstance::selectedChanged> SelectedChangedCaller;
2559
2560         bool selectedVertices() const {
2561                 return !m_vertexSelection.empty();
2562         }
2563
2564         bool selectedEdges() const {
2565                 return !m_edgeSelection.empty();
2566         }
2567
2568         bool isSelected() const {
2569                 return m_selectable.isSelected();
2570         }
2571
2572         bool selectedComponents() const {
2573                 return selectedVertices() || selectedEdges() || isSelected();
2574         }
2575
2576         bool selectedComponents( SelectionSystem::EComponentMode mode ) const {
2577                 switch ( mode )
2578                 {
2579                 case SelectionSystem::eVertex:
2580                         return selectedVertices();
2581                 case SelectionSystem::eEdge:
2582                         return selectedEdges();
2583                 case SelectionSystem::eFace:
2584                         return isSelected();
2585                 default:
2586                         return false;
2587                 }
2588         }
2589
2590         void setSelected( SelectionSystem::EComponentMode mode, bool select ){
2591                 switch ( mode )
2592                 {
2593                 case SelectionSystem::eFace:
2594                         m_selectable.setSelected( select );
2595                         break;
2596                 case SelectionSystem::eVertex:
2597                         ASSERT_MESSAGE( !select, "select-all not supported" );
2598
2599                         m_vertexSelection.clear();
2600                         m_selectableVertices.setSelected( false );
2601                         break;
2602                 case SelectionSystem::eEdge:
2603                         ASSERT_MESSAGE( !select, "select-all not supported" );
2604
2605                         m_edgeSelection.clear();
2606                         m_selectableEdges.setSelected( false );
2607                         break;
2608                 default:
2609                         break;
2610                 }
2611         }
2612
2613         template<typename Functor>
2614         void SelectedVertices_foreach( Functor functor ) const {
2615                 for ( VertexSelection::const_iterator i = m_vertexSelection.begin(); i != m_vertexSelection.end(); ++i )
2616                 {
2617                         std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *i );
2618                         if ( index != c_brush_maxFaces ) {
2619                                 functor( getFace().getWinding()[index].vertex );
2620                         }
2621                 }
2622         }
2623
2624         template<typename Functor>
2625         void SelectedEdges_foreach( Functor functor ) const {
2626                 for ( VertexSelection::const_iterator i = m_edgeSelection.begin(); i != m_edgeSelection.end(); ++i )
2627                 {
2628                         std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *i );
2629                         if ( index != c_brush_maxFaces ) {
2630                                 const Winding& winding = getFace().getWinding();
2631                                 std::size_t adjacent = Winding_next( winding, index );
2632                                 functor( vector3_mid( winding[index].vertex, winding[adjacent].vertex ) );
2633                         }
2634                 }
2635         }
2636
2637         template<typename Functor>
2638         void SelectedFaces_foreach( Functor functor ) const {
2639                 if ( isSelected() ) {
2640                         functor( centroid() );
2641                 }
2642         }
2643
2644         template<typename Functor>
2645         void SelectedComponents_foreach( Functor functor ) const {
2646                 SelectedVertices_foreach( functor );
2647                 SelectedEdges_foreach( functor );
2648                 SelectedFaces_foreach( functor );
2649         }
2650
2651         void iterate_selected( AABB& aabb ) const {
2652                 SelectedComponents_foreach([&](const Vector3 &point) {
2653                         aabb_extend_by_point_safe(aabb, point);
2654                 });
2655         }
2656
2657         void iterate_selected( RenderablePointVector& points ) const {
2658                 SelectedComponents_foreach([&](const Vector3 &point) {
2659                         const Colour4b colour_selected(0, 0, 255, 255);
2660                         points.push_back(pointvertex_for_windingpoint(point, colour_selected));
2661                 });
2662         }
2663
2664         bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const {
2665                 return m_face->intersectVolume( volume, localToWorld );
2666         }
2667
2668         void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
2669                 if ( !m_face->isFiltered() && m_face->contributes() && intersectVolume( volume, localToWorld ) ) {
2670                         renderer.PushState();
2671                         if ( selectedComponents() ) {
2672                                 renderer.Highlight( Renderer::eFace );
2673                         }
2674                         m_face->render( renderer, localToWorld );
2675                         renderer.PopState();
2676                 }
2677         }
2678
2679         void testSelect( SelectionTest& test, SelectionIntersection& best ){
2680                 if ( !m_face->isFiltered() ) {
2681                         m_face->testSelect( test, best );
2682                 }
2683         }
2684
2685         void testSelect( Selector& selector, SelectionTest& test ){
2686                 SelectionIntersection best;
2687                 testSelect( test, best );
2688                 if ( best.valid() ) {
2689                         Selector_add( selector, m_selectable, best );
2690                 }
2691         }
2692
2693         void testSelect_centroid( Selector& selector, SelectionTest& test ){
2694                 if ( m_face->contributes() && !m_face->isFiltered() ) {
2695                         SelectionIntersection best;
2696                         m_face->testSelect_centroid( test, best );
2697                         if ( best.valid() ) {
2698                                 Selector_add( selector, m_selectable, best );
2699                         }
2700                 }
2701         }
2702
2703         void selectPlane( Selector& selector, const Line& line, PlanesIterator first, PlanesIterator last, const PlaneCallback& selectedPlaneCallback ){
2704                 for ( Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i )
2705                 {
2706                         Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) );
2707                         double dot = vector3_dot( getFace().plane3().normal(), v );
2708                         if ( dot <= 0 ) {
2709                                 return;
2710                         }
2711                 }
2712
2713                 Selector_add( selector, m_selectable );
2714
2715                 selectedPlaneCallback( getFace().plane3() );
2716         }
2717
2718         void selectReversedPlane( Selector& selector, const SelectedPlanes& selectedPlanes ){
2719                 if ( selectedPlanes.contains( plane3_flipped( getFace().plane3() ) ) ) {
2720                         Selector_add( selector, m_selectable );
2721                 }
2722         }
2723
2724         void transformComponents( const Matrix4& matrix ){
2725                 if ( isSelected() ) {
2726                         m_face->transform( matrix, false );
2727                 }
2728                 if ( selectedVertices() ) {
2729                         if ( m_vertexSelection.size() == 1 ) {
2730                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] );
2731                                 m_face->assign_planepts( m_face->m_move_planeptsTransformed );
2732                         }
2733                         else if ( m_vertexSelection.size() == 2 ) {
2734                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] );
2735                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] );
2736                                 m_face->assign_planepts( m_face->m_move_planeptsTransformed );
2737                         }
2738                         else if ( m_vertexSelection.size() >= 3 ) {
2739                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] );
2740                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] );
2741                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] );
2742                                 m_face->assign_planepts( m_face->m_move_planeptsTransformed );
2743                         }
2744                 }
2745                 if ( selectedEdges() ) {
2746                         if ( m_edgeSelection.size() == 1 ) {
2747                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] );
2748                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] );
2749                                 m_face->assign_planepts( m_face->m_move_planeptsTransformed );
2750                         }
2751                         else if ( m_edgeSelection.size() >= 2 ) {
2752                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] );
2753                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] );
2754                                 matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] );
2755                                 m_face->assign_planepts( m_face->m_move_planeptsTransformed );
2756                         }
2757                 }
2758         }
2759
2760         void snapto( float snap ){
2761                 m_face->snapto( snap );
2762         }
2763
2764         void snapComponents( float snap ){
2765                 if ( isSelected() ) {
2766                         snapto( snap );
2767                 }
2768                 if ( selectedVertices() ) {
2769                         vector3_snap( m_face->m_move_planepts[0], snap );
2770                         vector3_snap( m_face->m_move_planepts[1], snap );
2771                         vector3_snap( m_face->m_move_planepts[2], snap );
2772                         m_face->assign_planepts( m_face->m_move_planepts );
2773                         planepts_assign( m_face->m_move_planeptsTransformed, m_face->m_move_planepts );
2774                         m_face->freezeTransform();
2775                 }
2776                 if ( selectedEdges() ) {
2777                         vector3_snap( m_face->m_move_planepts[0], snap );
2778                         vector3_snap( m_face->m_move_planepts[1], snap );
2779                         vector3_snap( m_face->m_move_planepts[2], snap );
2780                         m_face->assign_planepts( m_face->m_move_planepts );
2781                         planepts_assign( m_face->m_move_planeptsTransformed, m_face->m_move_planepts );
2782                         m_face->freezeTransform();
2783                 }
2784         }
2785
2786         void update_move_planepts_vertex( std::size_t index ){
2787                 m_face->update_move_planepts_vertex( index, m_face->m_move_planepts );
2788         }
2789
2790         void update_move_planepts_vertex2( std::size_t index, std::size_t other ){
2791                 const std::size_t numpoints = m_face->getWinding().numpoints;
2792                 ASSERT_MESSAGE( index < numpoints, "select_vertex: invalid index" );
2793
2794                 const std::size_t opposite = Winding_Opposite( m_face->getWinding(), index, other );
2795
2796                 if ( triangle_reversed( index, other, opposite ) ) {
2797                         std::swap( index, other );
2798                 }
2799
2800                 ASSERT_MESSAGE(
2801                         triangles_same_winding(
2802                                 m_face->getWinding()[opposite].vertex,
2803                                 m_face->getWinding()[index].vertex,
2804                                 m_face->getWinding()[other].vertex,
2805                                 m_face->getWinding()[0].vertex,
2806                                 m_face->getWinding()[1].vertex,
2807                                 m_face->getWinding()[2].vertex
2808                                 ),
2809                         "update_move_planepts_vertex2: error"
2810                         );
2811
2812                 m_face->m_move_planepts[0] = m_face->getWinding()[opposite].vertex;
2813                 m_face->m_move_planepts[1] = m_face->getWinding()[index].vertex;
2814                 m_face->m_move_planepts[2] = m_face->getWinding()[other].vertex;
2815                 planepts_quantise( m_face->m_move_planepts, GRID_MIN ); // winding points are very inaccurate
2816         }
2817
2818         void update_selection_vertex(){
2819                 if ( m_vertexSelection.size() == 0 ) {
2820                         m_selectableVertices.setSelected( false );
2821                 }
2822                 else
2823                 {
2824                         m_selectableVertices.setSelected( true );
2825
2826                         if ( m_vertexSelection.size() == 1 ) {
2827                                 std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_vertexSelection.begin() );
2828
2829                                 if ( index != c_brush_maxFaces ) {
2830                                         update_move_planepts_vertex( index );
2831                                 }
2832                         }
2833                         else if ( m_vertexSelection.size() == 2 ) {
2834                                 std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_vertexSelection.begin() );
2835                                 std::size_t other = Winding_FindAdjacent( getFace().getWinding(), *( ++m_vertexSelection.begin() ) );
2836
2837                                 if ( index != c_brush_maxFaces
2838                                          && other != c_brush_maxFaces ) {
2839                                         update_move_planepts_vertex2( index, other );
2840                                 }
2841                         }
2842                 }
2843         }
2844
2845         void select_vertex( std::size_t index, bool select ){
2846                 if ( select ) {
2847                         VertexSelection_insert( m_vertexSelection, getFace().getWinding()[index].adjacent );
2848                 }
2849                 else
2850                 {
2851                         VertexSelection_erase( m_vertexSelection, getFace().getWinding()[index].adjacent );
2852                 }
2853
2854                 SceneChangeNotify();
2855                 update_selection_vertex();
2856         }
2857
2858         bool selected_vertex( std::size_t index ) const {
2859                 return VertexSelection_find( m_vertexSelection, getFace().getWinding()[index].adjacent ) != m_vertexSelection.end();
2860         }
2861
2862         void update_move_planepts_edge( std::size_t index ){
2863                 std::size_t numpoints = m_face->getWinding().numpoints;
2864                 ASSERT_MESSAGE( index < numpoints, "select_edge: invalid index" );
2865
2866                 std::size_t adjacent = Winding_next( m_face->getWinding(), index );
2867                 std::size_t opposite = Winding_Opposite( m_face->getWinding(), index );
2868                 m_face->m_move_planepts[0] = m_face->getWinding()[index].vertex;
2869                 m_face->m_move_planepts[1] = m_face->getWinding()[adjacent].vertex;
2870                 m_face->m_move_planepts[2] = m_face->getWinding()[opposite].vertex;
2871                 planepts_quantise( m_face->m_move_planepts, GRID_MIN ); // winding points are very inaccurate
2872         }
2873
2874         void update_selection_edge(){
2875                 if ( m_edgeSelection.size() == 0 ) {
2876                         m_selectableEdges.setSelected( false );
2877                 }
2878                 else
2879                 {
2880                         m_selectableEdges.setSelected( true );
2881
2882                         if ( m_edgeSelection.size() == 1 ) {
2883                                 std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_edgeSelection.begin() );
2884
2885                                 if ( index != c_brush_maxFaces ) {
2886                                         update_move_planepts_edge( index );
2887                                 }
2888                         }
2889                 }
2890         }
2891
2892         void select_edge( std::size_t index, bool select ){
2893                 if ( select ) {
2894                         VertexSelection_insert( m_edgeSelection, getFace().getWinding()[index].adjacent );
2895                 }
2896                 else
2897                 {
2898                         VertexSelection_erase( m_edgeSelection, getFace().getWinding()[index].adjacent );
2899                 }
2900
2901                 SceneChangeNotify();
2902                 update_selection_edge();
2903         }
2904
2905         bool selected_edge( std::size_t index ) const {
2906                 return VertexSelection_find( m_edgeSelection, getFace().getWinding()[index].adjacent ) != m_edgeSelection.end();
2907         }
2908
2909         const Vector3& centroid() const {
2910                 return m_face->centroid();
2911         }
2912
2913         void connectivityChanged(){
2914                 // This occurs when a face is added or removed.
2915                 // The current vertex and edge selections no longer valid and must be cleared.
2916                 m_vertexSelection.clear();
2917                 m_selectableVertices.setSelected( false );
2918                 m_edgeSelection.clear();
2919                 m_selectableEdges.setSelected( false );
2920         }
2921 };
2922
2923 class BrushClipPlane : public OpenGLRenderable
2924 {
2925         Plane3 m_plane;
2926         Winding m_winding;
2927         static Shader* m_state;
2928 public:
2929         static void constructStatic(){
2930                 m_state = GlobalShaderCache().capture( "$CLIPPER_OVERLAY" );
2931         }
2932
2933         static void destroyStatic(){
2934                 GlobalShaderCache().release( "$CLIPPER_OVERLAY" );
2935         }
2936
2937         void setPlane( const Brush& brush, const Plane3& plane ){
2938                 m_plane = plane;
2939                 if ( plane3_valid( m_plane ) ) {
2940                         brush.windingForClipPlane( m_winding, m_plane );
2941                 }
2942                 else
2943                 {
2944                         m_winding.resize( 0 );
2945                 }
2946         }
2947
2948         void render( RenderStateFlags state ) const {
2949                 if ( ( state & RENDER_FILL ) != 0 ) {
2950                         Winding_Draw( m_winding, m_plane.normal(), state );
2951                 }
2952                 else
2953                 {
2954                         Winding_DrawWireframe( m_winding );
2955
2956                         // also draw a line indicating the direction of the cut
2957                         Vector3 lineverts[2];
2958                         Winding_Centroid( m_winding, m_plane, lineverts[0] );
2959                         lineverts[1] = vector3_added( lineverts[0], vector3_scaled( m_plane.normal(), Brush::m_maxWorldCoord * 4 ) );
2960
2961                         glVertexPointer( 3, GL_FLOAT, sizeof( Vector3 ), &lineverts[0] );
2962                         glDrawArrays( GL_LINES, 0, GLsizei( 2 ) );
2963                 }
2964         }
2965
2966         void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
2967                 renderer.SetState( m_state, Renderer::eWireframeOnly );
2968                 renderer.SetState( m_state, Renderer::eFullMaterials );
2969                 renderer.addRenderable( *this, localToWorld );
2970         }
2971 };
2972
2973 inline void Face_addLight( const FaceInstance& face, const Matrix4& localToWorld, const RendererLight& light ){
2974         const Plane3& facePlane = face.getFace().plane3();
2975         const Vector3& origin = light.aabb().origin;
2976         Plane3 tmp( plane3_transformed( Plane3( facePlane.normal(), -facePlane.dist() ), localToWorld ) );
2977         if ( !plane3_test_point( tmp, origin )
2978                  || !plane3_test_point( tmp, vector3_added( origin, light.offset() ) ) ) {
2979                 face.m_lights.addLight( light );
2980         }
2981 }
2982
2983
2984 typedef std::vector<FaceInstance> FaceInstances;
2985
2986 class EdgeInstance : public Selectable
2987 {
2988         FaceInstances& m_faceInstances;
2989         SelectableEdge* m_edge;
2990
2991         void select_edge( bool select ){
2992                 FaceVertexId faceVertex = m_edge->m_faceVertex;
2993                 m_faceInstances[faceVertex.getFace()].select_edge( faceVertex.getVertex(), select );
2994                 faceVertex = next_edge( m_edge->m_faces, faceVertex );
2995                 m_faceInstances[faceVertex.getFace()].select_edge( faceVertex.getVertex(), select );
2996         }
2997
2998         bool selected_edge() const {
2999                 FaceVertexId faceVertex = m_edge->m_faceVertex;
3000                 if ( !m_faceInstances[faceVertex.getFace()].selected_edge( faceVertex.getVertex() ) ) {
3001                         return false;
3002                 }
3003                 faceVertex = next_edge( m_edge->m_faces, faceVertex );
3004                 if ( !m_faceInstances[faceVertex.getFace()].selected_edge( faceVertex.getVertex() ) ) {
3005                         return false;
3006                 }
3007
3008                 return true;
3009         }
3010
3011 public:
3012         EdgeInstance( FaceInstances& faceInstances, SelectableEdge& edge )
3013                 : m_faceInstances( faceInstances ), m_edge( &edge ){
3014         }
3015         EdgeInstance& operator=( const EdgeInstance& other ){
3016                 m_edge = other.m_edge;
3017                 return *this;
3018         }
3019
3020         void setSelected( bool select ){
3021                 select_edge( select );
3022         }
3023
3024         bool isSelected() const {
3025                 return selected_edge();
3026         }
3027
3028
3029         void testSelect( Selector& selector, SelectionTest& test ){
3030                 SelectionIntersection best;
3031                 m_edge->testSelect( test, best );
3032                 if ( best.valid() ) {
3033                         Selector_add( selector, *this, best );
3034                 }
3035         }
3036 };
3037
3038 class VertexInstance : public Selectable
3039 {
3040         FaceInstances& m_faceInstances;
3041         SelectableVertex* m_vertex;
3042
3043         void select_vertex( bool select ){
3044                 FaceVertexId faceVertex = m_vertex->m_faceVertex;
3045                 do
3046                 {
3047                         m_faceInstances[faceVertex.getFace()].select_vertex( faceVertex.getVertex(), select );
3048                         faceVertex = next_vertex( m_vertex->m_faces, faceVertex );
3049                 }
3050                 while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() );
3051         }
3052
3053         bool selected_vertex() const {
3054                 FaceVertexId faceVertex = m_vertex->m_faceVertex;
3055                 do
3056                 {
3057                         if ( !m_faceInstances[faceVertex.getFace()].selected_vertex( faceVertex.getVertex() ) ) {
3058                                 return false;
3059                         }
3060                         faceVertex = next_vertex( m_vertex->m_faces, faceVertex );
3061                 }
3062                 while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() );
3063                 return true;
3064         }
3065
3066         public:
3067         VertexInstance( FaceInstances& faceInstances, SelectableVertex& vertex )
3068                 : m_faceInstances( faceInstances ), m_vertex( &vertex ){
3069         }
3070         VertexInstance& operator=( const VertexInstance& other ){
3071                 m_vertex = other.m_vertex;
3072                 return *this;
3073         }
3074
3075         void setSelected( bool select ){
3076                 select_vertex( select );
3077         }
3078
3079         bool isSelected() const {
3080                 return selected_vertex();
3081         }
3082
3083         void testSelect( Selector& selector, SelectionTest& test ){
3084                 SelectionIntersection best;
3085                 m_vertex->testSelect( test, best );
3086                 if ( best.valid() ) {
3087                         Selector_add( selector, *this, best );
3088                 }
3089         }
3090 };
3091
3092 class BrushInstanceVisitor
3093 {
3094 public:
3095         virtual void visit( FaceInstance& face ) const = 0;
3096 };
3097
3098 class BrushInstance :
3099         public BrushObserver,
3100         public scene::Instance,
3101         public Selectable,
3102         public Renderable,
3103         public SelectionTestable,
3104         public ComponentSelectionTestable,
3105         public ComponentEditable,
3106         public ComponentSnappable,
3107         public PlaneSelectable,
3108         public LightCullable
3109 {
3110         class TypeCasts
3111         {
3112                 InstanceTypeCastTable m_casts;
3113         public:
3114                 TypeCasts(){
3115                         InstanceStaticCast<BrushInstance, Selectable>::install( m_casts );
3116                         InstanceContainedCast<BrushInstance, Bounded>::install( m_casts );
3117                         InstanceContainedCast<BrushInstance, Cullable>::install( m_casts );
3118                         InstanceStaticCast<BrushInstance, Renderable>::install( m_casts );
3119                         InstanceStaticCast<BrushInstance, SelectionTestable>::install( m_casts );
3120                         InstanceStaticCast<BrushInstance, ComponentSelectionTestable>::install( m_casts );
3121                         InstanceStaticCast<BrushInstance, ComponentEditable>::install( m_casts );
3122                         InstanceStaticCast<BrushInstance, ComponentSnappable>::install( m_casts );
3123                         InstanceStaticCast<BrushInstance, PlaneSelectable>::install( m_casts );
3124                         InstanceIdentityCast<BrushInstance>::install( m_casts );
3125                         InstanceContainedCast<BrushInstance, Transformable>::install( m_casts );
3126                 }
3127
3128                 InstanceTypeCastTable& get(){
3129                         return m_casts;
3130                 }
3131         };
3132
3133
3134         Brush& m_brush;
3135
3136         FaceInstances m_faceInstances;
3137
3138         typedef std::vector<EdgeInstance> EdgeInstances;
3139         EdgeInstances m_edgeInstances;
3140         typedef std::vector<VertexInstance> VertexInstances;
3141         VertexInstances m_vertexInstances;
3142
3143         ObservedSelectable m_selectable;
3144
3145         mutable RenderableWireframe m_render_wireframe;
3146         mutable RenderablePointVector m_render_selected;
3147         mutable AABB m_aabb_component;
3148         mutable Array<PointVertex> m_faceCentroidPointsCulled;
3149         RenderablePointArray m_render_faces_wireframe;
3150         mutable bool m_viewChanged;   // requires re-evaluation of view-dependent cached data
3151
3152         BrushClipPlane m_clipPlane;
3153
3154         static Shader* m_state_selpoint;
3155
3156         const LightList* m_lightList;
3157
3158         TransformModifier m_transform;
3159
3160         BrushInstance( const BrushInstance& other ); // NOT COPYABLE
3161         BrushInstance& operator=( const BrushInstance& other ); // NOT ASSIGNABLE
3162
3163 public:
3164         static Counter* m_counter;
3165
3166         typedef LazyStatic<TypeCasts> StaticTypeCasts;
3167
3168         void lightsChanged(){
3169                 m_lightList->lightsChanged();
3170         }
3171
3172         typedef MemberCaller<BrushInstance, void(), &BrushInstance::lightsChanged> LightsChangedCaller;
3173
3174         STRING_CONSTANT( Name, "BrushInstance" );
3175
3176         BrushInstance( const scene::Path& path, scene::Instance* parent, Brush& brush ) :
3177                 Instance( path, parent, this, StaticTypeCasts::instance().get() ),
3178                 m_brush( brush ),
3179                 m_selectable( SelectedChangedCaller( *this ) ),
3180                 m_render_selected( GL_POINTS ),
3181                 m_render_faces_wireframe( m_faceCentroidPointsCulled, GL_POINTS ),
3182                 m_viewChanged( false ),
3183                 m_transform( Brush::TransformChangedCaller( m_brush ), ApplyTransformCaller( *this ) ){
3184                 m_brush.instanceAttach( Instance::path() );
3185                 m_brush.attach( *this );
3186                 m_counter->increment();
3187
3188                 m_lightList = &GlobalShaderCache().attach( *this );
3189                 m_brush.m_lightsChanged = LightsChangedCaller( *this ); ///\todo Make this work with instancing.
3190
3191                 Instance::setTransformChangedCallback( LightsChangedCaller( *this ) );
3192         }
3193
3194         ~BrushInstance(){
3195                 Instance::setTransformChangedCallback( Callback<void()>() );
3196
3197                 m_brush.m_lightsChanged = Callback<void()>();
3198                 GlobalShaderCache().detach( *this );
3199
3200                 m_counter->decrement();
3201                 m_brush.detach( *this );
3202                 m_brush.instanceDetach( Instance::path() );
3203         }
3204
3205         Brush& getBrush(){
3206                 return m_brush;
3207         }
3208         const Brush& getBrush() const {
3209                 return m_brush;
3210         }
3211
3212         Bounded& get( NullType<Bounded>){
3213                 return m_brush;
3214         }
3215
3216         Cullable& get( NullType<Cullable>){
3217                 return m_brush;
3218         }
3219
3220         Transformable& get( NullType<Transformable>){
3221                 return m_transform;
3222         }
3223
3224         void selectedChanged( const Selectable& selectable ){
3225                 GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable );
3226                 GlobalSelectionSystem().onSelectedChanged( *this, selectable );
3227
3228                 Instance::selectedChanged();
3229         }
3230         typedef MemberCaller<BrushInstance, void(const Selectable&), &BrushInstance::selectedChanged> SelectedChangedCaller;
3231
3232         void selectedChangedComponent( const Selectable& selectable ){
3233                 GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable );
3234                 GlobalSelectionSystem().onComponentSelection( *this, selectable );
3235         }
3236         typedef MemberCaller<BrushInstance, void(const Selectable&), &BrushInstance::selectedChangedComponent> SelectedChangedComponentCaller;
3237
3238         const BrushInstanceVisitor& forEachFaceInstance( const BrushInstanceVisitor& visitor ){
3239                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3240                 {
3241                         visitor.visit( *i );
3242                 }
3243                 return visitor;
3244         }
3245
3246         static void constructStatic(){
3247                 m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" );
3248         }
3249
3250         static void destroyStatic(){
3251                 GlobalShaderCache().release( "$SELPOINT" );
3252         }
3253
3254         void clear(){
3255                 m_faceInstances.clear();
3256         }
3257
3258         void reserve( std::size_t size ){
3259                 m_faceInstances.reserve( size );
3260         }
3261
3262         void push_back( Face& face ){
3263                 m_faceInstances.push_back( FaceInstance( face, SelectedChangedComponentCaller( *this ) ) );
3264         }
3265
3266         void pop_back(){
3267                 ASSERT_MESSAGE( !m_faceInstances.empty(), "erasing invalid element" );
3268                 m_faceInstances.pop_back();
3269         }
3270
3271         void erase( std::size_t index ){
3272                 ASSERT_MESSAGE( index < m_faceInstances.size(), "erasing invalid element" );
3273                 m_faceInstances.erase( m_faceInstances.begin() + index );
3274         }
3275
3276         void connectivityChanged(){
3277                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3278                 {
3279                         ( *i ).connectivityChanged();
3280                 }
3281         }
3282
3283         void edge_clear(){
3284                 m_edgeInstances.clear();
3285         }
3286
3287         void edge_push_back( SelectableEdge& edge ){
3288                 m_edgeInstances.push_back( EdgeInstance( m_faceInstances, edge ) );
3289         }
3290
3291         void vertex_clear(){
3292                 m_vertexInstances.clear();
3293         }
3294
3295         void vertex_push_back( SelectableVertex& vertex ){
3296                 m_vertexInstances.push_back( VertexInstance( m_faceInstances, vertex ) );
3297         }
3298
3299         void DEBUG_verify() const {
3300                 ASSERT_MESSAGE( m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch" );
3301         }
3302
3303         bool isSelected() const {
3304                 return m_selectable.isSelected();
3305         }
3306
3307         void setSelected( bool select ){
3308                 m_selectable.setSelected( select );
3309         }
3310
3311         void update_selected() const {
3312                 m_render_selected.clear();
3313                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3314                 {
3315                         if ( ( *i ).getFace().contributes() ) {
3316                                 ( *i ).iterate_selected( m_render_selected );
3317                         }
3318                 }
3319         }
3320
3321         void evaluateViewDependent( const VolumeTest& volume, const Matrix4& localToWorld ) const {
3322                 if ( m_viewChanged ) {
3323                         m_viewChanged = false;
3324
3325                         bool faces_visible[c_brush_maxFaces];
3326                         {
3327                                 bool* j = faces_visible;
3328                                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i, ++j )
3329                                 {
3330                                         *j = ( *i ).intersectVolume( volume, localToWorld );
3331                                 }
3332                         }
3333
3334                         m_brush.update_wireframe( m_render_wireframe, faces_visible );
3335                         m_brush.update_faces_wireframe( m_faceCentroidPointsCulled, faces_visible );
3336                 }
3337         }
3338
3339         void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
3340                 m_brush.evaluateBRep();
3341
3342                 update_selected();
3343                 if ( !m_render_selected.empty() ) {
3344                         renderer.Highlight( Renderer::ePrimitive, false );
3345                         renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly );
3346                         renderer.SetState( m_state_selpoint, Renderer::eFullMaterials );
3347                         renderer.addRenderable( m_render_selected, localToWorld );
3348                 }
3349         }
3350
3351         void renderComponents( Renderer& renderer, const VolumeTest& volume ) const {
3352                 m_brush.evaluateBRep();
3353
3354                 const Matrix4& localToWorld = Instance::localToWorld();
3355
3356                 renderer.SetState( m_brush.m_state_point, Renderer::eWireframeOnly );
3357                 renderer.SetState( m_brush.m_state_point, Renderer::eFullMaterials );
3358
3359                 if ( volume.fill() && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace ) {
3360                         evaluateViewDependent( volume, localToWorld );
3361                         renderer.addRenderable( m_render_faces_wireframe, localToWorld );
3362                 }
3363                 else
3364                 {
3365                         m_brush.renderComponents( GlobalSelectionSystem().ComponentMode(), renderer, volume, localToWorld );
3366                 }
3367         }
3368
3369         void renderClipPlane( Renderer& renderer, const VolumeTest& volume ) const {
3370                 if ( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && isSelected() ) {
3371                         m_clipPlane.render( renderer, volume, localToWorld() );
3372                 }
3373         }
3374
3375         void renderCommon( Renderer& renderer, const VolumeTest& volume ) const {
3376                 bool componentMode = GlobalSelectionSystem().Mode() == SelectionSystem::eComponent;
3377
3378                 if ( componentMode && isSelected() ) {
3379                         renderComponents( renderer, volume );
3380                 }
3381
3382                 if ( parentSelected() ) {
3383                         if ( !componentMode ) {
3384                                 renderer.Highlight( Renderer::eFace );
3385                         }
3386                         renderer.Highlight( Renderer::ePrimitive );
3387                 }
3388         }
3389
3390         void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
3391                 //renderCommon(renderer, volume);
3392
3393                 m_lightList->evaluateLights();
3394
3395                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3396                 {
3397                         renderer.setLights( ( *i ).m_lights );
3398                         ( *i ).render( renderer, volume, localToWorld );
3399                 }
3400
3401                 renderComponentsSelected( renderer, volume, localToWorld );
3402         }
3403
3404         void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
3405                 //renderCommon(renderer, volume);
3406
3407                 evaluateViewDependent( volume, localToWorld );
3408
3409                 if ( m_render_wireframe.m_size != 0 ) {
3410                         renderer.addRenderable( m_render_wireframe, localToWorld );
3411                 }
3412
3413                 renderComponentsSelected( renderer, volume, localToWorld );
3414         }
3415
3416         void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
3417                 m_brush.evaluateBRep();
3418
3419                 renderClipPlane( renderer, volume );
3420
3421                 renderSolid( renderer, volume, localToWorld() );
3422         }
3423
3424         void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
3425                 m_brush.evaluateBRep();
3426
3427                 renderClipPlane( renderer, volume );
3428
3429                 renderWireframe( renderer, volume, localToWorld() );
3430         }
3431
3432         void viewChanged() const {
3433                 m_viewChanged = true;
3434         }
3435
3436         void testSelect( Selector& selector, SelectionTest& test ){
3437                 test.BeginMesh( localToWorld() );
3438
3439                 SelectionIntersection best;
3440                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3441                 {
3442                         ( *i ).testSelect( test, best );
3443                 }
3444                 if ( best.valid() ) {
3445                         selector.addIntersection( best );
3446                 }
3447         }
3448
3449         bool isSelectedComponents() const {
3450                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3451                 {
3452                         if ( ( *i ).selectedComponents() ) {
3453                                 return true;
3454                         }
3455                 }
3456                 return false;
3457         }
3458
3459         void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){
3460                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3461                 {
3462                         ( *i ).setSelected( mode, select );
3463                 }
3464         }
3465
3466         void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){
3467                 test.BeginMesh( localToWorld() );
3468
3469                 switch ( mode )
3470                 {
3471                 case SelectionSystem::eVertex:
3472                 {
3473                         for ( VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i )
3474                         {
3475                                 ( *i ).testSelect( selector, test );
3476                         }
3477                 }
3478                 break;
3479                 case SelectionSystem::eEdge:
3480                 {
3481                         for ( EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i )
3482                         {
3483                                 ( *i ).testSelect( selector, test );
3484                         }
3485                 }
3486                 break;
3487                 case SelectionSystem::eFace:
3488                 {
3489                         if ( test.getVolume().fill() ) {
3490                                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3491                                 {
3492                                         ( *i ).testSelect( selector, test );
3493                                 }
3494                         }
3495                         else
3496                         {
3497                                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3498                                 {
3499                                         ( *i ).testSelect_centroid( selector, test );
3500                                 }
3501                         }
3502                 }
3503                 break;
3504                 default:
3505                         break;
3506                 }
3507         }
3508
3509         void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){
3510                 test.BeginMesh( localToWorld() );
3511
3512                 PlanePointer brushPlanes[c_brush_maxFaces];
3513                 PlanesIterator j = brushPlanes;
3514
3515                 for ( Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i )
3516                 {
3517                         *j++ = &( *i )->plane3();
3518                 }
3519
3520                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3521                 {
3522                         ( *i ).selectPlane( selector, Line( test.getNear(), test.getFar() ), brushPlanes, j, selectedPlaneCallback );
3523                 }
3524         }
3525
3526         void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){
3527                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3528                 {
3529                         ( *i ).selectReversedPlane( selector, selectedPlanes );
3530                 }
3531         }
3532
3533
3534         void transformComponents( const Matrix4& matrix ){
3535                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3536                 {
3537                         ( *i ).transformComponents( matrix );
3538                 }
3539         }
3540
3541         const AABB& getSelectedComponentsBounds() const {
3542                 m_aabb_component = AABB();
3543
3544                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3545                 {
3546                         ( *i ).iterate_selected( m_aabb_component );
3547                 }
3548
3549                 return m_aabb_component;
3550         }
3551
3552         void snapComponents( float snap ){
3553                 for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3554                 {
3555                         ( *i ).snapComponents( snap );
3556                 }
3557         }
3558
3559         void evaluateTransform(){
3560                 Matrix4 matrix( m_transform.calculateTransform() );
3561                 //globalOutputStream() << "matrix: " << matrix << "\n";
3562
3563                 if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) {
3564                         m_brush.transform( matrix );
3565                 }
3566                 else
3567                 {
3568                         transformComponents( matrix );
3569                 }
3570         }
3571
3572         void applyTransform(){
3573                 m_brush.revertTransform();
3574                 evaluateTransform();
3575                 m_brush.freezeTransform();
3576         }
3577
3578         typedef MemberCaller<BrushInstance, void(), &BrushInstance::applyTransform> ApplyTransformCaller;
3579
3580         void setClipPlane( const Plane3& plane ){
3581                 m_clipPlane.setPlane( m_brush, plane );
3582         }
3583
3584         bool testLight( const RendererLight& light ) const {
3585                 return light.testAABB( worldAABB() );
3586         }
3587
3588         void insertLight( const RendererLight& light ){
3589                 const Matrix4& localToWorld = Instance::localToWorld();
3590                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3591                 {
3592                         Face_addLight( *i, localToWorld, light );
3593                 }
3594         }
3595
3596         void clearLights(){
3597                 for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
3598                 {
3599                         ( *i ).m_lights.clear();
3600                 }
3601         }
3602 };
3603
3604 inline BrushInstance* Instance_getBrush( scene::Instance& instance ){
3605         return InstanceTypeCast<BrushInstance>::cast( instance );
3606 }
3607
3608
3609 template<typename Functor>
3610 class BrushSelectedVisitor : public SelectionSystem::Visitor
3611 {
3612         const Functor& m_functor;
3613 public:
3614         BrushSelectedVisitor( const Functor& functor ) : m_functor( functor ){
3615         }
3616
3617         void visit( scene::Instance& instance ) const {
3618                 BrushInstance* brush = Instance_getBrush( instance );
3619                 if ( brush != 0 ) {
3620                         m_functor( *brush );
3621                 }
3622         }
3623 };
3624
3625 template<typename Functor>
3626 inline const Functor& Scene_forEachSelectedBrush( const Functor& functor ){
3627         GlobalSelectionSystem().foreachSelected( BrushSelectedVisitor<Functor>( functor ) );
3628         return functor;
3629 }
3630
3631 template<typename Functor>
3632 class BrushVisibleSelectedVisitor : public SelectionSystem::Visitor
3633 {
3634         const Functor& m_functor;
3635 public:
3636         BrushVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){
3637         }
3638
3639         void visit( scene::Instance& instance ) const {
3640                 BrushInstance* brush = Instance_getBrush( instance );
3641                 if ( brush != 0
3642                          && instance.path().top().get().visible() ) {
3643                         m_functor( *brush );
3644                 }
3645         }
3646 };
3647
3648 template<typename Functor>
3649 inline const Functor& Scene_forEachVisibleSelectedBrush( const Functor& functor ){
3650         GlobalSelectionSystem().foreachSelected( BrushVisibleSelectedVisitor<Functor>( functor ) );
3651         return functor;
3652 }
3653
3654 class BrushForEachFace
3655 {
3656         const BrushInstanceVisitor& m_visitor;
3657 public:
3658         BrushForEachFace( const BrushInstanceVisitor& visitor ) : m_visitor( visitor ){
3659         }
3660
3661         void operator()( BrushInstance& brush ) const {
3662                 brush.forEachFaceInstance( m_visitor );
3663         }
3664 };
3665
3666 template<class Functor>
3667 class FaceInstanceVisitFace : public BrushInstanceVisitor
3668 {
3669         const Functor& functor;
3670 public:
3671         FaceInstanceVisitFace( const Functor& functor )
3672                 : functor( functor ){
3673         }
3674
3675         void visit( FaceInstance& face ) const {
3676                 functor( face.getFace() );
3677         }
3678 };
3679
3680 template<typename Functor>
3681 inline const Functor& Brush_forEachFace( BrushInstance& brush, const Functor& functor ){
3682         brush.forEachFaceInstance( FaceInstanceVisitFace<Functor>( functor ) );
3683         return functor;
3684 }
3685
3686 template<class Functor>
3687 class FaceVisitAll : public BrushVisitor
3688 {
3689         const Functor& functor;
3690 public:
3691         FaceVisitAll( const Functor& functor )
3692                 : functor( functor ){
3693         }
3694
3695         void visit( Face& face ) const {
3696                 functor( face );
3697         }
3698 };
3699
3700 template<typename Functor>
3701 inline const Functor& Brush_forEachFace( const Brush& brush, const Functor& functor ){
3702         brush.forEachFace( FaceVisitAll<Functor>( functor ) );
3703         return functor;
3704 }
3705
3706 template<typename Functor>
3707 inline const Functor& Brush_forEachFace( Brush& brush, const Functor& functor ){
3708         brush.forEachFace( FaceVisitAll<Functor>( functor ) );
3709         return functor;
3710 }
3711
3712 template<class Functor>
3713 class FaceInstanceVisitAll : public BrushInstanceVisitor
3714 {
3715         const Functor& functor;
3716 public:
3717         FaceInstanceVisitAll( const Functor& functor )
3718                 : functor( functor ){
3719         }
3720
3721         void visit( FaceInstance& face ) const {
3722                 functor( face );
3723         }
3724 };
3725
3726 template<typename Functor>
3727 inline const Functor& Brush_ForEachFaceInstance( BrushInstance& brush, const Functor& functor ){
3728         brush.forEachFaceInstance( FaceInstanceVisitAll<Functor>( functor ) );
3729         return functor;
3730 }
3731
3732 template<typename Functor>
3733 inline const Functor& Scene_forEachBrush( scene::Graph& graph, const Functor& functor ){
3734         graph.traverse( InstanceWalker< InstanceApply<BrushInstance, Functor> >( functor ) );
3735         return functor;
3736 }
3737
3738 template<typename Type, typename Functor>
3739 class InstanceIfVisible : public Functor
3740 {
3741 public:
3742         InstanceIfVisible( const Functor& functor ) : Functor( functor ){
3743         }
3744
3745         void operator()( scene::Instance& instance ){
3746                 if ( instance.path().top().get().visible() ) {
3747                         Functor::operator()( instance );
3748                 }
3749         }
3750 };
3751
3752 template<typename Functor>
3753 class BrushVisibleWalker : public scene::Graph::Walker
3754 {
3755         const Functor& m_functor;
3756 public:
3757         BrushVisibleWalker( const Functor& functor ) : m_functor( functor ){
3758         }
3759
3760         bool pre( const scene::Path& path, scene::Instance& instance ) const {
3761                 if ( path.top().get().visible() ) {
3762                         BrushInstance* brush = Instance_getBrush( instance );
3763                         if ( brush != 0 ) {
3764                                 m_functor( *brush );
3765                         }
3766                 }
3767                 return true;
3768         }
3769 };
3770
3771 template<typename Functor>
3772 inline const Functor& Scene_forEachVisibleBrush( scene::Graph& graph, const Functor& functor ){
3773         graph.traverse( BrushVisibleWalker<Functor>( functor ) );
3774         return functor;
3775 }
3776
3777 template<typename Functor>
3778 inline const Functor& Scene_ForEachBrush_ForEachFace( scene::Graph& graph, const Functor& functor ){
3779         Scene_forEachBrush( graph, BrushForEachFace( FaceInstanceVisitFace<Functor>( functor ) ) );
3780         return functor;
3781 }
3782
3783 // d1223m
3784 template<typename Functor>
3785 inline const Functor& Scene_ForEachBrush_ForEachFaceInstance( scene::Graph& graph, const Functor& functor ){
3786         Scene_forEachBrush( graph, BrushForEachFace( FaceInstanceVisitAll<Functor>( functor ) ) );
3787         return functor;
3788 }
3789
3790 template<typename Functor>
3791 inline const Functor& Scene_ForEachSelectedBrush_ForEachFace( scene::Graph& graph, const Functor& functor ){
3792         Scene_forEachSelectedBrush( BrushForEachFace( FaceInstanceVisitFace<Functor>( functor ) ) );
3793         return functor;
3794 }
3795
3796 template<typename Functor>
3797 inline const Functor& Scene_ForEachSelectedBrush_ForEachFaceInstance( scene::Graph& graph, const Functor& functor ){
3798         Scene_forEachSelectedBrush( BrushForEachFace( FaceInstanceVisitAll<Functor>( functor ) ) );
3799         return functor;
3800 }
3801
3802 template<typename Functor>
3803 class FaceVisitorWrapper
3804 {
3805         const Functor& functor;
3806 public:
3807         FaceVisitorWrapper( const Functor& functor ) : functor( functor ){
3808         }
3809
3810         void operator()( FaceInstance& faceInstance ) const {
3811                 functor( faceInstance.getFace() );
3812         }
3813 };
3814
3815 template<typename Functor>
3816 inline const Functor& Scene_ForEachSelectedBrushFace( scene::Graph& graph, const Functor& functor ){
3817         g_SelectedFaceInstances.foreach( FaceVisitorWrapper<Functor>( functor ) );
3818         return functor;
3819 }
3820
3821
3822 #endif