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