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;
51 return m_data.begin();
53 const_iterator begin() const
55 return m_data.begin();
61 const_iterator end() const
68 return m_data.empty();
70 std::size_t size() const
74 const RenderIndex* data() const
76 return &(*m_data.begin());
78 RenderIndex& operator[](std::size_t index)
82 const RenderIndex& operator[](std::size_t index) const
90 void reserve(std::size_t max_indices)
92 m_data.reserve(max_indices);
94 void insert(RenderIndex index)
96 m_data.push_back(index);
98 void swap(IndexBuffer& other)
100 std::swap(m_data, m_data);
106 /// \brief Swaps the values of \p self and \p other.
107 /// Overloads std::swap.
108 inline void swap(IndexBuffer& self, IndexBuffer& other)
114 /// \brief A resizable buffer of vertices.
115 /// \param Vertex The vertex data type.
116 template<typename Vertex>
119 typedef typename std::vector<Vertex> Vertices;
122 typedef typename Vertices::iterator iterator;
123 typedef typename Vertices::const_iterator const_iterator;
127 return m_data.begin();
133 const_iterator begin() const
135 return m_data.begin();
137 const_iterator end() const
144 return m_data.empty();
146 RenderIndex size() const
148 return RenderIndex(m_data.size());
150 const Vertex* data() const
152 return &(*m_data.begin());
154 Vertex& operator[](std::size_t index)
156 return m_data[index];
158 const Vertex& operator[](std::size_t index) const
160 return m_data[index];
167 void reserve(std::size_t max_vertices)
169 m_data.reserve(max_vertices);
171 void push_back(const Vertex& vertex)
173 m_data.push_back(vertex);
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
183 typedef VertexBuffer<Vertex> Vertices;
189 : m_left(0), m_right(0)
196 std::vector<bnode> m_btree;
201 const RenderIndex find_or_insert(const Vertex& vertex)
203 RenderIndex index = 0;
207 if(vertex < m_data[index])
209 bnode& node = m_btree[index];
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);
223 if(m_data[index] < vertex)
225 bnode& node = m_btree[index];
226 if(node.m_right != 0)
228 index = node.m_right;
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);
244 UniqueVertexBuffer(Vertices& data)
245 : m_data(data), m_prev0(0), m_prev1(0), m_prev2(0)
249 typedef typename Vertices::const_iterator iterator;
251 iterator begin() const
253 return m_data.begin();
260 std::size_t size() const
262 return m_data.size();
264 const Vertex* data() const
266 return &(*m_data.begin());
268 Vertex& operator[](std::size_t index)
270 return m_data[index];
272 const Vertex& operator[](std::size_t index) const
274 return m_data[index];
285 void reserve(std::size_t max_vertices)
287 m_data.reserve(max_vertices);
288 m_btree.reserve(max_vertices);
290 /// \brief Returns the index of the element equal to \p vertex.
291 RenderIndex insert(const Vertex& vertex)
295 m_data.push_back(vertex);
296 m_btree.push_back(bnode());
300 if(m_data[m_prev0] == vertex)
302 if(m_prev1 != m_prev0 && m_data[m_prev1] == vertex)
304 if(m_prev2 != m_prev0 && m_prev2 != m_prev1 && m_data[m_prev2] == vertex)
309 m_prev0 = find_or_insert(vertex);
316 /// \brief A 4-byte colour.
319 unsigned char r, g, b, a;
325 Colour4b(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a)
326 : r(_r), g(_g), b(_b), a(_a)
331 const Colour4b colour_vertex(0, 255, 0, 255);
332 const Colour4b colour_selected(0, 0, 255, 255);
334 inline bool operator<(const Colour4b& self, const Colour4b& other)
336 if(self.r != other.r)
338 return self.r < other.r;
340 if(self.g != other.g)
342 return self.g < other.g;
344 if(self.b != other.b)
346 return self.b < other.b;
348 if(self.a != other.a)
350 return self.a < other.a;
355 inline bool operator==(const Colour4b& self, const Colour4b& other)
357 return self.r == other.r && self.g == other.g && self.b == other.b && self.a == other.a;
360 inline bool operator!=(const Colour4b& self, const Colour4b& other)
362 return !operator==(self, other);
365 /// \brief A 3-float vertex.
366 struct Vertex3f : public Vector3
372 Vertex3f(float _x, float _y, float _z)
373 : Vector3(_x, _y, _z)
378 inline bool operator<(const Vertex3f& self, const Vertex3f& other)
380 if(self.x() != other.x())
382 return self.x() < other.x();
384 if(self.y() != other.y())
386 return self.y() < other.y();
388 if(self.z() != other.z())
390 return self.z() < other.z();
395 inline bool operator==(const Vertex3f& self, const Vertex3f& other)
397 return self.x() == other.x() && self.y() == other.y() && self.z() == other.z();
400 inline bool operator!=(const Vertex3f& self, const Vertex3f& other)
402 return !operator==(self, other);
406 inline Vertex3f vertex3f_from_array(const float* array)
408 return Vertex3f(array[0], array[1], array[2]);
411 inline float* vertex3f_to_array(Vertex3f& vertex)
413 return reinterpret_cast<float*>(&vertex);
416 inline const float* vertex3f_to_array(const Vertex3f& vertex)
418 return reinterpret_cast<const float*>(&vertex);
421 const Vertex3f vertex3f_identity(0, 0, 0);
423 inline Vertex3f vertex3f_for_vector3(const Vector3& vector3)
425 return Vertex3f(vector3.x(), vector3.y(), vector3.z());
428 inline const Vector3& vertex3f_to_vector3(const Vertex3f& vertex)
433 inline Vector3& vertex3f_to_vector3(Vertex3f& vertex)
439 /// \brief A 3-float normal.
440 struct Normal3f : public Vector3
446 Normal3f(float _x, float _y, float _z)
447 : Vector3(_x, _y, _z)
452 inline bool operator<(const Normal3f& self, const Normal3f& other)
454 if(self.x() != other.x())
456 return self.x() < other.x();
458 if(self.y() != other.y())
460 return self.y() < other.y();
462 if(self.z() != other.z())
464 return self.z() < other.z();
469 inline bool operator==(const Normal3f& self, const Normal3f& other)
471 return self.x() == other.x() && self.y() == other.y() && self.z() == other.z();
474 inline bool operator!=(const Normal3f& self, const Normal3f& other)
476 return !operator==(self, other);
480 inline Normal3f normal3f_from_array(const float* array)
482 return Normal3f(array[0], array[1], array[2]);
485 inline float* normal3f_to_array(Normal3f& normal)
487 return reinterpret_cast<float*>(&normal);
490 inline const float* normal3f_to_array(const Normal3f& normal)
492 return reinterpret_cast<const float*>(&normal);
495 inline Normal3f normal3f_for_vector3(const Vector3& vector3)
497 return Normal3f(vector3.x(), vector3.y(), vector3.z());
500 inline const Vector3& normal3f_to_vector3(const Normal3f& normal)
505 inline Vector3& normal3f_to_vector3(Normal3f& normal)
511 /// \brief A 2-float texture-coordinate set.
512 struct TexCoord2f : public Vector2
518 TexCoord2f(float _s, float _t)
527 const float& s() const
535 const float& t() const
541 inline bool operator<(const TexCoord2f& self, const TexCoord2f& other)
543 if(self.s() != other.s())
545 return self.s() < other.s();
547 if(self.t() != other.t())
549 return self.t() < other.t();
554 inline bool operator==(const TexCoord2f& self, const TexCoord2f& other)
556 return self.s() == other.s() && self.t() == other.t();
559 inline bool operator!=(const TexCoord2f& self, const TexCoord2f& other)
561 return !operator==(self, other);
565 inline float* texcoord2f_to_array(TexCoord2f& texcoord)
567 return reinterpret_cast<float*>(&texcoord);
570 inline const float* texcoord2f_to_array(const TexCoord2f& texcoord)
572 return reinterpret_cast<const float*>(&texcoord);
575 inline const TexCoord2f& texcoord2f_from_array(const float* array)
577 return *reinterpret_cast<const TexCoord2f*>(array);
580 inline TexCoord2f texcoord2f_for_vector2(const Vector2& vector2)
582 return TexCoord2f(vector2.x(), vector2.y());
585 inline const Vector2& texcoord2f_to_vector2(const TexCoord2f& vertex)
590 inline Vector2& texcoord2f_to_vector2(TexCoord2f& vertex)
595 /// \brief Returns \p normal rescaled to be unit-length.
596 inline Normal3f normal3f_normalised(const Normal3f& normal)
598 return normal3f_for_vector3(vector3_normalised(normal3f_to_vector3(normal)));
601 enum UnitSphereOctant
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,
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)
616 return static_cast<UnitSphereOctant>(
617 ((normal.x() > 0) << 0) | ((normal.y() > 0) << 1) | ((normal.z() > 0) << 2)
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)
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());
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)
651 return normal3f_fold_octant(normal, octant);
654 enum UnitSphereSextant
656 UNITSPHERESEXTANT_XYZ = 0,
657 UNITSPHERESEXTANT_XZY = 1,
658 UNITSPHERESEXTANT_YXZ = 2,
659 UNITSPHERESEXTANT_YZX = 3,
660 UNITSPHERESEXTANT_ZXY = 4,
661 UNITSPHERESEXTANT_ZYX = 5,
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)
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;
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)
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());
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)
711 return normal3f_fold_sextant(normal, sextant);
714 const std::size_t c_quantise_normal = 1 << 6;
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)
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);
725 return normal3f_normalised(Normal3f(
726 static_cast<float>(c_quantise_normal - zbits - ybits),
727 static_cast<float>(ybits),
728 static_cast<float>(zbits)
732 /// \brief Returns \p normal quantised by compressing and then decompressing its representation.
733 inline Normal3f normal3f_quantised_custom(const Normal3f& normal)
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);
746 double longditude, latitude;
748 spherical_t(double _longditude, double _latitude)
749 : longditude(_longditude), latitude(_latitude)
757 phi = acos((2 * V) - 1);
760 V = (cos(phi) + 1) / 2;
763 longitude = atan(y / x);
766 struct uniformspherical_t
770 uniformspherical_t(double U_, double V_)
777 inline spherical_t spherical_from_normal3f(const Normal3f& normal)
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()));
782 inline Normal3f normal3f_from_spherical(const spherical_t& spherical)
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))
791 inline uniformspherical_t uniformspherical_from_spherical(const spherical_t& spherical)
793 return uniformspherical_t(spherical.longditude * c_inv_2pi, (cos(spherical.latitude) + 1) * 0.5);
796 inline spherical_t spherical_from_uniformspherical(const uniformspherical_t& uniformspherical)
798 return spherical_t(c_2pi * uniformspherical.U, acos((2 * uniformspherical.V) - 1));
801 inline uniformspherical_t uniformspherical_from_normal3f(const Normal3f& normal)
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);
807 inline Normal3f normal3f_from_uniformspherical(const uniformspherical_t& uniformspherical)
809 return normal3f_from_spherical(spherical_from_uniformspherical(uniformspherical));
812 /// \brief Returns a single-precision \p component quantised to \p precision.
813 inline float float_quantise(float component, float precision)
815 return float_snapped(component, precision);
818 /// \brief Returns a double-precision \p component quantised to \p precision.
819 inline double double_quantise(double component, double precision)
821 return float_snapped(component, precision);
824 inline spherical_t spherical_quantised(const spherical_t& spherical, float snap)
826 return spherical_t(double_quantise(spherical.longditude, snap), double_quantise(spherical.latitude, snap));
829 inline uniformspherical_t uniformspherical_quantised(const uniformspherical_t& uniformspherical, float snap)
831 return uniformspherical_t(double_quantise(uniformspherical.U, snap), double_quantise(uniformspherical.V, snap));
834 /// \brief Returns a \p vertex quantised to \p precision.
835 inline Vertex3f vertex3f_quantised(const Vertex3f& vertex, float precision)
837 return Vertex3f(float_quantise(vertex.x(), precision), float_quantise(vertex.y(), precision), float_quantise(vertex.z(), precision));
840 /// \brief Returns a \p normal quantised to a fixed precision.
841 inline Normal3f normal3f_quantised(const Normal3f& normal)
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));
849 /// \brief Returns a \p texcoord quantised to \p precision.
850 inline TexCoord2f texcoord2f_quantised(const TexCoord2f& texcoord, float precision)
852 return TexCoord2f(float_quantise(texcoord.s(), precision), float_quantise(texcoord.t(), precision));
855 /// \brief Standard vertex type for lines and points.
864 PointVertex(Vertex3f _vertex)
865 : colour(Colour4b(255, 255, 255, 255)), vertex(_vertex)
868 PointVertex(Vertex3f _vertex, Colour4b _colour)
869 : colour(_colour), vertex(_vertex)
874 inline bool operator<(const PointVertex& self, const PointVertex& other)
876 if(self.vertex != other.vertex)
878 return self.vertex < other.vertex;
880 if(self.colour != other.colour)
882 return self.colour < other.colour;
887 inline bool operator==(const PointVertex& self, const PointVertex& other)
889 return self.colour == other.colour && self.vertex == other.vertex;
892 inline bool operator!=(const PointVertex& self, const PointVertex& other)
894 return !operator==(self, other);
897 /// \brief Standard vertex type for lit/textured meshes.
898 struct ArbitraryMeshVertex
906 ArbitraryMeshVertex() : tangent(0, 0, 0), bitangent(0, 0, 0)
909 ArbitraryMeshVertex(Vertex3f _vertex, Normal3f _normal, TexCoord2f _texcoord)
910 : texcoord(_texcoord), normal(_normal), vertex(_vertex), tangent(0, 0, 0), bitangent(0, 0, 0)
915 inline bool operator<(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
917 if(self.texcoord != other.texcoord)
919 return self.texcoord < other.texcoord;
921 if(self.normal != other.normal)
923 return self.normal < other.normal;
925 if(self.vertex != other.vertex)
927 return self.vertex < other.vertex;
932 inline bool operator==(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
934 return self.texcoord == other.texcoord && self.normal == other.normal && self.vertex == other.vertex;
937 inline bool operator!=(const ArbitraryMeshVertex& self, const ArbitraryMeshVertex& other)
939 return !operator==(self, other);
942 const float c_quantise_vertex = 1.f / static_cast<float>(1 << 3);
944 /// \brief Returns \p v with vertex quantised to a fixed precision.
945 inline PointVertex pointvertex_quantised(const PointVertex& v)
947 return PointVertex(vertex3f_quantised(v.vertex, c_quantise_vertex), v.colour);
950 const float c_quantise_texcoord = 1.f / static_cast<float>(1 << 8);
952 /// \brief Returns \p v with vertex, normal and texcoord quantised to a fixed precision.
953 inline ArbitraryMeshVertex arbitrarymeshvertex_quantised(const ArbitraryMeshVertex& v)
955 return ArbitraryMeshVertex(vertex3f_quantised(v.vertex, c_quantise_vertex), normal3f_quantised(v.normal), texcoord2f_quantised(v.texcoord, c_quantise_texcoord));
959 /// \brief Sets up the OpenGL colour and vertex arrays for \p array.
960 inline void pointvertex_gl_array(const PointVertex* array)
962 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &array->colour);
963 glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &array->vertex);
966 class RenderablePointArray : public OpenGLRenderable
968 const Array<PointVertex>& m_array;
971 RenderablePointArray(const Array<PointVertex>& array, GLenum mode)
972 : m_array(array), m_mode(mode)
975 void render(RenderStateFlags state) const
977 #define NV_DRIVER_BUG 1
979 glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
980 glVertexPointer(3, GL_FLOAT, 0, 0);
981 glDrawArrays(GL_TRIANGLE_FAN, 0, 0);
983 pointvertex_gl_array(m_array.data());
984 glDrawArrays(m_mode, 0, GLsizei(m_array.size()));
988 class RenderablePointVector : public OpenGLRenderable
990 std::vector<PointVertex> m_vector;
993 RenderablePointVector(GLenum mode)
998 void render(RenderStateFlags state) const
1000 pointvertex_gl_array(&m_vector.front());
1001 glDrawArrays(m_mode, 0, GLsizei(m_vector.size()));
1004 std::size_t size() const
1006 return m_vector.size();
1010 return m_vector.empty();
1016 void reserve(std::size_t size)
1018 m_vector.reserve(size);
1020 void push_back(const PointVertex& point)
1022 m_vector.push_back(point);
1027 class RenderableVertexBuffer : public OpenGLRenderable
1029 const GLenum m_mode;
1030 const VertexBuffer<PointVertex>& m_vertices;
1032 RenderableVertexBuffer(GLenum mode, const VertexBuffer<PointVertex>& vertices)
1033 : m_mode(mode), m_vertices(vertices)
1037 void render(RenderStateFlags state) const
1039 pointvertex_gl_array(m_vertices.data());
1040 glDrawArrays(m_mode, 0, m_vertices.size());
1044 class RenderableIndexBuffer : public OpenGLRenderable
1046 const GLenum m_mode;
1047 const IndexBuffer& m_indices;
1048 const VertexBuffer<PointVertex>& m_vertices;
1050 RenderableIndexBuffer(GLenum mode, const IndexBuffer& indices, const VertexBuffer<PointVertex>& vertices)
1051 : m_mode(mode), m_indices(indices), m_vertices(vertices)
1055 void render(RenderStateFlags state) const
1058 pointvertex_gl_array(m_vertices.data());
1059 glDrawElements(m_mode, GLsizei(m_indices.size()), RenderIndexTypeID, m_indices.data());
1062 if(state & RENDER_COLOURARRAY != 0)
1064 for(std::size_t i = 0; i < m_indices.size(); ++i)
1066 glColor4ubv(&m_vertices[m_indices[i]].colour.r);
1067 glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
1072 for(std::size_t i = 0; i < m_indices.size(); ++i)
1074 glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
1086 static void set(Vertex3f& vertex, float x, float y, float z)
1097 static void set(Vertex3f& vertex, float x, float y, float z)
1108 static void set(Vertex3f& vertex, float x, float y, float z)
1116 template<typename remap_policy>
1117 inline void draw_circle(const std::size_t segments, const float radius, PointVertex* vertices, remap_policy remap)
1119 const double increment = c_pi / double(segments << 2);
1121 std::size_t count = 0;
1124 while(count < segments)
1126 PointVertex* i = vertices + count;
1127 PointVertex* j = vertices + ((segments << 1) - (count + 1));
1129 PointVertex* k = i + (segments << 1);
1130 PointVertex* l = j + (segments << 1);
1132 PointVertex* m = i + (segments << 2);
1133 PointVertex* n = j + (segments << 2);
1134 PointVertex* o = k + (segments << 2);
1135 PointVertex* p = l + (segments << 2);
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);
1145 const double theta = increment * count;
1146 x = static_cast<float>(radius * cos(theta));
1147 y = static_cast<float>(radius * sin(theta));
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);
1158 class PointVertexArrayIterator
1160 PointVertex* m_point;
1162 PointVertexArrayIterator(PointVertex* point)
1166 PointVertexArrayIterator& operator++()
1171 PointVertexArrayIterator operator++(int)
1173 PointVertexArrayIterator tmp(*this);
1177 Vertex3f& operator*()
1179 return m_point.vertex;
1181 Vertex3f* operator->()
1183 return &(operator*());
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)
1190 const float increment = c_pi / (double)(segments << 2);
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)
1203 const float theta = increment * count;
1204 const float x = radius * cos(theta);
1205 const float y = radius * sin(theta);
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);
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);
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)
1222 const float increment = c_pi / (double)(segments << 2);
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)
1235 const float theta = increment * count;
1236 const float x = radius * cos(theta);
1237 const float y = radius * sin(theta);
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);
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);
1254 inline void draw_quad(const float radius, PointVertex* quad)
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);
1262 inline void draw_cube(const float radius, PointVertex* cube)
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);
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)
1278 s = Vector3(0, 0, 0);
1279 t = Vector3(0, 0, 0);
1284 Vector3(b.vertex.x(), b.texcoord.s(), b.texcoord.t()),
1285 Vector3(a.vertex.x(), a.texcoord.s(), a.texcoord.t())
1288 Vector3(c.vertex.x(), c.texcoord.s(), c.texcoord.t()),
1289 Vector3(a.vertex.x(), a.texcoord.s(), a.texcoord.t())
1294 if(fabs(cross.x()) > 0.000001f)
1296 s.x() = -cross.y() / cross.x();
1299 if(fabs(cross.x()) > 0.000001f)
1301 t.x() = -cross.z() / cross.x();
1309 Vector3(b.vertex.y(), b.texcoord.s(), b.texcoord.t()),
1310 Vector3(a.vertex.y(), a.texcoord.s(), a.texcoord.t())
1313 Vector3(c.vertex.y(), c.texcoord.s(), c.texcoord.t()),
1314 Vector3(a.vertex.y(), a.texcoord.s(), a.texcoord.t())
1319 if(fabs(cross.x()) > 0.000001f)
1321 s.y() = -cross.y() / cross.x();
1324 if(fabs(cross.x()) > 0.000001f)
1326 t.y() = -cross.z() / cross.x();
1334 Vector3(b.vertex.z(), b.texcoord.s(), b.texcoord.t()),
1335 Vector3(a.vertex.z(), a.texcoord.s(), a.texcoord.t())
1338 Vector3(c.vertex.z(), c.texcoord.s(), c.texcoord.t()),
1339 Vector3(a.vertex.z(), a.texcoord.s(), a.texcoord.t())
1344 if(fabs(cross.x()) > 0.000001f)
1346 s.z() = -cross.y() / cross.x();
1349 if(fabs(cross.x()) > 0.000001f)
1351 t.z() = -cross.z() / cross.x();
1356 inline void ArbitraryMeshTriangle_sumTangents(ArbitraryMeshVertex& a, ArbitraryMeshVertex& b, ArbitraryMeshVertex& c)
1360 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
1362 reinterpret_cast<Vector3&>(a.tangent) += s;
1363 reinterpret_cast<Vector3&>(b.tangent) += s;
1364 reinterpret_cast<Vector3&>(c.tangent) += s;
1366 reinterpret_cast<Vector3&>(a.bitangent) += t;
1367 reinterpret_cast<Vector3&>(b.bitangent) += t;
1368 reinterpret_cast<Vector3&>(c.bitangent) += t;