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

ModelSMF.cpp

Go to the documentation of this file.
00001 /*
00002  * ModelSMF.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2003 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00027 #include "../Include/Globals.h"
00028 #include "../Include/FlyLegacy.h"
00029 #include "../Include/Utility.h"
00030 
00031 
00032 //
00033 // Vertex information in a SMF part
00034 //
00035 typedef struct {
00036   float x, y, z;      // Vertex coordinates
00037   float nx, ny, nz;   // Normal coordinates
00038   float u, v;       // Texture coordinates
00039 } SVertex;
00040 
00041 
00042 CModelSMF::CModelSMF (const char* smfFilename)
00043 {
00044   top = new ssgTransform;
00045   top->setName (smfFilename);
00046 
00047   // Open POD file
00048   PODFILE *p = popen (&globals->pfs, smfFilename);
00049   if (p == NULL) {
00050     gtfo ("CModelSMF : Could not open SMF model %s", smfFilename);
00051   }
00052 
00053   GLuint texid = 0;
00054   char texfilename[256];
00055 
00056   static const int LINE_LENGTH = 128;
00057   char s[LINE_LENGTH+1];
00058 
00059   // Object type, this should be "C3DModel"
00060   pgets (s, LINE_LENGTH, p);
00061   if (strncmp (s, "C3DModel", strlen("C3DModel")) != 0) {
00062     globals->logWarning->Write ("CModelSMF : Incorrect object type in %s", smfFilename);
00063   }
00064 
00065   // Version (ignored)
00066   pgets (s, LINE_LENGTH, p);
00067 
00068   // Part count
00069   int nParts;
00070   pgets (s, LINE_LENGTH, p);
00071   if (sscanf (s, "%d", &nParts) != 1) {
00072     // Error
00073     gtfo ("CModelSMF : Error parsing part cound in %s", smfFilename);
00074   }
00075 
00076   // Use automatic detail, detail pixel height
00077   int autoDetail;
00078   float detailPixelHeight;
00079   pgets (s, LINE_LENGTH, p);
00080   if (sscanf (s, "%d,%f", &autoDetail, &detailPixelHeight) != 2) {
00081     // Error
00082     gtfo ("CModelSMF : Invalid auto detail data in %s", smfFilename);
00083   }
00084 
00085   // Part list
00086   for (int i=0; i<nParts; i++) {
00087     // Part name, trim trailing whitespace
00088     char name[LINE_LENGTH];
00089     pgets (s, LINE_LENGTH, p);
00090     char *q = s + strlen(s) - 1;
00091     while (isspace(*q)) q--;
00092     q++;
00093     *q = '\0';
00094     strcpy (name, s);
00095 
00096     // Part status (on/off)
00097     pgets (s, LINE_LENGTH, p);
00098 
00099     // Version (ignored)
00100     pgets (s, LINE_LENGTH, p);
00101 
00102     // Vertex count, frame count, face count, unused value
00103     int nVerts, nFrames, nFaces, dummy;
00104     pgets (s, LINE_LENGTH, p);
00105     if (sscanf (s, "%d,%d,%d,%d", &nVerts, &nFrames, &nFaces, &dummy) != 4) {
00106       // Error
00107       gtfo ("CModelSMF : Error parsing vertex and face counts in %s", smfFilename);
00108     }
00109 
00110     // Optional line "vl" ???
00111     bool v1flag = false;
00112     pgets (s, LINE_LENGTH, p);
00113     if (strncmp (s, "v1", 2) == 0) {
00114       //  ?? What does this mean?
00115       v1flag = true;
00116       //  Pre-read the next line
00117       pgets (s, LINE_LENGTH, p);
00118     }
00119 
00120     // Diffuse value, specular value, specular power, use transparency,
00121     //   use environment mapping, texture name
00122     int diffuse, specular, specpower, transparent, envmap;
00123     char texturename[LINE_LENGTH];
00124     if (sscanf (s, "%d,%d,%d,%d,%d,%s",
00125       &diffuse, &specular, &specpower, &transparent, &envmap, texturename) != 6) {
00126       // Error
00127       gtfo ("CModelSMF : Error parsing material parameters for part %d in %s",
00128         i, smfFilename) ;
00129     }
00130 
00131     // Load texture
00132     if (texid == 0) {
00133       // Construct full texture filename
00134       strcpy (texfilename, texturename);
00135       char texfullname[256];
00136       strcpy (texfullname, "Art\\");
00137       strcat (texfullname, texfilename);
00138 
00139       // Check extension of texture name
00140       char *p = strrchr (texturename, '.');
00141       if (p) {
00142         // File has an extension, now check for valid bitmaps
00143         if (stricmp (p, ".RAW") == 0) {
00144           CRawImage *raw = new CRawImage (texfullname);
00145           texid = raw->GetTexture (true);
00146           delete raw;
00147         } else if (stricmp (p, ".TIF") == 0) {
00148           CImageTIFF *tif = new CImageTIFF (texfullname);
00149           texid = tif->CreateTexture (true);
00150           delete tif;
00151         } else {
00152           gtfo ("SModelSMF : Unsupported texture %s in %s", texturename, smfFilename);
00153         }
00154       } else {
00155         gtfo ("SModelSMF : Invalid texture filename %s in %s",
00156           texturename, smfFilename);
00157       }
00158     } else {
00159       // Doublecheck that only one texture is used across all parts
00160       if (strcmp (texfilename, texturename) != 0) {
00161         globals->logWarning->Write ("CModelSMF : More than one texture filename at part %d in %s",
00162           i, smfFilename);
00163       }
00164     }
00165 
00166     // Create state information about this part
00167     ssgSimpleState *state = new ssgSimpleState ();
00168 
00169     sgVec4 spec = { 0.0f, 0.0f, 0.0f, 1.0f };
00170     sgVec4 emis = { 0.0f, 0.0f, 0.0f, 1.0f } ;
00171     float  shi  = { 0.0f } ;
00172 
00173     state->setMaterial ( GL_SPECULAR, spec ) ;
00174     state->setMaterial ( GL_EMISSION, emis ) ;
00175     state->setShininess ( shi ) ;
00176     state->enable ( GL_COLOR_MATERIAL ) ;
00177     state->setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ;
00178     state->enable  ( GL_LIGHTING ) ;
00179     state->setShadeModel ( GL_SMOOTH ) ;
00180 
00181     if (texid != 0) {
00182       // Texture was loaded, attach it to the part
00183       state->enable (GL_TEXTURE_2D);
00184       state->setTexture (texid);
00185 
00186       // Set rendering states for transparent/opaque parts
00187       if (transparent) {
00188         state->enable ( GL_BLEND ) ;
00189         state->enable (GL_ALPHA_TEST);
00190         state->setTranslucent();
00191       } else {
00192         state->disable ( GL_BLEND ) ;
00193         state->disable (GL_ALPHA_TEST);
00194         state->setOpaque();
00195       }
00196     } else {
00197       state->disable (GL_TEXTURE_2D);
00198       state->disable ( GL_BLEND ) ;
00199     }
00200 
00201     // If the line before last was "v1" then skip the next line, which is
00202     //   always a blank string ""
00203     if (v1flag) {
00204       pgets (s, LINE_LENGTH, p);
00205     }
00206 
00207     // Before reading vertex list, allocate table of (temporary) structs
00208     //   to hold the vertex table until the face data is read
00209     SVertex *vt = new SVertex[nVerts];
00210 
00211     // Vertex list
00212     for (int j=0; j<nVerts; j++) {
00213       // x, y, z, nx, ny, nz, u, v
00214       float x, y, z, nx, ny, nz, u, v;
00215       pgets (s, LINE_LENGTH, p);
00216       if (sscanf (s, "%f,%f,%f,%f,%f,%f,%f,%f",
00217         &x, &y, &z, &nx, &ny, &nz, &u, &v) != 8) {
00218         // Error
00219         gtfo ("CModelSMF : Error parsing vertex %d for part %d in %s",
00220           j, i, smfFilename) ;
00221       }
00222 
00223       // Assign values to (temporary) vertex table
00224       SVertex *pNext = &vt[j];
00225       pNext->x = x;
00226       pNext->y = z;
00227       pNext->z = y;
00228       pNext->nx = nx;
00229       pNext->ny = nz;
00230       pNext->nz = ny;
00231       pNext->u = u;
00232       pNext->v = v;
00233 //      pNext->v = 1.0f - v;    // For libtiff loaded TIF textures
00234     }
00235 
00236     // Before beginning to parse the vertex and face lists, create arrays
00237     //   for storage of the vertices, normals, texcoords and face indices
00238     ssgVertexArray *va = new ssgVertexArray(nFaces*3);
00239     ssgNormalArray *na = new ssgNormalArray(nFaces*3);
00240     ssgTexCoordArray *tca = new ssgTexCoordArray(nFaces*3);
00241 
00242     // Face list
00243     for (int k=0; k<nFaces; k++) {
00244       // i1, i2, i3 (vertex indices, clockwise)
00245       int i1, i2, i3;
00246       pgets (s, LINE_LENGTH, p);
00247       if (sscanf (s, "%d,%d,%d",
00248         &i1, &i2, &i3) != 3)
00249       {
00250         // Error
00251         gtfo ("CModelSMF : Error parsing face %d for part %d in %s",
00252           k, i, smfFilename);
00253       }
00254 
00255       // NOTE: ACM meshes are use left-hand coordinate system.
00256       //  In order to convert to OpenGL's right-hand system:
00257       //    - all triangle vertices are reversed order (3, 2, 1)
00258 
00259       // Add vertex coordinates to vertex array
00260       sgVec3 v1, v2, v3;
00261       sgSetVec3 (v1, vt[i1].x, vt[i1].y, vt[i1].z);
00262       sgSetVec3 (v2, vt[i2].x, vt[i2].y, vt[i2].z);
00263       sgSetVec3 (v3, vt[i3].x, vt[i3].y, vt[i3].z);
00264       va->add (v3);
00265       va->add (v2);
00266       va->add (v1);
00267 
00268       // Add normal coordinates to normal array
00269       sgVec3 n1, n2, n3;
00270       sgSetVec3 (n1, vt[i1].nx, vt[i1].ny, vt[i1].nz);
00271       sgSetVec3 (n2, vt[i2].nx, vt[i2].ny, vt[i2].nz);
00272       sgSetVec3 (n3, vt[i3].nx, vt[i3].ny, vt[i3].nz);
00273       na->add (n3);
00274       na->add (n2);
00275       na->add (n1);
00276 
00277       // Add texture coordinates to texcoord array
00278       sgVec2 tc1, tc2, tc3;
00279       sgSetVec2 (tc1, vt[i1].u, vt[i1].v);
00280       sgSetVec2 (tc2, vt[i2].u, vt[i2].v);
00281       sgSetVec2 (tc3, vt[i3].u, vt[i3].v);
00282       tca->add (tc3);
00283       tca->add (tc2);
00284       tca->add (tc1);
00285     }
00286 
00287     // Clean up SVertex list
00288     delete vt;
00289 
00290     // Create vertex table leaf for this part
00291     ssgVtxTable *vtab = new ssgVtxTable (GL_TRIANGLES, va, na, tca, NULL);
00292     vtab->setName (name);
00293     vtab->setState (state);
00294 
00295     // Temporary : Only add high-detail parts OPAQUE and TRANSP
00296     if ((strcmp (name, "OPAQUE") == 0) ||
00297         (strcmp (name, "TRANSP") == 0) ||
00298         (nParts == 1))
00299     {
00300       // Add the part to the top-level transform
00301       top->addKid (vtab);
00302     } else {
00303       // vtab will not be automatically deleted when removed from the
00304       //   SSG tree, so it must be deleted
00305       delete vtab;
00306     }
00307   }
00308 
00309   // Close pod file
00310   pclose (p);
00311 
00312   // Set transform
00313   sgMat4 T;
00314   sgMakeIdentMat4 (T);
00315   top->setTransform (T);
00316 }
00317 
00318 CModelSMF::~CModelSMF (void)
00319 {
00320   if (top->getRef() == 0) {
00321     top->removeAllKids();
00322     delete top;
00323   }
00324 }
00325 
00326 ssgEntity *CModelSMF::GetSSGEntity()
00327 {
00328   return top;
00329 }
00330 
SourceForge.net Logo Documentation generated by doxygen