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