glc_cylinder.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  http://glc-lib.sourceforge.net
00006 
00007  GLC-lib is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU Lesser General Public License as published by
00009  the Free Software Foundation; either version 3 of the License, or
00010  (at your option) any later version.
00011 
00012  GLC-lib is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU Lesser General Public License for more details.
00016 
00017  You should have received a copy of the GNU Lesser General Public License
00018  along with GLC-lib; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 *****************************************************************************/
00022 
00024 
00025 #include "glc_cylinder.h"
00026 #include "../glc_openglexception.h"
00027 #include "../shading/glc_selectionmaterial.h"
00028 #include "../glc_state.h"
00029 
00030 #include <QVector>
00031 
00032 // Class chunk id
00033 quint32 GLC_Cylinder::m_ChunkId= 0xA705;
00034 
00036 // Constructor destructor
00038 
00039 GLC_Cylinder::GLC_Cylinder(double dRadius, double dLength)
00040 :GLC_Mesh()
00041 , m_Radius(dRadius)
00042 , m_Length(dLength)
00043 , m_Discret(glc::GLC_POLYDISCRET)       // Default discretion
00044 , m_EndedIsCaped(true)                  // Cylinder ended are closed
00045 {
00046         Q_ASSERT((m_Radius > 0.0) && (m_Length > 0.0));
00047 }
00048 
00049 GLC_Cylinder::GLC_Cylinder(const GLC_Cylinder& sourceCylinder)
00050 :GLC_Mesh(sourceCylinder)
00051 , m_Radius(sourceCylinder.m_Radius)
00052 , m_Length(sourceCylinder.m_Length)
00053 , m_Discret(sourceCylinder.m_Discret)
00054 , m_EndedIsCaped(sourceCylinder.m_EndedIsCaped)
00055 {
00056         Q_ASSERT((m_Radius > 0.0) && (m_Length > 0.0) && (m_Discret > 0));
00057 
00058 }
00059 GLC_Cylinder::~GLC_Cylinder()
00060 {
00061 
00062 }
00063 
00065 // Get Functions
00067 
00068 quint32 GLC_Cylinder::chunckID()
00069 {
00070         return m_ChunkId;
00071 }
00072 
00073 
00074 GLC_Geometry* GLC_Cylinder::clone() const
00075 {
00076         return new GLC_Cylinder(*this);
00077 }
00078 
00079 
00080 const GLC_BoundingBox& GLC_Cylinder::boundingBox()
00081 {
00082         if (GLC_Mesh::isEmpty())
00083         {
00084                 createMeshAndWire();
00085         }
00086         return GLC_Mesh::boundingBox();
00087 }
00088 
00090 // Set Functions
00092 
00093 void GLC_Cylinder::setLength(double Length)
00094 {
00095         Q_ASSERT(Length > 0.0);
00096         m_Length= Length;
00097 
00098         GLC_Mesh::clearMeshWireAndBoundingBox();
00099 }
00100 
00101 
00102 void GLC_Cylinder::setRadius(double Radius)
00103 {
00104         Q_ASSERT(Radius > 0.0);
00105         m_Radius= Radius;
00106 
00107         GLC_Mesh::clearMeshWireAndBoundingBox();
00108 }
00109 
00110 
00111 void GLC_Cylinder::setDiscretion(int TargetDiscret)
00112 {
00113         Q_ASSERT(TargetDiscret > 0);
00114         if (TargetDiscret != m_Discret)
00115         {
00116                 m_Discret= TargetDiscret;
00117                 if (m_Discret < 6) m_Discret= 6;
00118 
00119                 GLC_Mesh::clearMeshWireAndBoundingBox();
00120         }
00121 }
00122 
00123 
00124 void GLC_Cylinder::setEndedCaps(bool CapsEnded)
00125 {
00126         if (m_EndedIsCaped != CapsEnded)
00127         {
00128                 m_EndedIsCaped= CapsEnded;
00129 
00130                 GLC_Mesh::clearMeshWireAndBoundingBox();
00131         }
00132 }
00133 
00135 // Private Opengl functions
00137 
00138 
00139 void GLC_Cylinder::glDraw(const GLC_RenderProperties& renderProperties)
00140 {
00141 
00142         if (GLC_Mesh::isEmpty())
00143         {
00144                 createMeshAndWire();
00145         }
00146 
00147         GLC_Mesh::glDraw(renderProperties);
00148 }
00149 
00150 
00151 void GLC_Cylinder::createMeshAndWire()
00152 {
00153         Q_ASSERT(GLC_Mesh::isEmpty());
00154         Q_ASSERT(m_WireData.isEmpty());
00155 
00156         // Create cosinus and sinus array according to the discretion and radius
00157         const int vertexNumber= m_Discret + 1;
00158         // Normals values
00159         QVector<float> cosNormalArray(vertexNumber);
00160         QVector<float> sinNormalArray(vertexNumber);
00161 
00162         QVector<float> cosArray(vertexNumber);
00163         QVector<float> sinArray(vertexNumber);
00164 
00165         const double angle= (2.0 * glc::PI) / static_cast<double>(m_Discret);
00166 
00167         for (int i= 0; i < vertexNumber; ++i)
00168         {
00169                 const double cosValue= cos(static_cast<double>(i) * angle);
00170                 const double sinValue= sin(static_cast<double>(i) * angle);
00171 
00172                 cosNormalArray[i]= static_cast<GLfloat>(cosValue);
00173                 sinNormalArray[i]= static_cast<GLfloat>(sinValue);
00174 
00175                 cosArray[i]= static_cast<GLfloat>(m_Radius * cosValue);
00176                 sinArray[i]= static_cast<GLfloat>(m_Radius * sinValue);
00177         }
00178 
00179         // Mesh Data
00180         GLfloatVector verticeVector;
00181         GLfloatVector normalsVector;
00182         GLfloatVector texelVector;
00183 
00184         // Wire Data
00185         GLfloatVector bottomWireData(vertexNumber * 3);
00186         GLfloatVector topWireData(vertexNumber * 3);
00187 
00188         if (m_EndedIsCaped)
00189         {
00190                 const int size= vertexNumber * 4;
00191                 verticeVector.resize(3 * size);
00192                 normalsVector.resize(3 * size);
00193                 texelVector.resize(2 * size);
00194         }
00195         else
00196         {
00197                 const int size= vertexNumber * 2;
00198                 verticeVector.resize(3 * size);
00199                 normalsVector.resize(3 * size);
00200                 texelVector.resize(2 * size);
00201         }
00202         for (int i= 0; i < vertexNumber; ++i)
00203         {
00204                 // Bottom Mesh
00205                 verticeVector[3 * i]= cosArray[i];
00206                 verticeVector[3 * i + 1]= sinArray[i];
00207                 verticeVector[3 * i + 2]= 0.0f;
00208 
00209                 normalsVector[3 * i]= cosNormalArray[i];
00210                 normalsVector[3 * i + 1]= sinNormalArray[i];
00211                 normalsVector[3 * i + 2]= 0.0f;
00212 
00213                 texelVector[2 * i]= static_cast<float>(i) / static_cast<float>(m_Discret);
00214                 texelVector[2 * i + 1]= 0.0f;
00215 
00216                 // Bottom Wire
00217                 bottomWireData[3 * i]= cosArray[i];
00218                 bottomWireData[3 * i + 1]= sinArray[i];
00219                 bottomWireData[3 * i + 2]= 0.0f;
00220 
00221                 // Top
00222                 verticeVector[3 * i + 3 * vertexNumber]= cosArray[i];
00223                 verticeVector[3 * i + 1 + 3 * vertexNumber]= sinArray[i];
00224                 verticeVector[3 * i + 2 + 3 * vertexNumber]= static_cast<float>(m_Length);
00225 
00226                 normalsVector[3 * i + 3 * vertexNumber]= cosNormalArray[i];
00227                 normalsVector[3 * i + 1 + 3 * vertexNumber]= sinNormalArray[i];
00228                 normalsVector[3 * i + 2 + 3 * vertexNumber]= 0.0f;
00229 
00230                 texelVector[2 * i + 2 * vertexNumber]= texelVector[2 * i];
00231                 texelVector[2 * i + 1 + 2 * vertexNumber]= 1.0f;
00232 
00233                 // Top Wire
00234                 topWireData[3 * i]= cosArray[i];
00235                 topWireData[3 * i + 1]= sinArray[i];
00236                 topWireData[3 * i + 2]= static_cast<float>(m_Length);
00237 
00238                 if (m_EndedIsCaped)
00239                 {
00240                         // Bottom Cap ends
00241                         verticeVector[3 * i + 2 * 3 * vertexNumber]= cosArray[i];
00242                         verticeVector[3 * i + 1 + 2 * 3 * vertexNumber]= sinArray[i];
00243                         verticeVector[3 * i + 2 + 2 * 3 * vertexNumber]= 0.0f;
00244 
00245                         normalsVector[3 * i + 2 * 3 * vertexNumber]= 0.0f;
00246                         normalsVector[3 * i + 1 + 2 * 3 * vertexNumber]= 0.0f;
00247                         normalsVector[3 * i + 2 + 2 * 3 * vertexNumber]= -1.0f;
00248 
00249                         texelVector[2 * i + 2 * 2 * vertexNumber]= texelVector[2 * i];
00250                         texelVector[2 * i + 1 + 2 * 2 * vertexNumber]= 0.0f;
00251 
00252                         // Top Cap ends
00253                         verticeVector[3 * i + 3 * 3 * vertexNumber]= cosArray[i];
00254                         verticeVector[3 * i + 1 + 3 * 3 * vertexNumber]= sinArray[i];
00255                         verticeVector[3 * i + 2 + 3 * 3 * vertexNumber]= static_cast<float>(m_Length);
00256 
00257                         normalsVector[3 * i + 3 * 3 * vertexNumber]= 0.0f;
00258                         normalsVector[3 * i + 1 + 3 * 3 * vertexNumber]= 0.0f;
00259                         normalsVector[3 * i + 2 + 3 * 3 * vertexNumber]= 1.0f;
00260 
00261                         texelVector[2 * i + 3 * 2 * vertexNumber]= texelVector[2 * i];
00262                         texelVector[2 * i + 1 + 3 * 2 * vertexNumber]= 1.0f;
00263                 }
00264         }
00265 
00266         // Add bulk data in to the mesh
00267         GLC_Mesh::addVertice(verticeVector);
00268         GLC_Mesh::addNormals(normalsVector);
00269         GLC_Mesh::addTexels(texelVector);
00270 
00271         // Add polyline to wire data
00272         GLC_Geometry::addVerticeGroup(bottomWireData);
00273         GLC_Geometry::addVerticeGroup(topWireData);
00274 
00275         // Set the material to use
00276         GLC_Material* pCylinderMaterial;
00277         if (hasMaterial())
00278         {
00279                 pCylinderMaterial= this->firstMaterial();
00280         }
00281         else
00282         {
00283                 pCylinderMaterial= new GLC_Material();
00284         }
00285 
00286         IndexList circumferenceStrips;
00287         // Create the index
00288         for (int i= 0; i < vertexNumber; ++i)
00289         {
00290                 circumferenceStrips.append(i + vertexNumber);
00291                 circumferenceStrips.append(i);
00292         }
00293         addTrianglesStrip(pCylinderMaterial, circumferenceStrips);
00294 
00295         if (m_EndedIsCaped)
00296         {
00297                 IndexList bottomCap;
00298                 IndexList topCap;
00299                 int id1= 0;
00300                 int id2= m_Discret - 1;
00301                 const int size= m_Discret / 2 + (m_Discret % 2);
00302                 for (int i= 0; i < size; ++i)
00303                 {
00304                         bottomCap.append(id1 + 2 * vertexNumber);
00305                         topCap.append(id2 + 3 * vertexNumber);
00306 
00307                         bottomCap.append(id2 + 2 * vertexNumber);
00308                         topCap.append(id1 + 3 * vertexNumber);
00309 
00310                         id1+= 1;
00311                         id2-= 1;
00312                 }
00313                 addTrianglesStrip(pCylinderMaterial, bottomCap);
00314                 addTrianglesStrip(pCylinderMaterial, topCap);
00315         }
00316 
00317         finish();
00318 }

SourceForge.net Logo

©2005-2011 Laurent Ribon