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         createMeshAndWire();
00048 }
00049 
00050 GLC_Cylinder::GLC_Cylinder(const GLC_Cylinder& sourceCylinder)
00051 :GLC_Mesh(sourceCylinder)
00052 , m_Radius(sourceCylinder.m_Radius)
00053 , m_Length(sourceCylinder.m_Length)
00054 , m_Discret(sourceCylinder.m_Discret)
00055 , m_EndedIsCaped(sourceCylinder.m_EndedIsCaped)
00056 {
00057         Q_ASSERT((m_Radius > 0.0) && (m_Length > 0.0) && (m_Discret > 0));
00058         createMeshAndWire();
00059 
00060 }
00061 GLC_Cylinder::~GLC_Cylinder()
00062 {
00063 
00064 }
00065 
00067 // Get Functions
00069 
00070 quint32 GLC_Cylinder::chunckID()
00071 {
00072         return m_ChunkId;
00073 }
00074 
00075 
00076 GLC_Geometry* GLC_Cylinder::clone() const
00077 {
00078         return new GLC_Cylinder(*this);
00079 }
00080 
00081 
00082 const GLC_BoundingBox& GLC_Cylinder::boundingBox()
00083 {
00084         if (GLC_Mesh::isEmpty())
00085         {
00086                 createMeshAndWire();
00087         }
00088         return GLC_Mesh::boundingBox();
00089 }
00090 
00092 // Set Functions
00094 
00095 void GLC_Cylinder::setLength(double Length)
00096 {
00097         Q_ASSERT(Length > 0.0);
00098         m_Length= Length;
00099 
00100         GLC_Mesh::clearMeshWireAndBoundingBox();
00101 }
00102 
00103 
00104 void GLC_Cylinder::setRadius(double Radius)
00105 {
00106         Q_ASSERT(Radius > 0.0);
00107         m_Radius= Radius;
00108 
00109         GLC_Mesh::clearMeshWireAndBoundingBox();
00110 }
00111 
00112 
00113 void GLC_Cylinder::setDiscretion(int TargetDiscret)
00114 {
00115         Q_ASSERT(TargetDiscret > 0);
00116         if (TargetDiscret != m_Discret)
00117         {
00118                 m_Discret= TargetDiscret;
00119                 if (m_Discret < 6) m_Discret= 6;
00120 
00121                 GLC_Mesh::clearMeshWireAndBoundingBox();
00122         }
00123 }
00124 
00125 
00126 void GLC_Cylinder::setEndedCaps(bool CapsEnded)
00127 {
00128         if (m_EndedIsCaped != CapsEnded)
00129         {
00130                 m_EndedIsCaped= CapsEnded;
00131 
00132                 GLC_Mesh::clearMeshWireAndBoundingBox();
00133         }
00134 }
00135 
00137 // Private Opengl functions
00139 
00140 
00141 void GLC_Cylinder::glDraw(const GLC_RenderProperties& renderProperties)
00142 {
00143 
00144         if (GLC_Mesh::isEmpty())
00145         {
00146                 createMeshAndWire();
00147         }
00148 
00149         GLC_Mesh::glDraw(renderProperties);
00150 }
00151 
00152 
00153 void GLC_Cylinder::createMeshAndWire()
00154 {
00155         Q_ASSERT(GLC_Mesh::isEmpty());
00156         Q_ASSERT(m_WireData.isEmpty());
00157 
00158         // Create cosinus and sinus array according to the discretion and radius
00159         const int vertexNumber= m_Discret + 1;
00160         // Normals values
00161         QVector<float> cosNormalArray(vertexNumber);
00162         QVector<float> sinNormalArray(vertexNumber);
00163 
00164         QVector<float> cosArray(vertexNumber);
00165         QVector<float> sinArray(vertexNumber);
00166 
00167         const double angle= (2.0 * glc::PI) / static_cast<double>(m_Discret);
00168 
00169         for (int i= 0; i < vertexNumber; ++i)
00170         {
00171                 const double cosValue= cos(static_cast<double>(i) * angle);
00172                 const double sinValue= sin(static_cast<double>(i) * angle);
00173 
00174                 cosNormalArray[i]= static_cast<GLfloat>(cosValue);
00175                 sinNormalArray[i]= static_cast<GLfloat>(sinValue);
00176 
00177                 cosArray[i]= static_cast<GLfloat>(m_Radius * cosValue);
00178                 sinArray[i]= static_cast<GLfloat>(m_Radius * sinValue);
00179         }
00180 
00181         // Mesh Data
00182         GLfloatVector verticeVector;
00183         GLfloatVector normalsVector;
00184         GLfloatVector texelVector;
00185 
00186         // Wire Data
00187         GLfloatVector bottomWireData(vertexNumber * 3);
00188         GLfloatVector topWireData(vertexNumber * 3);
00189 
00190         if (m_EndedIsCaped)
00191         {
00192                 const int size= vertexNumber * 4;
00193                 verticeVector.resize(3 * size);
00194                 normalsVector.resize(3 * size);
00195                 texelVector.resize(2 * size);
00196         }
00197         else
00198         {
00199                 const int size= vertexNumber * 2;
00200                 verticeVector.resize(3 * size);
00201                 normalsVector.resize(3 * size);
00202                 texelVector.resize(2 * size);
00203         }
00204         for (int i= 0; i < vertexNumber; ++i)
00205         {
00206                 // Bottom Mesh
00207                 verticeVector[3 * i]= cosArray[i];
00208                 verticeVector[3 * i + 1]= sinArray[i];
00209                 verticeVector[3 * i + 2]= 0.0f;
00210 
00211                 normalsVector[3 * i]= cosNormalArray[i];
00212                 normalsVector[3 * i + 1]= sinNormalArray[i];
00213                 normalsVector[3 * i + 2]= 0.0f;
00214 
00215                 texelVector[2 * i]= static_cast<float>(i) / static_cast<float>(m_Discret);
00216                 texelVector[2 * i + 1]= 0.0f;
00217 
00218                 // Bottom Wire
00219                 bottomWireData[3 * i]= cosArray[i];
00220                 bottomWireData[3 * i + 1]= sinArray[i];
00221                 bottomWireData[3 * i + 2]= 0.0f;
00222 
00223                 // Top
00224                 verticeVector[3 * i + 3 * vertexNumber]= cosArray[i];
00225                 verticeVector[3 * i + 1 + 3 * vertexNumber]= sinArray[i];
00226                 verticeVector[3 * i + 2 + 3 * vertexNumber]= static_cast<float>(m_Length);
00227 
00228                 normalsVector[3 * i + 3 * vertexNumber]= cosNormalArray[i];
00229                 normalsVector[3 * i + 1 + 3 * vertexNumber]= sinNormalArray[i];
00230                 normalsVector[3 * i + 2 + 3 * vertexNumber]= 0.0f;
00231 
00232                 texelVector[2 * i + 2 * vertexNumber]= texelVector[2 * i];
00233                 texelVector[2 * i + 1 + 2 * vertexNumber]= 1.0f;
00234 
00235                 // Top Wire
00236                 topWireData[3 * i]= cosArray[i];
00237                 topWireData[3 * i + 1]= sinArray[i];
00238                 topWireData[3 * i + 2]= static_cast<float>(m_Length);
00239 
00240                 if (m_EndedIsCaped)
00241                 {
00242                         // Bottom Cap ends
00243                         verticeVector[3 * i + 2 * 3 * vertexNumber]= cosArray[i];
00244                         verticeVector[3 * i + 1 + 2 * 3 * vertexNumber]= sinArray[i];
00245                         verticeVector[3 * i + 2 + 2 * 3 * vertexNumber]= 0.0f;
00246 
00247                         normalsVector[3 * i + 2 * 3 * vertexNumber]= 0.0f;
00248                         normalsVector[3 * i + 1 + 2 * 3 * vertexNumber]= 0.0f;
00249                         normalsVector[3 * i + 2 + 2 * 3 * vertexNumber]= -1.0f;
00250 
00251                         texelVector[2 * i + 2 * 2 * vertexNumber]= texelVector[2 * i];
00252                         texelVector[2 * i + 1 + 2 * 2 * vertexNumber]= 0.0f;
00253 
00254                         // Top Cap ends
00255                         verticeVector[3 * i + 3 * 3 * vertexNumber]= cosArray[i];
00256                         verticeVector[3 * i + 1 + 3 * 3 * vertexNumber]= sinArray[i];
00257                         verticeVector[3 * i + 2 + 3 * 3 * vertexNumber]= static_cast<float>(m_Length);
00258 
00259                         normalsVector[3 * i + 3 * 3 * vertexNumber]= 0.0f;
00260                         normalsVector[3 * i + 1 + 3 * 3 * vertexNumber]= 0.0f;
00261                         normalsVector[3 * i + 2 + 3 * 3 * vertexNumber]= 1.0f;
00262 
00263                         texelVector[2 * i + 3 * 2 * vertexNumber]= texelVector[2 * i];
00264                         texelVector[2 * i + 1 + 3 * 2 * vertexNumber]= 1.0f;
00265                 }
00266         }
00267 
00268         // Add bulk data in to the mesh
00269         GLC_Mesh::addVertice(verticeVector);
00270         GLC_Mesh::addNormals(normalsVector);
00271         GLC_Mesh::addTexels(texelVector);
00272 
00273         // Add polyline to wire data
00274         GLC_Geometry::addVerticeGroup(bottomWireData);
00275         GLC_Geometry::addVerticeGroup(topWireData);
00276 
00277         // Set the material to use
00278         GLC_Material* pCylinderMaterial;
00279         if (hasMaterial())
00280         {
00281                 pCylinderMaterial= this->firstMaterial();
00282         }
00283         else
00284         {
00285                 pCylinderMaterial= new GLC_Material();
00286         }
00287 
00288         IndexList circumferenceStrips;
00289         // Create the index
00290         for (int i= 0; i < vertexNumber; ++i)
00291         {
00292                 circumferenceStrips.append(i + vertexNumber);
00293                 circumferenceStrips.append(i);
00294         }
00295         addTrianglesStrip(pCylinderMaterial, circumferenceStrips);
00296 
00297         if (m_EndedIsCaped)
00298         {
00299                 IndexList bottomCap;
00300                 IndexList topCap;
00301                 int id1= 0;
00302                 int id2= m_Discret - 1;
00303                 const int size= m_Discret / 2 + (m_Discret % 2);
00304                 for (int i= 0; i < size; ++i)
00305                 {
00306                         bottomCap.append(id1 + 2 * vertexNumber);
00307                         topCap.append(id2 + 3 * vertexNumber);
00308 
00309                         bottomCap.append(id2 + 2 * vertexNumber);
00310                         topCap.append(id1 + 3 * vertexNumber);
00311 
00312                         id1+= 1;
00313                         id2-= 1;
00314                 }
00315                 addTrianglesStrip(pCylinderMaterial, bottomCap);
00316                 addTrianglesStrip(pCylinderMaterial, topCap);
00317         }
00318 
00319         finish();
00320 }

SourceForge.net Logo

©2005-2011 Laurent Ribon