00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "modelloader.h"
00021
00022 #include "ocm.h"
00023 #include "model.h"
00024
00025 #include "ac3dmodel.h"
00026 #include "ac3dobject.h"
00027
00028 #include "texture.h"
00029
00030 #include "star.h"
00031
00032 #include <vector>
00033 #include <fstream>
00034 #include <cstring>
00035
00036 #define OC_OCM_MAX_LINE_LENGTH 80
00037 #define OC_AC3D_MAX_LINE_LENGTH 1024
00038
00039 using std::vector;
00040 using std::ifstream;
00041
00042 using namespace AC3D;
00043
00044
00045
00046 float locAccu[3];
00047 bool bNeedAlpha;
00048
00049
00050
00051
00052
00053
00054
00055 Model* const
00056 ModelLoader::Load(
00057 const string & rcsFileName )
00058 {
00059 OPENCITY_DEBUG( rcsFileName.c_str() );
00060
00061
00062 if (rcsFileName.rfind(".ocm") != rcsFileName.npos)
00063 return ModelLoader::LoadOCM(rcsFileName);
00064 else
00065
00066 if (rcsFileName.rfind(".ac") != rcsFileName.npos)
00067 return ModelLoader::LoadAC3D(rcsFileName);
00068
00069
00070 assert(0);
00071 return NULL;
00072 }
00073
00074
00075
00076 Model* const
00077 ModelLoader::LoadOCM(
00078 const string & rcsFileName )
00079 {
00080 vector<GLfloat> vf;
00081 vector<GLuint> vui;
00082 GLfloat fValue;
00083 OC_CHAR tempStr [OC_OCM_MAX_LINE_LENGTH];
00084 OC_CHAR* endStr;
00085
00086
00087 GLfloat* ftab;
00088
00089
00090 ifstream ocmFile( rcsFileName.c_str() );
00091 if (ocmFile == NULL) {
00092 OPENCITY_DEBUG( "can not load file" );
00093 cerr << "Error loading model: " << rcsFileName << endl;
00094 assert(ocmFile != NULL);
00095 return NULL;
00096 }
00097
00098
00099 ocmFile.getline( tempStr, OC_OCM_MAX_LINE_LENGTH );
00100
00101
00102 while (!ocmFile.eof()) {
00103
00104
00105 if ((strlen(tempStr) != 0)
00106 && (tempStr[0] != '#')) {
00107 fValue = strtof( tempStr, &endStr );
00108
00109
00110 if ( tempStr == endStr ) {
00111 OPENCITY_DEBUG( "can not load file : " );
00112 ocmFile.close();
00113 return NULL;
00114 }
00115
00116
00117
00118 if ( fValue != OC_OCM_TEXFILE )
00119 vf.push_back( fValue );
00120
00121
00122 ocmFile.getline( tempStr, OC_OCM_MAX_LINE_LENGTH );
00123
00124 if (fValue
00125 == OC_OCM_VERTEX) {
00126
00127 fValue = strtof( tempStr, &endStr );
00128 vf.push_back( fValue );
00129 fValue = strtof( endStr, &endStr );
00130 vf.push_back( fValue );
00131 fValue = strtof( endStr, &endStr );
00132 vf.push_back( fValue );
00133 } else
00134 if (fValue
00135 == OC_OCM_COLOR) {
00136
00137 fValue = strtof( tempStr, &endStr );
00138 vf.push_back( fValue );
00139 fValue = strtof( endStr, &endStr );
00140 vf.push_back( fValue );
00141 fValue = strtof( endStr, &endStr );
00142 vf.push_back( fValue );
00143 fValue = strtof( endStr, &endStr );
00144 vf.push_back( fValue );
00145 } else
00146 if (fValue
00147 == OC_OCM_TEXCOOR) {
00148
00149 fValue = strtof( tempStr, &endStr );
00150 vf.push_back( fValue );
00151 fValue = strtof( endStr, &endStr );
00152 vf.push_back( fValue );
00153 fValue = strtof( endStr, &endStr );
00154 vf.push_back( fValue );
00155 } else
00156 if (fValue
00157 == OC_OCM_TEXFILE) {
00158 OPENCITY_DEBUG("Loading texture file");
00159 vui.push_back( Texture::Load( ocHomeDirPrefix( tempStr )));
00160
00161 } else
00162 if (fValue
00163 == OC_OCM_TEXBIND) {
00164
00165 fValue = strtof( tempStr, &endStr );
00166
00167
00168
00169
00170 if ( fValue != -1 )
00171 vf.push_back( vui[(GLuint)fValue] );
00172 else
00173 vf.push_back( .0 );
00174 }
00175 else {
00176 OPENCITY_DEBUG( "can not understand model file" );
00177 assert(0);
00178 }
00179
00180 }
00181
00182 ocmFile.getline( tempStr, OC_OCM_MAX_LINE_LENGTH );
00183 }
00184
00185
00186
00187
00188 ftab = new GLfloat [vf.size()];
00189 for (uint i = 0; i < vf.size(); i++) {
00190 ftab[i] = vf[i];
00191
00192 }
00193
00194 ocmFile.close();
00195 return new Model( ftab, vf.size() );
00196 }
00197
00198
00199
00200 Model* const
00201 ModelLoader::LoadAC3D(
00202 const string & rcsFileName )
00203 {
00204 AC3DModel ac3dmodel = AC3DModel( rcsFileName );
00205 vector<AC3DMaterial> vMaterial;
00206 map<string, GLuint> mapTexture;
00207 GLuint list = 0, listAlpha = 0;
00208 string strPath = "";
00209
00210 if (!ac3dmodel.IsGood())
00211 return NULL;
00212
00213
00214 const AC3DObject* const pObject = ac3dmodel.GetPObject();
00215 if (pObject == NULL)
00216 return NULL;
00217
00218
00219 if (rcsFileName.rfind( '/' ) != rcsFileName.npos ) {
00220 strPath = rcsFileName.substr( 0, rcsFileName.rfind('/') );
00221 }
00222 else {
00223 strPath = ".";
00224 }
00225
00226
00227 vMaterial = ac3dmodel.GetVMaterial();
00228
00229
00230 glMatrixMode( GL_MODELVIEW );
00231 glLoadIdentity();
00232
00233
00234 locAccu[0] = .0;
00235 locAccu[1] = .0;
00236 locAccu[2] = .0;
00237
00238
00239 bNeedAlpha = false;
00240
00241
00242
00243
00244
00245
00246 _AC3DTextureToGL( strPath, pObject, mapTexture );
00247
00248
00249 if (mapTexture.size() > 1) {
00250 OPENCITY_DEBUG("WARNING: more than 1 texture used by the model");
00251 assert( 0 );
00252 }
00253
00254
00255
00256 list = glGenLists( 1 );
00257 glNewList( list, GL_COMPILE );
00258
00259 glPushAttrib( GL_ENABLE_BIT );
00260 glDisable( GL_BLEND );
00261
00262 if (mapTexture.size() > 0) {
00263 glEnable( GL_TEXTURE_2D );
00264 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00265 glBindTexture( GL_TEXTURE_2D, (mapTexture.begin())->second);
00266 }
00267 else {
00268 glDisable( GL_TEXTURE_2D );
00269 }
00270
00271
00272 glBegin( GL_TRIANGLES );
00273 _AC3DVertexToGL( strPath, vMaterial, pObject, false );
00274 glEnd();
00275
00276
00277 glPopAttrib();
00278 glEndList();
00279
00280
00281 if (bNeedAlpha) {
00282
00283 listAlpha = glGenLists( 1 );
00284 glNewList( listAlpha, GL_COMPILE );
00285
00286 glPushAttrib( GL_ENABLE_BIT );
00287 glEnable( GL_BLEND );
00288 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00289 glEnable(GL_ALPHA_TEST);
00290 glAlphaFunc(GL_GREATER, 0.2);
00291
00292
00293
00294 if (mapTexture.size() > 0) {
00295 glEnable( GL_TEXTURE_2D );
00296 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00297
00298
00299
00300
00301
00302
00303 glBindTexture( GL_TEXTURE_2D, (mapTexture.begin())->second);
00304 }
00305 else {
00306 glDisable( GL_TEXTURE_2D );
00307 }
00308
00309
00310 glBegin( GL_TRIANGLES );
00311 _AC3DVertexToGL( strPath, vMaterial, pObject, true );
00312 glEnd();
00313
00314
00315 glPopAttrib();
00316 glEndList();
00317 }
00318
00319
00320
00321
00322
00323
00324 return new Model( list, listAlpha, mapTexture );
00325 }
00326
00327
00328
00329 Vertex
00330 ModelLoader::GetNormal(
00331 Vertex & vO,
00332 Vertex & vA,
00333 Vertex & vB )
00334 {
00335 static Vertex a, b, c;
00336
00338
00339
00340
00341
00342
00343 a.x = vA.x - vO.x;
00344 a.y = vA.y - vO.y;
00345 a.z = vA.z - vO.z;
00346
00347 b.x = vB.x - vO.x;
00348 b.y = vB.y - vO.y;
00349 b.z = vB.z - vO.z;
00350
00351
00352 c.x = a.y * b.z - b.y * a.z;
00353 c.y = b.x * a.z - a.x * b.z;
00354 c.z = a.x * b.y - b.x * a.y;
00355
00356 return c;
00357 }
00358
00359
00360
00361
00362
00363 void
00364 ModelLoader::_AC3DTextureToGL
00365 (
00366 const string& strPath,
00367 const AC3DObject* const pObject,
00368 map<string, GLuint>& mapTexture
00369 )
00370 {
00371 vector<AC3DObject*>::size_type posObj, sizeObj;
00372 vector<AC3DObject*> vpObj;
00373
00374 GLuint tex = 0;
00375
00376
00377 assert( pObject != NULL );
00378
00379
00380 if ( pObject->GetTextureFile() != "" ) {
00381
00382 if (mapTexture.find( pObject->GetTextureFile() ) == mapTexture.end() ) {
00383
00384 tex = Texture::Load( strPath + "/" + pObject->GetTextureFile() );
00385 mapTexture[ pObject->GetTextureFile() ] = tex;
00386 }
00387 else {
00388
00389
00390 tex = mapTexture[ pObject->GetTextureFile() ];
00391 }
00392 }
00393
00394
00395 vpObj = pObject->GetVPObject();
00396 sizeObj = vpObj.size();
00397 for (posObj = 0; posObj < sizeObj; posObj++) {
00398 _AC3DTextureToGL( strPath, vpObj[posObj], mapTexture );
00399 }
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 #undef TRIANGULATION_TEST
00655 #ifndef TRIANGULATION_TEST
00656 void
00657 ModelLoader::_AC3DVertexToGL
00658 (
00659 const string& strPath,
00660 const vector<AC3DMaterial>& vMaterial,
00661 const AC3DObject* const pObject,
00662 const bool bProcessTranslucent
00663 )
00664 {
00665 const float* loc;
00666 AC3DMaterial mat;
00667 vector<Vertex> vVertex;
00668
00669 vector<AC3DSurface*>::size_type pos, size;
00670 vector<AC3DSurface*> vpSurface;
00671
00672 vector<AC3DObject*>::size_type posObj, sizeObj;
00673 vector<AC3DObject*> vpObj;
00674
00675 vector<Ref>::size_type posRef, sizeRef;
00676 vector<Ref> vRef;
00677 Ref r1, r2, r3;
00678
00679
00680 Vertex v1, v2, v3, normal;
00681
00682
00683 assert( pObject != NULL );
00684
00685
00686
00687
00688
00689 loc = pObject->GetLoc();
00690 locAccu[0] += loc[0];
00691 locAccu[1] += loc[1];
00692 locAccu[2] += loc[2];
00693
00694
00695 if (pObject->IsTranslucent()) {
00696 bNeedAlpha = true;
00697 }
00698
00699
00700 if (bProcessTranslucent xor pObject->IsTranslucent())
00701 goto process_child_objects;
00702
00703 vVertex = pObject->GetVVertex();
00704 vpSurface = pObject->GetVPSurface();
00705
00706 size = vpSurface.size();
00707 for (pos = 0; pos < size; pos++) {
00708
00709
00710 mat = vMaterial[ vpSurface[pos]->GetMat() ];
00711
00712 glColor3f( mat.rgb.fR, mat.rgb.fG, mat.rgb.fB );
00713
00714
00715 vRef = vpSurface[pos]->GetVRef();
00716 sizeRef = vRef.size();
00717
00718
00719
00720 assert( sizeRef >= 3 );
00721
00722 for (posRef = 1; posRef < sizeRef-1; posRef++) {
00723
00724 r1 = vRef[0];
00725 v1.x = vVertex[r1.uiVertIndex].x + locAccu[0];
00726 v1.y = vVertex[r1.uiVertIndex].y + locAccu[1];
00727 v1.z = vVertex[r1.uiVertIndex].z + locAccu[2];
00728
00729
00730 r2 = vRef[posRef];
00731 v2.x = vVertex[r2.uiVertIndex].x + locAccu[0];
00732 v2.y = vVertex[r2.uiVertIndex].y + locAccu[1];
00733 v2.z = vVertex[r2.uiVertIndex].z + locAccu[2];
00734
00735
00736 r3 = vRef[posRef+1];
00737 v3.x = vVertex[r3.uiVertIndex].x + locAccu[0];
00738 v3.y = vVertex[r3.uiVertIndex].y + locAccu[1];
00739 v3.z = vVertex[r3.uiVertIndex].z + locAccu[2];
00740
00741
00742 normal = GetNormal( v1, v2, v3 );
00743 glNormal3f( normal.x, normal.y, normal.z );
00744
00745 glTexCoord2f( r1.fTexS, r1.fTexT );
00746 glVertex3f( v1.x, v1.y, v1.z );
00747
00748 glTexCoord2f( r2.fTexS, r2.fTexT );
00749 glVertex3f( v2.x, v2.y, v2.z );
00750
00751 glTexCoord2f( r3.fTexS, r3.fTexT );
00752 glVertex3f( v3.x, v3.y, v3.z );
00753 }
00754 }
00755
00756 process_child_objects:
00757
00758
00759 vpObj = pObject->GetVPObject();
00760 sizeObj = vpObj.size();
00761
00762
00763 for (posObj = 0; posObj < sizeObj; posObj++) {
00764 _AC3DVertexToGL( strPath, vMaterial, vpObj[posObj], bProcessTranslucent );
00765 }
00766
00767 locAccu[0] -= loc[0];
00768 locAccu[1] -= loc[1];
00769 locAccu[2] -= loc[2];
00770
00771
00772
00773 }
00774
00775
00776
00777
00778 #else
00779 void
00780 ModelLoader::_AC3DVertexToGL
00781 (
00782 const string& strPath,
00783 const vector<AC3DMaterial>& vMaterial,
00784 const AC3DObject* const pObject,
00785 const bool bProcessTranslucent
00786 )
00787 {
00788 const float* loc;
00789 AC3DMaterial mat;
00790 vector<Vertex> vVertex;
00791
00792 vector<AC3DSurface*>::size_type pos, size;
00793 vector<AC3DSurface*> vpSurface;
00794
00795 vector<AC3DObject*>::size_type posObj, sizeObj;
00796 vector<AC3DObject*> vpObj;
00797
00798 vector<Ref>::size_type posRef, sizeRef;
00799 vector<Ref> vRef;
00800 Ref r1, r2, r3;
00801
00802
00803 Vertex v1, v2, v3, normal;
00804
00805
00806 triangulation::Triangulation* triangulator = new triangulation::Star();
00807 triangulation::Triangle* triangles = NULL;
00808 triangulation::Vertex* triVertices = NULL;
00809
00810
00811 assert( pObject != NULL );
00812
00813
00814
00815
00816
00817 loc = pObject->GetLoc();
00818 locAccu[0] += loc[0];
00819 locAccu[1] += loc[1];
00820 locAccu[2] += loc[2];
00821
00822
00823 if (pObject->IsTranslucent()) {
00824 bNeedAlpha = true;
00825 }
00826
00827
00828 if (bProcessTranslucent xor pObject->IsTranslucent())
00829 goto process_child_objects;
00830
00831 vVertex = pObject->GetVVertex();
00832 vpSurface = pObject->GetVPSurface();
00833
00834 size = vpSurface.size();
00835 for (pos = 0; pos < size; pos++) {
00836
00837
00838 mat = vMaterial[ vpSurface[pos]->GetMat() ];
00839
00840 glColor3f( mat.rgb.fR, mat.rgb.fG, mat.rgb.fB );
00841
00842
00843 vRef = vpSurface[pos]->GetVRef();
00844 sizeRef = vRef.size();
00845
00846
00847
00848 assert( sizeRef >= 3 );
00849
00850
00851 triVertices = new triangulation::Vertex[sizeRef];
00852
00853 for (posRef = 0; posRef < sizeRef; posRef++) {
00854 r1 = vRef[posRef];
00855 triVertices[posRef].x = vVertex[r1.uiVertIndex].x + locAccu[0];
00856 triVertices[posRef].y = vVertex[r1.uiVertIndex].y + locAccu[1];
00857 triVertices[posRef].z = vVertex[r1.uiVertIndex].z + locAccu[2];
00858 triVertices[posRef].texCoord.fS = r1.fTexS;
00859 triVertices[posRef].texCoord.fT = r1.fTexT;
00860 }
00861
00862 triangles = triangulator->process( sizeRef, triVertices );
00863 delete [] triVertices;
00864
00865 for (posRef = 0; posRef < sizeRef-2; posRef++) {
00866
00867
00868
00869
00870
00871 glTexCoord2f(
00872 triangles[posRef].a.texCoord.fS, triangles[posRef].a.texCoord.fT );
00873 glVertex3f(
00874 triangles[posRef].a.x, triangles[posRef].a.y, triangles[posRef].a.z );
00875 glTexCoord2f(
00876 triangles[posRef].b.texCoord.fS, triangles[posRef].b.texCoord.fT );
00877 glVertex3f(
00878 triangles[posRef].b.x, triangles[posRef].b.y, triangles[posRef].b.z );
00879 glTexCoord2f(
00880 triangles[posRef].c.texCoord.fS, triangles[posRef].c.texCoord.fT );
00881 glVertex3f(
00882 triangles[posRef].c.x, triangles[posRef].c.y, triangles[posRef].c.z );
00883 }
00884
00885 delete [] triangles;
00886
00887 }
00888
00889 process_child_objects:
00890
00891
00892 vpObj = pObject->GetVPObject();
00893 sizeObj = vpObj.size();
00894
00895
00896 for (posObj = 0; posObj < sizeObj; posObj++) {
00897 _AC3DVertexToGL( strPath, vMaterial, vpObj[posObj], bProcessTranslucent );
00898 }
00899
00900 locAccu[0] -= loc[0];
00901 locAccu[1] -= loc[1];
00902 locAccu[2] -= loc[2];
00903
00904 delete triangulator;
00905
00906
00907
00908 }
00909 #endif
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929