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