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