glc_wiredata.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_wiredata.h"
00026 #include "glc_bsrep.h"
00027 #include "../glc_ext.h"
00028 #include "../glc_state.h"
00029 #include "../glc_exception.h"
00030 
00031 // Class chunk id
00032 // Old chunkId = 0xA706
00033 quint32 GLC_WireData::m_ChunkId= 0xA711;
00034 
00035 
00036 GLC_WireData::GLC_WireData()
00037 : m_VerticeBuffer()
00038 , m_NextPrimitiveLocalId(1)
00039 , m_Positions()
00040 , m_ColorBuffer()
00041 , m_Colors()
00042 , m_IndexBuffer(QGLBuffer::IndexBuffer)
00043 , m_IndexVector()
00044 , m_PositionSize(0)
00045 , m_ColorSize(0)
00046 , m_pBoundingBox(NULL)
00047 , m_VerticeGrouprSizes()
00048 , m_VerticeGroupOffseti()
00049 , m_VerticeGroupOffset()
00050 , m_VerticeGroupId()
00051 , m_VerticeGroupCount(0)
00052 , m_UseVbo(false)
00053 {
00054 
00055 }
00056 
00057 
00058 GLC_WireData::GLC_WireData(const GLC_WireData& data)
00059 : m_VerticeBuffer()
00060 , m_NextPrimitiveLocalId(data.m_NextPrimitiveLocalId)
00061 , m_Positions(data.positionVector())
00062 , m_ColorBuffer()
00063 , m_Colors(data.colorVector())
00064 , m_IndexBuffer(QGLBuffer::IndexBuffer)
00065 , m_IndexVector(data.indexVector())
00066 , m_PositionSize(data.m_PositionSize)
00067 , m_ColorSize(data.m_ColorSize)
00068 , m_pBoundingBox(NULL)
00069 , m_VerticeGrouprSizes(data.m_VerticeGrouprSizes)
00070 , m_VerticeGroupOffseti(data.m_VerticeGroupOffseti)
00071 , m_VerticeGroupOffset(data.m_VerticeGroupOffset)
00072 , m_VerticeGroupId(data.m_VerticeGroupId)
00073 , m_VerticeGroupCount(data.m_VerticeGroupCount)
00074 , m_UseVbo(data.m_UseVbo)
00075 {
00076         if (NULL != data.m_pBoundingBox)
00077         {
00078                 m_pBoundingBox= new GLC_BoundingBox(*(data.m_pBoundingBox));
00079         }
00080 }
00081 
00082 
00083 GLC_WireData& GLC_WireData::operator=(const GLC_WireData& data)
00084 {
00085         if (this != &data)
00086         {
00087                 clear();
00088                 m_NextPrimitiveLocalId= data.m_NextPrimitiveLocalId;
00089                 m_Positions= data.positionVector();
00090                 m_Colors= data.colorVector();
00091                 m_IndexVector= data.indexVector();
00092                 m_PositionSize= data.m_PositionSize;
00093                 m_ColorSize= data.m_ColorSize;
00094                 if (NULL != data.m_pBoundingBox)
00095                 {
00096                         m_pBoundingBox= new GLC_BoundingBox(*(data.m_pBoundingBox));
00097                 }
00098                 m_VerticeGrouprSizes= data.m_VerticeGrouprSizes;
00099                 m_VerticeGroupOffseti= data.m_VerticeGroupOffseti;
00100                 m_VerticeGroupOffset= data.m_VerticeGroupOffset;
00101                 m_VerticeGroupId= data.m_VerticeGroupId;
00102                 m_VerticeGroupCount= data.m_VerticeGroupCount;
00103                 m_UseVbo= data.m_UseVbo;
00104         }
00105         return *this;
00106 }
00107 
00108 GLC_WireData::~GLC_WireData()
00109 {
00110         clear();
00111 }
00113 // Get Functions
00115 
00116 
00117 quint32 GLC_WireData::chunckID()
00118 {
00119         return m_ChunkId;
00120 }
00121 
00122 
00123 GLfloatVector GLC_WireData::positionVector() const
00124 {
00125         if (m_VerticeBuffer.isCreated())
00126         {
00127                 Q_ASSERT((NULL != QGLContext::currentContext()) &&  QGLContext::currentContext()->isValid());
00128                 // VBO created get data from VBO
00129                 const int sizeOfVbo= m_PositionSize;
00130                 const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
00131                 GLfloatVector positionVector(sizeOfVbo);
00132 
00133                 const_cast<QGLBuffer&>(m_VerticeBuffer).bind();
00134                 GLvoid* pVbo = const_cast<QGLBuffer&>(m_VerticeBuffer).map(QGLBuffer::ReadOnly);
00135                 memcpy(positionVector.data(), pVbo, dataSize);
00136                 const_cast<QGLBuffer&>(m_VerticeBuffer).unmap();
00137                 const_cast<QGLBuffer&>(m_VerticeBuffer).release();
00138                 return positionVector;
00139         }
00140         else
00141         {
00142                 return m_Positions;
00143         }
00144 }
00145 
00146 // Return the color Vector
00147 GLfloatVector GLC_WireData::colorVector() const
00148 {
00149         if (m_ColorBuffer.isCreated())
00150         {
00151                 // VBO created get data from VBO
00152                 const int sizeOfVbo= m_ColorSize;
00153                 const GLsizeiptr dataSize= sizeOfVbo * sizeof(GLfloat);
00154                 GLfloatVector normalVector(sizeOfVbo);
00155 
00156                 const_cast<QGLBuffer&>(m_ColorBuffer).bind();
00157                 GLvoid* pVbo = const_cast<QGLBuffer&>(m_ColorBuffer).map(QGLBuffer::ReadOnly);
00158                 memcpy(normalVector.data(), pVbo, dataSize);
00159                 const_cast<QGLBuffer&>(m_ColorBuffer).unmap();
00160                 const_cast<QGLBuffer&>(m_ColorBuffer).release();
00161                 return normalVector;
00162         }
00163         else
00164         {
00165                 return m_Colors;
00166         }
00167 }
00168 
00169 QVector<GLuint> GLC_WireData::indexVector() const
00170 {
00171         if (m_IndexBuffer.isCreated())
00172         {
00173                 // VBO created get data from VBO
00174                 const int sizeOfIbo= m_PositionSize / 3;
00175                 const GLsizeiptr dataSize= sizeOfIbo * sizeof(GLuint);
00176                 QVector<GLuint> indexVector(sizeOfIbo);
00177 
00178                 const_cast<QGLBuffer&>(m_IndexBuffer).bind();
00179                 GLvoid* pIbo = const_cast<QGLBuffer&>(m_IndexBuffer).map(QGLBuffer::ReadOnly);
00180                 memcpy(indexVector.data(), pIbo, dataSize);
00181                 const_cast<QGLBuffer&>(m_IndexBuffer).unmap();
00182                 const_cast<QGLBuffer&>(m_IndexBuffer).release();
00183                 return indexVector;
00184         }
00185         else
00186         {
00187                 return m_IndexVector;
00188         }
00189 }
00190 
00191 
00192 GLC_BoundingBox& GLC_WireData::boundingBox()
00193 {
00194         if (NULL == m_pBoundingBox)
00195         {
00196                 m_pBoundingBox= new GLC_BoundingBox();
00197 
00198                 if (m_Positions.isEmpty())
00199                 {
00200                         //qDebug() << "GLC_WireData::getBoundingBox empty m_Positions";
00201                 }
00202                 else
00203                 {
00204                         const int max= m_Positions.size();
00205                         if (max == 3) // Only One point
00206                         {
00207                                 const double delta= 1e-2;
00208                                 GLC_Point3d lower(m_Positions[0] - delta,
00209                                                 m_Positions[1] - delta,
00210                                                 m_Positions[2] - delta);
00211                                 GLC_Point3d upper(m_Positions[0] + delta,
00212                                                 m_Positions[1] + delta,
00213                                                 m_Positions[2] + delta);
00214                                 m_pBoundingBox->combine(lower);
00215                                 m_pBoundingBox->combine(upper);
00216 
00217                         }
00218                         else
00219                         {
00220                                 for (int i= 0; i < max; i= i + 3)
00221                                 {
00222                                         GLC_Point3d point(m_Positions[i], m_Positions[i + 1], m_Positions[i + 2]);
00223                                         m_pBoundingBox->combine(point);
00224                                 }
00225                         }
00226                 }
00227 
00228         }
00229         return *m_pBoundingBox;
00230 }
00231 
00233 // Set Functions
00235 
00236 
00237 GLC_uint GLC_WireData::addVerticeGroup(const GLfloatVector& floatVector)
00238 {
00239         Q_ASSERT((floatVector.size() % 3) == 0);
00240 
00241         ++m_VerticeGroupCount;
00242         m_Positions+= floatVector;
00243 
00244         m_VerticeGrouprSizes.append(static_cast<GLsizei>(floatVector.size() / 3));
00245 
00246         if (m_VerticeGroupOffseti.isEmpty())
00247         {
00248                 m_VerticeGroupOffseti.append(0);
00249         }
00250         int offset= m_VerticeGroupOffseti.last() + m_VerticeGrouprSizes.last();
00251         m_VerticeGroupOffseti.append(offset);
00252 
00253         // The Polyline id
00254         m_VerticeGroupId.append(m_NextPrimitiveLocalId);
00255         return m_NextPrimitiveLocalId++;
00256 }
00257 
00258 void GLC_WireData::clear()
00259 {
00260         m_VerticeBuffer.destroy();
00261         m_NextPrimitiveLocalId= 1;
00262         m_Positions.clear();
00263         m_PositionSize= 0;
00264         delete m_pBoundingBox;
00265         m_pBoundingBox= NULL;
00266 
00267         m_VerticeGrouprSizes.clear();
00268         m_VerticeGroupOffseti.clear();
00269         m_VerticeGroupId.clear();
00270         m_VerticeGroupCount= 0;
00271 }
00272 
00273 void GLC_WireData::copyVboToClientSide()
00274 {
00275         if (m_VerticeBuffer.isCreated() && m_Positions.isEmpty())
00276         {
00277                 m_Positions= positionVector();
00278 
00279                 if (m_ColorBuffer.isCreated() && m_Colors.isEmpty())
00280                 {
00281                         m_Colors= colorVector();
00282                 }
00283                 m_IndexVector= indexVector();
00284         }
00285 
00286 }
00287 
00288 void GLC_WireData::releaseVboClientSide(bool update)
00289 {
00290         if (m_VerticeBuffer.isCreated() && !m_Positions.isEmpty())
00291         {
00292                 if (update) finishVbo();
00293         }
00294 }
00295 
00296 void GLC_WireData::setVboUsage(bool usage)
00297 {
00298         m_UseVbo= usage;
00299         if (!isEmpty())
00300         {
00301                 if (m_UseVbo && (m_PositionSize != 0) && (!m_Positions.isEmpty())&& (!m_VerticeBuffer.isCreated()))
00302                 {
00303                         finishVbo();
00304                 }
00305                 else if (!m_UseVbo && m_VerticeBuffer.isCreated())
00306                 {
00307                         m_Positions= positionVector();
00308                         m_VerticeBuffer.destroy();
00309                         m_Colors= colorVector();
00310                         m_ColorBuffer.destroy();
00311                         m_IndexVector= indexVector();
00312                         m_IndexBuffer.destroy();
00313                 }
00314         }
00315 }
00316 
00318 // OpenGL Functions
00320 
00321 void GLC_WireData::finishVbo()
00322 {
00323         Q_ASSERT((NULL != QGLContext::currentContext()) &&  QGLContext::currentContext()->isValid());
00324         if (!m_VerticeBuffer.isCreated())
00325         {
00326                 m_VerticeBuffer.create();
00327         }
00328         if ((m_Colors.size() > 0) && !m_ColorBuffer.isCreated())
00329         {
00330                 m_ColorBuffer.create();
00331         }
00332         if (!m_IndexBuffer.isCreated())
00333         {
00334                 m_IndexBuffer.create();
00335         }
00336         fillVBOs();
00337 
00338         m_PositionSize= m_Positions.size();
00339         m_Positions.clear();
00340 
00341         m_IndexVector.clear();
00342 
00343         if (m_ColorBuffer.isCreated())
00344         {
00345                 m_ColorSize= m_Colors.size();
00346                 m_Colors.clear();
00347         }
00348 }
00349 
00350 void GLC_WireData::useVBO(GLC_WireData::VboType type, bool use)
00351 {
00352         if (use)
00353         {
00354 
00355                 // Chose the right VBO
00356                 if (type == GLC_WireData::GLC_Vertex)
00357                 {
00358                         if (!m_VerticeBuffer.bind())
00359                         {
00360                                 GLC_Exception exception("GLC_WireData::useVBO  Failed to bind vertex buffer");
00361                                 throw(exception);
00362                         }
00363                 }
00364                 else if (type == GLC_WireData::GLC_Color)
00365                 {
00366                         Q_ASSERT(m_ColorSize > 0);
00367                         if (!m_ColorBuffer.bind())
00368                         {
00369                                 GLC_Exception exception("GLC_WireData::useVBO  Failed to bind color buffer");
00370                                 throw(exception);
00371                         }
00372                 }
00373                 else if ((type == GLC_WireData::GLC_Index) && m_IndexBuffer.isCreated())
00374                 {
00375                         if (!m_IndexBuffer.bind())
00376                         {
00377                                 GLC_Exception exception("GLC_WireData::useVBO  Failed to bind index buffer");
00378                                 throw(exception);
00379                         }
00380                 }
00381         }
00382         else
00383         {
00384                 QGLBuffer::release(QGLBuffer::VertexBuffer);
00385                 QGLBuffer::release(QGLBuffer::IndexBuffer);
00386         }
00387 }
00388 
00389 void GLC_WireData::glDraw(const GLC_RenderProperties&, GLenum mode)
00390 {
00391         Q_ASSERT((NULL != QGLContext::currentContext()) &&  QGLContext::currentContext()->isValid());
00392         Q_ASSERT(!isEmpty());
00393 
00394         const bool vboIsUsed= m_UseVbo  && GLC_State::vboSupported();
00395 
00396         if (vboIsUsed && ((m_PositionSize == 0) || !m_VerticeBuffer.isCreated()))
00397         {
00398                 finishOffset();
00399                 buidIndex();
00400                 finishVbo();
00401         }
00402         else if (!vboIsUsed && (m_PositionSize == 0))
00403         {
00404                 finishOffset();
00405                 buidIndex();
00406                 m_PositionSize= m_Positions.size();
00407                 m_ColorSize= m_Colors.size();
00408         }
00409 
00410         // Activate VBO or Vertex Array
00411         if (vboIsUsed)
00412         {
00413                 activateVboAndIbo();
00414                 glVertexPointer(3, GL_FLOAT, 0, 0);
00415                 glEnableClientState(GL_VERTEX_ARRAY);
00416                 if (m_ColorSize > 0)
00417                 {
00418                         glColorPointer(4, GL_FLOAT, 0, 0);
00419                         glEnableClientState(GL_COLOR_ARRAY);
00420                 }
00421 
00422                 // Render polylines
00423                 for (int i= 0; i < m_VerticeGroupCount; ++i)
00424                 {
00425                         glDrawElements(mode, m_VerticeGrouprSizes.at(i), GL_UNSIGNED_INT, m_VerticeGroupOffset.at(i));
00426                 }
00427 
00428                 useVBO(GLC_WireData::GLC_Index, false);
00429         }
00430         else
00431         {
00432                 glVertexPointer(3, GL_FLOAT, 0, m_Positions.data());
00433                 glEnableClientState(GL_VERTEX_ARRAY);
00434                 if (m_ColorSize > 0)
00435                 {
00436                         glColorPointer(4, GL_FLOAT, 0, m_Colors.data());
00437                         glEnableClientState(GL_COLOR_ARRAY);
00438                 }
00439                 // Render polylines
00440                 for (int i= 0; i < m_VerticeGroupCount; ++i)
00441                 {
00442                         glDrawElements(mode, m_VerticeGrouprSizes.at(i), GL_UNSIGNED_INT, &(m_IndexVector.data()[m_VerticeGroupOffseti.at(i)]));
00443                 }
00444 
00445         }
00446 
00447         if (m_ColorSize > 0)
00448         {
00449                 glDisableClientState(GL_COLOR_ARRAY);
00450         }
00451 
00452         glDisableClientState(GL_VERTEX_ARRAY);
00453 
00454         if (vboIsUsed)
00455         {
00456                 QGLBuffer::release(QGLBuffer::IndexBuffer);
00457                 QGLBuffer::release(QGLBuffer::VertexBuffer);
00458         }
00459 }
00460 
00461 
00462 void GLC_WireData::fillVBOs()
00463 {
00464         {
00465                 Q_ASSERT(m_VerticeBuffer.isCreated());
00466                 useVBO(GLC_WireData::GLC_Vertex, true);
00467                 const GLsizei dataNbr= static_cast<GLsizei>(m_Positions.size());
00468                 const GLsizeiptr dataSize= dataNbr * sizeof(GLfloat);
00469                 m_VerticeBuffer.allocate(m_Positions.data(), dataSize);
00470         }
00471 
00472         {
00473                 Q_ASSERT(m_IndexBuffer.isCreated());
00474                 useVBO(GLC_WireData::GLC_Index, true);
00475                 const GLsizei dataNbr= static_cast<GLsizei>(m_IndexVector.size());
00476                 const GLsizeiptr dataSize= dataNbr * sizeof(GLuint);
00477                 m_IndexBuffer.allocate(m_IndexVector.data(), dataSize);
00478         }
00479 
00480         if (m_ColorBuffer.isCreated())
00481         {
00482                 useVBO(GLC_WireData::GLC_Color, true);
00483                 const GLsizei dataNbr= static_cast<GLsizei>(m_Colors.size());
00484                 const GLsizeiptr dataSize= dataNbr * sizeof(GLfloat);
00485                 m_ColorBuffer.allocate(m_Colors.data(), dataSize);
00486         }
00487 }
00488 
00489 void GLC_WireData::buidIndex()
00490 {
00491         const int size= m_Positions.size();
00492         m_IndexVector.resize(size);
00493         for (int i= 0; i < size; ++i)
00494         {
00495                 m_IndexVector[i]= i;
00496         }
00497 }
00498 
00499 void GLC_WireData::activateVboAndIbo()
00500 {
00501         // Activate Vertices VBO
00502         useVBO(GLC_WireData::GLC_Vertex, true);
00503         glVertexPointer(3, GL_FLOAT, 0, 0);
00504         glEnableClientState(GL_VERTEX_ARRAY);
00505 
00506         // Activate Color VBO if needed
00507         if (m_ColorSize > 0)
00508         {
00509                 useVBO(GLC_WireData::GLC_Color, true);
00510                 glEnable(GL_COLOR_MATERIAL);
00511                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
00512                 glColorPointer(4, GL_FLOAT, 0, 0);
00513                 glEnableClientState(GL_COLOR_ARRAY);
00514         }
00515 
00516         // Activate index Buffer object
00517         useVBO(GLC_WireData::GLC_Index, true);
00518 }
00519 
00520 void GLC_WireData::finishOffset()
00521 {
00522         m_VerticeGroupOffseti.remove(m_VerticeGroupOffseti.size() - 1);
00523         m_VerticeGroupOffset.clear();
00524         const int offsetSize= m_VerticeGroupOffseti.size();
00525         for (int i= 0; i < offsetSize; ++i)
00526         {
00527                 m_VerticeGroupOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_VerticeGroupOffseti.at(i)) * sizeof(GLuint)));
00528         }
00529 }
00530 
00531 QDataStream &operator<<(QDataStream &stream, const GLC_WireData &wireData)
00532 {
00533         quint32 chunckId= GLC_WireData::m_ChunkId;
00534         stream << chunckId;
00535 
00536         stream << wireData.m_NextPrimitiveLocalId;
00537         stream << wireData.positionVector();
00538         stream << wireData.m_PositionSize;
00539 
00540         stream << wireData.m_VerticeGrouprSizes;
00541         stream << wireData.m_VerticeGroupOffseti;
00542         stream << wireData.m_VerticeGroupId;
00543         stream << wireData.m_VerticeGroupCount;
00544 
00545         // New version Data
00546         stream << wireData.colorVector();
00547         stream << wireData.m_ColorSize;
00548 
00549         return stream;
00550 }
00551 
00552 QDataStream &operator>>(QDataStream &stream, GLC_WireData &wireData)
00553 {
00554         quint32 chunckId;
00555         stream >> chunckId;
00556         Q_ASSERT((chunckId == GLC_WireData::m_ChunkId) || chunckId == 0xA706);
00557 
00558         wireData.clear();
00559         stream >> wireData.m_NextPrimitiveLocalId;
00560         stream >> wireData.m_Positions;
00561         stream >> wireData.m_PositionSize;
00562 
00563         stream >> wireData.m_VerticeGrouprSizes;
00564         stream >> wireData.m_VerticeGroupOffseti;
00565         stream >> wireData.m_VerticeGroupId;
00566         stream >> wireData.m_VerticeGroupCount;
00567 
00568         if (chunckId == GLC_WireData::m_ChunkId)
00569         {
00570                 // New version Data
00571                 stream >> wireData.m_Colors;
00572                 stream >> wireData.m_ColorSize;
00573         }
00574 
00575         return stream;
00576 }

SourceForge.net Logo

©2005-2011 Laurent Ribon