]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/render.h
71b94b7619cd0026cbede5bb49b32e6d9e6e89fb
[xonotic/netradiant.git] / libs / render.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_RENDER_H)
23 #define INCLUDED_RENDER_H
24
25 /// \file
26 /// \brief High-level constructs for efficient OpenGL rendering.
27
28 #include "irender.h"
29 #include "igl.h"
30
31 #include "container/array.h"
32 #include "math/vector.h" 
33 #include "math/pi.h"
34
35 #include <vector>
36
37 typedef unsigned int RenderIndex;
38 const GLenum RenderIndexTypeID = GL_UNSIGNED_INT;
39
40 /// \brief A resizable buffer of indices.
41 class IndexBuffer
42 {
43   typedef std::vector<RenderIndex> Indices;
44   Indices m_data;
45 public:
46   typedef Indices::iterator iterator;
47   typedef Indices::const_iterator const_iterator;
48
49   iterator begin()
50   {
51     return m_data.begin();
52   }
53   const_iterator begin() const
54   {
55     return m_data.begin();
56   }
57   iterator end()
58   {
59     return m_data.end();
60   }
61   const_iterator end() const
62   {
63     return m_data.end();
64   }
65
66   bool empty() const
67   {
68     return m_data.empty();
69   }
70   std::size_t size() const
71   {
72     return m_data.size();
73   }
74   const RenderIndex* data() const
75   {
76     return &(*m_data.begin());
77   }
78   RenderIndex& operator[](std::size_t index)
79   {
80     return m_data[index];
81   }
82   const RenderIndex& operator[](std::size_t index) const
83   {
84     return m_data[index];
85   }
86   void clear()
87   {
88     m_data.clear();
89   }
90   void reserve(std::size_t max_indices)
91   {
92     m_data.reserve(max_indices);
93   }
94   void insert(RenderIndex index)
95   {
96     m_data.push_back(index);
97   }
98   void swap(IndexBuffer& other)
99   {
100     std::swap(m_data, m_data);
101   }
102 };
103
104 namespace std
105 {
106   /// \brief Swaps the values of \p self and \p other.
107   /// Overloads std::swap.
108   inline void swap(IndexBuffer& self, IndexBuffer& other)
109   {
110     self.swap(other);
111   }
112 }
113
114 /// \brief A resizable buffer of vertices.
115 /// \param Vertex The vertex data type.
116 template<typename Vertex>
117 class VertexBuffer
118 {
119   typedef typename std::vector<Vertex> Vertices;
120   Vertices m_data;
121 public:
122   typedef typename Vertices::iterator iterator;
123   typedef typename Vertices::const_iterator const_iterator;
124
125   iterator begin()
126   {
127     return m_data.begin();
128   }
129   iterator end()
130   {
131     return m_data.end();
132   }
133   const_iterator begin() const
134   {
135     return m_data.begin();
136   }
137   const_iterator end() const
138   {
139     return m_data.end();
140   }
141
142   bool empty() const
143   {
144     return m_data.empty();
145   }
146   RenderIndex size() const
147   {
148     return RenderIndex(m_data.size());
149   }
150   const Vertex* data() const
151   {
152     return &(*m_data.begin());
153   }
154   Vertex& operator[](std::size_t index)
155   {
156     return m_data[index];
157   }
158   const Vertex& operator[](std::size_t index) const
159   {
160     return m_data[index];
161   }
162
163   void clear()
164   {
165     m_data.clear();
166   }
167   void reserve(std::size_t max_vertices)
168   {
169     m_data.reserve(max_vertices);
170   }
171   void push_back(const Vertex& vertex)
172   {
173     m_data.push_back(vertex);
174   }
175 };
176
177 /// \brief A wrapper around a VertexBuffer which inserts only vertices which have not already been inserted.
178 /// \param Vertex The vertex data type. Must support operator<, operator== and operator!=.
179 /// For best performance, quantise vertices before inserting them.
180 template<typename Vertex>
181 class UniqueVertexBuffer
182 {
183   typedef VertexBuffer<Vertex> Vertices;
184   Vertices& m_data;
185
186   struct bnode
187   {
188     bnode()
189       : m_left(0), m_right(0)
190     {
191     }
192     RenderIndex m_left;
193     RenderIndex m_right;
194   };
195
196   std::vector<bnode> m_btree;
197   RenderIndex m_prev0;
198   RenderIndex m_prev1;
199   RenderIndex m_prev2;
200
201   const RenderIndex find_or_insert(const Vertex& vertex)
202   {
203     RenderIndex index = 0;
204
205     while(1)
206     {
207       if(vertex < m_data[index])
208       {
209         bnode& node = m_btree[index];
210         if(node.m_left != 0)
211         {
212           index = node.m_left;
213           continue;
214         }
215         else
216         {
217           node.m_left = RenderIndex(m_btree.size());
218           m_btree.push_back(bnode());
219           m_data.push_back(vertex);
220           return RenderIndex(m_btree.size()-1);
221         }
222       }
223       if(m_data[index] < vertex)
224       {
225         bnode& node = m_btree[index];
226         if(node.m_right != 0)
227         {
228           index = node.m_right;
229           continue;
230         }
231         else
232         {
233           node.m_right = RenderIndex(m_btree.size());
234           m_btree.push_back(bnode());
235           m_data.push_back(vertex);
236           return RenderIndex(m_btree.size()-1);
237         }
238       }
239
240       return index;
241     }
242   }
243 public:
244   UniqueVertexBuffer(Vertices& data)
245     : m_data(data), m_prev0(0), m_prev1(0), m_prev2(0)
246   {
247   }
248
249   typedef typename Vertices::const_iterator iterator;
250
251   iterator begin() const
252   {
253     return m_data.begin();
254   }
255   iterator end() const
256   {
257     return m_data.end();
258   }
259
260   std::size_t size() const
261   {
262     return m_data.size();
263   }
264   const Vertex* data() const
265   {
266     return &(*m_data.begin());
267   }
268   Vertex& operator[](std::size_t index)
269   {
270     return m_data[index];
271   }
272   const Vertex& operator[](std::size_t index) const
273   {
274     return m_data[index];
275   }
276
277   void clear()
278   {
279     m_prev0 = 0;
280     m_prev1 = 0;
281     m_prev2 = 0;
282     m_data.clear();
283     m_btree.clear();
284   }
285   void reserve(std::size_t max_vertices)
286   {
287     m_data.reserve(max_vertices);
288     m_btree.reserve(max_vertices);
289   }
290   /// \brief Returns the index of the element equal to \p vertex.
291   RenderIndex insert(const Vertex& vertex)
292   {
293     if(m_data.empty())
294     {
295       m_data.push_back(vertex);
296       m_btree.push_back(bnode());
297       return 0;
298     }
299
300     if(m_data[m_prev0] == vertex)
301       return m_prev0;
302     if(m_prev1 != m_prev0 && m_data[m_prev1] == vertex)
303       return m_prev1;
304     if(m_prev2 != m_prev0 && m_prev2 != m_prev1 && m_data[m_prev2] == vertex)
305       return m_prev2;
306
307     m_prev2 = m_prev1;
308     m_prev1 = m_prev0;
309     m_prev0 = find_or_insert(vertex);
310
311     return m_prev0;
312   }
313 };
314
315
316 /// \brief A 4-byte colour.
317 struct Colour4b
318 {
319   unsigned char r, g, b, a;
320
321   Colour4b()
322   {
323   }
324
325   Colour4b(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a)
326     : r(_r), g(_g), b(_b), a(_a)
327   {
328   }
329 };
330
331 inline bool operator<(const Colour4b& self, const Colour4b& other)
332 {
333   if(self.r != other.r)
334   {
335     return self.r < other.r;
336   }
337   if(self.g != other.g)
338   {
339     return self.g < other.g;
340   }
341   if(self.b != other.b)
342   {
343     return self.b < other.b;
344   }
345   if(self.a != other.a)
346   {
347     return self.a < other.a;
348   }
349   return false;
350 }
351
352 inline bool operator==(const Colour4b& self, const Colour4b& other)
353 {
354   return self.r == other.r && self.g == other.g && self.b == other.b && self.a == other.a;
355 }
356
357 inline bool operator!=(const Colour4b& self, const Colour4b& other)
358 {
359   return !operator==(self, other);
360 }
361
362 /// \brief A 3-float vertex.
363 struct Vertex3f
364 {
365   float x, y, z;
366
367   Vertex3f()
368   {
369   }
370
371   Vertex3f(float _x, float _y, float _z)
372     : x(_x), y(_y), z(_z)
373   {
374   }
375 };
376
377 inline bool operator<(const Vertex3f& self, const Vertex3f& other)
378 {
379   if(self.x != other.x)
380   {
381     return self.x < other.x;
382   }
383   if(self.y != other.y)
384   {
385     return self.y < other.y;
386   }
387   if(self.z != other.z)
388   {
389     return self.z < other.z;
390   }
391   return false;
392 }
393
394 inline bool operator==(const Vertex3f& self, const Vertex3f& other)
395 {
396   return self.x == other.x && self.y == other.y && self.z == other.z;
397 }
398
399 inline bool operator!=(const Vertex3f& self, const Vertex3f& other)
400 {
401   return !operator==(self, other);
402 }
403
404
405 inline const Vertex3f& vertex3f_from_array(const float* array)
406 {
407   return *reinterpret_cast<const Vertex3f*>(array);
408 }
409
410 inline float* vertex3f_to_array(Vertex3f& vertex)
411 {
412   return reinterpret_cast<float*>(&vertex);
413 }
414
415 inline const float* vertex3f_to_array(const Vertex3f& vertex)
416 {
417   return reinterpret_cast<const float*>(&vertex);
418 }
419
420 const Vertex3f vertex3f_identity(0, 0, 0);
421
422 inline Vertex3f vertex3f_for_vector3(const Vector3& vector3)
423 {
424   return Vertex3f(vector3.x(), vector3.y(), vector3.z());
425 }
426
427 inline const Vector3& vertex3f_to_vector3(const Vertex3f& vertex)
428 {
429   return reinterpret_cast<const Vector3&>(vertex);
430 }
431
432 inline Vector3& vertex3f_to_vector3(Vertex3f& vertex)
433 {
434   return reinterpret_cast<Vector3&>(vertex);
435 }
436
437
438 /// \brief A 3-float normal.
439 struct Normal3f
440 {
441   float x, y, z;
442
443   Normal3f()
444   {
445   }
446
447   Normal3f(float _x, float _y, float _z)
448     : x(_x), y(_y), z(_z)
449   {
450   }
451 };
452
453 inline bool operator<(const Normal3f& self, const Normal3f& other)
454 {
455   if(self.x != other.x)
456   {
457     return self.x < other.x;
458   }
459   if(self.y != other.y)
460   {
461     return self.y < other.y;
462   }
463   if(self.z != other.z)
464   {
465     return self.z < other.z;
466   }
467   return false;
468 }
469
470 inline bool operator==(const Normal3f& self, const Normal3f& other)
471 {
472   return self.x == other.x && self.y == other.y && self.z == other.z;
473 }
474
475 inline bool operator!=(const Normal3f& self, const Normal3f& other)
476 {
477   return !operator==(self, other);
478 }
479
480
481 inline Normal3f normal3f_from_array(const float* array)
482 {
483   return Normal3f(array[0], array[1], array[2]);
484 }
485
486 inline float* normal3f_to_array(Normal3f& normal)
487 {
488   return reinterpret_cast<float*>(&normal);
489 }
490
491 inline const float* normal3f_to_array(const Normal3f& normal)
492 {
493   return reinterpret_cast<const float*>(&normal);
494 }
495
496 inline Normal3f normal3f_for_vector3(const Vector3& vector3)
497 {
498   return Normal3f(vector3.x(), vector3.y(), vector3.z());
499 }
500
501 inline const Vector3& normal3f_to_vector3(const Normal3f& normal)
502 {
503   return reinterpret_cast<const Vector3&>(normal);
504 }
505
506 inline Vector3& normal3f_to_vector3(Normal3f& normal)
507 {
508   return reinterpret_cast<Vector3&>(normal);
509 }
510
511
512 /// \brief A 2-float texture-coordinate set.
513 struct TexCoord2f
514 {
515   float s, t;
516
517   TexCoord2f()
518   {
519   }
520
521   TexCoord2f(float _s, float _t)
522     : s(_s), t(_t)
523   {
524   }
525 };
526
527 inline bool operator<(const TexCoord2f& self, const TexCoord2f& other)
528 {
529   if(self.s != other.s)
530   {
531     return self.s < other.s;
532   }
533   if(self.t != other.t)
534   {
535     return self.t < other.t;
536   }
537   return false;
538 }
539
540 inline bool operator==(const TexCoord2f& self, const TexCoord2f& other)
541 {
542   return self.s == other.s && self.t == other.t;
543 }
544
545 inline bool operator!=(const TexCoord2f& self, const TexCoord2f& other)
546 {
547   return !operator==(self, other);
548 }
549
550
551 inline float* texcoord2f_to_array(TexCoord2f& texcoord)
552 {
553   return reinterpret_cast<float*>(&texcoord);
554 }
555
556 inline const float* texcoord2f_to_array(const TexCoord2f& texcoord)
557 {
558   return reinterpret_cast<const float*>(&texcoord);
559 }
560
561 inline const TexCoord2f& texcoord2f_from_array(const float* array)
562 {
563   return *reinterpret_cast<const TexCoord2f*>(array);
564 }
565
566 inline TexCoord2f texcoord2f_for_vector2(const Vector2& vector2)
567 {
568   return TexCoord2f(vector2.x(), vector2.y());
569 }
570
571 inline const Vector2& texcoord2f_to_vector2(const TexCoord2f& vertex)
572 {
573   return reinterpret_cast<const Vector2&>(vertex);
574 }
575
576 inline Vector2& texcoord2f_to_vector2(TexCoord2f& vertex)
577 {
578   return reinterpret_cast<Vector2&>(vertex);
579 }
580
581 /// \brief Returns \p normal rescaled to be unit-length. 
582 inline Normal3f normal3f_normalised(const Normal3f& normal)
583 {
584   return normal3f_for_vector3(vector3_normalised(normal3f_to_vector3(normal)));
585 }
586
587 enum UnitSphereOctant
588 {
589   UNITSPHEREOCTANT_000 = 0 << 0 | 0 << 1 | 0 << 2,
590   UNITSPHEREOCTANT_001 = 0 << 0 | 0 << 1 | 1 << 2,
591   UNITSPHEREOCTANT_010 = 0 << 0 | 1 << 1 | 0 << 2,
592   UNITSPHEREOCTANT_011 = 0 << 0 | 1 << 1 | 1 << 2,
593   UNITSPHEREOCTANT_100 = 1 << 0 | 0 << 1 | 0 << 2,
594   UNITSPHEREOCTANT_101 = 1 << 0 | 0 << 1 | 1 << 2,
595   UNITSPHEREOCTANT_110 = 1 << 0 | 1 << 1 | 0 << 2,
596   UNITSPHEREOCTANT_111 = 1 << 0 | 1 << 1 | 1 << 2,
597 };
598
599 /// \brief Returns the octant for \p normal indicating the sign of the region of unit-sphere space it lies within.
600 inline UnitSphereOctant normal3f_classify_octant(const Normal3f& normal)
601 {
602   return static_cast<UnitSphereOctant>(
603     ((normal.x > 0) << 0) | ((normal.y > 0) << 1) | ((normal.z > 0) << 2)
604   );
605 }
606
607 /// \brief Returns \p normal with its components signs made positive based on \p octant.
608 inline Normal3f normal3f_fold_octant(const Normal3f& normal, UnitSphereOctant octant)
609 {
610   switch(octant)
611   {
612   case UNITSPHEREOCTANT_000:
613     return Normal3f(-normal.x, -normal.y, -normal.z);
614   case UNITSPHEREOCTANT_001:
615     return Normal3f(normal.x, -normal.y, -normal.z);
616   case UNITSPHEREOCTANT_010:
617     return Normal3f(-normal.x, normal.y, -normal.z);
618   case UNITSPHEREOCTANT_011:
619     return Normal3f(normal.x, normal.y, -normal.z);
620   case UNITSPHEREOCTANT_100:
621     return Normal3f(-normal.x, -normal.y, normal.z);
622   case UNITSPHEREOCTANT_101:
623     return Normal3f(normal.x, -normal.y, normal.z);
624   case UNITSPHEREOCTANT_110:
625     return Normal3f(-normal.x, normal.y, normal.z);
626   case UNITSPHEREOCTANT_111:
627     return Normal3f(normal.x, normal.y, normal.z);
628   }
629   return Normal3f();
630 }
631
632 /// \brief Reverses the effect of normal3f_fold_octant() on \p normal with \p octant.
633 /// \p normal must have been obtained with normal3f_fold_octant().
634 /// \p octant must have been obtained with normal3f_classify_octant().
635 inline Normal3f normal3f_unfold_octant(const Normal3f& normal, UnitSphereOctant octant)
636 {
637   return normal3f_fold_octant(normal, octant);
638 }
639
640 enum UnitSphereSextant
641 {
642   UNITSPHERESEXTANT_XYZ = 0,
643   UNITSPHERESEXTANT_XZY = 1,
644   UNITSPHERESEXTANT_YXZ = 2,
645   UNITSPHERESEXTANT_YZX = 3,
646   UNITSPHERESEXTANT_ZXY = 4,
647   UNITSPHERESEXTANT_ZYX = 5,
648 };
649
650 /// \brief Returns the sextant for \p normal indicating how to sort its components so that x > y > z.
651 /// All components of \p normal must be positive.
652 /// \p normal must be normalised.
653 inline UnitSphereSextant normal3f_classify_sextant(const Normal3f& normal)
654 {
655   return
656     normal.x >= normal.y
657     ? normal.x >= normal.z
658       ? normal.y >= normal.z
659         ? UNITSPHERESEXTANT_XYZ
660         : UNITSPHERESEXTANT_XZY
661         : UNITSPHERESEXTANT_ZXY
662         : normal.y >= normal.z
663         ? normal.x >= normal.z
664         ? UNITSPHERESEXTANT_YXZ
665         : UNITSPHERESEXTANT_YZX
666         : UNITSPHERESEXTANT_ZYX;
667 }
668
669 /// \brief Returns \p normal with its components sorted so that x > y > z based on \p sextant.
670 /// All components of \p normal must be positive.
671 /// \p normal must be normalised.
672 inline Normal3f normal3f_fold_sextant(const Normal3f& normal, UnitSphereSextant sextant)
673 {
674   switch(sextant)
675   {
676   case UNITSPHERESEXTANT_XYZ:
677     return Normal3f(normal.x, normal.y, normal.z);
678   case UNITSPHERESEXTANT_XZY:
679     return Normal3f(normal.x, normal.z, normal.y);
680   case UNITSPHERESEXTANT_YXZ:
681     return Normal3f(normal.y, normal.x, normal.z);
682   case UNITSPHERESEXTANT_YZX:
683     return Normal3f(normal.y, normal.z, normal.x);
684   case UNITSPHERESEXTANT_ZXY:
685     return Normal3f(normal.z, normal.x, normal.y);
686   case UNITSPHERESEXTANT_ZYX:
687     return Normal3f(normal.z, normal.y, normal.x);
688   }
689   return Normal3f();
690 }
691
692 /// \brief Reverses the effect of normal3f_fold_sextant() on \p normal with \p sextant.
693 /// \p normal must have been obtained with normal3f_fold_sextant().
694 /// \p sextant must have been obtained with normal3f_classify_sextant().
695 inline Normal3f normal3f_unfold_sextant(const Normal3f& normal, UnitSphereSextant sextant)
696 {
697         return normal3f_fold_sextant(normal, sextant);
698 }
699
700 const std::size_t c_quantise_normal = 1 << 6;
701
702 /// \brief All the components of \p folded must be positive and sorted so that x > y > z.
703 inline Normal3f normal3f_folded_quantised(const Normal3f& folded)
704 {
705   // compress
706   double scale = static_cast<float>(c_quantise_normal) / (folded.x + folded.y + folded.z);
707   unsigned int zbits = static_cast<unsigned int>(folded.z * scale);
708   unsigned int ybits = static_cast<unsigned int>(folded.y * scale);
709
710   // decompress
711   return normal3f_normalised(Normal3f(
712     static_cast<float>(c_quantise_normal - zbits - ybits),
713     static_cast<float>(ybits),
714     static_cast<float>(zbits)
715   ));
716 }
717
718 /// \brief Returns \p normal quantised by compressing and then decompressing its representation.
719 inline Normal3f normal3f_quantised_custom(const Normal3f& normal)
720 {
721   UnitSphereOctant octant = normal3f_classify_octant(normal);
722   Normal3f folded = normal3f_fold_octant(normal, octant);
723   UnitSphereSextant sextant = normal3f_classify_sextant(folded);
724   folded = normal3f_fold_sextant(folded, sextant);
725   return normal3f_unfold_octant(normal3f_unfold_sextant(normal3f_folded_quantised(folded), sextant), octant);
726 }
727
728
729
730 struct spherical_t
731 {
732   double longditude, latitude;
733
734   spherical_t(double _longditude, double _latitude)
735     : longditude(_longditude), latitude(_latitude)
736   {
737   }
738 };
739
740 /*
741 {
742   theta = 2pi * U;
743   phi = acos((2 * V) - 1);
744
745   U = theta / 2pi;
746   V = (cos(phi) + 1) / 2;
747 }
748
749 longitude = atan(y / x);
750 latitude = acos(z);
751 */
752 struct uniformspherical_t
753 {
754   double U, V;
755
756   uniformspherical_t(double U_, double V_)
757     : U(U_), V(V_)
758   {
759   }
760 };
761
762
763 inline spherical_t spherical_from_normal3f(const Normal3f& normal)
764 {
765   return spherical_t(normal.x == 0 ? c_pi / 2 : normal.x > 0 ? atan(normal.y / normal.x) : atan(normal.y / normal.x) + c_pi, acos(normal.z));
766 }
767
768 inline Normal3f normal3f_from_spherical(const spherical_t& spherical)
769 {
770   return Normal3f(
771     static_cast<float>(cos(spherical.longditude) * sin(spherical.latitude)),
772     static_cast<float>(sin(spherical.longditude) * sin(spherical.latitude)),
773     static_cast<float>(cos(spherical.latitude))
774   );
775 }
776
777 inline uniformspherical_t uniformspherical_from_spherical(const spherical_t& spherical)
778 {
779   return uniformspherical_t(spherical.longditude * c_inv_2pi, (cos(spherical.latitude) + 1) * 0.5);
780 }
781
782 inline spherical_t spherical_from_uniformspherical(const uniformspherical_t& uniformspherical)
783 {
784   return spherical_t(c_2pi * uniformspherical.U, acos((2 * uniformspherical.V) - 1));
785 }
786
787 inline uniformspherical_t uniformspherical_from_normal3f(const Normal3f& normal)
788 {
789   return uniformspherical_from_spherical(spherical_from_normal3f(normal));
790   //return uniformspherical_t(atan2(normal.y / normal.x) * c_inv_2pi, (normal.z + 1) * 0.5);
791 }
792
793 inline Normal3f normal3f_from_uniformspherical(const uniformspherical_t& uniformspherical)
794 {
795   return normal3f_from_spherical(spherical_from_uniformspherical(uniformspherical));
796 }
797
798 /// \brief Returns a single-precision \p component quantised to \p precision.
799 inline float float_quantise(float component, float precision)
800 {
801   return float_snapped(component, precision);
802 }
803
804 /// \brief Returns a double-precision \p component quantised to \p precision.
805 inline double double_quantise(double component, double precision)
806 {
807   return float_snapped(component, precision);
808 }
809
810 inline spherical_t spherical_quantised(const spherical_t& spherical, float snap)
811 {
812   return spherical_t(double_quantise(spherical.longditude, snap), double_quantise(spherical.latitude, snap));
813 }
814
815 inline uniformspherical_t uniformspherical_quantised(const uniformspherical_t& uniformspherical, float snap)
816 {
817   return uniformspherical_t(double_quantise(uniformspherical.U, snap), double_quantise(uniformspherical.V, snap));
818 }
819
820 /// \brief Returns a \p vertex quantised to \p precision.
821 inline Vertex3f vertex3f_quantised(const Vertex3f& vertex, float precision)
822 {
823   return Vertex3f(float_quantise(vertex.x, precision), float_quantise(vertex.y, precision), float_quantise(vertex.z, precision));
824 }
825
826 /// \brief Returns a \p normal quantised to a fixed precision.
827 inline Normal3f normal3f_quantised(const Normal3f& normal)
828 {
829         return normal3f_quantised_custom(normal);
830   //return normal3f_from_spherical(spherical_quantised(spherical_from_normal3f(normal), snap));
831   //return normal3f_from_uniformspherical(uniformspherical_quantised(uniformspherical_from_normal3f(normal), snap));
832   //  float_quantise(normal.x, snap), float_quantise(normal.y, snap), float_quantise(normal.y, snap));
833 }
834
835 /// \brief Returns a \p texcoord quantised to \p precision.
836 inline TexCoord2f texcoord2f_quantised(const TexCoord2f& texcoord, float precision)
837 {
838   return TexCoord2f(float_quantise(texcoord.s, precision), float_quantise(texcoord.t, precision));
839 }
840
841 /// \brief Standard vertex type for lines and points.
842 struct PointVertex
843 {
844   Colour4b colour;
845   Vertex3f vertex;
846
847   PointVertex()
848   {
849   }
850   PointVertex(Vertex3f _vertex)
851     : colour(Colour4b(255, 255, 255, 255)), vertex(_vertex)
852   {
853   }
854   PointVertex(Vertex3f _vertex, Colour4b _colour)
855     : colour(_colour), vertex(_vertex)
856   {
857   }
858 };
859
860 inline bool operator<(const PointVertex& self, const PointVertex& other)
861 {
862   if(self.vertex != other.vertex)
863   {
864     return self.vertex < other.vertex;
865   }
866   if(self.colour != other.colour)
867   {
868     return self.colour < other.colour;
869   }
870   return false;
871 }
872
873 inline bool operator==(const PointVertex& self, const PointVertex& other)
874 {
875   return self.colour == other.colour && self.vertex == other.vertex;
876 }
877
878 inline bool operator!=(const PointVertex& self, const PointVertex& other)
879 {
880   return !operator==(self, other);
881 }
882
883 /// \brief Standard vertex type for lit/textured meshes.
884 struct ArbitraryMeshVertex
885 {
886   TexCoord2f texcoord;
887   Normal3f normal;
888   Vertex3f vertex;
889   Normal3f tangent;
890   Normal3f bitangent;
891
892   ArbitraryMeshVertex() : tangent(0, 0, 0), bitangent(0, 0, 0)
893   {
894   }
895   ArbitraryMeshVertex(Vertex3f _vertex, Normal3f _normal, TexCoord2f _texcoord)
896     : texcoord(_texcoord), normal(_normal), vertex(_vertex), tangent(0, 0, 0), bitangent(0, 0, 0)
897   {
898   }
899 };
900
901 inline bool operator<(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
902 {
903   if(self.texcoord != other.texcoord)
904   {
905     return self.texcoord < other.texcoord;
906   }
907   if(self.normal != other.normal)
908   {
909     return self.normal < other.normal;
910   }
911   if(self.vertex != other.vertex)
912   {
913     return self.vertex < other.vertex;
914   }
915   return false;
916 }
917
918 inline bool operator==(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
919 {
920   return self.texcoord == other.texcoord && self.normal == other.normal && self.vertex == other.vertex;
921 }
922
923 inline bool operator!=(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
924 {
925   return !operator==(self, other);
926 }
927
928 const float c_quantise_vertex = 1.f / static_cast<float>(1 << 3);
929
930 /// \brief Returns \p v with vertex quantised to a fixed precision.
931 inline PointVertex pointvertex_quantised(const PointVertex& v)
932 {
933   return PointVertex(vertex3f_quantised(v.vertex, c_quantise_vertex), v.colour);
934 }
935
936 const float c_quantise_texcoord = 1.f / static_cast<float>(1 << 8);
937
938 /// \brief Returns \p v with vertex, normal and texcoord quantised to a fixed precision.
939 inline ArbitraryMeshVertex arbitrarymeshvertex_quantised(const ArbitraryMeshVertex& v)
940 {
941   return ArbitraryMeshVertex(vertex3f_quantised(v.vertex, c_quantise_vertex), normal3f_quantised(v.normal), texcoord2f_quantised(v.texcoord, c_quantise_texcoord));
942 }
943
944
945 /// \brief Sets up the OpenGL colour and vertex arrays for \p array.
946 inline void pointvertex_gl_array(const PointVertex* array)
947 {
948   glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &array->colour);
949   glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &array->vertex);
950 }
951
952 class RenderablePointArray : public OpenGLRenderable
953 {
954   const Array<PointVertex>& m_array;
955   const GLenum m_mode;
956 public:
957   RenderablePointArray(const Array<PointVertex>& array, GLenum mode)
958     : m_array(array), m_mode(mode)
959   {
960   }
961   void render(RenderStateFlags state) const
962   {
963 #define NV_DRIVER_BUG 1
964 #if NV_DRIVER_BUG
965     glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
966     glVertexPointer(3, GL_FLOAT, 0, 0);
967     glDrawArrays(GL_TRIANGLE_FAN, 0, 0);
968 #endif
969     pointvertex_gl_array(m_array.data());
970     glDrawArrays(m_mode, 0, GLsizei(m_array.size()));
971   }
972 };
973
974 class RenderablePointVector : public OpenGLRenderable
975 {
976   std::vector<PointVertex> m_vector;
977   const GLenum m_mode;
978 public:
979   RenderablePointVector(GLenum mode)
980     : m_mode(mode)
981   {
982   }
983
984   void render(RenderStateFlags state) const
985   {
986     pointvertex_gl_array(&m_vector.front());
987     glDrawArrays(m_mode, 0, GLsizei(m_vector.size()));
988   }
989
990   std::size_t size() const
991   {
992     return m_vector.size();
993   }
994   bool empty() const
995   {
996     return m_vector.empty();
997   }
998   void clear()
999   {
1000     m_vector.clear();
1001   }
1002   void reserve(std::size_t size)
1003   {
1004     m_vector.reserve(size);
1005   }
1006   void push_back(const PointVertex& point)
1007   {
1008     m_vector.push_back(point);
1009   }
1010 };
1011
1012
1013 class RenderableVertexBuffer : public OpenGLRenderable
1014 {
1015   const GLenum m_mode;
1016   const VertexBuffer<PointVertex>& m_vertices;
1017 public:
1018   RenderableVertexBuffer(GLenum mode, const VertexBuffer<PointVertex>& vertices)
1019     : m_mode(mode), m_vertices(vertices)
1020   {
1021   }
1022
1023   void render(RenderStateFlags state) const
1024   {
1025     pointvertex_gl_array(m_vertices.data());
1026     glDrawArrays(m_mode, 0, m_vertices.size());
1027   }
1028 };
1029
1030 class RenderableIndexBuffer : public OpenGLRenderable
1031 {
1032   const GLenum m_mode;
1033   const IndexBuffer& m_indices;
1034   const VertexBuffer<PointVertex>& m_vertices;
1035 public:
1036   RenderableIndexBuffer(GLenum mode, const IndexBuffer& indices, const VertexBuffer<PointVertex>& vertices)
1037     : m_mode(mode), m_indices(indices), m_vertices(vertices)
1038   {
1039   }
1040
1041   void render(RenderStateFlags state) const
1042   {
1043 #if 1
1044     pointvertex_gl_array(m_vertices.data());
1045     glDrawElements(m_mode, GLsizei(m_indices.size()), RenderIndexTypeID, m_indices.data());
1046 #else
1047     glBegin(m_mode);
1048     if(state & RENDER_COLOURARRAY != 0)
1049     {
1050       for(std::size_t i = 0; i < m_indices.size(); ++i)
1051       {
1052         glColor4ubv(&m_vertices[m_indices[i]].colour.r);
1053         glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
1054       }
1055     }
1056     else
1057     {
1058       for(std::size_t i = 0; i < m_indices.size(); ++i)
1059       {
1060         glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
1061       }
1062     }
1063     glEnd();
1064 #endif
1065   }
1066 };
1067
1068
1069 class RemapXYZ
1070 {
1071 public:
1072   static void set(Vertex3f& vertex, float x, float y, float z)
1073   {
1074     vertex.x = x;
1075     vertex.y = y;
1076     vertex.z = z;
1077   }
1078 };
1079
1080 class RemapYZX
1081 {
1082 public:
1083   static void set(Vertex3f& vertex, float x, float y, float z)
1084   {
1085     vertex.x = z;
1086     vertex.y = x;
1087     vertex.z = y;
1088   }
1089 };
1090
1091 class RemapZXY
1092 {
1093 public:
1094   static void set(Vertex3f& vertex, float x, float y, float z)
1095   {
1096     vertex.x = y;
1097     vertex.y = z;
1098     vertex.z = x;
1099   }
1100 };
1101
1102 template<typename remap_policy>
1103 inline void draw_circle(const std::size_t segments, const float radius, PointVertex* vertices, remap_policy remap)
1104 {
1105   const double increment = c_pi / double(segments << 2);
1106
1107   std::size_t count = 0;
1108   float x = radius;
1109   float y = 0;
1110   while(count < segments)
1111   {
1112     PointVertex* i = vertices + count;
1113     PointVertex* j = vertices + ((segments << 1) - (count + 1));
1114
1115     PointVertex* k = i + (segments << 1);
1116     PointVertex* l = j + (segments << 1);
1117
1118     PointVertex* m = i + (segments << 2);
1119     PointVertex* n = j + (segments << 2);
1120     PointVertex* o = k + (segments << 2);
1121     PointVertex* p = l + (segments << 2);
1122
1123     remap_policy::set(i->vertex, x,-y, 0);
1124     remap_policy::set(k->vertex,-y,-x, 0);
1125     remap_policy::set(m->vertex,-x, y, 0);
1126     remap_policy::set(o->vertex, y, x, 0);
1127
1128     ++count;
1129
1130     {
1131       const double theta = increment * count;
1132       x = static_cast<float>(radius * cos(theta));
1133       y = static_cast<float>(radius * sin(theta));
1134     }
1135
1136     remap_policy::set(j->vertex, y,-x, 0);
1137     remap_policy::set(l->vertex,-x,-y, 0);
1138     remap_policy::set(n->vertex,-y, x, 0);
1139     remap_policy::set(p->vertex, x, y, 0);
1140   }
1141 }
1142
1143 #if 0
1144 class PointVertexArrayIterator
1145 {
1146   PointVertex* m_point;
1147 public:
1148   PointVertexArrayIterator(PointVertex* point)
1149     : m_point(point)
1150   {
1151   }
1152   PointVertexArrayIterator& operator++()
1153   {
1154     ++m_point;
1155     return *this;
1156   }
1157   PointVertexArrayIterator operator++(int)
1158   {
1159     PointVertexArrayIterator tmp(*this);
1160     ++m_point;
1161     return tmp;
1162   }
1163   Vertex3f& operator*()
1164   {
1165     return m_point.vertex;
1166   }
1167   Vertex3f* operator->()
1168   {
1169     return &(operator*());
1170   }
1171 }
1172
1173 template<typename remap_policy, typename iterator_type
1174 inline void draw_circle(const std::size_t segments, const float radius, iterator_type start, remap_policy remap)
1175 {
1176   const float increment = c_pi / (double)(segments << 2);
1177
1178   std::size_t count = 0;
1179   iterator_type pxpy(start);
1180   iterator_type pypx(pxpy + (segments << 1));
1181   iterator_type pynx(pxpy + (segments << 1));
1182   iterator_type nxpy(pypx + (segments << 1));
1183   iterator_type nxny(pypx + (segments << 1));
1184   iterator_type nynx(nxpy + (segments << 1));
1185   iterator_type nypx(nxpy + (segments << 1));
1186   iterator_type pxny(start);
1187   while(count < segments)
1188   {
1189     const float theta = increment * count;
1190     const float x = radius * cos(theta);
1191     const float y = radius * sin(theta);
1192
1193     remap_policy::set((*pxpy), x, y, 0);
1194     remap_policy::set((*pxny), x,-y, 0);
1195     remap_policy::set((*nxpy),-x, y, 0);
1196     remap_policy::set((*nxny),-x,-y, 0);
1197
1198     remap_policy::set((*pypx), y, x, 0);
1199     remap_policy::set((*pynx), y,-x, 0);
1200     remap_policy::set((*nypx),-y, x, 0);
1201     remap_policy::set((*nynx),-y,-x, 0);
1202   }
1203 }
1204
1205 template<typename remap_policy, typename iterator_type
1206 inline void draw_semicircle(const std::size_t segments, const float radius, iterator_type start, remap_policy remap)
1207 {
1208   const float increment = c_pi / (double)(segments << 2);
1209
1210   std::size_t count = 0;
1211   iterator_type pxpy(start);
1212   iterator_type pypx(pxpy + (segments << 1));
1213   iterator_type pynx(pxpy + (segments << 1));
1214   iterator_type nxpy(pypx + (segments << 1));
1215   iterator_type nxny(pypx + (segments << 1));
1216   iterator_type nynx(nxpy + (segments << 1));
1217   iterator_type nypx(nxpy + (segments << 1));
1218   iterator_type pxny(start);
1219   while(count < segments)
1220   {
1221     const float theta = increment * count;
1222     const float x = radius * cos(theta);
1223     const float y = radius * sin(theta);
1224
1225     remap_policy::set((*pxpy), x, y, 0);
1226     remap_policy::set((*pxny), x,-y, 0);
1227     remap_policy::set((*nxpy),-x, y, 0);
1228     remap_policy::set((*nxny),-x,-y, 0);
1229
1230     //remap_policy::set((*pypx), y, x, 0);
1231     //remap_policy::set((*pynx), y,-x, 0);
1232     //remap_policy::set((*nypx),-y, x, 0);
1233     //remap_policy::set((*nynx),-y,-x, 0);
1234   }
1235 }
1236
1237
1238 #endif
1239
1240 inline void draw_quad(const float radius, PointVertex* quad)
1241 {
1242   (*quad++).vertex = Vertex3f(-radius, radius, 0);
1243   (*quad++).vertex = Vertex3f(radius, radius, 0);
1244   (*quad++).vertex = Vertex3f(radius, -radius, 0);
1245   (*quad++).vertex = Vertex3f(-radius, -radius, 0);
1246 }
1247
1248 inline void draw_cube(const float radius, PointVertex* cube)
1249 {
1250   (*cube++).vertex = Vertex3f(-radius, -radius, -radius);
1251   (*cube++).vertex = Vertex3f(radius, -radius, -radius);
1252   (*cube++).vertex = Vertex3f(-radius, radius, -radius);
1253   (*cube++).vertex = Vertex3f(radius, radius, -radius);
1254   (*cube++).vertex = Vertex3f(-radius, -radius, radius);
1255   (*cube++).vertex = Vertex3f(radius, -radius, radius);
1256   (*cube++).vertex = Vertex3f(-radius, radius, radius);
1257   (*cube++).vertex = Vertex3f(radius, radius, radius);
1258 }
1259
1260
1261 /// \brief Calculates the tangent vectors for a triangle \p a, \p b, \p c and stores the tangent in \p s and the bitangent in \p t.
1262 inline void ArbitraryMeshTriangle_calcTangents(const ArbitraryMeshVertex& a, const ArbitraryMeshVertex& b, const ArbitraryMeshVertex& c, Vector3& s, Vector3& t)
1263 {
1264   s = Vector3(0, 0, 0);
1265   t = Vector3(0, 0, 0);
1266   {
1267     Vector3 cross(
1268       vector3_cross(
1269         vector3_subtracted(
1270           Vector3(b.vertex.x, b.texcoord.s, b.texcoord.t),
1271           Vector3(a.vertex.x, a.texcoord.s, a.texcoord.t)
1272         ),
1273         vector3_subtracted(
1274           Vector3(c.vertex.x, c.texcoord.s, c.texcoord.t),
1275           Vector3(a.vertex.x, a.texcoord.s, a.texcoord.t)
1276         )
1277       )
1278     );
1279
1280     if(fabs(cross.x()) > 0.000001f)
1281     {
1282       s.x() = -cross.y() / cross.x();
1283     }
1284
1285     if(fabs(cross.x()) > 0.000001f)
1286     {
1287       t.x() = -cross.z() / cross.x();
1288     }
1289   }
1290
1291   {
1292     Vector3 cross(
1293       vector3_cross(
1294         vector3_subtracted(
1295           Vector3(b.vertex.y, b.texcoord.s, b.texcoord.t),
1296           Vector3(a.vertex.y, a.texcoord.s, a.texcoord.t)
1297         ),
1298         vector3_subtracted(
1299           Vector3(c.vertex.y, c.texcoord.s, c.texcoord.t),
1300           Vector3(a.vertex.y, a.texcoord.s, a.texcoord.t)
1301         )
1302       )
1303     );
1304
1305     if(fabs(cross.x()) > 0.000001f)
1306     {
1307       s.y() = -cross.y() / cross.x();
1308     }
1309
1310     if(fabs(cross.x()) > 0.000001f)
1311     {
1312       t.y() = -cross.z() / cross.x();
1313     }
1314   }
1315
1316   {
1317     Vector3 cross(
1318       vector3_cross(
1319         vector3_subtracted(
1320           Vector3(b.vertex.z, b.texcoord.s, b.texcoord.t),
1321           Vector3(a.vertex.z, a.texcoord.s, a.texcoord.t)
1322         ),
1323         vector3_subtracted(
1324           Vector3(c.vertex.z, c.texcoord.s, c.texcoord.t),
1325           Vector3(a.vertex.z, a.texcoord.s, a.texcoord.t)
1326         )
1327       )
1328     );
1329
1330     if(fabs(cross.x()) > 0.000001f)
1331     {
1332       s.z() = -cross.y() / cross.x();
1333     }
1334
1335     if(fabs(cross.x()) > 0.000001f)
1336     {
1337       t.z() = -cross.z() / cross.x();
1338     }
1339   }
1340 }
1341
1342 inline void ArbitraryMeshTriangle_sumTangents(ArbitraryMeshVertex& a, ArbitraryMeshVertex& b, ArbitraryMeshVertex& c)
1343 {
1344   Vector3 s, t;
1345
1346   ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
1347
1348   reinterpret_cast<Vector3&>(a.tangent) += s;
1349   reinterpret_cast<Vector3&>(b.tangent) += s;
1350   reinterpret_cast<Vector3&>(c.tangent) += s;
1351
1352   reinterpret_cast<Vector3&>(a.bitangent) += t;
1353   reinterpret_cast<Vector3&>(b.bitangent) += t;
1354   reinterpret_cast<Vector3&>(c.bitangent) += t;
1355 }
1356
1357
1358 #endif