00001
00002
00003
00004
00005
00006
00007
00008 #include "3dsLoader.h"
00009 #include <iostream>
00010
00018 CLoad3DS::CLoad3DS() {
00019 m_CurrentChunk = new tChunk;
00020 m_TempChunk = new tChunk;
00021 }
00022
00023
00028 bool
00029 CLoad3DS::import3DS(t3DModel *pModel, char *strFileName) {
00030
00031
00032 m_FilePointer = fopen(strFileName, "rb");
00033
00034
00035 if(!m_FilePointer) {
00036 cout << "Unable to find the file: " << strFileName << "\n";
00037 cout.flush();
00038 return false;
00039 }
00040
00041
00042
00043
00044
00045
00046 readChunk(m_CurrentChunk);
00047
00048
00049 if (m_CurrentChunk->ID != PRIMARY) {
00050 cout << "Unable to load PRIMARY chuck from file \n";
00051 cout.flush();
00052 return false;
00053 }
00054
00055
00056
00057 processNextChunk(pModel, m_CurrentChunk);
00058
00059
00060 computeNormals(pModel);
00061
00062
00063 cleanUp();
00064
00065 return 0;
00066 }
00067
00071 void
00072 CLoad3DS::cleanUp() {
00073 fclose(m_FilePointer);
00074 delete m_CurrentChunk;
00075 delete m_TempChunk;
00076 }
00077
00078
00082 void
00083 CLoad3DS::processNextChunk(t3DModel *pModel, tChunk *pPreviousChunk) {
00084 t3DObject newObject = {0};
00085 tMaterialInfo newTexture = {0};
00086 unsigned short version = 0;
00087 int buffer[50000] = {0};
00088
00089 m_CurrentChunk = new tChunk;
00090
00091
00092
00093
00094
00095
00096
00097 while (pPreviousChunk->bytesRead < pPreviousChunk->length) {
00098
00099
00100 readChunk(m_CurrentChunk);
00101
00102
00103 switch (m_CurrentChunk->ID) {
00104 case VERSION:
00105
00106
00107
00108
00109
00110
00111 m_CurrentChunk->bytesRead += fread(&version, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00112
00113
00114 if (version > 0x03)
00115 cout << "This 3DS file is over version 3 so it may load incorrectly \n";
00116 break;
00117
00118 case OBJECTINFO:
00119
00120
00121
00122
00123 readChunk(m_TempChunk);
00124
00125
00126 m_TempChunk->bytesRead += fread(&version, 1, m_TempChunk->length - m_TempChunk->bytesRead, m_FilePointer);
00127
00128
00129 m_CurrentChunk->bytesRead += m_TempChunk->bytesRead;
00130
00131
00132 processNextChunk(pModel, m_CurrentChunk);
00133 break;
00134
00135 case MATERIAL:
00136
00137
00138
00139 pModel->numOfMaterials++;
00140
00141
00142
00143
00144
00145 pModel->pMaterials.push_back(newTexture);
00146
00147
00148 processNextMaterialChunk(pModel, m_CurrentChunk);
00149 break;
00150
00151 case OBJECT:
00152
00153
00154
00155
00156
00157 pModel->numOfObjects++;
00158
00159
00160 pModel->pObject.push_back(newObject);
00161
00162
00163 memset(&(pModel->pObject[pModel->numOfObjects - 1]), 0, sizeof(t3DObject));
00164
00165
00166 m_CurrentChunk->bytesRead += getString(pModel->pObject[pModel->numOfObjects - 1].strName);
00167
00168
00169 processNextObjectChunk(pModel, &(pModel->pObject[pModel->numOfObjects - 1]), m_CurrentChunk);
00170 break;
00171
00172 case EDITKEYFRAME:
00173
00174
00175
00176
00177
00178
00179
00180 m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00181 break;
00182
00183 default:
00184
00185
00186 m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00187 break;
00188 }
00189
00190
00191 pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;
00192 }
00193
00194
00195 delete m_CurrentChunk;
00196 m_CurrentChunk = pPreviousChunk;
00197 }
00198
00199
00203 void
00204 CLoad3DS::processNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk) {
00205
00206 int buffer[50000] = {0};
00207
00208
00209 m_CurrentChunk = new tChunk;
00210
00211
00212 while (pPreviousChunk->bytesRead < pPreviousChunk->length) {
00213
00214
00215 readChunk(m_CurrentChunk);
00216
00217
00218 switch (m_CurrentChunk->ID) {
00219 case OBJECT_MESH:
00220
00221
00222 processNextObjectChunk(pModel, pObject, m_CurrentChunk);
00223 break;
00224
00225 case OBJECT_VERTICES:
00226 readVertices(pObject, m_CurrentChunk);
00227 break;
00228
00229 case OBJECT_FACES:
00230 readVertexIndices(pObject, m_CurrentChunk);
00231 break;
00232
00233 case OBJECT_MATERIAL:
00234
00235
00236
00237
00238
00239
00240
00241
00242 readObjectMaterial(pModel, pObject, m_CurrentChunk);
00243 break;
00244
00245 case OBJECT_UV:
00246
00247
00248 readUVCoordinates(pObject, m_CurrentChunk);
00249 break;
00250
00251 default:
00252
00253
00254 m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00255 break;
00256 }
00257
00258
00259 pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;
00260 }
00261
00262
00263 delete m_CurrentChunk;
00264 m_CurrentChunk = pPreviousChunk;
00265 }
00266
00267
00271 void
00272 CLoad3DS::processNextMaterialChunk(t3DModel *pModel, tChunk *pPreviousChunk) {
00273 int buffer[50000] = {0};
00274
00275
00276 m_CurrentChunk = new tChunk;
00277
00278
00279 while (pPreviousChunk->bytesRead < pPreviousChunk->length) {
00280
00281
00282 readChunk(m_CurrentChunk);
00283
00284
00285 switch (pModel, m_CurrentChunk->ID) {
00286
00287 case MATNAME:
00288
00289
00290 m_CurrentChunk->bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strName, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00291 break;
00292
00293 case MATDIFFUSE:
00294 readColorChunk(&(pModel->pMaterials[pModel->numOfMaterials - 1]), m_CurrentChunk);
00295 break;
00296
00297 case MATMAP:
00298
00299
00300 processNextMaterialChunk(pModel, m_CurrentChunk);
00301 break;
00302
00303 case MATMAPFILE:
00304
00305
00306 m_CurrentChunk->bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strFile, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00307 break;
00308
00309 default:
00310
00311
00312 m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
00313 break;
00314 }
00315
00316
00317 pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;
00318 }
00319
00320
00321 delete m_CurrentChunk;
00322 m_CurrentChunk = pPreviousChunk;
00323 }
00324
00325
00329 void
00330 CLoad3DS::readChunk(tChunk *pChunk) {
00331
00332
00333
00334 pChunk->bytesRead = fread(&pChunk->ID, 1, 2, m_FilePointer);
00335
00336
00337
00338 pChunk->bytesRead += fread(&pChunk->length, 1, 4, m_FilePointer);
00339 }
00340
00344 int
00345 CLoad3DS::getString(char *pBuffer)
00346 {
00347 int index = 0;
00348
00349
00350 fread(pBuffer, 1, 1, m_FilePointer);
00351
00352
00353 while (*(pBuffer + index++) != 0) {
00354
00355
00356 fread(pBuffer + index, 1, 1, m_FilePointer);
00357 }
00358
00359
00360 return strlen(pBuffer) + 1;
00361 }
00362
00363
00367 void
00368 CLoad3DS::readColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk) {
00369
00370 readChunk(m_TempChunk);
00371
00372
00373 m_TempChunk->bytesRead += fread(pMaterial->color, 1, m_TempChunk->length - m_TempChunk->bytesRead, m_FilePointer);
00374
00375
00376 pChunk->bytesRead += m_TempChunk->bytesRead;
00377 }
00378
00379
00383 void
00384 CLoad3DS::readVertexIndices(t3DObject *pObject, tChunk *pPreviousChunk) {
00385 unsigned short index = 0;
00386
00387
00388
00389
00390
00391
00392
00393 pPreviousChunk->bytesRead += fread(&pObject->numOfFaces, 1, 2, m_FilePointer);
00394
00395
00396 pObject->pFaces = new tFace [pObject->numOfFaces];
00397 memset(pObject->pFaces, 0, sizeof(tFace) * pObject->numOfFaces);
00398
00399
00400 for(int i = 0; i < pObject->numOfFaces; i++)
00401 {
00402
00403
00404 for(int j = 0; j < 4; j++)
00405 {
00406
00407 pPreviousChunk->bytesRead += fread(&index, 1, sizeof(index), m_FilePointer);
00408
00409 if(j < 3)
00410 {
00411
00412 pObject->pFaces[i].vertIndex[j] = index;
00413 }
00414 }
00415 }
00416 }
00417
00418
00422 void
00423 CLoad3DS::readUVCoordinates(t3DObject *pObject, tChunk *pPreviousChunk) {
00424
00425
00426
00427 pPreviousChunk->bytesRead += fread(&pObject->numTexVertex, 1, 2, m_FilePointer);
00428
00429
00430 pObject->pTexVerts = new tVector2 [pObject->numTexVertex];
00431
00432
00433 pPreviousChunk->bytesRead += fread(pObject->pTexVerts, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
00434 }
00435
00436
00440 void
00441 CLoad3DS::readVertices(t3DObject *pObject, tChunk *pPreviousChunk) {
00442
00443
00444
00445
00446
00447 pPreviousChunk->bytesRead += fread(&(pObject->numOfVerts), 1, 2, m_FilePointer);
00448
00449
00450 pObject->pVerts = new tVector3 [pObject->numOfVerts];
00451 memset(pObject->pVerts, 0, sizeof(tVector3) * pObject->numOfVerts);
00452
00453
00454 pPreviousChunk->bytesRead += fread(pObject->pVerts, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
00455 }
00456
00457
00461 void
00462 CLoad3DS::readObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk) {
00463 char strMaterial[255] = {0};
00464 int buffer[50000] = {0};
00465
00466
00467
00468
00469
00470
00471 pPreviousChunk->bytesRead += getString(strMaterial);
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 for(int i = 0; i < pModel->numOfMaterials; i++)
00482 {
00483
00484 if(strcmp(strMaterial, pModel->pMaterials[i].strName) == 0)
00485 {
00486
00487 pObject->materialID = i;
00488
00489
00490
00491 if(strlen(pModel->pMaterials[i].strFile) > 0) {
00492
00493
00494 pObject->bHasTexture = true;
00495 }
00496 break;
00497 }
00498 }
00499
00500
00501
00502 pPreviousChunk->bytesRead += fread(buffer, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
00503 }
00504
00505
00506
00507 #define MAG(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))
00508
00512 tVector3
00513 Vector(tVector3 vPoint1, tVector3 vPoint2) {
00514 tVector3 vVector;
00515
00516 vVector.x = vPoint1.x - vPoint2.x;
00517 vVector.y = vPoint1.y - vPoint2.y;
00518 vVector.z = vPoint1.z - vPoint2.z;
00519
00520 return vVector;
00521 }
00522
00526 tVector3
00527 addVector(tVector3 vVector1, tVector3 vVector2) {
00528 tVector3 vResult;
00529
00530 vResult.x = vVector2.x + vVector1.x;
00531 vResult.y = vVector2.y + vVector1.y;
00532 vResult.z = vVector2.z + vVector1.z;
00533
00534 return vResult;
00535 }
00536
00540 tVector3
00541 divideVectorByScaler(tVector3 vVector1, float scaler) {
00542 tVector3 vResult;
00543
00544 vResult.x = vVector1.x / scaler;
00545 vResult.y = vVector1.y / scaler;
00546 vResult.z = vVector1.z / scaler;
00547
00548 return vResult;
00549 }
00550
00554 tVector3
00555 cross(tVector3 vVector1, tVector3 vVector2) {
00556 tVector3 vCross;
00557
00558 vCross.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
00559 vCross.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
00560 vCross.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));
00561 return vCross;
00562 }
00563
00567 tVector3
00568 normalize(tVector3 vNormal) {
00569 double magnitude;
00570
00571 magnitude = MAG(vNormal);
00572
00573 vNormal.x /= (float)magnitude;
00574 vNormal.y /= (float)magnitude;
00575 vNormal.z /= (float)magnitude;
00576
00577 return vNormal;
00578 }
00579
00583 void
00584 CLoad3DS::computeNormals(t3DModel *pModel) {
00585 tVector3 vVector1, vVector2, vNormal, vPoly[3];
00586
00587
00588 if(pModel->numOfObjects <= 0)
00589 return;
00590
00591
00592 for(int index = 0; index < pModel->numOfObjects; index++)
00593 {
00594
00595 t3DObject *pObject = &(pModel->pObject[index]);
00596
00597
00598 tVector3 *pNormals = new tVector3 [pObject->numOfFaces];
00599 tVector3 *pTempNormals = new tVector3 [pObject->numOfFaces];
00600 pObject->pNormals = new tVector3 [pObject->numOfVerts];
00601
00602
00603 for(int i=0; i < pObject->numOfFaces; i++)
00604 {
00605
00606 vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
00607 vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
00608 vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];
00609
00610
00611
00612 vVector1 = Vector(vPoly[0], vPoly[2]);
00613 vVector2 = Vector(vPoly[2], vPoly[1]);
00614
00615 vNormal = cross(vVector1, vVector2);
00616 pTempNormals[i] = vNormal;
00617 vNormal = normalize(vNormal);
00618
00619 pNormals[i] = vNormal;
00620 }
00621
00623
00624 tVector3 vSum = {0.0, 0.0, 0.0};
00625 tVector3 vZero = vSum;
00626 int shared=0;
00627
00628 for (i = 0; i < pObject->numOfVerts; i++)
00629 {
00630 for (int j = 0; j < pObject->numOfFaces; j++)
00631 {
00632 if (pObject->pFaces[j].vertIndex[0] == i ||
00633 pObject->pFaces[j].vertIndex[1] == i ||
00634 pObject->pFaces[j].vertIndex[2] == i)
00635 {
00636 vSum = addVector(vSum, pTempNormals[j]);
00637 shared++;
00638 }
00639 }
00640
00641
00642 pObject->pNormals[i] = divideVectorByScaler(vSum, float(-shared));
00643
00644
00645 pObject->pNormals[i] = normalize(pObject->pNormals[i]);
00646
00647 vSum = vZero;
00648 shared = 0;
00649 }
00650
00651
00652 delete [] pTempNormals;
00653 delete [] pNormals;
00654 }
00655 }