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