glc_offtoworld.cpp

Go to the documentation of this file.
00001 
00002 /****************************************************************************
00003 
00004  This file is part of the GLC-lib library.
00005  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00006  Version 2.0.0 Beta 1, packaged on April 2010.
00007 
00008  http://glc-lib.sourceforge.net
00009 
00010  GLC-lib is free software; you can redistribute it and/or modify
00011  it under the terms of the GNU General Public License as published by
00012  the Free Software Foundation; either version 2 of the License, or
00013  (at your option) any later version.
00014 
00015  GLC-lib is distributed in the hope that it will be useful,
00016  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  GNU General Public License for more details.
00019 
00020  You should have received a copy of the GNU General Public License
00021  along with GLC-lib; if not, write to the Free Software
00022  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023 
00024 *****************************************************************************/
00025 
00027 
00028 #include "glc_offtoworld.h"
00029 #include "../sceneGraph/glc_world.h"
00030 #include "../glc_fileformatexception.h"
00031 #include "../sceneGraph/glc_structreference.h"
00032 #include "../sceneGraph/glc_structinstance.h"
00033 #include "../sceneGraph/glc_structoccurence.h"
00034 
00035 #include <QTextStream>
00036 #include <QFileInfo>
00037 #include <QGLContext>
00038 
00039 GLC_OffToWorld::GLC_OffToWorld()
00040 : m_pWorld(NULL)
00041 , m_FileName()
00042 , m_CurrentLineNumber(0)
00043 , m_pCurrentMesh(NULL)
00044 , m_CurVertexIndex(0)
00045 , m_NbrOfVertexs(0)
00046 , m_NbrOfFaces(0)
00047 , m_IsCoff(false)
00048 , m_Is4off(false)
00049 , m_PositionBulk()
00050 , m_NormalBulk()
00051 , m_ColorBulk()
00052 , m_IndexList()
00053 {
00054 
00055 }
00056 
00057 GLC_OffToWorld::~GLC_OffToWorld()
00058 {
00059         clear();
00060 }
00061 
00063 // Set Functions
00065 
00066 // Create an GLC_World from an input OFF File
00067 GLC_World* GLC_OffToWorld::CreateWorldFromOff(QFile &file)
00068 {
00069         clear();
00070         m_FileName= file.fileName();
00072         // Test if the file exist and can be opened
00074         if (!file.open(QIODevice::ReadOnly))
00075         {
00076                 QString message(QString("GLC_OffToWorld::CreateWorldFromOff File ") + m_FileName + QString(" doesn't exist"));
00077                 qDebug() << message;
00078                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00079                 throw(fileFormatException);
00080         }
00081 
00083         // Init member
00085         m_pWorld= new GLC_World;
00086 
00087         // Create Working variables
00088         int currentQuantumValue= 0;
00089         int previousQuantumValue= 0;
00090 
00091         // Create the input file stream
00092         QTextStream offStream(&file);
00093 
00094         // QString buffer
00095         QString lineBuff;
00096 
00098         // Check the OFF Header
00100         // Check if the file begin with "OFF" or "COFF"
00101         ++m_CurrentLineNumber;
00102         lineBuff= offStream.readLine();
00103         lineBuff= lineBuff.trimmed();
00104         if(offStream.atEnd() || (!lineBuff.startsWith("OFF") && !lineBuff.startsWith("COFF") && !lineBuff.startsWith("4OFF")))
00105         {
00106                 QString message= "GLC_OffToWorld::CreateWorldFromOff : OFF or COFF header not found";
00107                 qDebug() << message;
00108                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00109                 clear();
00110                 throw(fileFormatException);
00111         }
00112 
00113         // Set the COFF flag
00114         m_IsCoff= lineBuff.startsWith("COFF");
00115 
00116         // Set the 4OFF flag
00117         m_Is4off= lineBuff.startsWith("4OFF");
00118 
00119         // Create the mesh
00120         m_pCurrentMesh= new GLC_Mesh();
00121 
00122         // Set mesh color per vertex if needed
00123         if (m_IsCoff)
00124         {
00125                 m_pCurrentMesh->setColorPearVertex(true);
00126         }
00127         // Get the number of vertex and faces and skip comments
00128         ++m_CurrentLineNumber;
00129         lineBuff= offStream.readLine();
00130         lineBuff= lineBuff.trimmed();
00131         while(!offStream.atEnd() && lineBuff.startsWith(QChar('#')))
00132         {
00133                 ++m_CurrentLineNumber;
00134                 lineBuff= offStream.readLine();
00135                 lineBuff= lineBuff.trimmed();
00136         }
00137         extractNbrVertexsAndNbrFaces(lineBuff);
00138 
00140         // Read Buffer and load vertexs
00142         emit currentQuantum(currentQuantumValue);
00143 
00144         for (int currentVertex= 0; currentVertex < m_NbrOfVertexs; ++currentVertex)
00145         {
00146                 // Check it the end of file has been reached
00147                 if(offStream.atEnd())
00148                 {
00149                         QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
00150                         message.append("\nAt ligne : ");
00151                         message.append(QString::number(m_CurrentLineNumber));
00152                         qDebug() << message;
00153                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00154                         clear();
00155                         throw(fileFormatException);
00156                 }
00157 
00158                 ++m_CurrentLineNumber;
00159                 lineBuff= offStream.readLine();
00160                 // Skip empty line
00161                 while (lineBuff.isEmpty())
00162                 {
00163                         ++m_CurrentLineNumber;
00164                         lineBuff= offStream.readLine();
00165                 }
00166                 // Add current vertex and color if needed to the mesh
00167                 extractVertex(lineBuff);
00168 
00169                 // Update Current Quantum for progress bar usage.
00170                 currentQuantumValue = static_cast<int>((static_cast<double>(currentVertex) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
00171                 if (currentQuantumValue > previousQuantumValue)
00172                 {
00173                         emit currentQuantum(currentQuantumValue);
00174                 }
00175                 previousQuantumValue= currentQuantumValue;
00176         }
00177 
00179         // Read Buffer and load faces
00181         for (int currentFace= 0; currentFace < m_NbrOfFaces; ++currentFace)
00182         {
00183                 // Check it the end of file has been reached
00184                 if(offStream.atEnd())
00185                 {
00186                         QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
00187                         message.append("\nAt ligne : ");
00188                         message.append(QString::number(m_CurrentLineNumber));
00189                         qDebug() << message;
00190                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00191                         clear();
00192                         throw(fileFormatException);
00193                 }
00194 
00195                 ++m_CurrentLineNumber;
00196                 lineBuff= offStream.readLine();
00197                 while (lineBuff.isEmpty())
00198                 {
00199                         ++m_CurrentLineNumber;
00200                         lineBuff= offStream.readLine();
00201                 }
00202 
00203                 // Add current Face to the mesh
00204                 extractFaceIndex(lineBuff);
00205 
00206                 // Update Current Quantum for progress bar usage.
00207                 currentQuantumValue = static_cast<int>((static_cast<double>(currentFace + m_NbrOfVertexs + 1) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
00208                 if (currentQuantumValue > previousQuantumValue)
00209                 {
00210                         emit currentQuantum(currentQuantumValue);
00211                 }
00212                 previousQuantumValue= currentQuantumValue;
00213 
00214         }
00215 
00216         file.close();
00217         // Compute mesh normals
00218         computeNormal();
00219 
00220         m_pCurrentMesh->addVertice(m_PositionBulk.toVector());
00221         m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00222         if (!m_ColorBulk.isEmpty())
00223         {
00224                 m_pCurrentMesh->addColors(m_ColorBulk.toVector());
00225         }
00226         m_pCurrentMesh->addTriangles(NULL, m_IndexList);
00227 
00228         m_pCurrentMesh->finish();
00229         GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00230         m_pCurrentMesh= NULL;
00231         m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00232 
00233         return m_pWorld;
00234 }
00235 
00237 // Private services Functions
00239 
00240 // clear offToWorld allocate memmory and reset member
00241 void GLC_OffToWorld::clear()
00242 {
00243         if (NULL != m_pCurrentMesh)
00244         {
00245                 delete m_pCurrentMesh;
00246                 m_pCurrentMesh= NULL;
00247         }
00248         m_pWorld= NULL;
00249         m_FileName.clear();
00250         m_CurrentLineNumber= 0;
00251         m_pCurrentMesh= NULL;
00252         m_CurVertexIndex= 0;
00253         m_NbrOfVertexs= 0;
00254         m_NbrOfFaces= 0;
00255         m_IsCoff= false;
00256         m_Is4off= false;
00257         m_PositionBulk.clear();
00258         m_NormalBulk.clear();
00259         m_ColorBulk.clear();
00260 }
00261 
00262 // Extract a Vertex from a string and add color component if needed
00263 void GLC_OffToWorld::extractVertex(QString &line)
00264 {
00265 
00266         QTextStream stringVecteur(&line);
00267 
00268         QString xString, yString, zString;
00269 
00270         if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00271         {
00272                 bool xOk, yOk, zOk;
00273                 m_PositionBulk.append(xString.toFloat(&xOk));
00274                 m_PositionBulk.append(yString.toFloat(&yOk));
00275                 m_PositionBulk.append(zString.toFloat(&zOk));
00276                 if (!(xOk && yOk && zOk))
00277                 {
00278                         QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex component to float";
00279                         message.append("\nAt ligne : ");
00280                         message.append(QString::number(m_CurrentLineNumber));
00281                         qDebug() << message;
00282                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00283                         clear();
00284                         throw(fileFormatException);
00285                 }
00286                 if (m_Is4off)
00287                 {
00288                         QString wString;
00289                         if (((stringVecteur >> wString).status() == QTextStream::Ok))
00290                         {
00291                                 float w;
00292                                 bool wOk;
00293                                 w= wString.toFloat(&wOk);
00294                                 if (!wOk)
00295                                 {
00296                                         QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex fourth component to float";
00297                                         message.append("\nAt ligne : ");
00298                                         message.append(QString::number(m_CurrentLineNumber));
00299                                         qDebug() << message;
00300                                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00301                                         clear();
00302                                         throw(fileFormatException);
00303                                 }
00304                                 const int lastValue= m_PositionBulk.size() - 1;
00305                                 m_PositionBulk[lastValue - 2]= m_PositionBulk.at(lastValue - 2) / w;
00306                                 m_PositionBulk[lastValue - 1]= m_PositionBulk.at(lastValue - 1) / w;
00307                                 m_PositionBulk[lastValue]= m_PositionBulk.at(lastValue) / w;
00308                         }
00309                         else
00310                         {
00311                                 QString message= "GLC_OffToWorld::extractVertex : failed to read vector fourth component";
00312                                 message.append("\nAt ligne : ");
00313                                 message.append(QString::number(m_CurrentLineNumber));
00314                                 qDebug() << message;
00315                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00316                                 clear();
00317                                 throw(fileFormatException);
00318                         }
00319                 }
00320 
00321                 // Test if the file is a COFF
00322                 if (m_IsCoff)
00323                 {
00324                         QString rString, gString, bString, aString;
00325 
00326                         if (((stringVecteur >> rString >> gString >> bString >> aString).status() == QTextStream::Ok))
00327                         {
00328                                 bool rOk, gOk, bOk, aOk;
00329                                 m_ColorBulk.append(rString.toFloat(&rOk));
00330                                 m_ColorBulk.append(gString.toFloat(&gOk));
00331                                 m_ColorBulk.append(bString.toFloat(&bOk));
00332                                 m_ColorBulk.append(aString.toFloat(&aOk));
00333                                 if (!(rOk && gOk && bOk && aOk))
00334                                 {
00335                                         QString message= "GLC_OffToWorld::extractVertex : failed to convert color component to float";
00336                                         message.append("\nAt ligne : ");
00337                                         message.append(QString::number(m_CurrentLineNumber));
00338                                         qDebug() << message;
00339                                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00340                                         clear();
00341                                         throw(fileFormatException);
00342                                 }
00343                         }
00344                         else
00345                         {
00346                                 QString message= "GLC_OffToWorld::extractVertex : failed to read vertex color";
00347                                 message.append("\nAt ligne : ");
00348                                 message.append(QString::number(m_CurrentLineNumber));
00349                                 qDebug() << message;
00350                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00351                                 clear();
00352                                 throw(fileFormatException);
00353                         }
00354                 }
00355 
00356         }
00357         else
00358         {
00359                 QString message= "GLC_OffToWorld::extractVertex : failed to read vector component";
00360                 message.append("\nAt ligne : ");
00361                 message.append(QString::number(m_CurrentLineNumber));
00362                 qDebug() << message;
00363                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00364                 clear();
00365                 throw(fileFormatException);
00366         }
00367 
00368 }
00369 
00370 // Extract Number off Vertex and faces
00371 void GLC_OffToWorld::extractNbrVertexsAndNbrFaces(QString &line)
00372 {
00373         QTextStream stringVecteur(&line);
00374 
00375         QString xString, yString;
00376 
00377         if (((stringVecteur >> xString >> yString).status() == QTextStream::Ok))
00378         {
00379                 bool xOk, yOk;
00380                 m_NbrOfVertexs= xString.toInt(&xOk);
00381                 m_NbrOfFaces= yString.toInt(&yOk);
00382                 if (!(xOk && yOk))
00383                 {
00384                         QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to convert text to int";
00385                         message.append("\nAt ligne : ");
00386                         message.append(QString::number(m_CurrentLineNumber));
00387                         qDebug() << message;
00388                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00389                         clear();
00390                         throw(fileFormatException);
00391                 }
00392         }
00393         else
00394         {
00395                 QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to extract nbr of vertexs/faces";
00396                 message.append("\nAt ligne : ");
00397                 message.append(QString::number(m_CurrentLineNumber));
00398                 qDebug() << message;
00399                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00400                 clear();
00401                 throw(fileFormatException);
00402 
00403         }
00404 }
00405 
00406 // Extract a face from a string
00407 void GLC_OffToWorld::extractFaceIndex(QString &line)
00408 {
00409         QString buff;
00410 
00411         QList<GLuint> indexList;
00412 
00414         // Parse the line containing face index
00416         QTextStream streamFace(&line);
00417         // Get the number of vertex
00418         if((streamFace >> buff).status() != QTextStream::Ok)
00419         {
00420                 QString message= "GLC_OffToWorld::extractFaceIndex failed to extract number of vertex index";
00421                 message.append("\nAt line : ");
00422                 message.append(QString::number(m_CurrentLineNumber));
00423                 message.append(QString("\n") + line);
00424                 qDebug() << message;
00425                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00426                 clear();
00427                 throw(fileFormatException);
00428         }
00429         bool conversionOk;
00430         // Convert the QString Number of vertex to int
00431         int numberOfVertex= buff.toInt(&conversionOk);
00432         if (!conversionOk)
00433         {
00434                 QString message= "GLC_OffToWorld::extractFaceIndex failed to convert String to int";
00435                 message.append("\nAt line : ");
00436                 message.append(QString::number(m_CurrentLineNumber));
00437                 qDebug() << message;
00438                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00439                 clear();
00440                 throw(fileFormatException);
00441         }
00442         // Extract the face's vertexs index
00443         for (int i= 0; i < numberOfVertex; ++i)
00444         {
00445                 // Get a vertex index
00446                 if((streamFace >> buff).status() != QTextStream::Ok)
00447                 {
00448                         QString message= "GLC_OffToWorld::extractFaceIndex failed to extract vertex index";
00449                         message.append("\nAt line : ");
00450                         message.append(QString::number(m_CurrentLineNumber));
00451                         qDebug() << message;
00452                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00453                         clear();
00454                         throw(fileFormatException);
00455                 }
00456                 // Convert the QString vertex index into int
00457                 int index= buff.toInt(&conversionOk);
00458                 if (conversionOk)
00459                 {
00460                         indexList.append(index);
00461                 }
00462                 else
00463                 {
00464                         QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to int";
00465                         message.append("\nAt line : ");
00466                         message.append(QString::number(m_CurrentLineNumber));
00467                         qDebug() << message;
00468                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00469                         clear();
00470                         throw(fileFormatException);
00471                 }
00472         }
00473 
00474         // Trying to read face color
00475         QString rString, gString, bString;
00476         if((streamFace >> rString >> gString >> bString).status() == QTextStream::Ok)
00477         {
00478                 // Fill color bulk data if needed
00479                 if (m_ColorBulk.isEmpty())
00480                 {
00481                         const int size= m_PositionBulk.size() / 3 * 4;
00482                         for (int i= 0; i < size; ++i)
00483                         {
00484                                 m_PositionBulk.append(0.0);
00485                         }
00486                 }
00487                 float r, g, b;
00488                 bool rOk, gOk, bOk;
00489                 r= rString.toFloat(&rOk);
00490                 g= gString.toFloat(&gOk);
00491                 b= bString.toFloat(&bOk);
00492                 if (!rOk || !gOk || !bOk)
00493                 {
00494                         QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to float";
00495                         message.append("\nAt line : ");
00496                         message.append(QString::number(m_CurrentLineNumber));
00497                         qDebug() << message;
00498                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00499                         clear();
00500                         throw(fileFormatException);
00501                 }
00502                 for (int i= 0; i < numberOfVertex; ++i)
00503                 {
00504                         m_ColorBulk[indexList[i] * 4]= r;
00505                         m_ColorBulk[indexList[i] * 4 + 1]= g;
00506                         m_ColorBulk[indexList[i] * 4 + 2]= b;
00507                         m_ColorBulk[indexList[i] * 4 + 3]= 1.0f;
00508                 }
00509         }
00510 
00511         // Add the face to index List
00512         m_IndexList.append(indexList);
00513 }
00514 
00515 // compute face normal
00516 void GLC_OffToWorld::computeNormal()
00517 {
00518         qDebug() << "GLC_OffToWorld::computeNormal";
00519         qDebug() << "Position size= " << m_PositionBulk.size();
00520         qDebug() << "Normal size= " << m_NormalBulk.size();
00521         const QList<float>* pData= &m_PositionBulk;
00522         // Fill the list of normal
00523         QList<float>* pNormal= &m_NormalBulk;
00524         const int normalCount= pData->size();
00525         for (int i= 0; i < normalCount; ++i)
00526         {
00527                 pNormal->append(0.0f);
00528         }
00529         // Compute the normals and add them to the current mesh info
00530         const int size= m_IndexList.size();
00531         double xn, yn, zn;
00532 
00533 
00534         for (int i= 0; i < size; i+=3)
00535         {
00536                 // Vertex 1
00537                 xn= pData->at(m_IndexList.at(i) * 3);
00538                 yn= pData->at(m_IndexList.at(i) * 3 + 1);
00539                 zn= pData->at(m_IndexList.at(i) * 3 + 2);
00540                 const GLC_Vector3d vect1(xn, yn, zn);
00541 
00542                 // Vertex 2
00543                 xn= pData->at(m_IndexList.at(i + 1) * 3);
00544                 yn= pData->at(m_IndexList.at(i + 1) * 3  + 1);
00545                 zn= pData->at(m_IndexList.at(i + 1) * 3 + 2);
00546                 const GLC_Vector3d vect2(xn, yn, zn);
00547 
00548                 // Vertex 3
00549                 xn= pData->at(m_IndexList.at(i + 2) * 3);
00550                 yn= pData->at(m_IndexList.at(i + 2) * 3 + 1);
00551                 zn= pData->at(m_IndexList.at(i + 2) * 3 + 2);
00552                 const GLC_Vector3d vect3(xn, yn, zn);
00553 
00554                 const GLC_Vector3d edge1(vect3 - vect2);
00555                 const GLC_Vector3d edge2(vect1 - vect2);
00556 
00557                 GLC_Vector3d normal(edge1 ^ edge2);
00558                 normal.normalize();
00559 
00560                 GLC_Vector3df curNormal= normal.toVector3df();
00561                 for (int curVertex= 0; curVertex < 3; ++curVertex)
00562                 {
00563                         (*pNormal)[m_IndexList.at(i + curVertex) * 3]= curNormal.X();
00564                         (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 1]= curNormal.Y();
00565                         (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 2]= curNormal.Z();
00566                 }
00567         }
00568 
00569 }
00570 

SourceForge.net Logo

©2005 Laurent Ribon