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