00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00024
00025 #include "glc_3dstoworld.h"
00026
00027 #include "../geometry/glc_mesh.h"
00028 #include "../sceneGraph/glc_world.h"
00029 #include "../glc_fileformatexception.h"
00030 #include "../geometry/glc_circle.h"
00031 #include "../shading/glc_material.h"
00032 #include "../maths/glc_vector2df.h"
00033 #include "../maths/glc_vector3df.h"
00034 #include "../sceneGraph/glc_structreference.h"
00035 #include "../sceneGraph/glc_structinstance.h"
00036 #include "../sceneGraph/glc_structoccurence.h"
00037
00038
00039 #include "3rdparty/lib3ds/file.h"
00040 #include "3rdparty/lib3ds/mesh.h"
00041 #include "3rdparty/lib3ds/node.h"
00042 #include "3rdparty/lib3ds/matrix.h"
00043 #include "3rdparty/lib3ds/material.h"
00044
00045 #include <QFileInfo>
00046 #include <QGLContext>
00047
00048 GLC_3dsToWorld::GLC_3dsToWorld()
00049 : m_pWorld(NULL)
00050 , m_FileName()
00051 , m_pCurrentMesh(NULL)
00052 , m_pLib3dsFile(NULL)
00053 , m_Materials()
00054 , m_NextMaterialIndex(0)
00055 , m_LoadedMeshes()
00056 , m_InitQuantumValue(50)
00057 , m_CurrentQuantumValue(0)
00058 , m_PreviousQuantumValue(0)
00059 , m_NumberOfMeshes(0)
00060 , m_CurrentMeshNumber(0)
00061 , m_ListOfAttachedFileName()
00062 {
00063 }
00064
00065 GLC_3dsToWorld::~GLC_3dsToWorld()
00066 {
00067 clear();
00068 }
00069
00070
00071 GLC_World* GLC_3dsToWorld::CreateWorldFrom3ds(QFile &file)
00072 {
00073 clear();
00074 m_FileName= file.fileName();
00075
00077
00079 if (!file.open(QIODevice::ReadOnly))
00080 {
00081 QString message(QString("GLC_3dsToWorld::CreateWorldFrom3ds File ") + m_FileName + QString(" doesn't exist"));
00082 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00083 throw(fileFormatException);
00084 }
00085
00086 file.close();
00087
00089
00091 m_pWorld= new GLC_World;
00092
00093
00094 m_pLib3dsFile=lib3ds_file_load(m_FileName.toLocal8Bit().data());
00095 if (!m_pLib3dsFile)
00096 {
00097 QString message= "GLC_3dsToWorld::CreateWorldFrom3ds : Loading Failed";
00098 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00099 clear();
00100 throw(fileFormatException);
00101 }
00102
00103 lib3ds_file_eval(m_pLib3dsFile, 0.0);
00104 m_CurrentQuantumValue= m_InitQuantumValue;
00105 m_PreviousQuantumValue= m_CurrentQuantumValue;
00106
00107 emit currentQuantum(m_CurrentQuantumValue);
00108
00109 for(Lib3dsMesh *pMesh= m_pLib3dsFile->meshes; pMesh != NULL; pMesh = pMesh->next)
00110 {
00111 ++m_NumberOfMeshes;
00112 }
00113
00114 if (0 == m_NumberOfMeshes)
00115 {
00116 QString message= "GLC_3dsToWorld::CreateWorldFrom3ds : No mesh found !";
00117 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::NoMeshFound);
00118 clear();
00119 throw(fileFormatException);
00120 }
00121
00122
00123 for (Lib3dsNode *pNode=m_pLib3dsFile->nodes; pNode!=0; pNode=pNode->next)
00124 {
00125 createMeshes(m_pWorld->rootOccurence(), pNode);
00126 }
00127
00128
00129 for(Lib3dsMesh *pMesh= m_pLib3dsFile->meshes; pMesh != NULL; pMesh = pMesh->next)
00130 {
00131 if (!m_LoadedMeshes.contains(QString(pMesh->name)))
00132 {
00133
00134 Lib3dsNode *pNode= lib3ds_node_new_object();
00135 strcpy(pNode->name, pMesh->name);
00136 pNode->parent_id= LIB3DS_NO_PARENT;
00137 lib3ds_file_insert_node(m_pLib3dsFile, pNode);
00138 createMeshes(m_pWorld->rootOccurence(), pNode);
00139 }
00140 }
00141
00142
00143 lib3ds_file_free(m_pLib3dsFile);
00144 m_pLib3dsFile= NULL;
00145 emit currentQuantum(100);
00146
00147 m_pWorld->collection()->boundingBox();
00148 return m_pWorld;
00149 }
00150
00152
00154
00155
00156 void GLC_3dsToWorld::clear()
00157 {
00158 if (NULL != m_pCurrentMesh)
00159 {
00160 delete m_pCurrentMesh;
00161 m_pCurrentMesh= NULL;
00162 }
00163 m_pWorld= NULL;
00164 m_FileName.clear();
00165 if (NULL != m_pLib3dsFile)
00166 {
00167 lib3ds_file_free(m_pLib3dsFile);
00168 m_pLib3dsFile= NULL;
00169 }
00170
00171
00172 QHash<QString, GLC_Material*>::iterator i;
00173 for (i= m_Materials.begin(); i != m_Materials.end(); ++i)
00174 {
00175 if (i.value()->isUnused()) delete i.value();
00176 }
00177 m_Materials.clear();
00178 m_NextMaterialIndex= 0;
00179
00180 m_LoadedMeshes.clear();
00181
00182 m_CurrentQuantumValue= 0;
00183 m_PreviousQuantumValue= 0;
00184 m_NumberOfMeshes= 0;
00185 m_CurrentMeshNumber= 0;
00186 m_ListOfAttachedFileName.clear();
00187 }
00188
00189
00190 void GLC_3dsToWorld::createMeshes(GLC_StructOccurence* pProduct, Lib3dsNode* pFatherNode)
00191 {
00192 GLC_StructOccurence* pChildProduct= NULL;
00193 Lib3dsMesh *pMesh= NULL;
00194
00195 if (pFatherNode->type == LIB3DS_OBJECT_NODE)
00196 {
00197
00198
00199
00200
00201
00202 if (!(strcmp(pFatherNode->name,"$$$DUMMY")==0))
00203 {
00204 pMesh = lib3ds_file_mesh_by_name(m_pLib3dsFile, pFatherNode->name);
00205 if( pMesh != NULL )
00206 {
00207 GLC_3DRep representation(create3DRep(pMesh));
00208
00209 if (0 != representation.vertexCount())
00210 {
00211 m_LoadedMeshes.insert(representation.name());
00212
00213 GLC_Matrix4x4 nodeMat(&(pFatherNode->matrix[0][0]));
00214
00215 GLC_Matrix4x4 matInv(&(pMesh->matrix[0][0]));
00216 matInv.invert();
00217
00218 Lib3dsObjectData *pObjectData;
00219 pObjectData= &pFatherNode->data.object;
00220 GLC_Matrix4x4 trans(-pObjectData->pivot[0], -pObjectData->pivot[1], -pObjectData->pivot[2]);
00221
00222 nodeMat= nodeMat * trans * matInv;
00223 nodeMat.optimise();
00224
00225 pProduct->addChild((new GLC_StructInstance(new GLC_3DRep(representation)))->move(nodeMat));
00226 }
00227 else
00228 {
00229
00230 QSet<GLC_Material*> meshMaterials= representation.materialSet();
00231 QSet<GLC_Material*>::const_iterator iMat= meshMaterials.constBegin();
00232 while (iMat != meshMaterials.constEnd())
00233 {
00234 if ((*iMat)->numberOfUsage() == 1)
00235 {
00236 m_Materials.remove((*iMat)->name());
00237 }
00238 ++iMat;
00239 }
00240 }
00241 }
00242 }
00243 }
00244 else return;
00245
00246 if (NULL != pFatherNode->childs)
00247 {
00248 pChildProduct= new GLC_StructOccurence();
00249 pProduct->addChild(pChildProduct);
00250
00251 pChildProduct->setName(QString("Product") + QString::number(pFatherNode->node_id));
00252
00253
00254
00255
00256 for (Lib3dsNode* pNode= pFatherNode->childs; pNode!=0; pNode= pNode->next)
00257 {
00258 createMeshes(pChildProduct, pNode);
00259 }
00260 }
00261
00262
00263 }
00265 GLC_3DRep GLC_3dsToWorld::create3DRep(Lib3dsMesh* p3dsMesh)
00266 {
00267 QString meshName(p3dsMesh->name);
00268 if (m_LoadedMeshes.contains(meshName))
00269 {
00270
00271 QList<GLC_3DViewInstance*> instancesList(m_pWorld->collection()->instancesHandle());
00272 GLC_3DViewInstance* pCurrentInstance= NULL;
00273 int currentIndex= -1;
00274 do
00275 {
00276 pCurrentInstance= instancesList[++currentIndex];
00277 } while (pCurrentInstance->name() != meshName);
00278
00279
00280 return pCurrentInstance->representation();
00281 }
00282 GLC_Mesh * pMesh= new GLC_Mesh();
00283 pMesh->setName(p3dsMesh->name);
00284
00285 const int normalsNumber= p3dsMesh->faces * 3;
00286
00287 Lib3dsVector *normalL= static_cast<Lib3dsVector*>(malloc(normalsNumber * sizeof(Lib3dsVector)));
00288 lib3ds_mesh_calculate_normals(p3dsMesh, normalL);
00289
00290
00291 QVector<float> position(normalsNumber * 3);
00292
00293
00294 QVector<float> normal(normalsNumber * 3);
00295 memcpy((void*)normal.data(), normalL, normalsNumber * 3 * sizeof(float));
00296
00297
00298 QVector<float> texel;
00299 if (p3dsMesh->texels > 0)
00300 {
00301 texel.resize(normalsNumber * 2);
00302 }
00303
00304 int normalIndex= 0;
00305 for (unsigned int i= 0; i < p3dsMesh->faces; ++i)
00306 {
00307 IndexList triangleIndex;
00308 Lib3dsFace *p3dsFace=&p3dsMesh->faceL[i];
00309 for (int i=0; i < 3; ++i)
00310 {
00311 triangleIndex.append(normalIndex);
00312
00313 memcpy((void*)&(position.data()[normalIndex * 3]), &p3dsMesh->pointL[p3dsFace->points[i]], 3 * sizeof(float));
00314
00315
00316 if (p3dsMesh->texels > 0)
00317 {
00318 memcpy((void*)&(texel.data()[normalIndex * 2]), &p3dsMesh->texelL[p3dsFace->points[i]], 2 * sizeof(float));
00319 }
00320 ++normalIndex;
00321 }
00322
00323
00324
00325 GLC_Material* pCurMaterial= NULL;
00326 if (p3dsFace->material[0])
00327 {
00328 Lib3dsMaterial* p3dsMat=lib3ds_file_material_by_name(m_pLib3dsFile, p3dsFace->material);
00329 if (NULL != p3dsMat)
00330 {
00331
00332 const QString materialName(p3dsFace->material);
00333
00334 if (!m_Materials.contains(materialName))
00335 {
00336 loadMaterial(p3dsMat);
00337 }
00338 pCurMaterial= m_Materials.value(materialName);
00339 }
00340 }
00341 pMesh->addTriangles(pCurMaterial, triangleIndex);
00342 }
00343 pMesh->addVertice(position);
00344 pMesh->addNormals(normal);
00345 if (p3dsMesh->texels > 0)
00346 {
00347 pMesh->addTexels(texel);
00348 }
00349
00350
00351 delete[] normalL;
00352
00353 ++m_CurrentMeshNumber;
00354 m_CurrentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentMeshNumber) / m_NumberOfMeshes) * (100 - m_InitQuantumValue)) + m_InitQuantumValue;
00355 if (m_CurrentQuantumValue > m_PreviousQuantumValue)
00356 {
00357 emit currentQuantum(m_CurrentQuantumValue);
00358 }
00359 m_PreviousQuantumValue= m_CurrentQuantumValue;
00360
00361 pMesh->finish();
00362 return GLC_3DRep(pMesh);
00363 }
00364
00365
00366 void GLC_3dsToWorld::loadMaterial(Lib3dsMaterial* p3dsMaterial)
00367 {
00368 GLC_Material* pMaterial= new GLC_Material;
00369
00370 const QString materialName(p3dsMaterial->name);
00371 pMaterial->setName(materialName);
00372
00373 if (p3dsMaterial->texture1_map.name[0])
00374 {
00375 const QString textureName(p3dsMaterial->texture1_map.name);
00376
00377 QFileInfo fileInfo(m_FileName);
00378 QString textureFileName(fileInfo.absolutePath() + QDir::separator());
00379 textureFileName.append(textureName);
00380
00381
00382 if (!textureName.right(3).contains("TGA", Qt::CaseInsensitive))
00383 {
00384 QFile textureFile(textureFileName);
00385
00386 if (textureFile.open(QIODevice::ReadOnly))
00387 {
00388
00389 GLC_Texture *pTexture = new GLC_Texture(textureFile);
00390 pMaterial->setTexture(pTexture);
00391 m_ListOfAttachedFileName << textureFileName;
00392 textureFile.close();
00393 }
00394 else
00395 {
00396 QStringList stringList(m_FileName);
00397 stringList.append("Open File : " + textureFileName + " failed");
00398 GLC_ErrorLog::addError(stringList);
00399 }
00400
00401 }
00402 else
00403 {
00404 QStringList stringList(m_FileName);
00405 stringList.append("Image : " + textureFileName + " not suported");
00406 GLC_ErrorLog::addError(stringList);
00407 }
00408 }
00409
00410
00411 QColor ambient;
00412 ambient.setRgbF(p3dsMaterial->ambient[0], p3dsMaterial->ambient[1], p3dsMaterial->ambient[2]);
00413 ambient.setAlphaF(p3dsMaterial->ambient[3]);
00414 pMaterial->setAmbientColor(ambient);
00415
00416 QColor diffuse;
00417 diffuse.setRgbF(p3dsMaterial->diffuse[0], p3dsMaterial->diffuse[1], p3dsMaterial->diffuse[2]);
00418 diffuse.setAlphaF(p3dsMaterial->diffuse[3]);
00419 pMaterial->setDiffuseColor(diffuse);
00420
00421 QColor specular;
00422 specular.setRgbF(p3dsMaterial->specular[0], p3dsMaterial->specular[1], p3dsMaterial->specular[2]);
00423 specular.setAlphaF(p3dsMaterial->specular[3]);
00424 pMaterial->setSpecularColor(specular);
00425
00426
00427 if (0 != p3dsMaterial->shininess)
00428 {
00429 float matShininess= p3dsMaterial->shininess * 128.0f;
00430 if (matShininess > 128.0f) matShininess= 128.0f;
00431 if (matShininess < 5.0f) matShininess= 20.0f;
00432 pMaterial->setShininess(matShininess);
00433 }
00434
00435
00436 pMaterial->setOpacity(1.0 - p3dsMaterial->transparency);
00437
00438
00439 m_Materials.insert(materialName, pMaterial);
00440 }
00441