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