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