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