00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00025
00026 #include "glc_offtoworld.h"
00027 #include "../sceneGraph/glc_world.h"
00028 #include "../glc_fileformatexception.h"
00029 #include "../sceneGraph/glc_structreference.h"
00030 #include "../sceneGraph/glc_structinstance.h"
00031 #include "../sceneGraph/glc_structoccurence.h"
00032
00033 #include <QTextStream>
00034 #include <QFileInfo>
00035 #include <QGLContext>
00036
00037 GLC_OffToWorld::GLC_OffToWorld()
00038 : m_pWorld(NULL)
00039 , m_FileName()
00040 , m_CurrentLineNumber(0)
00041 , m_pCurrentMesh(NULL)
00042 , m_CurVertexIndex(0)
00043 , m_NbrOfVertexs(0)
00044 , m_NbrOfFaces(0)
00045 , m_IsCoff(false)
00046 , m_Is4off(false)
00047 , m_PositionBulk()
00048 , m_NormalBulk()
00049 , m_ColorBulk()
00050 , m_IndexList()
00051 {
00052
00053 }
00054
00055 GLC_OffToWorld::~GLC_OffToWorld()
00056 {
00057 clear();
00058 }
00059
00061
00063
00064
00065 GLC_World* GLC_OffToWorld::CreateWorldFromOff(QFile &file)
00066 {
00067 clear();
00068 m_FileName= file.fileName();
00070
00072 if (!file.open(QIODevice::ReadOnly))
00073 {
00074 QString message(QString("GLC_OffToWorld::CreateWorldFromOff File ") + m_FileName + QString(" doesn't exist"));
00075 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00076 throw(fileFormatException);
00077 }
00078
00080
00082 m_pWorld= new GLC_World;
00083
00084
00085 int currentQuantumValue= 0;
00086 int previousQuantumValue= 0;
00087
00088
00089 QTextStream offStream(&file);
00090
00091
00092 QString lineBuff;
00093
00095
00097
00098 ++m_CurrentLineNumber;
00099 lineBuff= offStream.readLine();
00100 lineBuff= lineBuff.trimmed();
00101 if(offStream.atEnd() || (!lineBuff.startsWith("OFF") && !lineBuff.startsWith("COFF") && !lineBuff.startsWith("4OFF")))
00102 {
00103 QString message= "GLC_OffToWorld::CreateWorldFromOff : OFF or COFF header not found";
00104 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00105 clear();
00106 throw(fileFormatException);
00107 }
00108
00109
00110 m_IsCoff= lineBuff.startsWith("COFF");
00111
00112
00113 m_Is4off= lineBuff.startsWith("4OFF");
00114
00115
00116 m_pCurrentMesh= new GLC_Mesh();
00117
00118
00119 if (m_IsCoff)
00120 {
00121 m_pCurrentMesh->setColorPearVertex(true);
00122 }
00123
00124 ++m_CurrentLineNumber;
00125 lineBuff= offStream.readLine();
00126 lineBuff= lineBuff.trimmed();
00127 while(!offStream.atEnd() && lineBuff.startsWith(QChar('#')))
00128 {
00129 ++m_CurrentLineNumber;
00130 lineBuff= offStream.readLine();
00131 lineBuff= lineBuff.trimmed();
00132 }
00133 extractNbrVertexsAndNbrFaces(lineBuff);
00134
00136
00138 emit currentQuantum(currentQuantumValue);
00139
00140 for (int currentVertex= 0; currentVertex < m_NbrOfVertexs; ++currentVertex)
00141 {
00142
00143 if(offStream.atEnd())
00144 {
00145 QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
00146 message.append("\nAt ligne : ");
00147 message.append(QString::number(m_CurrentLineNumber));
00148 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00149 clear();
00150 throw(fileFormatException);
00151 }
00152
00153 ++m_CurrentLineNumber;
00154 lineBuff= offStream.readLine();
00155
00156 while (lineBuff.isEmpty())
00157 {
00158 ++m_CurrentLineNumber;
00159 lineBuff= offStream.readLine();
00160 }
00161
00162 extractVertex(lineBuff);
00163
00164
00165 currentQuantumValue = static_cast<int>((static_cast<double>(currentVertex) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
00166 if (currentQuantumValue > previousQuantumValue)
00167 {
00168 emit currentQuantum(currentQuantumValue);
00169 }
00170 previousQuantumValue= currentQuantumValue;
00171 }
00172
00174
00176 for (int currentFace= 0; currentFace < m_NbrOfFaces; ++currentFace)
00177 {
00178
00179 if(offStream.atEnd())
00180 {
00181 QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
00182 message.append("\nAt ligne : ");
00183 message.append(QString::number(m_CurrentLineNumber));
00184 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00185 clear();
00186 throw(fileFormatException);
00187 }
00188
00189 ++m_CurrentLineNumber;
00190 lineBuff= offStream.readLine();
00191 while (lineBuff.isEmpty())
00192 {
00193 ++m_CurrentLineNumber;
00194 lineBuff= offStream.readLine();
00195 }
00196
00197
00198 extractFaceIndex(lineBuff);
00199
00200
00201 currentQuantumValue = static_cast<int>((static_cast<double>(currentFace + m_NbrOfVertexs + 1) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
00202 if (currentQuantumValue > previousQuantumValue)
00203 {
00204 emit currentQuantum(currentQuantumValue);
00205 }
00206 previousQuantumValue= currentQuantumValue;
00207
00208 }
00209
00210 file.close();
00211
00212 computeNormal();
00213
00214 m_pCurrentMesh->addVertice(m_PositionBulk.toVector());
00215 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00216 if (!m_ColorBulk.isEmpty())
00217 {
00218 m_pCurrentMesh->addColors(m_ColorBulk.toVector());
00219 }
00220 m_pCurrentMesh->addTriangles(NULL, m_IndexList);
00221
00222 m_pCurrentMesh->finish();
00223 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00224 m_pCurrentMesh= NULL;
00225 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00226
00227 return m_pWorld;
00228 }
00229
00231
00233
00234
00235 void GLC_OffToWorld::clear()
00236 {
00237 if (NULL != m_pCurrentMesh)
00238 {
00239 delete m_pCurrentMesh;
00240 m_pCurrentMesh= NULL;
00241 }
00242 m_pWorld= NULL;
00243 m_FileName.clear();
00244 m_CurrentLineNumber= 0;
00245 m_pCurrentMesh= NULL;
00246 m_CurVertexIndex= 0;
00247 m_NbrOfVertexs= 0;
00248 m_NbrOfFaces= 0;
00249 m_IsCoff= false;
00250 m_Is4off= false;
00251 m_PositionBulk.clear();
00252 m_NormalBulk.clear();
00253 m_ColorBulk.clear();
00254 }
00255
00256
00257 void GLC_OffToWorld::extractVertex(QString &line)
00258 {
00259
00260 QTextStream stringVecteur(&line);
00261
00262 QString xString, yString, zString;
00263
00264 if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00265 {
00266 bool xOk, yOk, zOk;
00267 m_PositionBulk.append(xString.toFloat(&xOk));
00268 m_PositionBulk.append(yString.toFloat(&yOk));
00269 m_PositionBulk.append(zString.toFloat(&zOk));
00270 if (!(xOk && yOk && zOk))
00271 {
00272 QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex component to float";
00273 message.append("\nAt ligne : ");
00274 message.append(QString::number(m_CurrentLineNumber));
00275 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00276 clear();
00277 throw(fileFormatException);
00278 }
00279 if (m_Is4off)
00280 {
00281 QString wString;
00282 if (((stringVecteur >> wString).status() == QTextStream::Ok))
00283 {
00284 float w;
00285 bool wOk;
00286 w= wString.toFloat(&wOk);
00287 if (!wOk)
00288 {
00289 QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex fourth component to float";
00290 message.append("\nAt ligne : ");
00291 message.append(QString::number(m_CurrentLineNumber));
00292 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00293 clear();
00294 throw(fileFormatException);
00295 }
00296 const int lastValue= m_PositionBulk.size() - 1;
00297 m_PositionBulk[lastValue - 2]= m_PositionBulk.at(lastValue - 2) / w;
00298 m_PositionBulk[lastValue - 1]= m_PositionBulk.at(lastValue - 1) / w;
00299 m_PositionBulk[lastValue]= m_PositionBulk.at(lastValue) / w;
00300 }
00301 else
00302 {
00303 QString message= "GLC_OffToWorld::extractVertex : failed to read vector fourth component";
00304 message.append("\nAt ligne : ");
00305 message.append(QString::number(m_CurrentLineNumber));
00306 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00307 clear();
00308 throw(fileFormatException);
00309 }
00310 }
00311
00312
00313 if (m_IsCoff)
00314 {
00315 QString rString, gString, bString, aString;
00316
00317 if (((stringVecteur >> rString >> gString >> bString >> aString).status() == QTextStream::Ok))
00318 {
00319 bool rOk, gOk, bOk, aOk;
00320 m_ColorBulk.append(rString.toFloat(&rOk));
00321 m_ColorBulk.append(gString.toFloat(&gOk));
00322 m_ColorBulk.append(bString.toFloat(&bOk));
00323 m_ColorBulk.append(aString.toFloat(&aOk));
00324 if (!(rOk && gOk && bOk && aOk))
00325 {
00326 QString message= "GLC_OffToWorld::extractVertex : failed to convert color component to float";
00327 message.append("\nAt ligne : ");
00328 message.append(QString::number(m_CurrentLineNumber));
00329 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00330 clear();
00331 throw(fileFormatException);
00332 }
00333 }
00334 else
00335 {
00336 QString message= "GLC_OffToWorld::extractVertex : failed to read vertex color";
00337 message.append("\nAt ligne : ");
00338 message.append(QString::number(m_CurrentLineNumber));
00339 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00340 clear();
00341 throw(fileFormatException);
00342 }
00343 }
00344
00345 }
00346 else
00347 {
00348 QString message= "GLC_OffToWorld::extractVertex : failed to read vector component";
00349 message.append("\nAt ligne : ");
00350 message.append(QString::number(m_CurrentLineNumber));
00351 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00352 clear();
00353 throw(fileFormatException);
00354 }
00355
00356 }
00357
00358
00359 void GLC_OffToWorld::extractNbrVertexsAndNbrFaces(QString &line)
00360 {
00361 QTextStream stringVecteur(&line);
00362
00363 QString xString, yString;
00364
00365 if (((stringVecteur >> xString >> yString).status() == QTextStream::Ok))
00366 {
00367 bool xOk, yOk;
00368 m_NbrOfVertexs= xString.toInt(&xOk);
00369 m_NbrOfFaces= yString.toInt(&yOk);
00370 if (!(xOk && yOk))
00371 {
00372 QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to convert text to int";
00373 message.append("\nAt ligne : ");
00374 message.append(QString::number(m_CurrentLineNumber));
00375 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00376 clear();
00377 throw(fileFormatException);
00378 }
00379 }
00380 else
00381 {
00382 QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to extract nbr of vertexs/faces";
00383 message.append("\nAt ligne : ");
00384 message.append(QString::number(m_CurrentLineNumber));
00385 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00386 clear();
00387 throw(fileFormatException);
00388
00389 }
00390 }
00391
00392
00393 void GLC_OffToWorld::extractFaceIndex(QString &line)
00394 {
00395 QString buff;
00396
00397 QList<GLuint> indexList;
00398
00400
00402 QTextStream streamFace(&line);
00403
00404 if((streamFace >> buff).status() != QTextStream::Ok)
00405 {
00406 QString message= "GLC_OffToWorld::extractFaceIndex failed to extract number of vertex index";
00407 message.append("\nAt line : ");
00408 message.append(QString::number(m_CurrentLineNumber));
00409 message.append(QString("\n") + line);
00410 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00411 clear();
00412 throw(fileFormatException);
00413 }
00414 bool conversionOk;
00415
00416 int numberOfVertex= buff.toInt(&conversionOk);
00417 if (!conversionOk)
00418 {
00419 QString message= "GLC_OffToWorld::extractFaceIndex failed to convert String to int";
00420 message.append("\nAt line : ");
00421 message.append(QString::number(m_CurrentLineNumber));
00422 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00423 clear();
00424 throw(fileFormatException);
00425 }
00426
00427 for (int i= 0; i < numberOfVertex; ++i)
00428 {
00429
00430 if((streamFace >> buff).status() != QTextStream::Ok)
00431 {
00432 QString message= "GLC_OffToWorld::extractFaceIndex failed to extract vertex index";
00433 message.append("\nAt line : ");
00434 message.append(QString::number(m_CurrentLineNumber));
00435 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00436 clear();
00437 throw(fileFormatException);
00438 }
00439
00440 int index= buff.toInt(&conversionOk);
00441 if (conversionOk)
00442 {
00443 indexList.append(index);
00444 }
00445 else
00446 {
00447 QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to int";
00448 message.append("\nAt line : ");
00449 message.append(QString::number(m_CurrentLineNumber));
00450 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00451 clear();
00452 throw(fileFormatException);
00453 }
00454 }
00455
00456
00457 QString rString, gString, bString;
00458 if((streamFace >> rString >> gString >> bString).status() == QTextStream::Ok)
00459 {
00460
00461 if (m_ColorBulk.isEmpty())
00462 {
00463 const int size= m_PositionBulk.size() / 3 * 4;
00464 for (int i= 0; i < size; ++i)
00465 {
00466 m_PositionBulk.append(0.0);
00467 }
00468 }
00469 float r, g, b;
00470 bool rOk, gOk, bOk;
00471 r= rString.toFloat(&rOk);
00472 g= gString.toFloat(&gOk);
00473 b= bString.toFloat(&bOk);
00474 if (!rOk || !gOk || !bOk)
00475 {
00476 QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to float";
00477 message.append("\nAt line : ");
00478 message.append(QString::number(m_CurrentLineNumber));
00479 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00480 clear();
00481 throw(fileFormatException);
00482 }
00483 for (int i= 0; i < numberOfVertex; ++i)
00484 {
00485 m_ColorBulk[indexList[i] * 4]= r;
00486 m_ColorBulk[indexList[i] * 4 + 1]= g;
00487 m_ColorBulk[indexList[i] * 4 + 2]= b;
00488 m_ColorBulk[indexList[i] * 4 + 3]= 1.0f;
00489 }
00490 }
00491
00492
00493 m_IndexList.append(indexList);
00494 }
00495
00496
00497 void GLC_OffToWorld::computeNormal()
00498 {
00499
00500
00501
00502 const QList<float>* pData= &m_PositionBulk;
00503
00504 QList<float>* pNormal= &m_NormalBulk;
00505 const int normalCount= pData->size();
00506 for (int i= 0; i < normalCount; ++i)
00507 {
00508 pNormal->append(0.0f);
00509 }
00510
00511 const int size= m_IndexList.size();
00512 double xn, yn, zn;
00513
00514
00515 for (int i= 0; i < size; i+=3)
00516 {
00517
00518 xn= pData->at(m_IndexList.at(i) * 3);
00519 yn= pData->at(m_IndexList.at(i) * 3 + 1);
00520 zn= pData->at(m_IndexList.at(i) * 3 + 2);
00521 const GLC_Vector3d vect1(xn, yn, zn);
00522
00523
00524 xn= pData->at(m_IndexList.at(i + 1) * 3);
00525 yn= pData->at(m_IndexList.at(i + 1) * 3 + 1);
00526 zn= pData->at(m_IndexList.at(i + 1) * 3 + 2);
00527 const GLC_Vector3d vect2(xn, yn, zn);
00528
00529
00530 xn= pData->at(m_IndexList.at(i + 2) * 3);
00531 yn= pData->at(m_IndexList.at(i + 2) * 3 + 1);
00532 zn= pData->at(m_IndexList.at(i + 2) * 3 + 2);
00533 const GLC_Vector3d vect3(xn, yn, zn);
00534
00535 const GLC_Vector3d edge1(vect3 - vect2);
00536 const GLC_Vector3d edge2(vect1 - vect2);
00537
00538 GLC_Vector3d normal(edge1 ^ edge2);
00539 normal.normalize();
00540
00541 GLC_Vector3df curNormal= normal.toVector3df();
00542 for (int curVertex= 0; curVertex < 3; ++curVertex)
00543 {
00544 (*pNormal)[m_IndexList.at(i + curVertex) * 3]= curNormal.x();
00545 (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 1]= curNormal.y();
00546 (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 2]= curNormal.z();
00547 }
00548 }
00549
00550 }
00551