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