Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

modelloader.cpp

00001 /***************************************************************************
00002                         modelloader.cpp  -  description
00003                             -------------------
00004     begin                : sam mai 22 2004
00005     copyright            : (C) 2004-2006 by Duong-Khang NGUYEN
00006     email                : neoneurone @ users sourceforge net
00007     
00008     $Id: modelloader.cpp 83 2006-11-05 20:46:42Z neoneurone $
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   any later version.                                                    *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 #include "modelloader.h"
00021 
00022 #include "ocm.h"
00023 #include "model.h"
00024 
00025 #include "ac3dmodel.h"          // For AC3D structure manipulation
00026 #include "ac3dobject.h"         // For normal calculation
00027 
00028 #include "texture.h"            // for texture manipulation
00029 
00030 #include "star.h"               // Triangulation algorithms
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 // Accumulate the locations command
00046 float locAccu[3];
00047 bool bNeedAlpha;
00048 
00049 // Debug variables
00050 //  unsigned int nbPoly;
00051 //  unsigned int nbVertex;
00052 
00053 
00054    /*=====================================================================*/
00055 Model* const
00056 ModelLoader::Load(
00057     const string & rcsFileName )
00058 {
00059     OPENCITY_DEBUG( rcsFileName.c_str() );
00060 
00061 // IF it's an OCM file THEN
00062     if (rcsFileName.rfind(".ocm") != rcsFileName.npos)
00063         return ModelLoader::LoadOCM(rcsFileName);
00064     else
00065 // IF it's an AC3D file THEN
00066     if (rcsFileName.rfind(".ac") != rcsFileName.npos)
00067         return ModelLoader::LoadAC3D(rcsFileName);
00068 
00069 // otherwise, return NULL
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 // model's parameter
00087     GLfloat* ftab;
00088 
00089 // open the stream for reading
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 // read the first line
00099     ocmFile.getline( tempStr, OC_OCM_MAX_LINE_LENGTH );
00100 
00101 // while not EOF do processing
00102     while (!ocmFile.eof()) {
00103 //debug printf("tempstr: '%s' \n", tempStr );
00104     // if not NULL nor commented out then
00105         if ((strlen(tempStr) != 0)
00106         &&  (tempStr[0] != '#')) {
00107             fValue = strtof( tempStr, &endStr );
00108 
00109         // is there any conversion error ?
00110             if ( tempStr == endStr ) {
00111                 OPENCITY_DEBUG( "can not load file : " );
00112                 ocmFile.close();
00113                 return NULL;
00114             }
00115 
00116         // WARNING no error checking below here, tired of this :)
00117         // store the OCM value type code
00118             if ( fValue != OC_OCM_TEXFILE )
00119                 vf.push_back( fValue );
00120 
00121         // read the primitive's values
00122             ocmFile.getline( tempStr, OC_OCM_MAX_LINE_LENGTH );
00123 
00124             if (fValue
00125             == OC_OCM_VERTEX) {
00126             // read 3 floats
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             // read 4 floats
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             // read 3 floats
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 //debug cout << "Texture id got: " << vui.back() << endl;
00161             } else
00162             if (fValue
00163             == OC_OCM_TEXBIND) {
00164             // read 1 float
00165                 fValue = strtof( tempStr, &endStr );
00166             // WARNING: no error checking
00167             // it's quite dangerous
00168             // 0 is a default texture in OpenGL
00169             // however in OCM it's -1
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         } // if not commented out then
00181     // read the next line
00182         ocmFile.getline( tempStr, OC_OCM_MAX_LINE_LENGTH );
00183     }
00184 
00185 //debug cout << "vector size: " << vf.size() << endl;
00186 
00187 // convert vector<GLfloat> to GLfloat bla []
00188     ftab = new GLfloat [vf.size()];
00189     for (uint i = 0; i < vf.size(); i++) {
00190         ftab[i] = vf[i];
00191 //debug cout << ftab[i] << " / ";
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 // Don't go further if there is no object to parse
00214     const AC3DObject* const pObject = ac3dmodel.GetPObject();
00215     if (pObject == NULL)
00216         return NULL;
00217 
00218 // Get the path
00219     if (rcsFileName.rfind( '/' ) != rcsFileName.npos ) {
00220         strPath = rcsFileName.substr( 0, rcsFileName.rfind('/') );
00221     }
00222     else {
00223         strPath = ".";
00224     }
00225 //debug cout << "path: " << strPath << endl;
00226 
00227     vMaterial = ac3dmodel.GetVMaterial();
00228 
00229 // Initialize the model view matrix
00230     glMatrixMode( GL_MODELVIEW );
00231     glLoadIdentity();
00232 
00233 // Initialize the "loc" command accumulation variable
00234     locAccu[0] = .0;
00235     locAccu[1] = .0;
00236     locAccu[2] = .0;
00237 
00238 // Initialize the alpha state
00239     bNeedAlpha = false;
00240 
00241 // Debug: count the number of polys and vertex
00242 //  nbPoly = 0;
00243 //  nbVertex = 0;
00244 
00245 // Load all the texture used by the model
00246     _AC3DTextureToGL( strPath, pObject, mapTexture );
00247 
00248 // Debug
00249     if (mapTexture.size() > 1) {
00250         OPENCITY_DEBUG("WARNING: more than 1 texture used by the model");
00251         assert( 0 );
00252     }
00253 
00254    /*=====================================================================*/
00255 // Recursively load all the objects into the _opaque_ display list
00256     list = glGenLists( 1 );
00257     glNewList( list, GL_COMPILE );
00258 // Save the all enabled GL bits
00259     glPushAttrib( GL_ENABLE_BIT );
00260     glDisable( GL_BLEND );
00261 // Enable the texture target and bind the _first_ texture only
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 // Load all the vertex
00272     glBegin( GL_TRIANGLES );
00273     _AC3DVertexToGL( strPath, vMaterial, pObject, false );
00274     glEnd();
00275 
00276 // Restore all enabled bits
00277     glPopAttrib();
00278     glEndList();
00279 
00280    /*=====================================================================*/
00281     if (bNeedAlpha) {
00282 // Recursively load all the objects into the _alpha_ display list
00283     listAlpha = glGenLists( 1 );
00284     glNewList( listAlpha, GL_COMPILE );
00285 // Save the all enabled GL bits
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 //  glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA );
00292 //  glBlendFunc( GL_ONE, GL_ZERO );
00293 // Enable the texture target and bind the _first_ texture only
00294     if (mapTexture.size() > 0) {
00295         glEnable( GL_TEXTURE_2D );
00296         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00297 //      glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND );
00298 //      GLfloat env_color [] = { 0, 0, 0, 0 };
00299 //      GLfloat env_color [] = { 1, 1, 1, 0 };
00300 //      glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color );
00301 //      GLfloat obj_color [] = { 01, 01, 01, 01 };
00302 //      glColor4fv( obj_color );
00303         glBindTexture( GL_TEXTURE_2D, (mapTexture.begin())->second);
00304     }
00305     else {
00306         glDisable( GL_TEXTURE_2D );
00307     }
00308 
00309 // Load all the vertex
00310     glBegin( GL_TRIANGLES );
00311     _AC3DVertexToGL( strPath, vMaterial, pObject, true );
00312     glEnd();
00313 
00314 // Restore all enabled bits
00315     glPopAttrib();
00316     glEndList();
00317     }       // if (bNeedAlpha)
00318 
00319 
00320 // Debug: print out the number of polys
00321 //  cout << "Number of polygons: " << nbPoly
00322 //       << " / vertex: " << nbVertex << endl;
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 //  cx = ay * bz - by * az;
00339 //  cy = bx * az - ax * bz;
00340 //  cz = ax * by - bx * ay;
00341 
00342 // Calculate the relative coordinates of A and B to O
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 // Now, calculate the normal
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    /*                        PRIVATE      METHODS                         */
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 // Get the texture
00380     if ( pObject->GetTextureFile() != "" ) {
00381     // IF the specified texture has not been loaded already THEN
00382         if (mapTexture.find( pObject->GetTextureFile() ) == mapTexture.end() ) {
00383         // Load the texture as specified by the texture command
00384             tex = Texture::Load( strPath + "/" + pObject->GetTextureFile() );
00385             mapTexture[ pObject->GetTextureFile() ] = tex;
00386         }
00387         else {
00388         // Assign the cached texture to the model
00389         //  OPENCITY_DEBUG("Texture loading cache hit");
00390             tex = mapTexture[ pObject->GetTextureFile() ];
00391         }
00392     }
00393 
00394 // Parse all the child objects and retrieve the texture
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 /* POLYGON version
00405 void
00406 ModelLoader::_AC3DToGL(
00407     const string& strPath,
00408     const vector<AC3DMaterial>& vMaterial,
00409     const AC3DObject* const pObject,
00410     map<string, GLuint>& mapTexture
00411     )
00412 {
00413     const float* loc;
00414     AC3DMaterial mat;
00415     vector<Vertex> vVertex;
00416 
00417     vector<AC3DSurface*>::size_type pos, size;
00418     vector<AC3DSurface*> vpSurface;
00419 
00420     vector<AC3DObject*>::size_type posObj, sizeObj;
00421     vector<AC3DObject*> vpObj;
00422 
00423     vector<Ref>::size_type posRef, sizeRef;
00424     vector<Ref> vRef;
00425     Ref ref;
00426 
00427     GLuint tex = 0;
00428     bool texEnabled = false;
00429 
00430 
00431     assert( pObject != NULL );
00432 
00433 // Set the texture
00434     if ( pObject->GetTextureFile() != "" ) {
00435         texEnabled = true;
00436 
00437     // IF the specified texture has not been loaded already THEN
00438         if (mapTexture.find( pObject->GetTextureFile() ) == mapTexture.end() ) {
00439         // Load the texture as specified by the texture command
00440             tex = Texture::Load( strPath + "/" + pObject->GetTextureFile() );
00441             mapTexture[ pObject->GetTextureFile() ] = tex;
00442         }
00443         else {
00444         // Assign the cached texture to the model
00445             OPENCITY_DEBUG("Texture loading cache hit");
00446             tex = mapTexture[ pObject->GetTextureFile() ];
00447         }
00448 
00449         glEnable( GL_TEXTURE_2D );
00450         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00451         glBindTexture( GL_TEXTURE_2D, tex);
00452     }
00453 
00454     loc = pObject->GetLoc();
00455     locAccu[0] += loc[0];
00456     locAccu[1] += loc[1];
00457     locAccu[2] += loc[2];
00458 
00459     vVertex = pObject->GetVVertex();
00460     vpSurface = pObject->GetVPSurface();
00461 
00462     size = vpSurface.size();
00463     for (pos = 0; pos < size; pos++) {
00464     // Debug
00465         ++nbPoly;
00466     // Get the material of the current surface
00467         mat = vMaterial[ vpSurface[pos]->GetMat() ];
00468     // Set the color of the surface with COLOR_MATERIAL enabled
00469         glColor3f( mat.rgb.fR, mat.rgb.fG, mat.rgb.fB );
00470 
00471         vRef = vpSurface[pos]->GetVRef();
00472         sizeRef = vRef.size();
00473     // Debug
00474         cout << "Vertex per surface: " << sizeRef << endl;
00475 
00476         glBegin( GL_POLYGON );
00477         for (posRef = 0; posRef < sizeRef; posRef++) {
00478         // Debug
00479             ++nbVertex;
00480 
00481             ref = vRef[posRef];
00482             if (texEnabled)
00483                 glTexCoord2f( ref.fTexS, ref.fTexT );
00484             glVertex3f(
00485                 vVertex[ref.uiVertIndex].x + locAccu[0],
00486                 vVertex[ref.uiVertIndex].y + locAccu[1],
00487                 vVertex[ref.uiVertIndex].z + locAccu[2]
00488             );
00489         }
00490         glEnd();
00491     } // For each surface
00492 
00493     if (texEnabled) {
00494         texEnabled = false;         // Safe
00495         glDisable( GL_TEXTURE_2D );
00496     }
00497 
00498 // Parse all the child objects
00499     vpObj = pObject->GetVPObject();
00500     sizeObj = vpObj.size();
00501     for (posObj = 0; posObj < sizeObj; posObj++) {
00502         _AC3DToGL( strPath, vMaterial, vpObj[posObj], mapTexture );
00503     }
00504 
00505     locAccu[0] -= loc[0];
00506     locAccu[1] -= loc[1];
00507     locAccu[2] -= loc[2];
00508 }
00509 */
00510 
00511 
00512    /*=====================================================================*/
00513 // TRIANGLE_FAN version
00514 /*
00515 void
00516 ModelLoader::_AC3DVertexToGL
00517 (
00518     const string& strPath,
00519     const vector<AC3DMaterial>& vMaterial,
00520     const AC3DObject* const pObject,
00521     const bool bProcessTranslucent
00522 )
00523 {
00524     const float* loc;
00525     AC3DMaterial mat;
00526     vector<Vertex> vVertex;
00527 
00528     vector<AC3DSurface*>::size_type pos, size;
00529     vector<AC3DSurface*> vpSurface;
00530 
00531     vector<AC3DObject*>::size_type posObj, sizeObj;
00532     vector<AC3DObject*> vpObj;
00533 
00534     vector<Ref>::size_type posRef, sizeRef;
00535     vector<Ref> vRef;
00536     Ref r1, r2, r3;
00537 
00538 // Used for normal calculation
00539     Vertex v1, v2, v3, normal;
00540 
00541 
00542     assert( pObject != NULL );
00543 
00544 
00545 // debug, location calculation
00546 //cout << "in  : " << locAccu[0] << "/" << locAccu[1] << "/" << locAccu[2] << endl;
00547 
00548     loc = pObject->GetLoc();
00549     locAccu[0] += loc[0];
00550     locAccu[1] += loc[1];
00551     locAccu[2] += loc[2];
00552 
00553 // Does this object need alpha processing ?
00554     if (pObject->IsTranslucent()) {
00555         bNeedAlpha = true;
00556     }
00557 
00558 // Process only objects that we are asked to do
00559     if (bProcessTranslucent xor pObject->IsTranslucent())
00560         goto process_child_objects;
00561 
00562     vVertex = pObject->GetVVertex();
00563     vpSurface = pObject->GetVPSurface();
00564 
00565     size = vpSurface.size();
00566     for (pos = 0; pos < size; pos++) {
00567 // Debug ++nbPoly;
00568     // Get the material of the current surface
00569         mat = vMaterial[ vpSurface[pos]->GetMat() ];
00570     // Set the color of the surface with COLOR_MATERIAL enabled
00571         glColor3f( mat.rgb.fR, mat.rgb.fG, mat.rgb.fB );
00572 //      glColor4f( 1, 1, 1, 1 );
00573 
00574         vRef = vpSurface[pos]->GetVRef();
00575         sizeRef = vRef.size();
00576 
00577 // Debug cout << "Vertex per surface: " << sizeRef << endl;
00578 
00579         assert( sizeRef >= 3 );     // We need at least one triangle
00580 // Debug nbVertex += sizeRef;
00581 
00582 
00583     // With 3 first vertices, we can calculate the normal for the current surface
00584     // Fist vertex
00585         r1 = vRef[0];
00586         v1.x = vVertex[r1.uiVertIndex].x + locAccu[0];
00587         v1.y = vVertex[r1.uiVertIndex].y + locAccu[1];
00588         v1.z = vVertex[r1.uiVertIndex].z + locAccu[2];
00589 
00590     // Second vertex
00591         r2 = vRef[1];
00592         v2.x = vVertex[r2.uiVertIndex].x + locAccu[0];
00593         v2.y = vVertex[r2.uiVertIndex].y + locAccu[1];
00594         v2.z = vVertex[r2.uiVertIndex].z + locAccu[2];
00595 
00596     // Third vertex
00597         r3 = vRef[2];
00598         v3.x = vVertex[r3.uiVertIndex].x + locAccu[0];
00599         v3.y = vVertex[r3.uiVertIndex].y + locAccu[1];
00600         v3.z = vVertex[r3.uiVertIndex].z + locAccu[2];
00601 
00602     // Set the normal
00603         glBegin( GL_TRIANGLE_FAN );
00604         normal = GetNormal( v1, v2, v3 );
00605         glNormal3f( normal.x, normal.y, normal.z );
00606 
00607     // Draw the first 3 vertices
00608         glTexCoord2f( r1.fTexS, r1.fTexT );
00609         glVertex3f( v1.x, v1.y, v1.z );
00610 
00611         glTexCoord2f( r2.fTexS, r2.fTexT );
00612         glVertex3f( v2.x, v2.y, v2.z );
00613 
00614         glTexCoord2f( r3.fTexS, r3.fTexT );
00615         glVertex3f( v3.x, v3.y, v3.z );
00616 
00617     // Draw the other vertices
00618         for (posRef = 3; posRef < sizeRef; posRef++) {
00619             r1 = vRef[posRef];
00620             v1.x = vVertex[r1.uiVertIndex].x + locAccu[0];
00621             v1.y = vVertex[r1.uiVertIndex].y + locAccu[1];
00622             v1.z = vVertex[r1.uiVertIndex].z + locAccu[2];
00623 
00624             glTexCoord2f( r1.fTexS, r1.fTexT );
00625             glVertex3f( v1.x, v1.y, v1.z );
00626         } // For each vertex
00627         glEnd();
00628     } // For each surface
00629 
00630 process_child_objects:
00631 
00632 // Parse all the child objects
00633     vpObj = pObject->GetVPObject();
00634     sizeObj = vpObj.size();
00635 //debug
00636 //cout << "kids: " << pObject->GetNumberKid() << " / objects: " << sizeObj << endl;
00637     for (posObj = 0; posObj < sizeObj; posObj++) {
00638         _AC3DVertexToGL( strPath, vMaterial, vpObj[posObj], bProcessTranslucent );
00639     }
00640 
00641     locAccu[0] -= loc[0];
00642     locAccu[1] -= loc[1];
00643     locAccu[2] -= loc[2];
00644 
00645 // debug, location calculation
00646 //cout << "out : " << locAccu[0] << "/" << locAccu[1] << "/" << locAccu[2] << endl;
00647 }
00648 */
00649 
00650 
00651    /*=====================================================================*/
00652 // TRIANGLES version, inline triangulation
00653 //#define TRIANGULATION_TEST 1
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 // Used for normal calculation
00680     Vertex v1, v2, v3, normal;
00681 
00682 
00683     assert( pObject != NULL );
00684 
00685 
00686 // debug, location calculation
00687 //cout << "in  : " << locAccu[0] << "/" << locAccu[1] << "/" << locAccu[2] << endl;
00688 
00689     loc = pObject->GetLoc();
00690     locAccu[0] += loc[0];
00691     locAccu[1] += loc[1];
00692     locAccu[2] += loc[2];
00693 
00694 // Does this object need alpha processing ?
00695     if (pObject->IsTranslucent()) {
00696         bNeedAlpha = true;
00697     }
00698 
00699 // Process only objects that we are asked to do
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 // Debug ++nbPoly;
00709     // Get the material of the current surface
00710         mat = vMaterial[ vpSurface[pos]->GetMat() ];
00711     // Set the color of the surface with COLOR_MATERIAL enabled
00712         glColor3f( mat.rgb.fR, mat.rgb.fG, mat.rgb.fB );
00713 //      glColor4f( 1, 1, 1, 1 );
00714 
00715         vRef = vpSurface[pos]->GetVRef();
00716         sizeRef = vRef.size();
00717 
00718 // Debug cout << "Vertex per surface: " << sizeRef << endl;
00719 
00720         assert( sizeRef >= 3 );     // We need at least one triangle
00721 // Debug nbVertex += sizeRef;
00722         for (posRef = 1; posRef < sizeRef-1; posRef++) {
00723         // Fist vertex
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         // Second vertex
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         // Third vertex
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         // Now issue the OpenGL commands
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     } // For each surface
00755 
00756 process_child_objects:
00757 
00758 // Parse all the child objects
00759     vpObj = pObject->GetVPObject();
00760     sizeObj = vpObj.size();
00761 //debug
00762 //cout << "kids: " << pObject->GetNumberKid() << " / objects: " << sizeObj << endl;
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 // debug, location calculation
00772 //cout << "out : " << locAccu[0] << "/" << locAccu[1] << "/" << locAccu[2] << endl;
00773 }
00774 
00775 
00776    /*=====================================================================*/
00777 // TRIANGLES version, external triangulation
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 // Used for normal calculation
00803     Vertex v1, v2, v3, normal;
00804 
00805 // Triangulation
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 // debug, location calculation
00815 //cout << "in  : " << locAccu[0] << "/" << locAccu[1] << "/" << locAccu[2] << endl;
00816 
00817     loc = pObject->GetLoc();
00818     locAccu[0] += loc[0];
00819     locAccu[1] += loc[1];
00820     locAccu[2] += loc[2];
00821 
00822 // Does this object need alpha processing ?
00823     if (pObject->IsTranslucent()) {
00824         bNeedAlpha = true;
00825     }
00826 
00827 // Process only objects that we are asked to do
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 // Debug ++nbPoly;
00837     // Get the material of the current surface
00838         mat = vMaterial[ vpSurface[pos]->GetMat() ];
00839     // Set the color of the surface with COLOR_MATERIAL enabled
00840         glColor3f( mat.rgb.fR, mat.rgb.fG, mat.rgb.fB );
00841 //      glColor4f( 1, 1, 1, 1 );
00842 
00843         vRef = vpSurface[pos]->GetVRef();
00844         sizeRef = vRef.size();
00845 
00846 // Debug cout << "Vertex per surface: " << sizeRef << endl;
00847 
00848         assert( sizeRef >= 3 );     // We need at least one triangle
00849 // Debug nbVertex += sizeRef;
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         // Now issue the OpenGL commands
00867         //  normal = GetNormal(
00868         //      triangles[posRef].a, triangles[posRef].b, triangles[posRef].c );
00869         //  glNormal3f( normal.x, normal.y, normal.z );
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     } // For each surface
00888 
00889 process_child_objects:
00890 
00891 // Parse all the child objects
00892     vpObj = pObject->GetVPObject();
00893     sizeObj = vpObj.size();
00894 //debug
00895 //cout << "kids: " << pObject->GetNumberKid() << " / objects: " << sizeObj << endl;
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 // debug, location calculation
00907 //cout << "out : " << locAccu[0] << "/" << locAccu[1] << "/" << locAccu[2] << endl;
00908 }
00909 #endif
00910 
00911 
00912 
00913 
00914 
00915 
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00928 
00929 

Generated on Sat Nov 11 10:21:10 2006 for OpenCity by  doxygen 1.4.2