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