]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/patch.h
Remove -Wno-reorder
[xonotic/netradiant.git] / radiant / patch.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_PATCH_H )
23 #define INCLUDED_PATCH_H
24
25 /// \file
26 /// \brief The patch primitive.
27 ///
28 /// A 2-dimensional matrix of vertices that define a quadratic bezier surface.
29 /// The Boundary-Representation of this primitive is a triangle mesh.
30 /// The surface is recursively tesselated until the angle between each triangle
31 /// edge is smaller than a specified tolerance.
32
33
34 #include "nameable.h"
35 #include "ifilter.h"
36 #include "imap.h"
37 #include "ipatch.h"
38 #include "cullable.h"
39 #include "renderable.h"
40 #include "editable.h"
41 #include "selectable.h"
42
43 #include "debugging/debugging.h"
44
45 #include <set>
46 #include <limits>
47
48 #include "math/frustum.h"
49 #include "string/string.h"
50 #include "stream/stringstream.h"
51 #include "stream/textstream.h"
52 #include "xml/xmlelement.h"
53 #include "scenelib.h"
54 #include "transformlib.h"
55 #include "instancelib.h"
56 #include "selectionlib.h"
57 #include "traverselib.h"
58 #include "render.h"
59 #include "stringio.h"
60 #include "shaderlib.h"
61 #include "generic/callback.h"
62 #include "signal/signalfwd.h"
63 #include "texturelib.h"
64 #include "xml/ixml.h"
65 #include "dragplanes.h"
66
67 enum EPatchType
68 {
69         ePatchTypeQuake3,
70         ePatchTypeDoom3,
71 };
72
73 extern int g_PatchSubdivideThreshold;
74
75
76 #define MIN_PATCH_WIDTH 3
77 #define MIN_PATCH_HEIGHT 3
78
79 extern std::size_t MAX_PATCH_WIDTH;
80 extern std::size_t MAX_PATCH_HEIGHT;
81
82 #define MAX_PATCH_ROWCTRL ( ( ( MAX_PATCH_WIDTH - 1 ) - 1 ) / 2 )
83 #define MAX_PATCH_COLCTRL ( ( ( MAX_PATCH_HEIGHT - 1 ) - 1 ) / 2 )
84
85 enum EPatchCap
86 {
87         eCapBevel,
88         eCapEndCap,
89         eCapIBevel,
90         eCapIEndCap,
91         eCapCylinder,
92 };
93
94 enum EPatchPrefab
95 {
96         ePlane,
97         eBevel,
98         eEndCap,
99         eCylinder,
100         eDenseCylinder,
101         eVeryDenseCylinder,
102         eSqCylinder,
103         eCone,
104         eSphere,
105         eXactCylinder,
106         eXactSphere,
107         eXactCone,
108 };
109
110 enum EMatrixMajor
111 {
112         ROW, COL,
113 };
114
115 struct BezierCurve
116 {
117         Vector3 crd;
118         Vector3 left;
119         Vector3 right;
120 };
121
122 const std::size_t BEZIERCURVETREE_MAX_INDEX = std::size_t( 1 ) << ( std::numeric_limits<std::size_t>::digits - 1 );
123
124 struct BezierCurveTree
125 {
126         std::size_t index;
127         BezierCurveTree* left;
128         BezierCurveTree* right;
129 };
130
131 inline bool BezierCurveTree_isLeaf( const BezierCurveTree* node ){
132         return node->left == 0 && node->right == 0;
133 }
134
135 void BezierCurveTree_Delete( BezierCurveTree *pCurve );
136
137
138 inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVertex* array ){
139         return VertexPointer( VertexPointer::pointer( &array->vertex ), sizeof( ArbitraryMeshVertex ) );
140 }
141
142 typedef PatchControl* PatchControlIter;
143 typedef const PatchControl* PatchControlConstIter;
144
145 inline void copy_ctrl( PatchControlIter ctrl, PatchControlConstIter begin, PatchControlConstIter end ){
146         std::copy( begin, end, ctrl );
147 }
148
149 const Colour4b colour_corner( 0, 255, 0, 255 );
150 const Colour4b colour_inside( 255, 0, 255, 255 );
151
152 class Patch;
153
154 class PatchFilter
155 {
156 public:
157 virtual bool filter( const Patch& patch ) const = 0;
158 };
159
160 bool patch_filtered( Patch& patch );
161 void add_patch_filter( PatchFilter& filter, int mask, bool invert = false );
162
163 void Patch_addTextureChangedCallback( const SignalHandler& handler );
164 void Patch_textureChanged();
165
166 inline void BezierCurveTreeArray_deleteAll( Array<BezierCurveTree*>& curveTrees ){
167         for ( Array<BezierCurveTree*>::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i )
168         {
169                 BezierCurveTree_Delete( *i );
170         }
171 }
172
173 inline void PatchControlArray_invert( Array<PatchControl>& ctrl, std::size_t width, std::size_t height ){
174         Array<PatchControl> tmp( width );
175
176         PatchControlIter from = ctrl.data() + ( width * ( height - 1 ) );
177         PatchControlIter to = ctrl.data();
178         for ( std::size_t h = 0; h != ( ( height - 1 ) >> 1 ); ++h, to += width, from -= width )
179         {
180                 copy_ctrl( tmp.data(), to, to + width );
181                 copy_ctrl( to, from, from + width );
182                 copy_ctrl( from, tmp.data(), tmp.data() + width );
183         }
184 }
185
186 class PatchTesselation
187 {
188 public:
189 PatchTesselation()
190         : m_numStrips( 0 ), m_lenStrips( 0 ), m_nArrayWidth( 0 ), m_nArrayHeight( 0 ){
191 }
192 Array<ArbitraryMeshVertex> m_vertices;
193 Array<RenderIndex> m_indices;
194 std::size_t m_numStrips;
195 std::size_t m_lenStrips;
196
197 Array<std::size_t> m_arrayWidth;
198 std::size_t m_nArrayWidth;
199 Array<std::size_t> m_arrayHeight;
200 std::size_t m_nArrayHeight;
201
202 Array<BezierCurveTree*> m_curveTreeU;
203 Array<BezierCurveTree*> m_curveTreeV;
204 };
205
206 class RenderablePatchWireframe : public OpenGLRenderable
207 {
208 PatchTesselation& m_tess;
209 public:
210 RenderablePatchWireframe( PatchTesselation& tess ) : m_tess( tess ){
211 }
212 void render( RenderStateFlags state ) const {
213         {
214   #if NV_DRIVER_BUG
215                 glVertexPointer( 3, GL_FLOAT, 0, 0 );
216                 glDrawArrays( GL_TRIANGLE_FAN, 0, 0 );
217   #endif
218
219                 std::size_t n = 0;
220                 glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex );
221                 for ( std::size_t i = 0; i <= m_tess.m_curveTreeV.size(); ++i )
222                 {
223                         glDrawArrays( GL_LINE_STRIP, GLint( n ), GLsizei( m_tess.m_nArrayWidth ) );
224
225                         if ( i == m_tess.m_curveTreeV.size() ) {
226                                 break;
227                         }
228
229                         if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeV[i] ) ) {
230                                 glDrawArrays( GL_LINE_STRIP, GLint( m_tess.m_curveTreeV[i]->index ), GLsizei( m_tess.m_nArrayWidth ) );
231                         }
232
233                         n += ( m_tess.m_arrayHeight[i] * m_tess.m_nArrayWidth );
234
235                 }
236         }
237
238         {
239                 const ArbitraryMeshVertex* p = m_tess.m_vertices.data();
240                 std::size_t n = m_tess.m_nArrayWidth * sizeof( ArbitraryMeshVertex );
241                 for ( std::size_t i = 0; i <= m_tess.m_curveTreeU.size(); ++i )
242                 {
243                         glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &p->vertex );
244                         glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) );
245
246                         if ( i == m_tess.m_curveTreeU.size() ) {
247                                 break;
248                         }
249
250                         if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeU[i] ) ) {
251                                 glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &( m_tess.m_vertices.data() + ( m_tess.m_curveTreeU[i]->index ) )->vertex );
252                                 glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) );
253                         }
254
255                         p += m_tess.m_arrayWidth[i];
256                 }
257         }
258 }
259 };
260
261 class RenderablePatchFixedWireframe : public OpenGLRenderable
262 {
263 PatchTesselation& m_tess;
264 public:
265 RenderablePatchFixedWireframe( PatchTesselation& tess ) : m_tess( tess ){
266 }
267 void render( RenderStateFlags state ) const {
268         glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex );
269         const RenderIndex* strip_indices = m_tess.m_indices.data();
270         for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips )
271         {
272                 glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices );
273         }
274 }
275 };
276
277 class RenderablePatchSolid : public OpenGLRenderable
278 {
279 PatchTesselation& m_tess;
280 public:
281 RenderablePatchSolid( PatchTesselation& tess ) : m_tess( tess ){
282 }
283 void 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 defined( _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 m_evaluateTransform;
451 Callback 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 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& evaluateTransform, const Callback& 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& evaluateTransform, const Callback& 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, &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 PatchControlArray& getControlPointsTransformed(){
884         return m_ctrlTransformed;
885 }
886
887 void setDims( std::size_t w, std::size_t h );
888 std::size_t getWidth() const {
889         return m_width;
890 }
891 std::size_t getHeight() const {
892         return m_height;
893 }
894 PatchControl& ctrlAt( std::size_t row, std::size_t col ){
895         return m_ctrl[row * m_width + col];
896 }
897 const PatchControl& ctrlAt( std::size_t row, std::size_t col ) const {
898         return m_ctrl[row * m_width + col];
899 }
900
901 void ConstructPrefab( const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3 );
902 void constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height );
903 void InvertMatrix();
904 void TransposeMatrix();
905 void Redisperse( EMatrixMajor mt );
906 void Smooth( EMatrixMajor mt );
907 void InsertRemove( bool bInsert, bool bColumn, bool bFirst );
908 Patch* MakeCap( Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst );
909 void ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width );
910
911 void FlipTexture( int nAxis );
912 void TranslateTexture( float s, float t );
913 void ScaleTexture( float s, float t );
914 void RotateTexture( float angle );
915 void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT
916 void CapTexture();
917 void NaturalTexture();
918 void ProjectTexture( int nAxis );
919
920 void undoSave(){
921         if ( m_map != 0 ) {
922                 m_map->changed();
923         }
924         if ( m_undoable_observer != 0 ) {
925                 m_undoable_observer->save( this );
926         }
927 }
928
929 UndoMemento* exportState() const {
930         return new SavedState( m_width, m_height, m_ctrl, m_shader.c_str(), m_patchDef3, m_subdivisions_x, m_subdivisions_y );
931 }
932 void importState( const UndoMemento* state ){
933         undoSave();
934
935         const SavedState& other = *( static_cast<const SavedState*>( state ) );
936
937         // begin duplicate of SavedState copy constructor, needs refactoring
938
939         // copy construct
940         {
941                 m_width = other.m_width;
942                 m_height = other.m_height;
943                 SetShader( other.m_shader.c_str() );
944                 m_ctrl = other.m_ctrl;
945                 onAllocate( m_ctrl.size() );
946                 m_patchDef3 = other.m_patchDef3;
947                 m_subdivisions_x = other.m_subdivisions_x;
948                 m_subdivisions_y = other.m_subdivisions_y;
949         }
950
951         // end duplicate code
952
953         Patch_textureChanged();
954
955         controlPointsChanged();
956 }
957
958 static void constructStatic( EPatchType type ){
959         Patch::m_type = type;
960         Patch::m_state_ctrl = GlobalShaderCache().capture( "$POINT" );
961         Patch::m_state_lattice = GlobalShaderCache().capture( "$LATTICE" );
962 }
963
964 static void destroyStatic(){
965         GlobalShaderCache().release( "$LATTICE" );
966         GlobalShaderCache().release( "$POINT" );
967 }
968 private:
969 void captureShader(){
970         m_state = GlobalShaderCache().capture( m_shader.c_str() );
971 }
972
973 void releaseShader(){
974         GlobalShaderCache().release( m_shader.c_str() );
975 }
976
977 void check_shader(){
978         if ( !shader_valid( GetShader() ) ) {
979                 globalErrorStream() << "patch has invalid texture name: '" << GetShader() << "'\n";
980         }
981 }
982
983 void InsertPoints( EMatrixMajor mt, bool bFirst );
984 void RemovePoints( EMatrixMajor mt, bool bFirst );
985
986 void AccumulateBBox();
987
988 void TesselateSubMatrixFixed( ArbitraryMeshVertex * vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl * subMatrix[3][3] );
989
990 // uses binary trees representing bezier curves to recursively tesselate a bezier sub-patch
991 void TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
992                                                  std::size_t offStartX, std::size_t offStartY,
993                                                  std::size_t offEndX, std::size_t offEndY,
994                                                  std::size_t nFlagsX, std::size_t nFlagsY,
995                                                  Vector3& left, Vector3& mid, Vector3& right,
996                                                  Vector2& texLeft, Vector2& texMid, Vector2& texRight,
997                                                  bool bTranspose );
998
999 // tesselates the entire surface
1000 void BuildTesselationCurves( EMatrixMajor major );
1001 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 );
1002 void BuildVertexArray();
1003 };
1004
1005 inline bool Patch_importHeader( Patch& patch, Tokeniser& tokeniser ){
1006         tokeniser.nextLine();
1007         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) );
1008         return true;
1009 }
1010
1011 inline bool Patch_importShader( Patch& patch, Tokeniser& tokeniser ){
1012         // parse shader name
1013         tokeniser.nextLine();
1014         const char* texture = tokeniser.getToken();
1015         if ( texture == 0 ) {
1016                 Tokeniser_unexpectedError( tokeniser, texture, "#texture-name" );
1017                 return false;
1018         }
1019         if ( string_equal( texture, "NULL" ) ) {
1020                 patch.SetShader( texdef_name_default() );
1021         }
1022         else
1023         {
1024                 StringOutputStream shader( string_length( GlobalTexturePrefix_get() ) + string_length( texture ) );
1025                 shader << GlobalTexturePrefix_get() << texture;
1026                 patch.SetShader( shader.c_str() );
1027         }
1028         return true;
1029 }
1030
1031 inline bool PatchDoom3_importShader( Patch& patch, Tokeniser& tokeniser ){
1032         // parse shader name
1033         tokeniser.nextLine();
1034         const char *shader = tokeniser.getToken();
1035         if ( shader == 0 ) {
1036                 Tokeniser_unexpectedError( tokeniser, shader, "#shader-name" );
1037                 return false;
1038         }
1039         if ( string_equal( shader, "_emptyname" ) ) {
1040                 shader = texdef_name_default();
1041         }
1042         patch.SetShader( shader );
1043         return true;
1044 }
1045
1046 inline bool Patch_importParams( Patch& patch, Tokeniser& tokeniser ){
1047         tokeniser.nextLine();
1048         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1049
1050         // parse matrix dimensions
1051         {
1052                 std::size_t c, r;
1053                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, c ) );
1054                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, r ) );
1055
1056                 patch.setDims( c, r );
1057         }
1058
1059         if ( patch.m_patchDef3 ) {
1060                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_x ) );
1061                 RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_y ) );
1062         }
1063
1064         // ignore contents/flags/value
1065         int tmp;
1066         RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) );
1067         RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) );
1068         RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) );
1069
1070         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1071         return true;
1072 }
1073
1074 inline bool Patch_importMatrix( Patch& patch, Tokeniser& tokeniser ){
1075         // parse matrix
1076         tokeniser.nextLine();
1077         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1078         {
1079                 for ( std::size_t c = 0; c < patch.getWidth(); c++ )
1080                 {
1081                         tokeniser.nextLine();
1082                         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1083                         for ( std::size_t r = 0; r < patch.getHeight(); r++ )
1084                         {
1085                                 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
1086
1087                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[0] ) );
1088                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[1] ) );
1089                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[2] ) );
1090                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_texcoord[0] ) );
1091                                 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_texcoord[1] ) );
1092
1093                                 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1094                         }
1095                         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1096                 }
1097         }
1098         tokeniser.nextLine();
1099         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
1100         return true;
1101 }
1102
1103 inline bool Patch_importFooter( Patch& patch, Tokeniser& tokeniser ){
1104         patch.controlPointsChanged();
1105
1106         tokeniser.nextLine();
1107         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
1108
1109         tokeniser.nextLine();
1110         RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
1111         return true;
1112 }
1113
1114 class PatchTokenImporter : public MapImporter
1115 {
1116 Patch& m_patch;
1117 public:
1118 PatchTokenImporter( Patch& patch ) : m_patch( patch ){
1119 }
1120 bool importTokens( Tokeniser& tokeniser ){
1121         RETURN_FALSE_IF_FAIL( Patch_importHeader( m_patch, tokeniser ) );
1122         RETURN_FALSE_IF_FAIL( Patch_importShader( m_patch, tokeniser ) );
1123         RETURN_FALSE_IF_FAIL( Patch_importParams( m_patch, tokeniser ) );
1124         RETURN_FALSE_IF_FAIL( Patch_importMatrix( m_patch, tokeniser ) );
1125         RETURN_FALSE_IF_FAIL( Patch_importFooter( m_patch, tokeniser ) );
1126
1127         return true;
1128 }
1129 };
1130
1131 class PatchDoom3TokenImporter : public MapImporter
1132 {
1133 Patch& m_patch;
1134 public:
1135 PatchDoom3TokenImporter( Patch& patch ) : m_patch( patch ){
1136 }
1137 bool importTokens( Tokeniser& tokeniser ){
1138         RETURN_FALSE_IF_FAIL( Patch_importHeader( m_patch, tokeniser ) );
1139         RETURN_FALSE_IF_FAIL( PatchDoom3_importShader( m_patch, tokeniser ) );
1140         RETURN_FALSE_IF_FAIL( Patch_importParams( m_patch, tokeniser ) );
1141         RETURN_FALSE_IF_FAIL( Patch_importMatrix( m_patch, tokeniser ) );
1142         RETURN_FALSE_IF_FAIL( Patch_importFooter( m_patch, tokeniser ) );
1143
1144         return true;
1145 }
1146 };
1147
1148 inline void Patch_exportHeader( const Patch& patch, TokenWriter& writer ){
1149         writer.writeToken( "{" );
1150         writer.nextLine();
1151         writer.writeToken( patch.m_patchDef3 ? "patchDef3" : "patchDef2" );
1152         writer.nextLine();
1153         writer.writeToken( "{" );
1154         writer.nextLine();
1155 }
1156
1157 inline void Patch_exportShader( const Patch& patch, TokenWriter& writer ){
1158         // write shader name
1159         if ( *( shader_get_textureName( patch.GetShader() ) ) == '\0' ) {
1160                 writer.writeToken( "NULL" );
1161         }
1162         else
1163         {
1164                 writer.writeToken( shader_get_textureName( patch.GetShader() ) );
1165         }
1166         writer.nextLine();
1167 }
1168
1169 inline void PatchDoom3_exportShader( const Patch& patch, TokenWriter& writer ){
1170         // write shader name
1171         if ( *( shader_get_textureName( patch.GetShader() ) ) == '\0' ) {
1172                 writer.writeString( "_emptyname" );
1173         }
1174         else
1175         {
1176                 writer.writeString( patch.GetShader() );
1177         }
1178         writer.nextLine();
1179 }
1180
1181 inline void Patch_exportParams( const Patch& patch, TokenWriter& writer ){
1182         // write matrix dimensions
1183         writer.writeToken( "(" );
1184         writer.writeUnsigned( patch.getWidth() );
1185         writer.writeUnsigned( patch.getHeight() );
1186         if ( patch.m_patchDef3 ) {
1187                 writer.writeUnsigned( patch.m_subdivisions_x );
1188                 writer.writeUnsigned( patch.m_subdivisions_y );
1189         }
1190         writer.writeInteger( 0 );
1191         writer.writeInteger( 0 );
1192         writer.writeInteger( 0 );
1193         writer.writeToken( ")" );
1194         writer.nextLine();
1195 }
1196
1197 inline void Patch_exportMatrix( const Patch& patch, TokenWriter& writer ){
1198         // write matrix
1199         writer.writeToken( "(" );
1200         writer.nextLine();
1201         for ( std::size_t c = 0; c < patch.getWidth(); c++ )
1202         {
1203                 writer.writeToken( "(" );
1204                 for ( std::size_t r = 0; r < patch.getHeight(); r++ )
1205                 {
1206                         writer.writeToken( "(" );
1207
1208                         writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[0] );
1209                         writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[1] );
1210                         writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[2] );
1211                         writer.writeFloat( patch.ctrlAt( r,c ).m_texcoord[0] );
1212                         writer.writeFloat( patch.ctrlAt( r,c ).m_texcoord[1] );
1213
1214                         writer.writeToken( ")" );
1215                 }
1216                 writer.writeToken( ")" );
1217                 writer.nextLine();
1218         }
1219         writer.writeToken( ")" );
1220         writer.nextLine();
1221 }
1222
1223 inline void Patch_exportFooter( const Patch& patch, TokenWriter& writer ){
1224         writer.writeToken( "}" );
1225         writer.nextLine();
1226         writer.writeToken( "}" );
1227         writer.nextLine();
1228 }
1229
1230 class PatchTokenExporter : public MapExporter
1231 {
1232 const Patch& m_patch;
1233 public:
1234 PatchTokenExporter( Patch& patch ) : m_patch( patch ){
1235 }
1236 void exportTokens( TokenWriter& writer ) const {
1237         Patch_exportHeader( m_patch, writer );
1238         Patch_exportShader( m_patch, writer );
1239         Patch_exportParams( m_patch, writer );
1240         Patch_exportMatrix( m_patch, writer );
1241         Patch_exportFooter( m_patch, writer );
1242 }
1243 };
1244
1245 class PatchDoom3TokenExporter : public MapExporter
1246 {
1247 const Patch& m_patch;
1248 public:
1249 PatchDoom3TokenExporter( Patch& patch ) : m_patch( patch ){
1250 }
1251 void exportTokens( TokenWriter& writer ) const {
1252         Patch_exportHeader( m_patch, writer );
1253         PatchDoom3_exportShader( m_patch, writer );
1254         Patch_exportParams( m_patch, writer );
1255         Patch_exportMatrix( m_patch, writer );
1256         Patch_exportFooter( m_patch, writer );
1257 }
1258 };
1259
1260 class PatchControlInstance
1261 {
1262 public:
1263 PatchControl* m_ctrl;
1264 ObservedSelectable m_selectable;
1265
1266 PatchControlInstance( PatchControl* ctrl, const SelectionChangeCallback& observer )
1267         : m_ctrl( ctrl ), m_selectable( observer ){
1268 }
1269
1270 void testSelect( Selector& selector, SelectionTest& test ){
1271         SelectionIntersection best;
1272         test.TestPoint( m_ctrl->m_vertex, best );
1273         if ( best.valid() ) {
1274                 Selector_add( selector, m_selectable, best );
1275         }
1276 }
1277 void snapto( float snap ){
1278         vector3_snap( m_ctrl->m_vertex, snap );
1279 }
1280 };
1281
1282
1283 class PatchInstance :
1284         public Patch::Observer,
1285         public scene::Instance,
1286         public Selectable,
1287         public Renderable,
1288         public SelectionTestable,
1289         public ComponentSelectionTestable,
1290         public ComponentEditable,
1291         public ComponentSnappable,
1292         public PlaneSelectable,
1293         public LightCullable
1294 {
1295 class TypeCasts
1296 {
1297 InstanceTypeCastTable m_casts;
1298 public:
1299 TypeCasts(){
1300         InstanceStaticCast<PatchInstance, Selectable>::install( m_casts );
1301         InstanceContainedCast<PatchInstance, Bounded>::install( m_casts );
1302         InstanceContainedCast<PatchInstance, Cullable>::install( m_casts );
1303         InstanceStaticCast<PatchInstance, Renderable>::install( m_casts );
1304         InstanceStaticCast<PatchInstance, SelectionTestable>::install( m_casts );
1305         InstanceStaticCast<PatchInstance, ComponentSelectionTestable>::install( m_casts );
1306         InstanceStaticCast<PatchInstance, ComponentEditable>::install( m_casts );
1307         InstanceStaticCast<PatchInstance, ComponentSnappable>::install( m_casts );
1308         InstanceStaticCast<PatchInstance, PlaneSelectable>::install( m_casts );
1309         InstanceIdentityCast<PatchInstance>::install( m_casts );
1310         InstanceContainedCast<PatchInstance, Transformable>::install( m_casts );
1311 }
1312 InstanceTypeCastTable& get(){
1313         return m_casts;
1314 }
1315 };
1316
1317
1318 Patch& m_patch;
1319 typedef std::vector<PatchControlInstance> PatchControlInstances;
1320 PatchControlInstances m_ctrl_instances;
1321
1322 ObservedSelectable m_selectable;
1323
1324 DragPlanes m_dragPlanes;
1325
1326 mutable RenderablePointVector m_render_selected;
1327 mutable AABB m_aabb_component;
1328
1329 static Shader* m_state_selpoint;
1330
1331 const LightList* m_lightList;
1332
1333 TransformModifier m_transform;
1334 public:
1335
1336 typedef LazyStatic<TypeCasts> StaticTypeCasts;
1337
1338 void lightsChanged(){
1339         m_lightList->lightsChanged();
1340 }
1341 typedef MemberCaller<PatchInstance, &PatchInstance::lightsChanged> LightsChangedCaller;
1342
1343 STRING_CONSTANT( Name, "PatchInstance" );
1344
1345 PatchInstance( const scene::Path& path, scene::Instance* parent, Patch& patch ) :
1346         Instance( path, parent, this, StaticTypeCasts::instance().get() ),
1347         m_patch( patch ),
1348         m_selectable( SelectedChangedCaller( *this ) ),
1349         m_dragPlanes( SelectedChangedComponentCaller( *this ) ),
1350         m_render_selected( GL_POINTS ),
1351         m_transform( Patch::TransformChangedCaller( m_patch ), ApplyTransformCaller( *this ) ){
1352         m_patch.instanceAttach( Instance::path() );
1353         m_patch.attach( this );
1354
1355         m_lightList = &GlobalShaderCache().attach( *this );
1356         m_patch.m_lightsChanged = LightsChangedCaller( *this );
1357
1358         Instance::setTransformChangedCallback( LightsChangedCaller( *this ) );
1359 }
1360 ~PatchInstance(){
1361         Instance::setTransformChangedCallback( Callback() );
1362
1363         m_patch.m_lightsChanged = Callback();
1364         GlobalShaderCache().detach( *this );
1365
1366         m_patch.detach( this );
1367         m_patch.instanceDetach( Instance::path() );
1368 }
1369
1370 void selectedChanged( const Selectable& selectable ){
1371         GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable );
1372         GlobalSelectionSystem().onSelectedChanged( *this, selectable );
1373
1374         Instance::selectedChanged();
1375 }
1376 typedef MemberCaller1<PatchInstance, const Selectable&, &PatchInstance::selectedChanged> SelectedChangedCaller;
1377
1378 void selectedChangedComponent( const Selectable& selectable ){
1379         GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable );
1380         GlobalSelectionSystem().onComponentSelection( *this, selectable );
1381 }
1382 typedef MemberCaller1<PatchInstance, const Selectable&, &PatchInstance::selectedChangedComponent> SelectedChangedComponentCaller;
1383
1384 Patch& getPatch(){
1385         return m_patch;
1386 }
1387 Bounded& get( NullType<Bounded>){
1388         return m_patch;
1389 }
1390 Cullable& get( NullType<Cullable>){
1391         return m_patch;
1392 }
1393 Transformable& get( NullType<Transformable>){
1394         return m_transform;
1395 }
1396
1397 static void constructStatic(){
1398         m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" );
1399 }
1400
1401 static void destroyStatic(){
1402         GlobalShaderCache().release( "$SELPOINT" );
1403 }
1404
1405
1406 void allocate( std::size_t size ){
1407         m_ctrl_instances.clear();
1408         m_ctrl_instances.reserve( size );
1409         for ( Patch::iterator i = m_patch.begin(); i != m_patch.end(); ++i )
1410         {
1411                 m_ctrl_instances.push_back( PatchControlInstance( &( *i ), SelectedChangedComponentCaller( *this ) ) );
1412         }
1413 }
1414
1415 void setSelected( bool select ){
1416         m_selectable.setSelected( select );
1417 }
1418 bool isSelected() const {
1419         return m_selectable.isSelected();
1420 }
1421
1422
1423 void update_selected() const {
1424         m_render_selected.clear();
1425         Patch::iterator ctrl = m_patch.getControlPointsTransformed().begin();
1426         for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl )
1427         {
1428                 if ( ( *i ).m_selectable.isSelected() ) {
1429                         const Colour4b colour_selected( 0, 0, 255, 255 );
1430                         m_render_selected.push_back( PointVertex( reinterpret_cast<Vertex3f&>( ( *ctrl ).m_vertex ), colour_selected ) );
1431                 }
1432         }
1433 }
1434
1435 #if 0
1436 void render( Renderer& renderer, const VolumeTest& volume ) const {
1437         if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent
1438                  && m_selectable.isSelected() ) {
1439                 renderer.Highlight( Renderer::eFace, false );
1440
1441                 m_patch.render( renderer, volume, localToWorld() );
1442
1443                 if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) {
1444                         renderer.Highlight( Renderer::ePrimitive, false );
1445
1446                         m_patch.render_component( renderer, volume, localToWorld() );
1447
1448                         renderComponentsSelected( renderer, volume );
1449                 }
1450         }
1451         else{
1452                 m_patch.render( renderer, volume, localToWorld() );
1453         }
1454 }
1455 #endif
1456
1457 void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
1458         m_patch.evaluateTransform();
1459         renderer.setLights( *m_lightList );
1460         m_patch.render_solid( renderer, volume, localToWorld() );
1461
1462         renderComponentsSelected( renderer, volume );
1463 }
1464
1465 void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
1466         m_patch.evaluateTransform();
1467         m_patch.render_wireframe( renderer, volume, localToWorld() );
1468
1469         renderComponentsSelected( renderer, volume );
1470 }
1471
1472 void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume ) const {
1473         m_patch.evaluateTransform();
1474         update_selected();
1475         if ( !m_render_selected.empty() ) {
1476                 renderer.Highlight( Renderer::ePrimitive, false );
1477                 renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly );
1478                 renderer.SetState( m_state_selpoint, Renderer::eFullMaterials );
1479                 renderer.addRenderable( m_render_selected, localToWorld() );
1480         }
1481 }
1482 void renderComponents( Renderer& renderer, const VolumeTest& volume ) const {
1483         m_patch.evaluateTransform();
1484         if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) {
1485                 m_patch.render_component( renderer, volume, localToWorld() );
1486         }
1487 }
1488
1489 void testSelect( Selector& selector, SelectionTest& test ){
1490         test.BeginMesh( localToWorld(), true );
1491         m_patch.testSelect( selector, test );
1492 }
1493
1494 void selectCtrl( bool select ){
1495         for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1496         {
1497                 ( *i ).m_selectable.setSelected( select );
1498         }
1499 }
1500 bool isSelectedComponents() const {
1501         for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1502         {
1503                 if ( ( *i ).m_selectable.isSelected() ) {
1504                         return true;
1505                 }
1506         }
1507         return false;
1508 }
1509 void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){
1510         if ( mode == SelectionSystem::eVertex ) {
1511                 selectCtrl( select );
1512         }
1513         else if ( mode == SelectionSystem::eFace ) {
1514                 m_dragPlanes.setSelected( select );
1515         }
1516 }
1517 const AABB& getSelectedComponentsBounds() const {
1518         m_aabb_component = AABB();
1519
1520         for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1521         {
1522                 if ( ( *i ).m_selectable.isSelected() ) {
1523                         aabb_extend_by_point_safe( m_aabb_component, ( *i ).m_ctrl->m_vertex );
1524                 }
1525         }
1526
1527         return m_aabb_component;
1528 }
1529
1530 void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){
1531         test.BeginMesh( localToWorld() );
1532
1533         switch ( mode )
1534         {
1535         case SelectionSystem::eVertex:
1536         {
1537                 for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1538                 {
1539                         ( *i ).testSelect( selector, test );
1540                 }
1541         }
1542         break;
1543         default:
1544                 break;
1545         }
1546 }
1547
1548 bool selectedVertices(){
1549         for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1550         {
1551                 if ( ( *i ).m_selectable.isSelected() ) {
1552                         return true;
1553                 }
1554         }
1555         return false;
1556 }
1557
1558 void transformComponents( const Matrix4& matrix ){
1559         if ( selectedVertices() ) {
1560                 PatchControlIter ctrl = m_patch.getControlPointsTransformed().begin();
1561                 for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl )
1562                 {
1563                         if ( ( *i ).m_selectable.isSelected() ) {
1564                                 matrix4_transform_point( matrix, ( *ctrl ).m_vertex );
1565                         }
1566                 }
1567                 m_patch.UpdateCachedData();
1568         }
1569
1570         if ( m_dragPlanes.isSelected() ) { // this should only be true when the transform is a pure translation.
1571                 m_patch.transform( m_dragPlanes.evaluateTransform( vector4_to_vector3( matrix.t() ) ) );
1572         }
1573 }
1574
1575
1576 void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){
1577         test.BeginMesh( localToWorld() );
1578
1579         m_dragPlanes.selectPlanes( m_patch.localAABB(), selector, test, selectedPlaneCallback );
1580 }
1581 void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){
1582         m_dragPlanes.selectReversedPlanes( m_patch.localAABB(), selector, selectedPlanes );
1583 }
1584
1585
1586 void snapComponents( float snap ){
1587         if ( selectedVertices() ) {
1588                 m_patch.undoSave();
1589                 for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
1590                 {
1591                         if ( ( *i ).m_selectable.isSelected() ) {
1592                                 ( *i ).snapto( snap );
1593                         }
1594                 }
1595                 m_patch.controlPointsChanged();
1596         }
1597 }
1598
1599 void evaluateTransform(){
1600         Matrix4 matrix( m_transform.calculateTransform() );
1601
1602         if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) {
1603                 m_patch.transform( matrix );
1604         }
1605         else
1606         {
1607                 transformComponents( matrix );
1608         }
1609 }
1610 void applyTransform(){
1611         m_patch.revertTransform();
1612         evaluateTransform();
1613         m_patch.freezeTransform();
1614 }
1615 typedef MemberCaller<PatchInstance, &PatchInstance::applyTransform> ApplyTransformCaller;
1616
1617
1618 bool testLight( const RendererLight& light ) const {
1619         return light.testAABB( worldAABB() );
1620 }
1621 };
1622
1623
1624 template<typename TokenImporter, typename TokenExporter>
1625 class PatchNode :
1626         public scene::Node::Symbiot,
1627         public scene::Instantiable,
1628         public scene::Cloneable
1629 {
1630 typedef PatchNode<TokenImporter, TokenExporter> Self;
1631
1632 class TypeCasts
1633 {
1634 InstanceTypeCastTable m_casts;
1635 public:
1636 TypeCasts(){
1637         NodeStaticCast<PatchNode, scene::Instantiable>::install( m_casts );
1638         NodeStaticCast<PatchNode, scene::Cloneable>::install( m_casts );
1639         NodeContainedCast<PatchNode, Snappable>::install( m_casts );
1640         NodeContainedCast<PatchNode, TransformNode>::install( m_casts );
1641         NodeContainedCast<PatchNode, Patch>::install( m_casts );
1642         NodeContainedCast<PatchNode, XMLImporter>::install( m_casts );
1643         NodeContainedCast<PatchNode, XMLExporter>::install( m_casts );
1644         NodeContainedCast<PatchNode, MapImporter>::install( m_casts );
1645         NodeContainedCast<PatchNode, MapExporter>::install( m_casts );
1646         NodeContainedCast<PatchNode, Nameable>::install( m_casts );
1647 }
1648 InstanceTypeCastTable& get(){
1649         return m_casts;
1650 }
1651 };
1652
1653
1654 scene::Node m_node;
1655 InstanceSet m_instances;
1656 Patch m_patch;
1657 TokenImporter m_importMap;
1658 TokenExporter m_exportMap;
1659
1660 public:
1661
1662 typedef LazyStatic<TypeCasts> StaticTypeCasts;
1663
1664 Snappable& get( NullType<Snappable>){
1665         return m_patch;
1666 }
1667 TransformNode& get( NullType<TransformNode>){
1668         return m_patch;
1669 }
1670 Patch& get( NullType<Patch>){
1671         return m_patch;
1672 }
1673 XMLImporter& get( NullType<XMLImporter>){
1674         return m_patch;
1675 }
1676 XMLExporter& get( NullType<XMLExporter>){
1677         return m_patch;
1678 }
1679 MapImporter& get( NullType<MapImporter>){
1680         return m_importMap;
1681 }
1682 MapExporter& get( NullType<MapExporter>){
1683         return m_exportMap;
1684 }
1685 Nameable& get( NullType<Nameable>){
1686         return m_patch;
1687 }
1688
1689 PatchNode( bool patchDef3 = false ) :
1690         m_node( this, this, StaticTypeCasts::instance().get() ),
1691         m_patch( m_node, InstanceSetEvaluateTransform<PatchInstance>::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ),
1692         m_importMap( m_patch ),
1693         m_exportMap( m_patch ){
1694         m_patch.m_patchDef3 = patchDef3;
1695 }
1696 PatchNode( const PatchNode& other ) :
1697         scene::Node::Symbiot( other ),
1698         scene::Instantiable( other ),
1699         scene::Cloneable( other ),
1700         m_node( this, this, StaticTypeCasts::instance().get() ),
1701         m_patch( other.m_patch, m_node, InstanceSetEvaluateTransform<PatchInstance>::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ),
1702         m_importMap( m_patch ),
1703         m_exportMap( m_patch ){
1704 }
1705 void release(){
1706         delete this;
1707 }
1708 scene::Node& node(){
1709         return m_node;
1710 }
1711 Patch& get(){
1712         return m_patch;
1713 }
1714 const Patch& get() const {
1715         return m_patch;
1716 }
1717
1718 scene::Node& clone() const {
1719         return ( new PatchNode( *this ) )->node();
1720 }
1721
1722 scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
1723         return new PatchInstance( path, parent, m_patch );
1724 }
1725 void forEachInstance( const scene::Instantiable::Visitor& visitor ){
1726         m_instances.forEachInstance( visitor );
1727 }
1728 void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
1729         m_instances.insert( observer, path, instance );
1730 }
1731 scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
1732         return m_instances.erase( observer, path );
1733 }
1734 };
1735
1736
1737
1738 typedef PatchNode<PatchTokenImporter, PatchTokenExporter> PatchNodeQuake3;
1739 typedef PatchNode<PatchDoom3TokenImporter, PatchDoom3TokenExporter> PatchNodeDoom3;
1740
1741 inline Patch* Node_getPatch( scene::Node& node ){
1742         return NodeTypeCast<Patch>::cast( node );
1743 }
1744
1745 inline PatchInstance* Instance_getPatch( scene::Instance& instance ){
1746         return InstanceTypeCast<PatchInstance>::cast( instance );
1747 }
1748
1749 template<typename Functor>
1750 class PatchSelectedVisitor : public SelectionSystem::Visitor
1751 {
1752 const Functor& m_functor;
1753 public:
1754 PatchSelectedVisitor( const Functor& functor ) : m_functor( functor ){
1755 }
1756 void visit( scene::Instance& instance ) const {
1757         PatchInstance* patch = Instance_getPatch( instance );
1758         if ( patch != 0 ) {
1759                 m_functor( *patch );
1760         }
1761 }
1762 };
1763
1764 template<typename Functor>
1765 inline void Scene_forEachSelectedPatch( const Functor& functor ){
1766         GlobalSelectionSystem().foreachSelected( PatchSelectedVisitor<Functor>( functor ) );
1767 }
1768
1769
1770 template<typename Functor>
1771 class PatchVisibleSelectedVisitor : public SelectionSystem::Visitor
1772 {
1773 const Functor& m_functor;
1774 public:
1775 PatchVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){
1776 }
1777 void visit( scene::Instance& instance ) const {
1778         PatchInstance* patch = Instance_getPatch( instance );
1779         if ( patch != 0
1780                  && instance.path().top().get().visible() ) {
1781                 m_functor( *patch );
1782         }
1783 }
1784 };
1785
1786 template<typename Functor>
1787 inline void Scene_forEachVisibleSelectedPatchInstance( const Functor& functor ){
1788         GlobalSelectionSystem().foreachSelected( PatchVisibleSelectedVisitor<Functor>( functor ) );
1789 }
1790
1791 template<typename Functor>
1792 class PatchForEachWalker : public scene::Graph::Walker
1793 {
1794 const Functor& m_functor;
1795 public:
1796 PatchForEachWalker( const Functor& functor ) : m_functor( functor ){
1797 }
1798 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1799         if ( path.top().get().visible() ) {
1800                 Patch* patch = Node_getPatch( path.top() );
1801                 if ( patch != 0 ) {
1802                         m_functor( *patch );
1803                 }
1804         }
1805         return true;
1806 }
1807 };
1808
1809 template<typename Functor>
1810 inline void Scene_forEachVisiblePatch( const Functor& functor ){
1811         GlobalSceneGraph().traverse( PatchForEachWalker<Functor>( functor ) );
1812 }
1813
1814 template<typename Functor>
1815 class PatchForEachSelectedWalker : public scene::Graph::Walker
1816 {
1817 const Functor& m_functor;
1818 public:
1819 PatchForEachSelectedWalker( const Functor& functor ) : m_functor( functor ){
1820 }
1821 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1822         if ( path.top().get().visible() ) {
1823                 Patch* patch = Node_getPatch( path.top() );
1824                 if ( patch != 0
1825                          && Instance_getSelectable( instance )->isSelected() ) {
1826                         m_functor( *patch );
1827                 }
1828         }
1829         return true;
1830 }
1831 };
1832
1833 template<typename Functor>
1834 inline void Scene_forEachVisibleSelectedPatch( const Functor& functor ){
1835         GlobalSceneGraph().traverse( PatchForEachSelectedWalker<Functor>( functor ) );
1836 }
1837
1838 template<typename Functor>
1839 class PatchForEachInstanceWalker : public scene::Graph::Walker
1840 {
1841 const Functor& m_functor;
1842 public:
1843 PatchForEachInstanceWalker( const Functor& functor ) : m_functor( functor ){
1844 }
1845 bool pre( const scene::Path& path, scene::Instance& instance ) const {
1846         if ( path.top().get().visible() ) {
1847                 PatchInstance* patch = Instance_getPatch( instance );
1848                 if ( patch != 0 ) {
1849                         m_functor( *patch );
1850                 }
1851         }
1852         return true;
1853 }
1854 };
1855
1856 template<typename Functor>
1857 inline void Scene_forEachVisiblePatchInstance( const Functor& functor ){
1858         GlobalSceneGraph().traverse( PatchForEachInstanceWalker<Functor>( functor ) );
1859 }
1860
1861 #endif