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