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