]> icculus.org git repositories - divverent/netradiant.git/blob - libs/render.h
initial
[divverent/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 const Colour4b colour_vertex(0, 255, 0, 255);
332 const Colour4b colour_selected(0, 0, 255, 255);
333
334 inline bool operator<(const Colour4b& self, const Colour4b& other)
335 {
336   if(self.r != other.r)
337   {
338     return self.r < other.r;
339   }
340   if(self.g != other.g)
341   {
342     return self.g < other.g;
343   }
344   if(self.b != other.b)
345   {
346     return self.b < other.b;
347   }
348   if(self.a != other.a)
349   {
350     return self.a < other.a;
351   }
352   return false;
353 }
354
355 inline bool operator==(const Colour4b& self, const Colour4b& other)
356 {
357   return self.r == other.r && self.g == other.g && self.b == other.b && self.a == other.a;
358 }
359
360 inline bool operator!=(const Colour4b& self, const Colour4b& other)
361 {
362   return !operator==(self, other);
363 }
364
365 /// \brief A 3-float vertex.
366 struct Vertex3f : public Vector3
367 {
368   Vertex3f()
369   {
370   }
371
372   Vertex3f(float _x, float _y, float _z)
373     : Vector3(_x, _y, _z)
374   {
375   }
376 };
377
378 inline bool operator<(const Vertex3f& self, const Vertex3f& other)
379 {
380   if(self.x() != other.x())
381   {
382     return self.x() < other.x();
383   }
384   if(self.y() != other.y())
385   {
386     return self.y() < other.y();
387   }
388   if(self.z() != other.z())
389   {
390     return self.z() < other.z();
391   }
392   return false;
393 }
394
395 inline bool operator==(const Vertex3f& self, const Vertex3f& other)
396 {
397   return self.x() == other.x() && self.y() == other.y() && self.z() == other.z();
398 }
399
400 inline bool operator!=(const Vertex3f& self, const Vertex3f& other)
401 {
402   return !operator==(self, other);
403 }
404
405
406 inline Vertex3f vertex3f_from_array(const float* array)
407 {
408   return Vertex3f(array[0], array[1], array[2]);
409 }
410
411 inline float* vertex3f_to_array(Vertex3f& vertex)
412 {
413   return reinterpret_cast<float*>(&vertex);
414 }
415
416 inline const float* vertex3f_to_array(const Vertex3f& vertex)
417 {
418   return reinterpret_cast<const float*>(&vertex);
419 }
420
421 const Vertex3f vertex3f_identity(0, 0, 0);
422
423 inline Vertex3f vertex3f_for_vector3(const Vector3& vector3)
424 {
425   return Vertex3f(vector3.x(), vector3.y(), vector3.z());
426 }
427
428 inline const Vector3& vertex3f_to_vector3(const Vertex3f& vertex)
429 {
430   return vertex;
431 }
432
433 inline Vector3& vertex3f_to_vector3(Vertex3f& vertex)
434 {
435   return vertex;
436 }
437
438
439 /// \brief A 3-float normal.
440 struct Normal3f : public Vector3
441 {
442   Normal3f()
443   {
444   }
445
446   Normal3f(float _x, float _y, float _z)
447     : Vector3(_x, _y, _z)
448   {
449   }
450 };
451
452 inline bool operator<(const Normal3f& self, const Normal3f& other)
453 {
454   if(self.x() != other.x())
455   {
456     return self.x() < other.x();
457   }
458   if(self.y() != other.y())
459   {
460     return self.y() < other.y();
461   }
462   if(self.z() != other.z())
463   {
464     return self.z() < other.z();
465   }
466   return false;
467 }
468
469 inline bool operator==(const Normal3f& self, const Normal3f& other)
470 {
471   return self.x() == other.x() && self.y() == other.y() && self.z() == other.z();
472 }
473
474 inline bool operator!=(const Normal3f& self, const Normal3f& other)
475 {
476   return !operator==(self, other);
477 }
478
479
480 inline Normal3f normal3f_from_array(const float* array)
481 {
482   return Normal3f(array[0], array[1], array[2]);
483 }
484
485 inline float* normal3f_to_array(Normal3f& normal)
486 {
487   return reinterpret_cast<float*>(&normal);
488 }
489
490 inline const float* normal3f_to_array(const Normal3f& normal)
491 {
492   return reinterpret_cast<const float*>(&normal);
493 }
494
495 inline Normal3f normal3f_for_vector3(const Vector3& vector3)
496 {
497   return Normal3f(vector3.x(), vector3.y(), vector3.z());
498 }
499
500 inline const Vector3& normal3f_to_vector3(const Normal3f& normal)
501 {
502   return normal;
503 }
504
505 inline Vector3& normal3f_to_vector3(Normal3f& normal)
506 {
507   return normal;
508 }
509
510
511 /// \brief A 2-float texture-coordinate set.
512 struct TexCoord2f : public Vector2
513 {
514   TexCoord2f()
515   {
516   }
517
518   TexCoord2f(float _s, float _t)
519     : Vector2(_s, _t)
520   {
521   }
522
523   float& s()
524   {
525     return x();
526   }
527   const float& s() const
528   {
529     return x();
530   }
531   float& t()
532   {
533     return y();
534   }
535   const float& t() const
536   {
537     return y();
538   }
539 };
540
541 inline bool operator<(const TexCoord2f& self, const TexCoord2f& other)
542 {
543   if(self.s() != other.s())
544   {
545     return self.s() < other.s();
546   }
547   if(self.t() != other.t())
548   {
549     return self.t() < other.t();
550   }
551   return false;
552 }
553
554 inline bool operator==(const TexCoord2f& self, const TexCoord2f& other)
555 {
556   return self.s() == other.s() && self.t() == other.t();
557 }
558
559 inline bool operator!=(const TexCoord2f& self, const TexCoord2f& other)
560 {
561   return !operator==(self, other);
562 }
563
564
565 inline float* texcoord2f_to_array(TexCoord2f& texcoord)
566 {
567   return reinterpret_cast<float*>(&texcoord);
568 }
569
570 inline const float* texcoord2f_to_array(const TexCoord2f& texcoord)
571 {
572   return reinterpret_cast<const float*>(&texcoord);
573 }
574
575 inline const TexCoord2f& texcoord2f_from_array(const float* array)
576 {
577   return *reinterpret_cast<const TexCoord2f*>(array);
578 }
579
580 inline TexCoord2f texcoord2f_for_vector2(const Vector2& vector2)
581 {
582   return TexCoord2f(vector2.x(), vector2.y());
583 }
584
585 inline const Vector2& texcoord2f_to_vector2(const TexCoord2f& vertex)
586 {
587   return vertex;
588 }
589
590 inline Vector2& texcoord2f_to_vector2(TexCoord2f& vertex)
591 {
592   return vertex;
593 }
594
595 /// \brief Returns \p normal rescaled to be unit-length. 
596 inline Normal3f normal3f_normalised(const Normal3f& normal)
597 {
598   return normal3f_for_vector3(vector3_normalised(normal3f_to_vector3(normal)));
599 }
600
601 enum UnitSphereOctant
602 {
603   UNITSPHEREOCTANT_000 = 0 << 0 | 0 << 1 | 0 << 2,
604   UNITSPHEREOCTANT_001 = 0 << 0 | 0 << 1 | 1 << 2,
605   UNITSPHEREOCTANT_010 = 0 << 0 | 1 << 1 | 0 << 2,
606   UNITSPHEREOCTANT_011 = 0 << 0 | 1 << 1 | 1 << 2,
607   UNITSPHEREOCTANT_100 = 1 << 0 | 0 << 1 | 0 << 2,
608   UNITSPHEREOCTANT_101 = 1 << 0 | 0 << 1 | 1 << 2,
609   UNITSPHEREOCTANT_110 = 1 << 0 | 1 << 1 | 0 << 2,
610   UNITSPHEREOCTANT_111 = 1 << 0 | 1 << 1 | 1 << 2,
611 };
612
613 /// \brief Returns the octant for \p normal indicating the sign of the region of unit-sphere space it lies within.
614 inline UnitSphereOctant normal3f_classify_octant(const Normal3f& normal)
615 {
616   return static_cast<UnitSphereOctant>(
617     ((normal.x() > 0) << 0) | ((normal.y() > 0) << 1) | ((normal.z() > 0) << 2)
618   );
619 }
620
621 /// \brief Returns \p normal with its components signs made positive based on \p octant.
622 inline Normal3f normal3f_fold_octant(const Normal3f& normal, UnitSphereOctant octant)
623 {
624   switch(octant)
625   {
626   case UNITSPHEREOCTANT_000:
627     return Normal3f(-normal.x(), -normal.y(), -normal.z());
628   case UNITSPHEREOCTANT_001:
629     return Normal3f(normal.x(), -normal.y(), -normal.z());
630   case UNITSPHEREOCTANT_010:
631     return Normal3f(-normal.x(), normal.y(), -normal.z());
632   case UNITSPHEREOCTANT_011:
633     return Normal3f(normal.x(), normal.y(), -normal.z());
634   case UNITSPHEREOCTANT_100:
635     return Normal3f(-normal.x(), -normal.y(), normal.z());
636   case UNITSPHEREOCTANT_101:
637     return Normal3f(normal.x(), -normal.y(), normal.z());
638   case UNITSPHEREOCTANT_110:
639     return Normal3f(-normal.x(), normal.y(), normal.z());
640   case UNITSPHEREOCTANT_111:
641     return Normal3f(normal.x(), normal.y(), normal.z());
642   }
643   return Normal3f();
644 }
645
646 /// \brief Reverses the effect of normal3f_fold_octant() on \p normal with \p octant.
647 /// \p normal must have been obtained with normal3f_fold_octant().
648 /// \p octant must have been obtained with normal3f_classify_octant().
649 inline Normal3f normal3f_unfold_octant(const Normal3f& normal, UnitSphereOctant octant)
650 {
651   return normal3f_fold_octant(normal, octant);
652 }
653
654 enum UnitSphereSextant
655 {
656   UNITSPHERESEXTANT_XYZ = 0,
657   UNITSPHERESEXTANT_XZY = 1,
658   UNITSPHERESEXTANT_YXZ = 2,
659   UNITSPHERESEXTANT_YZX = 3,
660   UNITSPHERESEXTANT_ZXY = 4,
661   UNITSPHERESEXTANT_ZYX = 5,
662 };
663
664 /// \brief Returns the sextant for \p normal indicating how to sort its components so that x > y > z.
665 /// All components of \p normal must be positive.
666 /// \p normal must be normalised.
667 inline UnitSphereSextant normal3f_classify_sextant(const Normal3f& normal)
668 {
669   return
670     normal.x() >= normal.y()
671     ? normal.x() >= normal.z()
672       ? normal.y() >= normal.z()
673         ? UNITSPHERESEXTANT_XYZ
674         : UNITSPHERESEXTANT_XZY
675         : UNITSPHERESEXTANT_ZXY
676         : normal.y() >= normal.z()
677         ? normal.x() >= normal.z()
678         ? UNITSPHERESEXTANT_YXZ
679         : UNITSPHERESEXTANT_YZX
680         : UNITSPHERESEXTANT_ZYX;
681 }
682
683 /// \brief Returns \p normal with its components sorted so that x > y > z based on \p sextant.
684 /// All components of \p normal must be positive.
685 /// \p normal must be normalised.
686 inline Normal3f normal3f_fold_sextant(const Normal3f& normal, UnitSphereSextant sextant)
687 {
688   switch(sextant)
689   {
690   case UNITSPHERESEXTANT_XYZ:
691     return Normal3f(normal.x(), normal.y(), normal.z());
692   case UNITSPHERESEXTANT_XZY:
693     return Normal3f(normal.x(), normal.z(), normal.y());
694   case UNITSPHERESEXTANT_YXZ:
695     return Normal3f(normal.y(), normal.x(), normal.z());
696   case UNITSPHERESEXTANT_YZX:
697     return Normal3f(normal.y(), normal.z(), normal.x());
698   case UNITSPHERESEXTANT_ZXY:
699     return Normal3f(normal.z(), normal.x(), normal.y());
700   case UNITSPHERESEXTANT_ZYX:
701     return Normal3f(normal.z(), normal.y(), normal.x());
702   }
703   return Normal3f();
704 }
705
706 /// \brief Reverses the effect of normal3f_fold_sextant() on \p normal with \p sextant.
707 /// \p normal must have been obtained with normal3f_fold_sextant().
708 /// \p sextant must have been obtained with normal3f_classify_sextant().
709 inline Normal3f normal3f_unfold_sextant(const Normal3f& normal, UnitSphereSextant sextant)
710 {
711         return normal3f_fold_sextant(normal, sextant);
712 }
713
714 const std::size_t c_quantise_normal = 1 << 6;
715
716 /// \brief All the components of \p folded must be positive and sorted so that x > y > z.
717 inline Normal3f normal3f_folded_quantised(const Normal3f& folded)
718 {
719   // compress
720   double scale = static_cast<float>(c_quantise_normal) / (folded.x() + folded.y() + folded.z());
721   unsigned int zbits = static_cast<unsigned int>(folded.z() * scale);
722   unsigned int ybits = static_cast<unsigned int>(folded.y() * scale);
723
724   // decompress
725   return normal3f_normalised(Normal3f(
726     static_cast<float>(c_quantise_normal - zbits - ybits),
727     static_cast<float>(ybits),
728     static_cast<float>(zbits)
729   ));
730 }
731
732 /// \brief Returns \p normal quantised by compressing and then decompressing its representation.
733 inline Normal3f normal3f_quantised_custom(const Normal3f& normal)
734 {
735   UnitSphereOctant octant = normal3f_classify_octant(normal);
736   Normal3f folded = normal3f_fold_octant(normal, octant);
737   UnitSphereSextant sextant = normal3f_classify_sextant(folded);
738   folded = normal3f_fold_sextant(folded, sextant);
739   return normal3f_unfold_octant(normal3f_unfold_sextant(normal3f_folded_quantised(folded), sextant), octant);
740 }
741
742
743
744 struct spherical_t
745 {
746   double longditude, latitude;
747
748   spherical_t(double _longditude, double _latitude)
749     : longditude(_longditude), latitude(_latitude)
750   {
751   }
752 };
753
754 /*
755 {
756   theta = 2pi * U;
757   phi = acos((2 * V) - 1);
758
759   U = theta / 2pi;
760   V = (cos(phi) + 1) / 2;
761 }
762
763 longitude = atan(y / x);
764 latitude = acos(z);
765 */
766 struct uniformspherical_t
767 {
768   double U, V;
769
770   uniformspherical_t(double U_, double V_)
771     : U(U_), V(V_)
772   {
773   }
774 };
775
776
777 inline spherical_t spherical_from_normal3f(const Normal3f& normal)
778 {
779   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()));
780 }
781
782 inline Normal3f normal3f_from_spherical(const spherical_t& spherical)
783 {
784   return Normal3f(
785     static_cast<float>(cos(spherical.longditude) * sin(spherical.latitude)),
786     static_cast<float>(sin(spherical.longditude) * sin(spherical.latitude)),
787     static_cast<float>(cos(spherical.latitude))
788   );
789 }
790
791 inline uniformspherical_t uniformspherical_from_spherical(const spherical_t& spherical)
792 {
793   return uniformspherical_t(spherical.longditude * c_inv_2pi, (cos(spherical.latitude) + 1) * 0.5);
794 }
795
796 inline spherical_t spherical_from_uniformspherical(const uniformspherical_t& uniformspherical)
797 {
798   return spherical_t(c_2pi * uniformspherical.U, acos((2 * uniformspherical.V) - 1));
799 }
800
801 inline uniformspherical_t uniformspherical_from_normal3f(const Normal3f& normal)
802 {
803   return uniformspherical_from_spherical(spherical_from_normal3f(normal));
804   //return uniformspherical_t(atan2(normal.y / normal.x) * c_inv_2pi, (normal.z + 1) * 0.5);
805 }
806
807 inline Normal3f normal3f_from_uniformspherical(const uniformspherical_t& uniformspherical)
808 {
809   return normal3f_from_spherical(spherical_from_uniformspherical(uniformspherical));
810 }
811
812 /// \brief Returns a single-precision \p component quantised to \p precision.
813 inline float float_quantise(float component, float precision)
814 {
815   return float_snapped(component, precision);
816 }
817
818 /// \brief Returns a double-precision \p component quantised to \p precision.
819 inline double double_quantise(double component, double precision)
820 {
821   return float_snapped(component, precision);
822 }
823
824 inline spherical_t spherical_quantised(const spherical_t& spherical, float snap)
825 {
826   return spherical_t(double_quantise(spherical.longditude, snap), double_quantise(spherical.latitude, snap));
827 }
828
829 inline uniformspherical_t uniformspherical_quantised(const uniformspherical_t& uniformspherical, float snap)
830 {
831   return uniformspherical_t(double_quantise(uniformspherical.U, snap), double_quantise(uniformspherical.V, snap));
832 }
833
834 /// \brief Returns a \p vertex quantised to \p precision.
835 inline Vertex3f vertex3f_quantised(const Vertex3f& vertex, float precision)
836 {
837   return Vertex3f(float_quantise(vertex.x(), precision), float_quantise(vertex.y(), precision), float_quantise(vertex.z(), precision));
838 }
839
840 /// \brief Returns a \p normal quantised to a fixed precision.
841 inline Normal3f normal3f_quantised(const Normal3f& normal)
842 {
843         return normal3f_quantised_custom(normal);
844   //return normal3f_from_spherical(spherical_quantised(spherical_from_normal3f(normal), snap));
845   //return normal3f_from_uniformspherical(uniformspherical_quantised(uniformspherical_from_normal3f(normal), snap));
846   //  float_quantise(normal.x, snap), float_quantise(normal.y, snap), float_quantise(normal.y, snap));
847 }
848
849 /// \brief Returns a \p texcoord quantised to \p precision.
850 inline TexCoord2f texcoord2f_quantised(const TexCoord2f& texcoord, float precision)
851 {
852   return TexCoord2f(float_quantise(texcoord.s(), precision), float_quantise(texcoord.t(), precision));
853 }
854
855 /// \brief Standard vertex type for lines and points.
856 struct PointVertex
857 {
858   Colour4b colour;
859   Vertex3f vertex;
860
861   PointVertex()
862   {
863   }
864   PointVertex(Vertex3f _vertex)
865     : colour(Colour4b(255, 255, 255, 255)), vertex(_vertex)
866   {
867   }
868   PointVertex(Vertex3f _vertex, Colour4b _colour)
869     : colour(_colour), vertex(_vertex)
870   {
871   }
872 };
873
874 inline bool operator<(const PointVertex& self, const PointVertex& other)
875 {
876   if(self.vertex != other.vertex)
877   {
878     return self.vertex < other.vertex;
879   }
880   if(self.colour != other.colour)
881   {
882     return self.colour < other.colour;
883   }
884   return false;
885 }
886
887 inline bool operator==(const PointVertex& self, const PointVertex& other)
888 {
889   return self.colour == other.colour && self.vertex == other.vertex;
890 }
891
892 inline bool operator!=(const PointVertex& self, const PointVertex& other)
893 {
894   return !operator==(self, other);
895 }
896
897 /// \brief Standard vertex type for lit/textured meshes.
898 struct ArbitraryMeshVertex
899 {
900   TexCoord2f texcoord;
901   Normal3f normal;
902   Vertex3f vertex;
903   Normal3f tangent;
904   Normal3f bitangent;
905
906   ArbitraryMeshVertex() : tangent(0, 0, 0), bitangent(0, 0, 0)
907   {
908   }
909   ArbitraryMeshVertex(Vertex3f _vertex, Normal3f _normal, TexCoord2f _texcoord)
910     : texcoord(_texcoord), normal(_normal), vertex(_vertex), tangent(0, 0, 0), bitangent(0, 0, 0)
911   {
912   }
913 };
914
915 inline bool operator<(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
916 {
917   if(self.texcoord != other.texcoord)
918   {
919     return self.texcoord < other.texcoord;
920   }
921   if(self.normal != other.normal)
922   {
923     return self.normal < other.normal;
924   }
925   if(self.vertex != other.vertex)
926   {
927     return self.vertex < other.vertex;
928   }
929   return false;
930 }
931
932 inline bool operator==(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
933 {
934   return self.texcoord == other.texcoord && self.normal == other.normal && self.vertex == other.vertex;
935 }
936
937 inline bool operator!=(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
938 {
939   return !operator==(self, other);
940 }
941
942 const float c_quantise_vertex = 1.f / static_cast<float>(1 << 3);
943
944 /// \brief Returns \p v with vertex quantised to a fixed precision.
945 inline PointVertex pointvertex_quantised(const PointVertex& v)
946 {
947   return PointVertex(vertex3f_quantised(v.vertex, c_quantise_vertex), v.colour);
948 }
949
950 const float c_quantise_texcoord = 1.f / static_cast<float>(1 << 8);
951
952 /// \brief Returns \p v with vertex, normal and texcoord quantised to a fixed precision.
953 inline ArbitraryMeshVertex arbitrarymeshvertex_quantised(const ArbitraryMeshVertex& v)
954 {
955   return ArbitraryMeshVertex(vertex3f_quantised(v.vertex, c_quantise_vertex), normal3f_quantised(v.normal), texcoord2f_quantised(v.texcoord, c_quantise_texcoord));
956 }
957
958
959 /// \brief Sets up the OpenGL colour and vertex arrays for \p array.
960 inline void pointvertex_gl_array(const PointVertex* array)
961 {
962   glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &array->colour);
963   glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &array->vertex);
964 }
965
966 class RenderablePointArray : public OpenGLRenderable
967 {
968   const Array<PointVertex>& m_array;
969   const GLenum m_mode;
970 public:
971   RenderablePointArray(const Array<PointVertex>& array, GLenum mode)
972     : m_array(array), m_mode(mode)
973   {
974   }
975   void render(RenderStateFlags state) const
976   {
977 #define NV_DRIVER_BUG 1
978 #if NV_DRIVER_BUG
979     glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
980     glVertexPointer(3, GL_FLOAT, 0, 0);
981     glDrawArrays(GL_TRIANGLE_FAN, 0, 0);
982 #endif
983     pointvertex_gl_array(m_array.data());
984     glDrawArrays(m_mode, 0, GLsizei(m_array.size()));
985   }
986 };
987
988 class RenderablePointVector : public OpenGLRenderable
989 {
990   std::vector<PointVertex> m_vector;
991   const GLenum m_mode;
992 public:
993   RenderablePointVector(GLenum mode)
994     : m_mode(mode)
995   {
996   }
997
998   void render(RenderStateFlags state) const
999   {
1000     pointvertex_gl_array(&m_vector.front());
1001     glDrawArrays(m_mode, 0, GLsizei(m_vector.size()));
1002   }
1003
1004   std::size_t size() const
1005   {
1006     return m_vector.size();
1007   }
1008   bool empty() const
1009   {
1010     return m_vector.empty();
1011   }
1012   void clear()
1013   {
1014     m_vector.clear();
1015   }
1016   void reserve(std::size_t size)
1017   {
1018     m_vector.reserve(size);
1019   }
1020   void push_back(const PointVertex& point)
1021   {
1022     m_vector.push_back(point);
1023   }
1024 };
1025
1026
1027 class RenderableVertexBuffer : public OpenGLRenderable
1028 {
1029   const GLenum m_mode;
1030   const VertexBuffer<PointVertex>& m_vertices;
1031 public:
1032   RenderableVertexBuffer(GLenum mode, const VertexBuffer<PointVertex>& vertices)
1033     : m_mode(mode), m_vertices(vertices)
1034   {
1035   }
1036
1037   void render(RenderStateFlags state) const
1038   {
1039     pointvertex_gl_array(m_vertices.data());
1040     glDrawArrays(m_mode, 0, m_vertices.size());
1041   }
1042 };
1043
1044 class RenderableIndexBuffer : public OpenGLRenderable
1045 {
1046   const GLenum m_mode;
1047   const IndexBuffer& m_indices;
1048   const VertexBuffer<PointVertex>& m_vertices;
1049 public:
1050   RenderableIndexBuffer(GLenum mode, const IndexBuffer& indices, const VertexBuffer<PointVertex>& vertices)
1051     : m_mode(mode), m_indices(indices), m_vertices(vertices)
1052   {
1053   }
1054
1055   void render(RenderStateFlags state) const
1056   {
1057 #if 1
1058     pointvertex_gl_array(m_vertices.data());
1059     glDrawElements(m_mode, GLsizei(m_indices.size()), RenderIndexTypeID, m_indices.data());
1060 #else
1061     glBegin(m_mode);
1062     if(state & RENDER_COLOURARRAY != 0)
1063     {
1064       for(std::size_t i = 0; i < m_indices.size(); ++i)
1065       {
1066         glColor4ubv(&m_vertices[m_indices[i]].colour.r);
1067         glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
1068       }
1069     }
1070     else
1071     {
1072       for(std::size_t i = 0; i < m_indices.size(); ++i)
1073       {
1074         glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
1075       }
1076     }
1077     glEnd();
1078 #endif
1079   }
1080 };
1081
1082
1083 class RemapXYZ
1084 {
1085 public:
1086   static void set(Vertex3f& vertex, float x, float y, float z)
1087   {
1088     vertex.x() = x;
1089     vertex.y() = y;
1090     vertex.z() = z;
1091   }
1092 };
1093
1094 class RemapYZX
1095 {
1096 public:
1097   static void set(Vertex3f& vertex, float x, float y, float z)
1098   {
1099     vertex.x() = z;
1100     vertex.y() = x;
1101     vertex.z() = y;
1102   }
1103 };
1104
1105 class RemapZXY
1106 {
1107 public:
1108   static void set(Vertex3f& vertex, float x, float y, float z)
1109   {
1110     vertex.x() = y;
1111     vertex.y() = z;
1112     vertex.z() = x;
1113   }
1114 };
1115
1116 template<typename remap_policy>
1117 inline void draw_circle(const std::size_t segments, const float radius, PointVertex* vertices, remap_policy remap)
1118 {
1119   const double increment = c_pi / double(segments << 2);
1120
1121   std::size_t count = 0;
1122   float x = radius;
1123   float y = 0;
1124   while(count < segments)
1125   {
1126     PointVertex* i = vertices + count;
1127     PointVertex* j = vertices + ((segments << 1) - (count + 1));
1128
1129     PointVertex* k = i + (segments << 1);
1130     PointVertex* l = j + (segments << 1);
1131
1132     PointVertex* m = i + (segments << 2);
1133     PointVertex* n = j + (segments << 2);
1134     PointVertex* o = k + (segments << 2);
1135     PointVertex* p = l + (segments << 2);
1136
1137     remap_policy::set(i->vertex, x,-y, 0);
1138     remap_policy::set(k->vertex,-y,-x, 0);
1139     remap_policy::set(m->vertex,-x, y, 0);
1140     remap_policy::set(o->vertex, y, x, 0);
1141
1142     ++count;
1143
1144     {
1145       const double theta = increment * count;
1146       x = static_cast<float>(radius * cos(theta));
1147       y = static_cast<float>(radius * sin(theta));
1148     }
1149
1150     remap_policy::set(j->vertex, y,-x, 0);
1151     remap_policy::set(l->vertex,-x,-y, 0);
1152     remap_policy::set(n->vertex,-y, x, 0);
1153     remap_policy::set(p->vertex, x, y, 0);
1154   }
1155 }
1156
1157 #if 0
1158 class PointVertexArrayIterator
1159 {
1160   PointVertex* m_point;
1161 public:
1162   PointVertexArrayIterator(PointVertex* point)
1163     : m_point(point)
1164   {
1165   }
1166   PointVertexArrayIterator& operator++()
1167   {
1168     ++m_point;
1169     return *this;
1170   }
1171   PointVertexArrayIterator operator++(int)
1172   {
1173     PointVertexArrayIterator tmp(*this);
1174     ++m_point;
1175     return tmp;
1176   }
1177   Vertex3f& operator*()
1178   {
1179     return m_point.vertex;
1180   }
1181   Vertex3f* operator->()
1182   {
1183     return &(operator*());
1184   }
1185 }
1186
1187 template<typename remap_policy, typename iterator_type
1188 inline void draw_circle(const std::size_t segments, const float radius, iterator_type start, remap_policy remap)
1189 {
1190   const float increment = c_pi / (double)(segments << 2);
1191
1192   std::size_t count = 0;
1193   iterator_type pxpy(start);
1194   iterator_type pypx(pxpy + (segments << 1));
1195   iterator_type pynx(pxpy + (segments << 1));
1196   iterator_type nxpy(pypx + (segments << 1));
1197   iterator_type nxny(pypx + (segments << 1));
1198   iterator_type nynx(nxpy + (segments << 1));
1199   iterator_type nypx(nxpy + (segments << 1));
1200   iterator_type pxny(start);
1201   while(count < segments)
1202   {
1203     const float theta = increment * count;
1204     const float x = radius * cos(theta);
1205     const float y = radius * sin(theta);
1206
1207     remap_policy::set((*pxpy), x, y, 0);
1208     remap_policy::set((*pxny), x,-y, 0);
1209     remap_policy::set((*nxpy),-x, y, 0);
1210     remap_policy::set((*nxny),-x,-y, 0);
1211
1212     remap_policy::set((*pypx), y, x, 0);
1213     remap_policy::set((*pynx), y,-x, 0);
1214     remap_policy::set((*nypx),-y, x, 0);
1215     remap_policy::set((*nynx),-y,-x, 0);
1216   }
1217 }
1218
1219 template<typename remap_policy, typename iterator_type
1220 inline void draw_semicircle(const std::size_t segments, const float radius, iterator_type start, remap_policy remap)
1221 {
1222   const float increment = c_pi / (double)(segments << 2);
1223
1224   std::size_t count = 0;
1225   iterator_type pxpy(start);
1226   iterator_type pypx(pxpy + (segments << 1));
1227   iterator_type pynx(pxpy + (segments << 1));
1228   iterator_type nxpy(pypx + (segments << 1));
1229   iterator_type nxny(pypx + (segments << 1));
1230   iterator_type nynx(nxpy + (segments << 1));
1231   iterator_type nypx(nxpy + (segments << 1));
1232   iterator_type pxny(start);
1233   while(count < segments)
1234   {
1235     const float theta = increment * count;
1236     const float x = radius * cos(theta);
1237     const float y = radius * sin(theta);
1238
1239     remap_policy::set((*pxpy), x, y, 0);
1240     remap_policy::set((*pxny), x,-y, 0);
1241     remap_policy::set((*nxpy),-x, y, 0);
1242     remap_policy::set((*nxny),-x,-y, 0);
1243
1244     //remap_policy::set((*pypx), y, x, 0);
1245     //remap_policy::set((*pynx), y,-x, 0);
1246     //remap_policy::set((*nypx),-y, x, 0);
1247     //remap_policy::set((*nynx),-y,-x, 0);
1248   }
1249 }
1250
1251
1252 #endif
1253
1254 inline void draw_quad(const float radius, PointVertex* quad)
1255 {
1256   (*quad++).vertex = Vertex3f(-radius, radius, 0);
1257   (*quad++).vertex = Vertex3f(radius, radius, 0);
1258   (*quad++).vertex = Vertex3f(radius, -radius, 0);
1259   (*quad++).vertex = Vertex3f(-radius, -radius, 0);
1260 }
1261
1262 inline void draw_cube(const float radius, PointVertex* cube)
1263 {
1264   (*cube++).vertex = Vertex3f(-radius, -radius, -radius);
1265   (*cube++).vertex = Vertex3f(radius, -radius, -radius);
1266   (*cube++).vertex = Vertex3f(-radius, radius, -radius);
1267   (*cube++).vertex = Vertex3f(radius, radius, -radius);
1268   (*cube++).vertex = Vertex3f(-radius, -radius, radius);
1269   (*cube++).vertex = Vertex3f(radius, -radius, radius);
1270   (*cube++).vertex = Vertex3f(-radius, radius, radius);
1271   (*cube++).vertex = Vertex3f(radius, radius, radius);
1272 }
1273
1274
1275 /// \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.
1276 inline void ArbitraryMeshTriangle_calcTangents(const ArbitraryMeshVertex& a, const ArbitraryMeshVertex& b, const ArbitraryMeshVertex& c, Vector3& s, Vector3& t)
1277 {
1278   s = Vector3(0, 0, 0);
1279   t = Vector3(0, 0, 0);
1280   {
1281     Vector3 cross(
1282       vector3_cross(
1283         vector3_subtracted(
1284           Vector3(b.vertex.x(), b.texcoord.s(), b.texcoord.t()),
1285           Vector3(a.vertex.x(), a.texcoord.s(), a.texcoord.t())
1286         ),
1287         vector3_subtracted(
1288           Vector3(c.vertex.x(), c.texcoord.s(), c.texcoord.t()),
1289           Vector3(a.vertex.x(), a.texcoord.s(), a.texcoord.t())
1290         )
1291       )
1292     );
1293
1294     if(fabs(cross.x()) > 0.000001f)
1295     {
1296       s.x() = -cross.y() / cross.x();
1297     }
1298
1299     if(fabs(cross.x()) > 0.000001f)
1300     {
1301       t.x() = -cross.z() / cross.x();
1302     }
1303   }
1304
1305   {
1306     Vector3 cross(
1307       vector3_cross(
1308         vector3_subtracted(
1309           Vector3(b.vertex.y(), b.texcoord.s(), b.texcoord.t()),
1310           Vector3(a.vertex.y(), a.texcoord.s(), a.texcoord.t())
1311         ),
1312         vector3_subtracted(
1313           Vector3(c.vertex.y(), c.texcoord.s(), c.texcoord.t()),
1314           Vector3(a.vertex.y(), a.texcoord.s(), a.texcoord.t())
1315         )
1316       )
1317     );
1318
1319     if(fabs(cross.x()) > 0.000001f)
1320     {
1321       s.y() = -cross.y() / cross.x();
1322     }
1323
1324     if(fabs(cross.x()) > 0.000001f)
1325     {
1326       t.y() = -cross.z() / cross.x();
1327     }
1328   }
1329
1330   {
1331     Vector3 cross(
1332       vector3_cross(
1333         vector3_subtracted(
1334           Vector3(b.vertex.z(), b.texcoord.s(), b.texcoord.t()),
1335           Vector3(a.vertex.z(), a.texcoord.s(), a.texcoord.t())
1336         ),
1337         vector3_subtracted(
1338           Vector3(c.vertex.z(), c.texcoord.s(), c.texcoord.t()),
1339           Vector3(a.vertex.z(), a.texcoord.s(), a.texcoord.t())
1340         )
1341       )
1342     );
1343
1344     if(fabs(cross.x()) > 0.000001f)
1345     {
1346       s.z() = -cross.y() / cross.x();
1347     }
1348
1349     if(fabs(cross.x()) > 0.000001f)
1350     {
1351       t.z() = -cross.z() / cross.x();
1352     }
1353   }
1354 }
1355
1356 inline void ArbitraryMeshTriangle_sumTangents(ArbitraryMeshVertex& a, ArbitraryMeshVertex& b, ArbitraryMeshVertex& c)
1357 {
1358   Vector3 s, t;
1359
1360   ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
1361
1362   reinterpret_cast<Vector3&>(a.tangent) += s;
1363   reinterpret_cast<Vector3&>(b.tangent) += s;
1364   reinterpret_cast<Vector3&>(c.tangent) += s;
1365
1366   reinterpret_cast<Vector3&>(a.bitangent) += t;
1367   reinterpret_cast<Vector3&>(b.bitangent) += t;
1368   reinterpret_cast<Vector3&>(c.bitangent) += t;
1369 }
1370
1371
1372 #endif