2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #if !defined( INCLUDED_RENDER_H )
23 #define INCLUDED_RENDER_H
26 /// \brief High-level constructs for efficient OpenGL rendering.
31 #include "container/array.h"
32 #include "math/vector.h"
37 typedef unsigned int RenderIndex;
38 const GLenum RenderIndexTypeID = GL_UNSIGNED_INT;
40 /// \brief A resizable buffer of indices.
43 typedef std::vector<RenderIndex> Indices;
46 typedef Indices::iterator iterator;
47 typedef Indices::const_iterator const_iterator;
50 return m_data.begin();
52 const_iterator begin() const {
53 return m_data.begin();
58 const_iterator end() const {
63 return m_data.empty();
65 std::size_t size() const {
68 const RenderIndex* data() const {
69 return &( *m_data.begin() );
71 RenderIndex& operator[]( std::size_t index ){
74 const RenderIndex& operator[]( std::size_t index ) const {
80 void reserve( std::size_t max_indices ){
81 m_data.reserve( max_indices );
83 void insert( RenderIndex index ){
84 m_data.push_back( index );
86 void swap( IndexBuffer& other ){
87 std::swap( m_data, other.m_data );
93 /// \brief Swaps the values of \p self and \p other.
94 /// Overloads std::swap.
95 inline void swap( IndexBuffer& self, IndexBuffer& other ){
100 /// \brief A resizable buffer of vertices.
101 /// \param Vertex The vertex data type.
102 template<typename Vertex>
105 typedef typename std::vector<Vertex> Vertices;
108 typedef typename Vertices::iterator iterator;
109 typedef typename Vertices::const_iterator const_iterator;
112 return m_data.begin();
117 const_iterator begin() const {
118 return m_data.begin();
120 const_iterator end() const {
125 return m_data.empty();
127 RenderIndex size() const {
128 return RenderIndex( m_data.size() );
130 const Vertex* data() const {
131 return &( *m_data.begin() );
133 Vertex& operator[]( std::size_t index ){
134 return m_data[index];
136 const Vertex& operator[]( std::size_t index ) const {
137 return m_data[index];
143 void reserve( std::size_t max_vertices ){
144 m_data.reserve( max_vertices );
146 void push_back( const Vertex& vertex ){
147 m_data.push_back( vertex );
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
157 typedef VertexBuffer<Vertex> Vertices;
163 : m_left( 0 ), m_right( 0 ){
169 std::vector<bnode> m_btree;
174 RenderIndex find_or_insert( const Vertex& vertex ){
175 RenderIndex index = 0;
179 if ( vertex < m_data[index] ) {
180 bnode& node = m_btree[index];
181 if ( node.m_left != 0 ) {
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 );
193 if ( m_data[index] < vertex ) {
194 bnode& node = m_btree[index];
195 if ( node.m_right != 0 ) {
196 index = node.m_right;
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 );
212 UniqueVertexBuffer( Vertices& data )
213 : m_data( data ), m_prev0( 0 ), m_prev1( 0 ), m_prev2( 0 ){
216 typedef typename Vertices::const_iterator iterator;
218 iterator begin() const {
219 return m_data.begin();
221 iterator end() const {
225 std::size_t size() const {
226 return m_data.size();
228 const Vertex* data() const {
229 return &( *m_data.begin() );
231 Vertex& operator[]( std::size_t index ){
232 return m_data[index];
234 const Vertex& operator[]( std::size_t index ) const {
235 return m_data[index];
245 void reserve( std::size_t max_vertices ){
246 m_data.reserve( max_vertices );
247 m_btree.reserve( max_vertices );
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() );
257 if ( m_data[m_prev0] == vertex ) {
260 if ( m_prev1 != m_prev0 && m_data[m_prev1] == vertex ) {
263 if ( m_prev2 != m_prev0 && m_prev2 != m_prev1 && m_data[m_prev2] == vertex ) {
269 m_prev0 = find_or_insert( vertex );
276 /// \brief A 4-byte colour.
279 unsigned char r, g, b, a;
284 Colour4b( unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a )
285 : r( _r ), g( _g ), b( _b ), a( _a ){
289 const Colour4b colour_vertex( 0, 255, 0, 255 );
290 const Colour4b colour_selected( 0, 0, 255, 255 );
292 inline bool operator<( const Colour4b& self, const Colour4b& other ){
293 if ( self.r != other.r ) {
294 return self.r < other.r;
296 if ( self.g != other.g ) {
297 return self.g < other.g;
299 if ( self.b != other.b ) {
300 return self.b < other.b;
302 if ( self.a != other.a ) {
303 return self.a < other.a;
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;
312 inline bool operator!=( const Colour4b& self, const Colour4b& other ){
313 return !operator==( self, other );
316 /// \brief A 3-float vertex.
317 struct Vertex3f : public Vector3
322 Vertex3f( float _x, float _y, float _z )
323 : Vector3( _x, _y, _z ){
327 inline bool operator<( const Vertex3f& self, const Vertex3f& other ){
328 if ( self.x() != other.x() ) {
329 return self.x() < other.x();
331 if ( self.y() != other.y() ) {
332 return self.y() < other.y();
334 if ( self.z() != other.z() ) {
335 return self.z() < other.z();
340 inline bool operator==( const Vertex3f& self, const Vertex3f& other ){
341 return self.x() == other.x() && self.y() == other.y() && self.z() == other.z();
344 inline bool operator!=( const Vertex3f& self, const Vertex3f& other ){
345 return !operator==( self, other );
349 inline Vertex3f vertex3f_from_array( const float* array ){
350 return Vertex3f( array[0], array[1], array[2] );
353 inline float* vertex3f_to_array( Vertex3f& vertex ){
354 return reinterpret_cast<float*>( &vertex );
357 inline const float* vertex3f_to_array( const Vertex3f& vertex ){
358 return reinterpret_cast<const float*>( &vertex );
361 const Vertex3f vertex3f_identity( 0, 0, 0 );
363 inline Vertex3f vertex3f_for_vector3( const Vector3& vector3 ){
364 return Vertex3f( vector3.x(), vector3.y(), vector3.z() );
367 inline const Vector3& vertex3f_to_vector3( const Vertex3f& vertex ){
371 inline Vector3& vertex3f_to_vector3( Vertex3f& vertex ){
376 /// \brief A 3-float normal.
377 struct Normal3f : public Vector3
382 Normal3f( float _x, float _y, float _z )
383 : Vector3( _x, _y, _z ){
387 inline bool operator<( const Normal3f& self, const Normal3f& other ){
388 if ( self.x() != other.x() ) {
389 return self.x() < other.x();
391 if ( self.y() != other.y() ) {
392 return self.y() < other.y();
394 if ( self.z() != other.z() ) {
395 return self.z() < other.z();
400 inline bool operator==( const Normal3f& self, const Normal3f& other ){
401 return self.x() == other.x() && self.y() == other.y() && self.z() == other.z();
404 inline bool operator!=( const Normal3f& self, const Normal3f& other ){
405 return !operator==( self, other );
409 inline Normal3f normal3f_from_array( const float* array ){
410 return Normal3f( array[0], array[1], array[2] );
413 inline float* normal3f_to_array( Normal3f& normal ){
414 return reinterpret_cast<float*>( &normal );
417 inline const float* normal3f_to_array( const Normal3f& normal ){
418 return reinterpret_cast<const float*>( &normal );
421 inline Normal3f normal3f_for_vector3( const Vector3& vector3 ){
422 return Normal3f( vector3.x(), vector3.y(), vector3.z() );
425 inline const Vector3& normal3f_to_vector3( const Normal3f& normal ){
429 inline Vector3& normal3f_to_vector3( Normal3f& normal ){
434 /// \brief A 2-float texture-coordinate set.
435 struct TexCoord2f : public Vector2
440 TexCoord2f( float _s, float _t )
447 const float& s() const {
453 const float& t() const {
458 inline bool operator<( const TexCoord2f& self, const TexCoord2f& other ){
459 if ( self.s() != other.s() ) {
460 return self.s() < other.s();
462 if ( self.t() != other.t() ) {
463 return self.t() < other.t();
468 inline bool operator==( const TexCoord2f& self, const TexCoord2f& other ){
469 return self.s() == other.s() && self.t() == other.t();
472 inline bool operator!=( const TexCoord2f& self, const TexCoord2f& other ){
473 return !operator==( self, other );
477 inline float* texcoord2f_to_array( TexCoord2f& texcoord ){
478 return reinterpret_cast<float*>( &texcoord );
481 inline const float* texcoord2f_to_array( const TexCoord2f& texcoord ){
482 return reinterpret_cast<const float*>( &texcoord );
485 inline const TexCoord2f& texcoord2f_from_array( const float* array ){
486 return *reinterpret_cast<const TexCoord2f*>( array );
489 inline TexCoord2f texcoord2f_for_vector2( const Vector2& vector2 ){
490 return TexCoord2f( vector2.x(), vector2.y() );
493 inline const Vector2& texcoord2f_to_vector2( const TexCoord2f& vertex ){
497 inline Vector2& texcoord2f_to_vector2( TexCoord2f& vertex ){
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 ) ) );
506 enum UnitSphereOctant
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,
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 )
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 ){
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() );
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 );
556 enum UnitSphereSextant
558 UNITSPHERESEXTANT_XYZ = 0,
559 UNITSPHERESEXTANT_XZY = 1,
560 UNITSPHERESEXTANT_YXZ = 2,
561 UNITSPHERESEXTANT_YZX = 3,
562 UNITSPHERESEXTANT_ZXY = 4,
563 UNITSPHERESEXTANT_ZYX = 5,
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 ){
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;
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 ){
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() );
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 );
613 const std::size_t c_quantise_normal = 1 << 6;
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 ){
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 );
623 return normal3f_normalised( Normal3f(
624 static_cast<float>( c_quantise_normal - zbits - ybits ),
625 static_cast<float>( ybits ),
626 static_cast<float>( zbits )
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 );
643 double longditude, latitude;
645 spherical_t( double _longditude, double _latitude )
646 : longditude( _longditude ), latitude( _latitude ){
653 phi = acos((2 * V) - 1);
656 V = (cos(phi) + 1) / 2;
659 longitude = atan(y / x);
662 struct uniformspherical_t
666 uniformspherical_t( double U_, double V_ )
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() ) );
676 inline Normal3f normal3f_from_spherical( const spherical_t& spherical ){
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 ) )
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 );
688 inline spherical_t spherical_from_uniformspherical( const uniformspherical_t& uniformspherical ){
689 return spherical_t( c_2pi * uniformspherical.U, acos( ( 2 * uniformspherical.V ) - 1 ) );
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);
697 inline Normal3f normal3f_from_uniformspherical( const uniformspherical_t& uniformspherical ){
698 return normal3f_from_spherical( spherical_from_uniformspherical( uniformspherical ) );
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 );
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 );
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 ) );
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 ) );
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 ) );
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));
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 ) );
737 /// \brief Standard vertex type for lines and points.
745 PointVertex( Vertex3f _vertex )
746 : colour( Colour4b( 255, 255, 255, 255 ) ), vertex( _vertex ){
748 PointVertex( Vertex3f _vertex, Colour4b _colour )
749 : colour( _colour ), vertex( _vertex ){
753 inline bool operator<( const PointVertex& self, const PointVertex& other ){
754 if ( self.vertex != other.vertex ) {
755 return self.vertex < other.vertex;
757 if ( self.colour != other.colour ) {
758 return self.colour < other.colour;
763 inline bool operator==( const PointVertex& self, const PointVertex& other ){
764 return self.colour == other.colour && self.vertex == other.vertex;
767 inline bool operator!=( const PointVertex& self, const PointVertex& other ){
768 return !operator==( self, other );
771 /// \brief Standard vertex type for lit/textured meshes.
772 struct ArbitraryMeshVertex
780 ArbitraryMeshVertex() : tangent( 0, 0, 0 ), bitangent( 0, 0, 0 ){
782 ArbitraryMeshVertex( Vertex3f _vertex, Normal3f _normal, TexCoord2f _texcoord )
783 : texcoord( _texcoord ), normal( _normal ), vertex( _vertex ), tangent( 0, 0, 0 ), bitangent( 0, 0, 0 ){
787 inline bool operator<( const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other ){
788 if ( self.texcoord != other.texcoord ) {
789 return self.texcoord < other.texcoord;
791 if ( self.normal != other.normal ) {
792 return self.normal < other.normal;
794 if ( self.vertex != other.vertex ) {
795 return self.vertex < other.vertex;
800 inline bool operator==( const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other ){
801 return self.texcoord == other.texcoord && self.normal == other.normal && self.vertex == other.vertex;
804 inline bool operator!=( const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other ){
805 return !operator==( self, other );
808 const float c_quantise_vertex = 1.f / static_cast<float>( 1 << 3 );
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 );
815 const float c_quantise_texcoord = 1.f / static_cast<float>( 1 << 8 );
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 ) );
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 );
829 class RenderablePointArray : public OpenGLRenderable
831 const Array<PointVertex>& m_array;
834 RenderablePointArray( const Array<PointVertex>& array, GLenum mode )
835 : m_array( array ), m_mode( mode ){
837 void render( RenderStateFlags state ) const {
838 #define NV_DRIVER_BUG 1
840 glColorPointer( 4, GL_UNSIGNED_BYTE, 0, 0 );
841 glVertexPointer( 3, GL_FLOAT, 0, 0 );
842 glDrawArrays( GL_TRIANGLE_FAN, 0, 0 );
844 pointvertex_gl_array( m_array.data() );
845 glDrawArrays( m_mode, 0, GLsizei( m_array.size() ) );
849 class RenderablePointVector : public OpenGLRenderable
851 std::vector<PointVertex> m_vector;
854 RenderablePointVector( GLenum mode )
858 void render( RenderStateFlags state ) const {
859 pointvertex_gl_array( &m_vector.front() );
860 glDrawArrays( m_mode, 0, GLsizei( m_vector.size() ) );
863 std::size_t size() const {
864 return m_vector.size();
867 return m_vector.empty();
872 void reserve( std::size_t size ){
873 m_vector.reserve( size );
875 void push_back( const PointVertex& point ){
876 m_vector.push_back( point );
881 class RenderableVertexBuffer : public OpenGLRenderable
884 const VertexBuffer<PointVertex>& m_vertices;
886 RenderableVertexBuffer( GLenum mode, const VertexBuffer<PointVertex>& vertices )
887 : m_mode( mode ), m_vertices( vertices ){
890 void render( RenderStateFlags state ) const {
891 pointvertex_gl_array( m_vertices.data() );
892 glDrawArrays( m_mode, 0, m_vertices.size() );
896 class RenderableIndexBuffer : public OpenGLRenderable
899 const IndexBuffer& m_indices;
900 const VertexBuffer<PointVertex>& m_vertices;
902 RenderableIndexBuffer( GLenum mode, const IndexBuffer& indices, const VertexBuffer<PointVertex>& vertices )
903 : m_mode( mode ), m_indices( indices ), m_vertices( vertices ){
906 void render( RenderStateFlags state ) const {
908 pointvertex_gl_array( m_vertices.data() );
909 glDrawElements( m_mode, GLsizei( m_indices.size() ), RenderIndexTypeID, m_indices.data() );
912 if ( state & RENDER_COLOURARRAY != 0 ) {
913 for ( std::size_t i = 0; i < m_indices.size(); ++i )
915 glColor4ubv( &m_vertices[m_indices[i]].colour.r );
916 glVertex3fv( &m_vertices[m_indices[i]].vertex.x );
921 for ( std::size_t i = 0; i < m_indices.size(); ++i )
923 glVertex3fv( &m_vertices[m_indices[i]].vertex.x );
935 static void set( Vertex3f& vertex, float x, float y, float z ){
945 static void set( Vertex3f& vertex, float x, float y, float z ){
955 static void set( Vertex3f& vertex, float x, float y, float z ){
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);
966 std::size_t count = 0;
969 while ( count < segments )
971 PointVertex* i = vertices + count;
972 PointVertex* j = vertices + ( ( segments << 1 ) - ( count + 1 ) );
974 PointVertex* k = i + ( segments << 1 );
975 PointVertex* l = j + ( segments << 1 );
977 PointVertex* m = i + ( segments << 2 );
978 PointVertex* n = j + ( segments << 2 );
979 PointVertex* o = k + ( segments << 2 );
980 PointVertex* p = l + ( segments << 2 );
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 );
990 const double theta = increment * count;
991 x = static_cast<float>( radius * cos( theta ) );
992 y = static_cast<float>( radius * sin( theta ) );
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 );
1003 class PointVertexArrayIterator
1005 PointVertex* m_point;
1007 PointVertexArrayIterator( PointVertex* point )
1010 PointVertexArrayIterator& operator++(){
1014 PointVertexArrayIterator operator++( int ){
1015 PointVertexArrayIterator tmp( *this );
1019 Vertex3f& operator*(){
1020 return m_point.vertex;
1022 Vertex3f* operator->(){
1023 return &( operator*() );
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 );
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 )
1042 const float theta = increment * count;
1043 const float x = radius * cos( theta );
1044 const float y = radius * sin( theta );
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 );
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 );
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 )
1061 const float increment = c_pi / (double)( segments << 2 );
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 )
1074 const float theta = increment * count;
1075 const float x = radius * cos( theta );
1076 const float y = radius * sin( theta );
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 );
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);
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 );
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 );
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 );
1120 Vector3( b.vertex.x(), b.texcoord.s(), b.texcoord.t() ),
1121 Vector3( a.vertex.x(), a.texcoord.s(), a.texcoord.t() )
1124 Vector3( c.vertex.x(), c.texcoord.s(), c.texcoord.t() ),
1125 Vector3( a.vertex.x(), a.texcoord.s(), a.texcoord.t() )
1130 if ( fabs( cross.x() ) > 0.000001f ) {
1131 s.x() = -cross.y() / cross.x();
1134 if ( fabs( cross.x() ) > 0.000001f ) {
1135 t.x() = -cross.z() / cross.x();
1143 Vector3( b.vertex.y(), b.texcoord.s(), b.texcoord.t() ),
1144 Vector3( a.vertex.y(), a.texcoord.s(), a.texcoord.t() )
1147 Vector3( c.vertex.y(), c.texcoord.s(), c.texcoord.t() ),
1148 Vector3( a.vertex.y(), a.texcoord.s(), a.texcoord.t() )
1153 if ( fabs( cross.x() ) > 0.000001f ) {
1154 s.y() = -cross.y() / cross.x();
1157 if ( fabs( cross.x() ) > 0.000001f ) {
1158 t.y() = -cross.z() / cross.x();
1166 Vector3( b.vertex.z(), b.texcoord.s(), b.texcoord.t() ),
1167 Vector3( a.vertex.z(), a.texcoord.s(), a.texcoord.t() )
1170 Vector3( c.vertex.z(), c.texcoord.s(), c.texcoord.t() ),
1171 Vector3( a.vertex.z(), a.texcoord.s(), a.texcoord.t() )
1176 if ( fabs( cross.x() ) > 0.000001f ) {
1177 s.z() = -cross.y() / cross.x();
1180 if ( fabs( cross.x() ) > 0.000001f ) {
1181 t.z() = -cross.z() / cross.x();
1186 inline void ArbitraryMeshTriangle_sumTangents( ArbitraryMeshVertex& a, ArbitraryMeshVertex& b, ArbitraryMeshVertex& c ){
1189 ArbitraryMeshTriangle_calcTangents( a, b, c, s, t );
1191 reinterpret_cast<Vector3&>( a.tangent ) += s;
1192 reinterpret_cast<Vector3&>( b.tangent ) += s;
1193 reinterpret_cast<Vector3&>( c.tangent ) += s;
1195 reinterpret_cast<Vector3&>( a.bitangent ) += t;
1196 reinterpret_cast<Vector3&>( b.bitangent ) += t;
1197 reinterpret_cast<Vector3&>( c.bitangent ) += t;