/* * Stellarium * Copyright (C) 2009 Fabien Chereau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __STELVERTEXARRAY_HPP__ #define __STELVERTEXARRAY_HPP__ #include #include #include "VecMath.hpp" struct StelVertexArray { // TODO maybe merge this with StelPainter DrawingMode enum StelPrimitiveType { Points = 0x0000, // GL_POINTS Lines = 0x0001, // GL_LINES LineLoop = 0x0002, // GL_LINE_LOOP LineStrip = 0x0003, // GL_LINE_STRIP Triangles = 0x0004, // GL_TRIANGLES TriangleStrip = 0x0005, // GL_TRIANGLE_STRIP TriangleFan = 0x0006 // GL_TRIANGLE_FAN }; StelVertexArray(StelPrimitiveType pType=StelVertexArray::Triangles) : primitiveType(pType) {;} StelVertexArray(const QVector& v, StelPrimitiveType pType=StelVertexArray::Triangles,const QVector& t=QVector(), const QVector i=QVector()) : vertex(v), texCoords(t), indices(i), primitiveType(pType) {;} //! OpenGL compatible array of 3D vertex to be displayed using vertex arrays. //! TODO, move to float? Most of the vectors are normalized, thus the precision is around 1E-45 using float //! which is enough (=2E-37 milli arcsec). QVector vertex; //! OpenGL compatible array of edge flags to be displayed using vertex arrays. QVector texCoords; //! OpenGL compatible array of indices for the vertex and the textures QVector indices; StelPrimitiveType primitiveType; bool isIndexed() const {return !indices.isEmpty();} bool isTextured() const {return !texCoords.isEmpty();} //! call a function for each triangle of the array. //! func should define the following method : //! void operator() (const Vec3d* vertex[3], const Vec2f* tex[3], unsigned int indices[3]) //! The method takes arrays of *pointers* as arguments because we can't assume the values are contiguous template inline Func foreachTriangle(Func func) const; //! Create a copy of the array with all the triangles intersecting the projector discontinuty removed. StelVertexArray removeDiscontinuousTriangles(const class StelProjector* prj) const; private: // Below we define a few methods that are templated to be optimized according to different types of VertexArray : // The template parameter defines whether the array has a texture. // The template parameter defines whether the array is indexed. template const Vec3d* specVertexAt(int i) const { return &vertex.at(specIndiceAt(i)); } template const Vec2f* specTexCoordAt(int i) const { return T ? &texCoords.at(specIndiceAt(i)) : NULL; } template unsigned int specIndiceAt(unsigned int i) const { return I ? indices.at(i) : i; } template inline Func specForeachTriangle(Func func) const; }; // Serialization routines QDataStream& operator<<(QDataStream& out, const StelVertexArray&); QDataStream& operator>>(QDataStream& in, StelVertexArray&); template Func StelVertexArray::foreachTriangle(Func func) const { // Here we just dispach the method into one of the 4 possible cases bool textured = isTextured(); bool useIndice = isIndexed(); if (textured) if (useIndice) return specForeachTriangle(func); else return specForeachTriangle(func); else if (useIndice) return specForeachTriangle(func); else return specForeachTriangle(func); } template Func StelVertexArray::specForeachTriangle(Func func) const { switch (primitiveType) { case StelVertexArray::Triangles: Q_ASSERT(vertex.size() % 3 == 0); for (int i = 0; i < vertex.size(); i += 3) { func(specVertexAt(i), specVertexAt(i+1), specVertexAt(i+2), specTexCoordAt(i), specTexCoordAt(i+1), specTexCoordAt(i+2), specIndiceAt(i), specIndiceAt(i+1), specIndiceAt(i+2)); } break; case StelVertexArray::TriangleFan: { const Vec3d* v0 = specVertexAt(0); const Vec2f* t0 = specTexCoordAt(0); unsigned int i0 = specIndiceAt(0); for (int i = 1; i < vertex.size() - 1; ++i) { func(v0, specVertexAt(i), specVertexAt(i+1), t0, specTexCoordAt(i), specTexCoordAt(i+1), i0, specIndiceAt(i), specIndiceAt(i+1)); } break; } case StelVertexArray::TriangleStrip: { for (int i = 2; i < vertex.size(); ++i) { if (i % 2 == 0) func(specVertexAt(i-2), specVertexAt(i-1), specVertexAt(i), specTexCoordAt(i-2), specTexCoordAt(i-1), specTexCoordAt(i), specIndiceAt(i-2), specIndiceAt(i-1), specIndiceAt(i)); else func(specVertexAt(i-1), specVertexAt(i-2), specVertexAt(i), specTexCoordAt(i-1), specTexCoordAt(i-2), specTexCoordAt(i), specIndiceAt(i-1), specIndiceAt(i-2), specIndiceAt(i)); } break; } default: Q_ASSERT_X(0, Q_FUNC_INFO, "unsuported primitive type"); } return func; } #endif // __STELVERTEXARRAY_HPP__