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