]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/patch.h
Remove some dead/debug code
[xonotic/netradiant.git] / radiant / patch.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
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_PATCH_H )
23 #define INCLUDED_PATCH_H
24
25 /// \file
26 /// \brief The patch primitive.
27 ///
28 /// A 2-dimensional matrix of vertices that define a quadratic bezier surface.
29 /// The Boundary-Representation of this primitive is a triangle mesh.
30 /// The surface is recursively tesselated until the angle between each triangle
31 /// edge is smaller than a specified tolerance.
32
33
34 #include "nameable.h"
35 #include "ifilter.h"
36 #include "imap.h"
37 #include "ipatch.h"
38 #include "cullable.h"
39 #include "renderable.h"
40 #include "editable.h"
41 #include "selectable.h"
42
43 #include "debugging/debugging.h"
44
45 #include <set>
46 #include <limits>
47
48 #include "math/frustum.h"
49 #include "string/string.h"
50 #include "stream/stringstream.h"
51 #include "stream/textstream.h"
52 #include "xml/xmlelement.h"
53 #include "scenelib.h"
54 #include "transformlib.h"
55 #include "instancelib.h"
56 #include "selectionlib.h"
57 #include "traverselib.h"
58 #include "render.h"
59 #include "stringio.h"
60 #include "shaderlib.h"
61 #include "generic/callback.h"
62 #include "signal/signalfwd.h"
63 #include "texturelib.h"
64 #include "xml/ixml.h"
65 #include "dragplanes.h"
66
67 enum EPatchType
68 {
69         ePatchTypeQuake3,
70         ePatchTypeDoom3,
71 };
72
73 extern int g_PatchSubdivideThreshold;
74
75
76 #define MIN_PATCH_WIDTH 3
77 #define MIN_PATCH_HEIGHT 3
78
79 extern std::size_t MAX_PATCH_WIDTH;
80 extern std::size_t MAX_PATCH_HEIGHT;
81
82 #define MAX_PATCH_ROWCTRL ( ( ( MAX_PATCH_WIDTH - 1 ) - 1 ) / 2 )
83 #define MAX_PATCH_COLCTRL ( ( ( MAX_PATCH_HEIGHT - 1 ) - 1 ) / 2 )
84
85 enum EPatchCap
86 {
87         eCapBevel,
88         eCapEndCap,
89         eCapIBevel,
90         eCapIEndCap,
91         eCapCylinder,
92 };
93
94 enum EPatchPrefab
95 {
96         ePlane,
97         eBevel,
98         eEndCap,
99         eCylinder,
100         eDenseCylinder,
101         eVeryDenseCylinder,
102         eSqCylinder,
103         eCone,
104         eSphere,
105         eXactCylinder,
106         eXactSphere,
107         eXactCone,
108 };
109
110 enum EMatrixMajor
111 {
112         ROW, COL,
113 };
114
115 struct BezierCurve
116 {
117         Vector3 crd;
118         Vector3 left;
119         Vector3 right;
120 };
121
122 const std::size_t BEZIERCURVETREE_MAX_INDEX = std::size_t( 1 ) << ( std::numeric_limits<std::size_t>::digits - 1 );
123
124 struct BezierCurveTree
125 {
126         std::size_t index;
127         BezierCurveTree* left;
128         BezierCurveTree* right;
129 };
130
131 inline bool BezierCurveTree_isLeaf( const BezierCurveTree* node ){
132         return node->left == 0 && node->right == 0;
133 }
134
135 void BezierCurveTree_Delete( BezierCurveTree *pCurve );
136
137
138 inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVertex* array ){
139         return VertexPointer( VertexPointer::pointer( &array->vertex ), sizeof( ArbitraryMeshVertex ) );
140 }
141
142 typedef PatchControl* PatchControlIter;
143 typedef const PatchControl* PatchControlConstIter;
144
145 inline void copy_ctrl( PatchControlIter ctrl, PatchControlConstIter begin, PatchControlConstIter end ){
146         std::copy( begin, end, ctrl );
147 }
148
149 const Colour4b colour_corner( 0, 255, 0, 255 );
150 const Colour4b colour_inside( 255, 0, 255, 255 );
151
152 class Patch;
153
154 class PatchFilter
155 {
156 public:
157 virtual bool filter( const Patch& patch ) const = 0;
158 };
159
160 bool patch_filtered( Patch& patch );
161 void add_patch_filter( PatchFilter& filter, int mask, bool invert = false );
162
163 void Patch_addTextureChangedCallback( const SignalHandler& handler );
164 void Patch_textureChanged();
165
166 inline void BezierCurveTreeArray_deleteAll( Array<BezierCurveTree*>& curveTrees ){
167         for ( Array<BezierCurveTree*>::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i )
168         {
169                 BezierCurveTree_Delete( *i );
170         }
171 }
172
173 inline void PatchControlArray_invert( Array<PatchControl>& ctrl, std::size_t width, std::size_t height ){
174         Array<PatchControl> tmp( width );
175
176         PatchControlIter from = ctrl.data() + ( width * ( height - 1 ) );
177         PatchControlIter to = ctrl.data();
178         for ( std::size_t h = 0; h != ( ( height - 1 ) >> 1 ); ++h, to += width, from -= width )
179         {
180                 copy_ctrl( tmp.data(), to, to + width );
181                 copy_ctrl( to, from, from + width );
182                 copy_ctrl( from, tmp.data(), tmp.data() + width );
183         }
184 }
185
186 class PatchTesselation
187 {
188 public:
189 PatchTesselation()
190         : m_numStrips( 0 ), m_lenStrips( 0 ), m_nArrayWidth( 0 ), m_nArrayHeight( 0 ){
191 }
192 Array<ArbitraryMeshVertex> m_vertices;
193 Array<RenderIndex> m_indices;
194 std::size_t m_numStrips;
195 std::size_t m_lenStrips;
196
197 Array<std::size_t> m_arrayWidth;
198 std::size_t m_nArrayWidth;
199 Array<std::size_t> m_arrayHeight;
200 std::size_t m_nArrayHeight;
201
202 Array<BezierCurveTree*> m_curveTreeU;
203 Array<BezierCurveTree*> m_curveTreeV;
204 };
205
206 class RenderablePatchWireframe : public OpenGLRenderable
207 {
208 PatchTesselation& m_tess;
209 public:
210 RenderablePatchWireframe( PatchTesselation& tess ) : m_tess( tess ){
211 }
212 void render( RenderStateFlags state ) const {
213         {
214   #if NV_DRIVER_BUG
215                 glVertexPointer( 3, GL_FLOAT, 0, 0 );
216                 glDrawArrays( GL_TRIANGLE_FAN, 0, 0 );
217   #endif
218
219                 std::size_t n = 0;
220                 glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex );
221                 for ( std::size_t i = 0; i <= m_tess.m_curveTreeV.size(); ++i )
222                 {
223                         glDrawArrays( GL_LINE_STRIP, GLint( n ), GLsizei( m_tess.m_nArrayWidth ) );
224
225                         if ( i == m_tess.m_curveTreeV.size() ) {
226                                 break;
227                         }
228
229                         if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeV[i] ) ) {
230                                 glDrawArrays( GL_LINE_STRIP, GLint( m_tess.m_curveTreeV[i]->index ), GLsizei( m_tess.m_nArrayWidth ) );
231                         }
232
233                         n += ( m_tess.m_arrayHeight[i] * m_tess.m_nArrayWidth );
234
235                 }
236         }
237
238         {
239                 const ArbitraryMeshVertex* p = m_tess.m_vertices.data();
240                 std::size_t n = m_tess.m_nArrayWidth * sizeof( ArbitraryMeshVertex );
241                 for ( std::size_t i = 0; i <= m_tess.m_curveTreeU.size(); ++i )
242                 {
243                         glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &p->vertex );
244                         glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) );
245
246                         if ( i == m_tess.m_curveTreeU.size() ) {
247                                 break;
248                         }
249
250                         if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeU[i] ) ) {
251                                 glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &( m_tess.m_vertices.data() + ( m_tess.m_curveTreeU[i]->index ) )->vertex );
252                                 glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) );
253                         }
254
255                         p += m_tess.m_arrayWidth[i];
256                 }
257         }
258 }
259 };
260
261 class RenderablePatchFixedWireframe : public OpenGLRenderable
262 {
263 PatchTesselation& m_tess;
264 public:
265 RenderablePatchFixedWireframe( PatchTesselation& tess ) : m_tess( tess ){
266 }
267 void render( RenderStateFlags state ) const {
268         glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex );
269         const RenderIndex* strip_indices = m_tess.m_indices.data();
270         for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips )
271         {
272                 glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices );
273         }
274 }
275 };
276
277 class RenderablePatchSolid : public OpenGLRenderable
278 {
279 PatchTesselation& m_tess;
280 public:
281 RenderablePatchSolid( PatchTesselation& tess ) : m_tess( tess ){
282 }
283 void render( RenderStateFlags state ) const {
284         if ( ( state & RENDER_BUMP ) != 0 ) {
285                 if ( GlobalShaderCache().useShaderLanguage() ) {
286                         glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal );
287                         glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord );
288                         glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->tangent );
289                         glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->bitangent );
290                 }
291                 else
292                 {
293                         glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal );
294                         glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord );
295                         glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->tangent );
296                         glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->bitangent );
297                 }
298         }
299         else
300         {
301                 glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal );
302                 glTexCoordPointer( 2, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord );
303         }
304         glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex );
305         const RenderIndex* strip_indices = m_tess.m_indices.data();
306         for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips )
307         {
308                 glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices );
309         }
310 }
311 };
312
313 // parametric surface defined by quadratic bezier control curves
314 class Patch :
315         public XMLImporter,
316         public XMLExporter,
317         public TransformNode,
318         public Bounded,
319         public Cullable,
320         public Snappable,
321         public Undoable,
322         public Filterable,
323         public Nameable
324 {
325 class xml_state_t
326 {
327 public:
328 enum EState
329 {
330         eDefault,
331         ePatch,
332         eMatrix,
333         eShader,
334 };
335 xml_state_t( EState state )
336         : m_state( state )
337 {}
338 EState state() const {
339         return m_state;
340 }
341 const char* content() const {
342         return m_content.c_str();
343 }
344 std::size_t write( const char* buffer, std::size_t length ){
345         return m_content.write( buffer, length );
346 }
347 private:
348 EState m_state;
349 StringOutputStream m_content;
350 };
351
352 std::vector<xml_state_t> m_xml_state;
353
354 typedef Array<PatchControl> PatchControlArray;
355
356 class SavedState : public UndoMemento
357 {
358 public:
359 SavedState(
360         std::size_t width,
361         std::size_t height,
362         const PatchControlArray& ctrl,
363         const char* shader,
364         bool patchDef3,
365         std::size_t subdivisions_x,
366         std::size_t subdivisions_y
367         ) :
368         m_width( width ),
369         m_height( height ),
370         m_shader( shader ),
371         m_ctrl( ctrl ),
372         m_patchDef3( patchDef3 ),
373         m_subdivisions_x( subdivisions_x ),
374         m_subdivisions_y( subdivisions_y ){
375 }
376
377 void release(){
378         delete this;
379 }
380
381 std::size_t m_width, m_height;
382 CopiedString m_shader;
383 PatchControlArray m_ctrl;
384 bool m_patchDef3;
385 std::size_t m_subdivisions_x;
386 std::size_t m_subdivisions_y;
387 };
388
389 public:
390 class Observer
391 {
392 public:
393 virtual void allocate( std::size_t size ) = 0;
394 };
395
396 private:
397 typedef UniqueSet<Observer*> Observers;
398 Observers m_observers;
399
400 scene::Node* m_node;
401
402 AABB m_aabb_local;   // local bbox
403
404 CopiedString m_shader;
405 Shader* m_state;
406
407 std::size_t m_width;
408 std::size_t m_height;
409 public:
410 bool m_patchDef3;
411 std::size_t m_subdivisions_x;
412 std::size_t m_subdivisions_y;
413 private:
414
415 UndoObserver* m_undoable_observer;
416 MapFile* m_map;
417
418 // dynamically allocated array of control points, size is m_width*m_height
419 PatchControlArray m_ctrl;
420 PatchControlArray m_ctrlTransformed;
421
422 PatchTesselation m_tess;
423 RenderablePatchSolid m_render_solid;
424 RenderablePatchWireframe m_render_wireframe;
425 RenderablePatchFixedWireframe m_render_wireframe_fixed;
426
427 static Shader* m_state_ctrl;
428 static Shader* m_state_lattice;
429 VertexBuffer<PointVertex> m_ctrl_vertices;
430 RenderableVertexBuffer m_render_ctrl;
431 IndexBuffer m_lattice_indices;
432 RenderableIndexBuffer m_render_lattice;
433
434 bool m_bOverlay;
435
436 bool m_transformChanged;
437 Callback m_evaluateTransform;
438 Callback m_boundsChanged;
439
440 void construct(){
441         m_bOverlay = false;
442         m_width = m_height = 0;
443
444         m_patchDef3 = false;
445         m_subdivisions_x = 0;
446         m_subdivisions_y = 0;
447
448         check_shader();
449         captureShader();
450
451         m_xml_state.push_back( xml_state_t::eDefault );
452 }
453
454 public:
455 Callback m_lightsChanged;
456
457 static int m_CycleCapIndex;  // = 0;
458 static EPatchType m_type;
459
460 STRING_CONSTANT( Name, "Patch" );
461
462 Patch( scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) :
463         m_node( &node ),
464         m_shader( texdef_name_default() ),
465         m_state( 0 ),
466         m_undoable_observer( 0 ),
467         m_map( 0 ),
468         m_render_solid( m_tess ),
469         m_render_wireframe( m_tess ),
470         m_render_wireframe_fixed( m_tess ),
471         m_render_ctrl( GL_POINTS, m_ctrl_vertices ),
472         m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ),
473         m_transformChanged( false ),
474         m_evaluateTransform( evaluateTransform ),
475         m_boundsChanged( boundsChanged ){
476         construct();
477 }
478 Patch( const Patch& other, scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) :
479         m_node( &node ),
480         m_shader( texdef_name_default() ),
481         m_state( 0 ),
482         m_undoable_observer( 0 ),
483         m_map( 0 ),
484         m_render_solid( m_tess ),
485         m_render_wireframe( m_tess ),
486         m_render_wireframe_fixed( m_tess ),
487         m_render_ctrl( GL_POINTS, m_ctrl_vertices ),
488         m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ),
489         m_transformChanged( false ),
490         m_evaluateTransform( evaluateTransform ),
491         m_boundsChanged( boundsChanged ){
492         construct();
493
494         m_patchDef3 = other.m_patchDef3;
495         m_subdivisions_x = other.m_subdivisions_x;
496         m_subdivisions_y = other.m_subdivisions_y;
497         setDims( other.m_width, other.m_height );
498         copy_ctrl( m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + ( m_width * m_height ) );
499         SetShader( other.m_shader.c_str() );
500         controlPointsChanged();
501 }
502
503 Patch( const Patch& other ) :
504         XMLImporter( other ),
505         XMLExporter( other ),
506         TransformNode( other ),
507         Bounded( other ),
508         Cullable( other ),
509         Snappable(),
510         Undoable( other ),
511         Filterable( other ),
512         Nameable( other ),
513         m_state( 0 ),
514         m_undoable_observer( 0 ),
515         m_map( 0 ),
516         m_render_solid( m_tess ),
517         m_render_wireframe( m_tess ),
518         m_render_wireframe_fixed( m_tess ),
519         m_render_ctrl( GL_POINTS, m_ctrl_vertices ),
520         m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ),
521         m_transformChanged( false ),
522         m_evaluateTransform( other.m_evaluateTransform ),
523         m_boundsChanged( other.m_boundsChanged ){
524         m_bOverlay = false;
525
526         m_patchDef3 = other.m_patchDef3;
527         m_subdivisions_x = other.m_subdivisions_x;
528         m_subdivisions_y = other.m_subdivisions_y;
529         setDims( other.m_width, other.m_height );
530         copy_ctrl( m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + ( m_width * m_height ) );
531         SetShader( other.m_shader.c_str() );
532         controlPointsChanged();
533 }
534
535 ~Patch(){
536         BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeU );
537         BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeV );
538
539         releaseShader();
540
541         ASSERT_MESSAGE( m_observers.empty(), "Patch::~Patch: observers still attached" );
542 }
543
544 InstanceCounter m_instanceCounter;
545 void instanceAttach( const scene::Path& path ){
546         if ( ++m_instanceCounter.m_count == 1 ) {
547                 m_state->incrementUsed();
548                 m_map = path_find_mapfile( path.begin(), path.end() );
549                 m_undoable_observer = GlobalUndoSystem().observer( this );
550                 GlobalFilterSystem().registerFilterable( *this );
551         }
552         else
553         {
554                 ASSERT_MESSAGE( path_find_mapfile( path.begin(), path.end() ) == m_map, "node is instanced across more than one file" );
555         }
556 }
557 void instanceDetach( const scene::Path& path ){
558         if ( --m_instanceCounter.m_count == 0 ) {
559                 m_map = 0;
560                 m_undoable_observer = 0;
561                 GlobalUndoSystem().release( this );
562                 GlobalFilterSystem().unregisterFilterable( *this );
563                 m_state->decrementUsed();
564         }
565 }
566
567 const char* name() const {
568         return "patch";
569 }
570 void attach( const NameCallback& callback ){
571 }
572 void detach( const NameCallback& callback ){
573 }
574
575 void attach( Observer* observer ){
576         observer->allocate( m_width * m_height );
577
578         m_observers.insert( observer );
579 }
580 void detach( Observer* observer ){
581         m_observers.erase( observer );
582 }
583
584 void updateFiltered(){
585         if ( m_node != 0 ) {
586                 if ( patch_filtered( *this ) ) {
587                         m_node->enable( scene::Node::eFiltered );
588                 }
589                 else
590                 {
591                         m_node->disable( scene::Node::eFiltered );
592                 }
593         }
594 }
595
596 void onAllocate( std::size_t size ){
597         for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i )
598         {
599                 ( *i )->allocate( size );
600         }
601 }
602
603 const Matrix4& localToParent() const {
604         return g_matrix4_identity;
605 }
606 const AABB& localAABB() const {
607         return m_aabb_local;
608 }
609 VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const {
610         return test.TestAABB( m_aabb_local, localToWorld );
611 }
612 void render_solid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
613         renderer.SetState( m_state, Renderer::eFullMaterials );
614         renderer.addRenderable( m_render_solid, localToWorld );
615 }
616 void render_wireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
617         renderer.SetState( m_state, Renderer::eFullMaterials );
618         if ( m_patchDef3 ) {
619                 renderer.addRenderable( m_render_wireframe_fixed, localToWorld );
620         }
621         else
622         {
623                 renderer.addRenderable( m_render_wireframe, localToWorld );
624         }
625 }
626
627 void render_component( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
628         renderer.SetState( m_state_lattice, Renderer::eWireframeOnly );
629         renderer.SetState( m_state_lattice, Renderer::eFullMaterials );
630         renderer.addRenderable( m_render_lattice, localToWorld );
631
632         renderer.SetState( m_state_ctrl, Renderer::eWireframeOnly );
633         renderer.SetState( m_state_ctrl, Renderer::eFullMaterials );
634         renderer.addRenderable( m_render_ctrl, localToWorld );
635 }
636 void testSelect( Selector& selector, SelectionTest& test ){
637         SelectionIntersection best;
638         IndexPointer::index_type* pIndex = m_tess.m_indices.data();
639         for ( std::size_t s = 0; s < m_tess.m_numStrips; s++ )
640         {
641                 test.TestQuadStrip( vertexpointer_arbitrarymeshvertex( m_tess.m_vertices.data() ), IndexPointer( pIndex, m_tess.m_lenStrips ), best );
642                 pIndex += m_tess.m_lenStrips;
643         }
644         if ( best.valid() ) {
645                 selector.addIntersection( best );
646         }
647 }
648 void transform( const Matrix4& matrix ){
649         for ( PatchControlIter i = m_ctrlTransformed.data(); i != m_ctrlTransformed.data() + m_ctrlTransformed.size(); ++i )
650         {
651                 matrix4_transform_point( matrix, ( *i ).m_vertex );
652         }
653
654         if ( matrix4_handedness( matrix ) == MATRIX4_LEFTHANDED ) {
655                 PatchControlArray_invert( m_ctrlTransformed, m_width, m_height );
656         }
657         UpdateCachedData();
658 }
659 void transformChanged(){
660         m_transformChanged = true;
661         m_lightsChanged();
662         SceneChangeNotify();
663 }
664 typedef MemberCaller<Patch, &Patch::transformChanged> TransformChangedCaller;
665
666 void evaluateTransform(){
667         if ( m_transformChanged ) {
668                 m_transformChanged = false;
669                 revertTransform();
670                 m_evaluateTransform();
671         }
672 }
673
674 void revertTransform(){
675         m_ctrlTransformed = m_ctrl;
676 }
677 void freezeTransform(){
678         undoSave();
679         evaluateTransform();
680         ASSERT_MESSAGE( m_ctrlTransformed.size() == m_ctrl.size(), "Patch::freeze: size mismatch" );
681         std::copy( m_ctrlTransformed.begin(), m_ctrlTransformed.end(), m_ctrl.begin() );
682 }
683
684 void controlPointsChanged(){
685         transformChanged();
686         evaluateTransform();
687         UpdateCachedData();
688 }
689 bool isValid() const;
690
691 void snapto( float snap ){
692         undoSave();
693
694         for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i )
695         {
696                 vector3_snap( ( *i ).m_vertex, snap );
697         }
698
699         controlPointsChanged();
700 }
701
702
703
704
705 void RenderDebug( RenderStateFlags state ) const;
706
707 void pushElement( const XMLElement& element ){
708         switch ( m_xml_state.back().state() )
709         {
710         case xml_state_t::eDefault:
711                 ASSERT_MESSAGE( string_equal( element.name(), "patch" ), "parse error" );
712                 m_xml_state.push_back( xml_state_t::ePatch );
713                 break;
714         case xml_state_t::ePatch:
715                 if ( string_equal( element.name(), "matrix" ) ) {
716                         setDims( atoi( element.attribute( "width" ) ), atoi( element.attribute( "height" ) ) );
717                         m_xml_state.push_back( xml_state_t::eMatrix );
718                 }
719                 else if ( string_equal( element.name(), "shader" ) ) {
720                         m_xml_state.push_back( xml_state_t::eShader );
721                 }
722                 break;
723         default:
724                 ERROR_MESSAGE( "parse error" );
725         }
726
727 }
728 void popElement( const char* name ){
729         switch ( m_xml_state.back().state() )
730         {
731         case xml_state_t::eDefault:
732                 ERROR_MESSAGE( "parse error" );
733                 break;
734         case xml_state_t::ePatch:
735                 break;
736         case xml_state_t::eMatrix:
737         {
738                 StringTokeniser content( m_xml_state.back().content() );
739
740                 for ( PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i )
741                 {
742                         ( *i ).m_vertex[0] = string_read_float( content.getToken() );
743                         ( *i ).m_vertex[1] = string_read_float( content.getToken() );
744                         ( *i ).m_vertex[2] = string_read_float( content.getToken() );
745                         ( *i ).m_texcoord[0] = string_read_float( content.getToken() );
746                         ( *i ).m_texcoord[1] = string_read_float( content.getToken() );
747                 }
748                 controlPointsChanged();
749         }
750         break;
751         case xml_state_t::eShader:
752         {
753                 SetShader( m_xml_state.back().content() );
754         }
755         break;
756         default:
757                 ERROR_MESSAGE( "parse error" );
758         }
759
760         ASSERT_MESSAGE( !m_xml_state.empty(), "popping empty stack" );
761         m_xml_state.pop_back();
762 }
763 std::size_t write( const char* buffer, std::size_t length ){
764         switch ( m_xml_state.back().state() )
765         {
766         case xml_state_t::eDefault:
767                 break;
768         case xml_state_t::ePatch:
769                 break;
770         case xml_state_t::eMatrix:
771         case xml_state_t::eShader:
772                 return m_xml_state.back().write( buffer, length );
773                 break;
774         default:
775                 ERROR_MESSAGE( "parse error" );
776         }
777         return length;
778 }
779
780 void exportXML( XMLImporter& importer ){
781         StaticElement patchElement( "patch" );
782         importer.pushElement( patchElement );
783
784         {
785                 const StaticElement element( "shader" );
786                 importer.pushElement( element );
787                 importer.write( m_shader.c_str(), strlen( m_shader.c_str() ) );
788                 importer.popElement( element.name() );
789         }
790
791         {
792                 char width[16], height[16];
793                 sprintf( width, "%u", Unsigned( m_width ) );
794                 sprintf( height, "%u", Unsigned( m_height ) );
795                 StaticElement element( "matrix" );
796                 element.insertAttribute( "width", width );
797                 element.insertAttribute( "height", height );
798
799                 importer.pushElement( element );
800                 {
801                         for ( PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i )
802                         {
803                                 importer << ( *i ).m_vertex[0]
804                                                  << ' ' << ( *i ).m_vertex[1]
805                                                  << ' ' << ( *i ).m_vertex[2]
806                                                  << ' ' << ( *i ).m_texcoord[0]
807                                                  << ' ' << ( *i ).m_texcoord[1];
808                         }
809                 }
810                 importer.popElement( element.name() );
811         }
812
813         importer.popElement( patchElement.name() );
814 }
815
816 void UpdateCachedData();
817
818 const char *GetShader() const {
819         return m_shader.c_str();
820 }
821 void SetShader( const char* name ){
822         ASSERT_NOTNULL( name );
823
824         if ( shader_equal( m_shader.c_str(), name ) ) {
825                 return;
826         }
827
828         undoSave();
829
830         if ( m_instanceCounter.m_count != 0 ) {
831                 m_state->decrementUsed();
832         }
833         releaseShader();
834         m_shader = name;
835         captureShader();
836         if ( m_instanceCounter.m_count != 0 ) {
837                 m_state->incrementUsed();
838         }
839
840         check_shader();
841         Patch_textureChanged();
842 }
843 int getShaderFlags() const {
844         if ( m_state != 0 ) {
845                 return m_state->getFlags();
846         }
847         return 0;
848 }
849
850 typedef PatchControl* iterator;
851 typedef const PatchControl* const_iterator;
852
853 iterator begin(){
854         return m_ctrl.data();
855 }
856 const_iterator begin() const {
857         return m_ctrl.data();
858 }
859 iterator end(){
860         return m_ctrl.data() + m_ctrl.size();
861 }
862 const_iterator end() const {
863         return m_ctrl.data() + m_ctrl.size();
864 }
865
866 PatchControlArray& getControlPoints(){
867         return m_ctrl;
868 }
869 PatchControlArray& getControlPointsTransformed(){
870         return m_ctrlTransformed;
871 }
872
873 void setDims( std::size_t w, std::size_t h );
874 std::size_t getWidth() const {
875         return m_width;
876 }
877 std::size_t getHeight() const {
878         return m_height;
879 }
880 PatchControl& ctrlAt( std::size_t row, std::size_t col ){
881         return m_ctrl[row * m_width + col];
882 }
883 const PatchControl& ctrlAt( std::size_t row, std::size_t col ) const {
884         return m_ctrl[row * m_width + col];
885 }
886
887 void ConstructPrefab( const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3 );
888 void constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height );
889 void InvertMatrix();
890 void TransposeMatrix();
891 void Redisperse( EMatrixMajor mt );
892 void Smooth( EMatrixMajor mt );
893 void InsertRemove( bool bInsert, bool bColumn, bool bFirst );
894 Patch* MakeCap( Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst );
895 void ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width );
896
897 void FlipTexture( int nAxis );
898 void TranslateTexture( float s, float t );
899 void ScaleTexture( float s, float t );
900 void RotateTexture( float angle );
901 void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT
902 void CapTexture();
903 void NaturalTexture();
904 void ProjectTexture( int nAxis );
905
906 void undoSave(){
907         if ( m_map != 0 ) {
908                 m_map->changed();
909         }
910         if ( m_undoable_observer != 0 ) {
911                 m_undoable_observer->save( this );
912         }
913 }
914
915 UndoMemento* exportState() const {
916         return new SavedState( m_width, m_height, m_ctrl, m_shader.c_str(), m_patchDef3, m_subdivisions_x, m_subdivisions_y );
917 }
918 void importState( const UndoMemento* state ){
919         undoSave();
920
921         const SavedState& other = *( static_cast<const SavedState*>( state ) );
922
923         // begin duplicate of SavedState copy constructor, needs refactoring
924
925         // copy construct
926         {
927                 m_width = other.m_width;
928                 m_height = other.m_height;
929                 SetShader( other.m_shader.c_str() );
930                 m_ctrl = other.m_ctrl;
931                 onAllocate( m_ctrl.size() );
932                 m_patchDef3 = other.m_patchDef3;
933                 m_subdivisions_x = other.m_subdivisions_x;
934                 m_subdivisions_y = other.m_subdivisions_y;
935         }
936
937         // end duplicate code
938
939         Patch_textureChanged();
940
941         controlPointsChanged();
942 }
943
944 static void constructStatic( EPatchType type ){
945         Patch::m_type = type;
946         Patch::m_state_ctrl = GlobalShaderCache().capture( "$POINT" );
947         Patch::m_state_lattice = GlobalShaderCache().capture( "$LATTICE" );
948 }
949
950 static void destroyStatic(){
951         GlobalShaderCache().release( "$LATTICE" );
952         GlobalShaderCache().release( "$POINT" );
953 }
954 private:
955 void captureShader(){
956         m_state = GlobalShaderCache().capture( m_shader.c_str() );
957 }
958
959 void releaseShader(){
960         GlobalShaderCache().release( m_shader.c_str() );
961 }
962
963 void check_shader(){
964         if ( !shader_valid( GetShader() ) ) {
965                 globalErrorStream() << "patch has invalid texture name: '" << GetShader() << "'\n";
966         }
967 }
968
969 void InsertPoints( EMatrixMajor mt, bool bFirst );
970 void RemovePoints( EMatrixMajor mt, bool bFirst );
971
972 void AccumulateBBox();
973
974 void TesselateSubMatrixFixed( ArbitraryMeshVertex * vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl * subMatrix[3][3] );
975
976 // uses binary trees representing bezier curves to recursively tesselate a bezier sub-patch
977 void TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
978                                                  std::size_t offStartX, std::size_t offStartY,
979                                                  std::size_t offEndX, std::size_t offEndY,
980                                                  std::size_t nFlagsX, std::size_t nFlagsY,
981                                                  Vector3& left, Vector3& mid, Vector3& right,
982                                                  Vector2& texLeft, Vector2& texMid, Vector2& texRight,
983                                                  bool bTranspose );
984
985 // tesselates the entire surface
986 void BuildTesselationCurves( EMatrixMajor major );
987 void accumulateVertexTangentSpace( std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1 );
988 void BuildVertexArray();
989 };
990
991 inline bool Patch_importHeader( Patch& patch, Tokeniser& tokeniser ){
992         tokeniser.nextLine();
993         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) );
994         return true;
995 }
996
997 inline bool Patch_importShader( Patch& patch, Tokeniser& tokeniser ){
998         // parse shader name
999         tokeniser.nextLine();
1000         const char* texture = tokeniser.getToken();
1001         if ( texture == 0 ) {
1002                 Tokeniser_unexpectedError( tokeniser, texture, "#texture-name" );
1003                 return false;
1004         }
1005         if ( string_equal( texture, "NULL" ) ) {
1006                 patch.SetShader( texdef_name_default() );
1007         }
1008         else
1009         {
1010                 StringOutputStream shader( string_length( GlobalTexturePrefix_get() ) + string_length( texture ) );
1011                 shader << GlobalTexturePrefix_get() << texture;
1012                 patch.SetShader( shader.c_str() );
1013         }
1014         return true;
1015 }
1016
1017 inline bool PatchDoom3_importShader( Patch& patch, Tokeniser& tokeniser ){
1018         // parse shader name
1019         tokeniser.nextLine();
1020         const char *shader = tokeniser.getToken();
1021         if ( shader == 0 ) {
1022                 Tokeniser_unexpectedError( tokeniser, shader, "#shader-name" );
1023                 return false;
1024         }
1025         if ( string_equal( shader, "_emptyname" ) ) {
1026                 shader = texdef_name_default();
1027         }
1028         patch.SetShader( shader );
1029         return true;
1030 }
1031
1032 inline bool Patch_importParams( Patch& patch, Tokeniser& tokeniser ){
1033         tokeniser.nextLine();
1034         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1035
1036         // parse matrix dimensions
1037         {
1038                 std::size_t c, r;
1039                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, c ) );
1040                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, r ) );
1041
1042                 patch.setDims( c, r );
1043         }
1044
1045         if ( patch.m_patchDef3 ) {
1046                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_x ) );
1047                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_y ) );
1048         }
1049
1050         // ignore contents/flags/value
1051         int tmp;
1052         RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) );
1053         RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) );
1054         RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) );
1055
1056         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1057         return true;
1058 }
1059
1060 inline bool Patch_importMatrix( Patch& patch, Tokeniser& tokeniser ){
1061         // parse matrix
1062         tokeniser.nextLine();
1063         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1064         {
1065                 for ( std::size_t c = 0; c < patch.getWidth(); c++ )
1066                 {
1067                         tokeniser.nextLine();
1068                         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1069                         for ( std::size_t r = 0; r < patch.getHeight(); r++ )
1070                         {
1071                                 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1072
1073                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[0] ) );
1074                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[1] ) );
1075                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[2] ) );
1076                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_texcoord[0] ) );
1077                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_texcoord[1] ) );
1078
1079                                 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1080                         }
1081                         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1082                 }
1083         }
1084         tokeniser.nextLine();
1085         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1086         return true;
1087 }
1088
1089 inline bool Patch_importFooter( Patch& patch, Tokeniser& tokeniser ){
1090         patch.controlPointsChanged();
1091
1092         tokeniser.nextLine();
1093         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
1094
1095         tokeniser.nextLine();
1096         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
1097         return true;
1098 }
1099
1100 class PatchTokenImporter : public MapImporter
1101 {
1102 Patch& m_patch;
1103 public:
1104 PatchTokenImporter( Patch& patch ) : m_patch( patch ){
1105 }
1106 bool importTokens( Tokeniser& tokeniser ){
1107         RETURN_FALSE_IF_FAIL( Patch_importHeader( m_patch, tokeniser ) );
1108         RETURN_FALSE_IF_FAIL( Patch_importShader( m_patch, tokeniser ) );
1109         RETURN_FALSE_IF_FAIL( Patch_importParams( m_patch, tokeniser ) );
1110         RETURN_FALSE_IF_FAIL( Patch_importMatrix( m_patch, tokeniser ) );
1111         RETURN_FALSE_IF_FAIL( Patch_importFooter( m_patch, tokeniser ) );
1112
1113         return true;
1114 }
1115 };
1116
1117 class PatchDoom3TokenImporter : public MapImporter
1118 {
1119 Patch& m_patch;
1120 public:
1121 PatchDoom3TokenImporter( Patch& patch ) : m_patch( patch ){
1122 }
1123 bool importTokens( Tokeniser& tokeniser ){
1124         RETURN_FALSE_IF_FAIL( Patch_importHeader( m_patch, tokeniser ) );
1125         RETURN_FALSE_IF_FAIL( PatchDoom3_importShader( m_patch, tokeniser ) );
1126         RETURN_FALSE_IF_FAIL( Patch_importParams( m_patch, tokeniser ) );
1127         RETURN_FALSE_IF_FAIL( Patch_importMatrix( m_patch, tokeniser ) );
1128         RETURN_FALSE_IF_FAIL( Patch_importFooter( m_patch, tokeniser ) );
1129
1130         return true;
1131 }
1132 };
1133
1134 inline void Patch_exportHeader( const Patch& patch, TokenWriter& writer ){
1135         writer.writeToken( "{" );
1136         writer.nextLine();
1137         writer.writeToken( patch.m_patchDef3 ? "patchDef3" : "patchDef2" );
1138         writer.nextLine();
1139         writer.writeToken( "{" );
1140         writer.nextLine();
1141 }
1142
1143 inline void Patch_exportShader( const Patch& patch, TokenWriter& writer ){
1144         // write shader name
1145         if ( *( shader_get_textureName( patch.GetShader() ) ) == '\0' ) {
1146                 writer.writeToken( "NULL" );
1147         }
1148         else
1149         {
1150                 writer.writeToken( shader_get_textureName( patch.GetShader() ) );
1151         }
1152         writer.nextLine();
1153 }
1154
1155 inline void PatchDoom3_exportShader( const Patch& patch, TokenWriter& writer ){
1156         // write shader name
1157         if ( *( shader_get_textureName( patch.GetShader() ) ) == '\0' ) {
1158                 writer.writeString( "_emptyname" );
1159         }
1160         else
1161         {
1162                 writer.writeString( patch.GetShader() );
1163         }
1164         writer.nextLine();
1165 }
1166
1167 inline void Patch_exportParams( const Patch& patch, TokenWriter& writer ){
1168         // write matrix dimensions
1169         writer.writeToken( "(" );
1170         writer.writeUnsigned( patch.getWidth() );
1171         writer.writeUnsigned( patch.getHeight() );
1172         if ( patch.m_patchDef3 ) {
1173                 writer.writeUnsigned( patch.m_subdivisions_x );
1174                 writer.writeUnsigned( patch.m_subdivisions_y );
1175         }
1176         writer.writeInteger( 0 );
1177         writer.writeInteger( 0 );
1178         writer.writeInteger( 0 );
1179         writer.writeToken( ")" );
1180         writer.nextLine();
1181 }
1182
1183 inline void Patch_exportMatrix( const Patch& patch, TokenWriter& writer ){
1184         // write matrix
1185         writer.writeToken( "(" );
1186         writer.nextLine();
1187         for ( std::size_t c = 0; c < patch.getWidth(); c++ )
1188         {
1189                 writer.writeToken( "(" );
1190                 for ( std::size_t r = 0; r < patch.getHeight(); r++ )
1191                 {
1192                         writer.writeToken( "(" );
1193
1194                         writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[0] );
1195                         writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[1] );
1196                         writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[2] );
1197                         writer.writeFloat( patch.ctrlAt( r,c ).m_texcoord[0] );
1198                         writer.writeFloat( patch.ctrlAt( r,c ).m_texcoord[1] );
1199
1200                         writer.writeToken( ")" );
1201                 }
1202                 writer.writeToken( ")" );
1203                 writer.nextLine();
1204         }
1205         writer.writeToken( ")" );
1206         writer.nextLine();
1207 }
1208
1209 inline void Patch_exportFooter( const Patch& patch, TokenWriter& writer ){
1210         writer.writeToken( "}" );
1211         writer.nextLine();
1212         writer.writeToken( "}" );
1213         writer.nextLine();
1214 }
1215
1216 class PatchTokenExporter : public MapExporter
1217 {
1218 const Patch& m_patch;
1219 public:
1220 PatchTokenExporter( Patch& patch ) : m_patch( patch ){
1221 }
1222 void exportTokens( TokenWriter& writer ) const {
1223         Patch_exportHeader( m_patch, writer );
1224         Patch_exportShader( m_patch, writer );
1225         Patch_exportParams( m_patch, writer );
1226         Patch_exportMatrix( m_patch, writer );
1227         Patch_exportFooter( m_patch, writer );
1228 }
1229 };
1230
1231 class PatchDoom3TokenExporter : public MapExporter
1232 {
1233 const Patch& m_patch;
1234 public:
1235 PatchDoom3TokenExporter( Patch& patch ) : m_patch( patch ){
1236 }
1237 void exportTokens( TokenWriter& writer ) const {
1238         Patch_exportHeader( m_patch, writer );
1239         PatchDoom3_exportShader( m_patch, writer );
1240         Patch_exportParams( m_patch, writer );
1241         Patch_exportMatrix( m_patch, writer );
1242         Patch_exportFooter( m_patch, writer );
1243 }
1244 };
1245
1246 class PatchControlInstance
1247 {
1248 public:
1249 PatchControl* m_ctrl;
1250 ObservedSelectable m_selectable;
1251
1252 PatchControlInstance( PatchControl* ctrl, const SelectionChangeCallback& observer )
1253         : m_ctrl( ctrl ), m_selectable( observer ){
1254 }
1255
1256 void testSelect( Selector& selector, SelectionTest& test ){
1257         SelectionIntersection best;
1258         test.TestPoint( m_ctrl->m_vertex, best );
1259         if ( best.valid() ) {
1260                 Selector_add( selector, m_selectable, best );
1261         }
1262 }
1263 void snapto( float snap ){
1264         vector3_snap( m_ctrl->m_vertex, snap );
1265 }
1266 };
1267
1268
1269 class PatchInstance :
1270         public Patch::Observer,
1271         public scene::Instance,
1272         public Selectable,
1273         public Renderable,
1274         public SelectionTestable,
1275         public ComponentSelectionTestable,
1276         public ComponentEditable,
1277         public ComponentSnappable,
1278         public PlaneSelectable,
1279         public LightCullable
1280 {
1281 class TypeCasts
1282 {
1283 InstanceTypeCastTable m_casts;
1284 public:
1285 TypeCasts(){
1286         InstanceStaticCast<PatchInstance, Selectable>::install( m_casts );
1287         InstanceContainedCast<PatchInstance, Bounded>::install( m_casts );
1288         InstanceContainedCast<PatchInstance, Cullable>::install( m_casts );
1289         InstanceStaticCast<PatchInstance, Renderable>::install( m_casts );
1290         InstanceStaticCast<PatchInstance, SelectionTestable>::install( m_casts );
1291         InstanceStaticCast<PatchInstance, ComponentSelectionTestable>::install( m_casts );
1292         InstanceStaticCast<PatchInstance, ComponentEditable>::install( m_casts );
1293         InstanceStaticCast<PatchInstance, ComponentSnappable>::install( m_casts );
1294         InstanceStaticCast<PatchInstance, PlaneSelectable>::install( m_casts );
1295         InstanceIdentityCast<PatchInstance>::install( m_casts );
1296         InstanceContainedCast<PatchInstance, Transformable>::install( m_casts );
1297 }
1298 InstanceTypeCastTable& get(){
1299         return m_casts;
1300 }
1301 };
1302
1303
1304 Patch& m_patch;
1305 typedef std::vector<PatchControlInstance> PatchControlInstances;
1306 PatchControlInstances m_ctrl_instances;
1307
1308 ObservedSelectable m_selectable;
1309
1310 DragPlanes m_dragPlanes;
1311
1312 mutable RenderablePointVector m_render_selected;
1313 mutable AABB m_aabb_component;
1314
1315 static Shader* m_state_selpoint;
1316
1317 const LightList* m_lightList;
1318
1319 TransformModifier m_transform;
1320 public:
1321
1322 typedef LazyStatic<TypeCasts> StaticTypeCasts;
1323
1324 void lightsChanged(){
1325         m_lightList->lightsChanged();
1326 }
1327 typedef MemberCaller<PatchInstance, &PatchInstance::lightsChanged> LightsChangedCaller;
1328
1329 STRING_CONSTANT( Name, "PatchInstance" );
1330
1331 PatchInstance( const scene::Path& path, scene::Instance* parent, Patch& patch ) :
1332         Instance( path, parent, this, StaticTypeCasts::instance().get() ),
1333         m_patch( patch ),
1334         m_selectable( SelectedChangedCaller( *this ) ),
1335         m_dragPlanes( SelectedChangedComponentCaller( *this ) ),
1336         m_render_selected( GL_POINTS ),
1337         m_transform( Patch::TransformChangedCaller( m_patch ), ApplyTransformCaller( *this ) ){
1338         m_patch.instanceAttach( Instance::path() );
1339         m_patch.attach( this );
1340
1341         m_lightList = &GlobalShaderCache().attach( *this );
1342         m_patch.m_lightsChanged = LightsChangedCaller( *this );
1343
1344         Instance::setTransformChangedCallback( LightsChangedCaller( *this ) );
1345 }
1346 ~PatchInstance(){
1347         Instance::setTransformChangedCallback( Callback() );
1348
1349         m_patch.m_lightsChanged = Callback();
1350         GlobalShaderCache().detach( *this );
1351
1352         m_patch.detach( this );
1353         m_patch.instanceDetach( Instance::path() );
1354 }
1355
1356 void selectedChanged( const Selectable& selectable ){
1357         GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable );
1358         GlobalSelectionSystem().onSelectedChanged( *this, selectable );
1359
1360         Instance::selectedChanged();
1361 }
1362 typedef MemberCaller1<PatchInstance, const Selectable&, &PatchInstance::selectedChanged> SelectedChangedCaller;
1363
1364 void selectedChangedComponent( const Selectable& selectable ){
1365         GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable );
1366         GlobalSelectionSystem().onComponentSelection( *this, selectable );
1367 }
1368 typedef MemberCaller1<PatchInstance, const Selectable&, &PatchInstance::selectedChangedComponent> SelectedChangedComponentCaller;
1369
1370 Patch& getPatch(){
1371         return m_patch;
1372 }
1373 Bounded& get( NullType<Bounded>){
1374         return m_patch;
1375 }
1376 Cullable& get( NullType<Cullable>){
1377         return m_patch;
1378 }
1379 Transformable& get( NullType<Transformable>){
1380         return m_transform;
1381 }
1382
1383 static void constructStatic(){
1384         m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" );
1385 }
1386
1387 static void destroyStatic(){
1388         GlobalShaderCache().release( "$SELPOINT" );
1389 }
1390
1391
1392 void allocate( std::size_t size ){
1393         m_ctrl_instances.clear();
1394         m_ctrl_instances.reserve( size );
1395         for ( Patch::iterator i = m_patch.begin(); i != m_patch.end(); ++i )
1396         {
1397                 m_ctrl_instances.push_back( PatchControlInstance( &( *i ), SelectedChangedComponentCaller( *this ) ) );
1398         }
1399 }
1400
1401 void setSelected( bool select ){
1402         m_selectable.setSelected( select );
1403 }
1404 bool isSelected() const {
1405         return m_selectable.isSelected();
1406 }
1407
1408
1409 void update_selected() const {
1410         m_render_selected.clear();
1411         Patch::iterator ctrl = m_patch.getControlPointsTransformed().begin();
1412         for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl )
1413         {
1414                 if ( ( *i ).m_selectable.isSelected() ) {
1415                         const Colour4b colour_selected( 0, 0, 255, 255 );
1416                         m_render_selected.push_back( PointVertex( reinterpret_cast<Vertex3f&>( ( *ctrl ).m_vertex ), colour_selected ) );
1417                 }
1418         }
1419 }
1420
1421 void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
1422         m_patch.evaluateTransform();
1423         renderer.setLights( *m_lightList );
1424         m_patch.render_solid( renderer, volume, localToWorld() );
1425
1426         renderComponentsSelected( renderer, volume );
1427 }
1428
1429 void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
1430         m_patch.evaluateTransform();
1431         m_patch.render_wireframe( renderer, volume, localToWorld() );
1432
1433         renderComponentsSelected( renderer, volume );
1434 }
1435
1436 void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume ) const {
1437         m_patch.evaluateTransform();
1438         update_selected();
1439         if ( !m_render_selected.empty() ) {
1440                 renderer.Highlight( Renderer::ePrimitive, false );
1441                 renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly );
1442                 renderer.SetState( m_state_selpoint, Renderer::eFullMaterials );
1443                 renderer.addRenderable( m_render_selected, localToWorld() );
1444         }
1445 }
1446 void renderComponents( Renderer& renderer, const VolumeTest& volume ) const {
1447         m_patch.evaluateTransform();
1448         if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) {
1449                 m_patch.render_component( renderer, volume, localToWorld() );
1450         }
1451 }
1452
1453 void testSelect( Selector& selector, SelectionTest& test ){
1454         test.BeginMesh( localToWorld(), true );
1455         m_patch.testSelect( selector, test );
1456 }
1457
1458 void selectCtrl( bool select ){
1459         for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1460         {
1461                 ( *i ).m_selectable.setSelected( select );
1462         }
1463 }
1464 bool isSelectedComponents() const {
1465         for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1466         {
1467                 if ( ( *i ).m_selectable.isSelected() ) {
1468                         return true;
1469                 }
1470         }
1471         return false;
1472 }
1473 void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){
1474         if ( mode == SelectionSystem::eVertex ) {
1475                 selectCtrl( select );
1476         }
1477         else if ( mode == SelectionSystem::eFace ) {
1478                 m_dragPlanes.setSelected( select );
1479         }
1480 }
1481 const AABB& getSelectedComponentsBounds() const {
1482         m_aabb_component = AABB();
1483
1484         for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1485         {
1486                 if ( ( *i ).m_selectable.isSelected() ) {
1487                         aabb_extend_by_point_safe( m_aabb_component, ( *i ).m_ctrl->m_vertex );
1488                 }
1489         }
1490
1491         return m_aabb_component;
1492 }
1493
1494 void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){
1495         test.BeginMesh( localToWorld() );
1496
1497         switch ( mode )
1498         {
1499         case SelectionSystem::eVertex:
1500         {
1501                 for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1502                 {
1503                         ( *i ).testSelect( selector, test );
1504                 }
1505         }
1506         break;
1507         default:
1508                 break;
1509         }
1510 }
1511
1512 bool selectedVertices(){
1513         for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1514         {
1515                 if ( ( *i ).m_selectable.isSelected() ) {
1516                         return true;
1517                 }
1518         }
1519         return false;
1520 }
1521
1522 void transformComponents( const Matrix4& matrix ){
1523         if ( selectedVertices() ) {
1524                 PatchControlIter ctrl = m_patch.getControlPointsTransformed().begin();
1525                 for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl )
1526                 {
1527                         if ( ( *i ).m_selectable.isSelected() ) {
1528                                 matrix4_transform_point( matrix, ( *ctrl ).m_vertex );
1529                         }
1530                 }
1531                 m_patch.UpdateCachedData();
1532         }
1533
1534         if ( m_dragPlanes.isSelected() ) { // this should only be true when the transform is a pure translation.
1535                 m_patch.transform( m_dragPlanes.evaluateTransform( vector4_to_vector3( matrix.t() ) ) );
1536         }
1537 }
1538
1539
1540 void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){
1541         test.BeginMesh( localToWorld() );
1542
1543         m_dragPlanes.selectPlanes( m_patch.localAABB(), selector, test, selectedPlaneCallback );
1544 }
1545 void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){
1546         m_dragPlanes.selectReversedPlanes( m_patch.localAABB(), selector, selectedPlanes );
1547 }
1548
1549
1550 void snapComponents( float snap ){
1551         if ( selectedVertices() ) {
1552                 m_patch.undoSave();
1553                 for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1554                 {
1555                         if ( ( *i ).m_selectable.isSelected() ) {
1556                                 ( *i ).snapto( snap );
1557                         }
1558                 }
1559                 m_patch.controlPointsChanged();
1560         }
1561 }
1562
1563 void evaluateTransform(){
1564         Matrix4 matrix( m_transform.calculateTransform() );
1565
1566         if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) {
1567                 m_patch.transform( matrix );
1568         }
1569         else
1570         {
1571                 transformComponents( matrix );
1572         }
1573 }
1574 void applyTransform(){
1575         m_patch.revertTransform();
1576         evaluateTransform();
1577         m_patch.freezeTransform();
1578 }
1579 typedef MemberCaller<PatchInstance, &PatchInstance::applyTransform> ApplyTransformCaller;
1580
1581
1582 bool testLight( const RendererLight& light ) const {
1583         return light.testAABB( worldAABB() );
1584 }
1585 };
1586
1587
1588 template<typename TokenImporter, typename TokenExporter>
1589 class PatchNode :
1590         public scene::Node::Symbiot,
1591         public scene::Instantiable,
1592         public scene::Cloneable
1593 {
1594 typedef PatchNode<TokenImporter, TokenExporter> Self;
1595
1596 class TypeCasts
1597 {
1598 InstanceTypeCastTable m_casts;
1599 public:
1600 TypeCasts(){
1601         NodeStaticCast<PatchNode, scene::Instantiable>::install( m_casts );
1602         NodeStaticCast<PatchNode, scene::Cloneable>::install( m_casts );
1603         NodeContainedCast<PatchNode, Snappable>::install( m_casts );
1604         NodeContainedCast<PatchNode, TransformNode>::install( m_casts );
1605         NodeContainedCast<PatchNode, Patch>::install( m_casts );
1606         NodeContainedCast<PatchNode, XMLImporter>::install( m_casts );
1607         NodeContainedCast<PatchNode, XMLExporter>::install( m_casts );
1608         NodeContainedCast<PatchNode, MapImporter>::install( m_casts );
1609         NodeContainedCast<PatchNode, MapExporter>::install( m_casts );
1610         NodeContainedCast<PatchNode, Nameable>::install( m_casts );
1611 }
1612 InstanceTypeCastTable& get(){
1613         return m_casts;
1614 }
1615 };
1616
1617
1618 scene::Node m_node;
1619 InstanceSet m_instances;
1620 Patch m_patch;
1621 TokenImporter m_importMap;
1622 TokenExporter m_exportMap;
1623
1624 public:
1625
1626 typedef LazyStatic<TypeCasts> StaticTypeCasts;
1627
1628 Snappable& get( NullType<Snappable>){
1629         return m_patch;
1630 }
1631 TransformNode& get( NullType<TransformNode>){
1632         return m_patch;
1633 }
1634 Patch& get( NullType<Patch>){
1635         return m_patch;
1636 }
1637 XMLImporter& get( NullType<XMLImporter>){
1638         return m_patch;
1639 }
1640 XMLExporter& get( NullType<XMLExporter>){
1641         return m_patch;
1642 }
1643 MapImporter& get( NullType<MapImporter>){
1644         return m_importMap;
1645 }
1646 MapExporter& get( NullType<MapExporter>){
1647         return m_exportMap;
1648 }
1649 Nameable& get( NullType<Nameable>){
1650         return m_patch;
1651 }
1652
1653 PatchNode( bool patchDef3 = false ) :
1654         m_node( this, this, StaticTypeCasts::instance().get() ),
1655         m_patch( m_node, InstanceSetEvaluateTransform<PatchInstance>::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ),
1656         m_importMap( m_patch ),
1657         m_exportMap( m_patch ){
1658         m_patch.m_patchDef3 = patchDef3;
1659 }
1660 PatchNode( const PatchNode& other ) :
1661         scene::Node::Symbiot( other ),
1662         scene::Instantiable( other ),
1663         scene::Cloneable( other ),
1664         m_node( this, this, StaticTypeCasts::instance().get() ),
1665         m_patch( other.m_patch, m_node, InstanceSetEvaluateTransform<PatchInstance>::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ),
1666         m_importMap( m_patch ),
1667         m_exportMap( m_patch ){
1668 }
1669 void release(){
1670         delete this;
1671 }
1672 scene::Node& node(){
1673         return m_node;
1674 }
1675 Patch& get(){
1676         return m_patch;
1677 }
1678 const Patch& get() const {
1679         return m_patch;
1680 }
1681
1682 scene::Node& clone() const {
1683         return ( new PatchNode( *this ) )->node();
1684 }
1685
1686 scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
1687         return new PatchInstance( path, parent, m_patch );
1688 }
1689 void forEachInstance( const scene::Instantiable::Visitor& visitor ){
1690         m_instances.forEachInstance( visitor );
1691 }
1692 void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
1693         m_instances.insert( observer, path, instance );
1694 }
1695 scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
1696         return m_instances.erase( observer, path );
1697 }
1698 };
1699
1700
1701
1702 typedef PatchNode<PatchTokenImporter, PatchTokenExporter> PatchNodeQuake3;
1703 typedef PatchNode<PatchDoom3TokenImporter, PatchDoom3TokenExporter> PatchNodeDoom3;
1704
1705 inline Patch* Node_getPatch( scene::Node& node ){
1706         return NodeTypeCast<Patch>::cast( node );
1707 }
1708
1709 inline PatchInstance* Instance_getPatch( scene::Instance& instance ){
1710         return InstanceTypeCast<PatchInstance>::cast( instance );
1711 }
1712
1713 template<typename Functor>
1714 class PatchSelectedVisitor : public SelectionSystem::Visitor
1715 {
1716 const Functor& m_functor;
1717 public:
1718 PatchSelectedVisitor( const Functor& functor ) : m_functor( functor ){
1719 }
1720 void visit( scene::Instance& instance ) const {
1721         PatchInstance* patch = Instance_getPatch( instance );
1722         if ( patch != 0 ) {
1723                 m_functor( *patch );
1724         }
1725 }
1726 };
1727
1728 template<typename Functor>
1729 inline void Scene_forEachSelectedPatch( const Functor& functor ){
1730         GlobalSelectionSystem().foreachSelected( PatchSelectedVisitor<Functor>( functor ) );
1731 }
1732
1733
1734 template<typename Functor>
1735 class PatchVisibleSelectedVisitor : public SelectionSystem::Visitor
1736 {
1737 const Functor& m_functor;
1738 public:
1739 PatchVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){
1740 }
1741 void visit( scene::Instance& instance ) const {
1742         PatchInstance* patch = Instance_getPatch( instance );
1743         if ( patch != 0
1744                  && instance.path().top().get().visible() ) {
1745                 m_functor( *patch );
1746         }
1747 }
1748 };
1749
1750 template<typename Functor>
1751 inline void Scene_forEachVisibleSelectedPatchInstance( const Functor& functor ){
1752         GlobalSelectionSystem().foreachSelected( PatchVisibleSelectedVisitor<Functor>( functor ) );
1753 }
1754
1755 template<typename Functor>
1756 class PatchForEachWalker : public scene::Graph::Walker
1757 {
1758 const Functor& m_functor;
1759 public:
1760 PatchForEachWalker( const Functor& functor ) : m_functor( functor ){
1761 }
1762 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1763         if ( path.top().get().visible() ) {
1764                 Patch* patch = Node_getPatch( path.top() );
1765                 if ( patch != 0 ) {
1766                         m_functor( *patch );
1767                 }
1768         }
1769         return true;
1770 }
1771 };
1772
1773 template<typename Functor>
1774 inline void Scene_forEachVisiblePatch( const Functor& functor ){
1775         GlobalSceneGraph().traverse( PatchForEachWalker<Functor>( functor ) );
1776 }
1777
1778 template<typename Functor>
1779 class PatchForEachSelectedWalker : public scene::Graph::Walker
1780 {
1781 const Functor& m_functor;
1782 public:
1783 PatchForEachSelectedWalker( const Functor& functor ) : m_functor( functor ){
1784 }
1785 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1786         if ( path.top().get().visible() ) {
1787                 Patch* patch = Node_getPatch( path.top() );
1788                 if ( patch != 0
1789                          && Instance_getSelectable( instance )->isSelected() ) {
1790                         m_functor( *patch );
1791                 }
1792         }
1793         return true;
1794 }
1795 };
1796
1797 template<typename Functor>
1798 inline void Scene_forEachVisibleSelectedPatch( const Functor& functor ){
1799         GlobalSceneGraph().traverse( PatchForEachSelectedWalker<Functor>( functor ) );
1800 }
1801
1802 template<typename Functor>
1803 class PatchForEachInstanceWalker : public scene::Graph::Walker
1804 {
1805 const Functor& m_functor;
1806 public:
1807 PatchForEachInstanceWalker( const Functor& functor ) : m_functor( functor ){
1808 }
1809 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1810         if ( path.top().get().visible() ) {
1811                 PatchInstance* patch = Instance_getPatch( instance );
1812                 if ( patch != 0 ) {
1813                         m_functor( *patch );
1814                 }
1815         }
1816         return true;
1817 }
1818 };
1819
1820 template<typename Functor>
1821 inline void Scene_forEachVisiblePatchInstance( const Functor& functor ){
1822         GlobalSceneGraph().traverse( PatchForEachInstanceWalker<Functor>( functor ) );
1823 }
1824
1825 #endif