AaronCameron.net
I care not for your petty politics.
Not a Member? - Login or Create an Account
Tuesday the 22nd of May 2012 @ 03:02am
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cRVisualTriMesh.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2002  Aaron Cameron
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Lesser General Public
00007 License as published by the Free Software Foundation; either
00008 version 2.1 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019 A copy of the GNU Lesser General Public License has been provided with
00020 this library in the file 'COPYING'.
00021 
00022 Contact information for the author of this library has been provided
00023 with this library in the file 'AUTHOR'.
00024 ************************************************************************/
00025 #include "renderObjects/cRVisualTriMesh.h"
00026 
00027 #include "n2l/materials.h"
00028 #include "n2l/dynVars.h"
00029 #include "n2l/vfs.h"
00030 
00031 #include <iostream>
00032 using namespace std;
00033 
00034 /******************************************************************************/
00035 namespace n2l
00036 {
00037 
00038     /**************************************************************************/
00039     cRVisualTriMesh::cRVisualTriMesh()
00040     {
00041         init();
00042     }
00043 
00044     /**************************************************************************/
00045     cRVisualTriMesh::cRVisualTriMesh( const cRVisualTriMesh &iMesh )
00046     {
00047         init();
00048         *this = iMesh;
00049     }
00050 
00051     /**************************************************************************/
00052     cRVisualTriMesh::cRVisualTriMesh( const cVfsNodeInterface &iNode )
00053     {
00054         init();
00055         load( iNode );
00056     }
00057 
00058     /**************************************************************************/
00059     cRVisualTriMesh::cRVisualTriMesh( const cDynVar &iDef )
00060     {
00061         init();
00062         load( iDef );
00063     }
00064 
00065     /**************************************************************************/
00066     cRVisualTriMesh::~cRVisualTriMesh()
00067     {
00068         clear();
00069     }
00070 
00071     /**************************************************************************/
00072     void cRVisualTriMesh::load( const cVfsNodeInterface &iNode )
00073     {
00074         tVfsFileBuffer buffer;
00075         tUint DataOffset;
00076         try
00077         {
00078             DataOffset = vfsNodeFileWithHeader( iNode, "n2l::cRVisualTriMesh",
00079                 buffer );
00080         }
00081         catch ( const cBadDataUseException &iException )
00082         {
00083             throw cBadDataUseException( "cRVisualTriMesh::load",
00084                 "Failed to load: \"" + iNode.name() + "\": " + iException );
00085         }
00086         cDynVar def;
00087         def.unserialize( buffer, DataOffset );
00088         load( def );
00089     }
00090 
00091     /**************************************************************************/
00092     void cRVisualTriMesh::load( const cDynVar &iDef )
00093     {
00094         // Check the encoding type
00095         tString encoding = iDef["encoding"];
00096         if (encoding=="serialized")
00097             load_serialized( iDef["data"] );
00098         if (encoding=="n2lASCII1.0")
00099             load_n2lASCII1_0( tString(iDef["data"]) );
00100         else
00101             throw cUnsupportedFileFormatException( "cRVisualTriMesh::load",
00102                 "Unknown mesh encoding", encoding );
00103     }
00104 
00105     /**************************************************************************/
00106     void cRVisualTriMesh::render( const cAutoPtr<const cGLTexture> &i_iTexture,
00107         const tRenderOptions iOptions ) const
00108     {
00109         if (!mFaces)
00110             throw cBadDataUseException( "cRVisualTriMesh::render",
00111                 "Render of a mesh with no faces" );
00112 
00113         // Push all rendering attributes
00114         glPushAttrib( GL_ALL_ATTRIB_BITS );
00115 
00116         // Multi pass is disabled at the moment.  The depth check seems to
00117         // break the method I read online, and when disabled the spec
00118         tUint numPasses( 1 );
00119 
00120         // Resolve rendering options
00121         const tBool Textured( mNumValues[Header_TexCoords] &&
00122             i_iTexture.isSet() &&
00123             !(iOptions & R_NoTextures) );
00124 
00125         const tBool Normals(mNumValues[Header_Normals] &&
00126             !(iOptions & R_NoNormals) );
00127 
00128         const tBool VertLighting( !(iOptions & R_FaceLighting) );
00129 
00130         const tBool NoMaterials( iOptions & R_NoMaterials );
00131 
00132 
00133         // Figure out what material options we're using
00134         tMaterialOptions materialOptions( MatOpt_Normal );
00135 
00136         if (iOptions & R_NoTextures)
00137             materialOptions = materialOptions | MatOpt_NoTextures;
00138 
00139         // Calculate the number of required passes
00140         if ( (iOptions & R_MultiPass) && Textured && !NoMaterials ) {
00141             numPasses = 2;
00142             materialOptions = materialOptions | MatOpt_ZeroSpecular;
00143         }
00144 
00145         const GLenum renderType = 
00146             (iOptions & R_Wireframe)?GL_LINE_STRIP:GL_TRIANGLES;
00147 
00148         // Do the draw
00149         glEnable( GL_DEPTH_TEST );
00150         if (!(iOptions & R_TwoSided)) {
00151             glCullFace(GL_BACK);
00152             glEnable(GL_CULL_FACE);
00153         } else {
00154             glDisable(GL_CULL_FACE);
00155         }
00156 
00157         if (!Textured) glDisable(GL_TEXTURE_2D);
00158 
00159         cRTriMeshFace * face;
00160         tUint currentMaterial( tUint(-1) );
00161         
00162         glShadeModel( GL_SMOOTH );
00163         tBool smoothShading( true );
00164         tBool noTexture( false );
00165 
00166         for (tUint pass=0; pass<numPasses; ++pass) {
00167 
00168             // For pass 1, if textured bind the texture.
00169             if (pass==0 && Textured) {
00170                 glEnable( GL_TEXTURE_2D );
00171                 i_iTexture->bind();
00172                 materialOptions = materialOptions | MatOpt_NoTextures;
00173 
00174             } else if (pass==1) {
00175                 // Enable specular highlighting, texturing is already
00176                 // off.  Also disable diffuse, ambient and emission.
00177                 materialOptions = materialOptions & ~MatOpt_ZeroSpecular;
00178                 materialOptions = materialOptions | MatOpt_ZeroDiffAmbEmis;
00179                 glDepthFunc( GL_LEQUAL );
00180                 glEnable( GL_BLEND );
00181                 glBlendFunc(GL_ONE,GL_ONE);
00182             }
00183             
00184             glBegin( renderType );
00185             
00186             for (tUint f=0; f<mNumValues[Header_Faces]; ++f)
00187             {
00188                 face = &(mFaces[f]);
00189 
00190                 // Map the material
00191                 if (!NoMaterials && currentMaterial!=face->mMat) {
00192                     currentMaterial = face->mMat;
00193                     // You're supposed to be able to set material properties
00194                     // between begin/end, but after the NVIDIA 53.28 driver
00195                     // was released it broke.  Likely it's something I'm
00196                     // doing, but regardless, the material properties are
00197                     // completely erratic if set between begin/end.
00198                     glEnd();
00199                     mMaterials[currentMaterial].useMaterial( materialOptions );
00200                     glBegin( renderType );
00201                 }
00202 
00203                 if (smoothShading!=(face->mFlags&FaceFlag_SmoothShading)) {
00204                     glEnd();
00205                     if (face->mFlags&FaceFlag_SmoothShading) {
00206                         smoothShading = true;
00207                         glShadeModel(GL_SMOOTH);
00208                     } else {
00209                         smoothShading = false;
00210                         glShadeModel(GL_FLAT);
00211                     }
00212                     glBegin( renderType );
00213                 }
00214 
00215                 if (noTexture!=(face->mFlags&FaceFlag_NoTexture)) {
00216                     glEnd();
00217                     if (face->mFlags&FaceFlag_NoTexture) {
00218                         noTexture = true;
00219                         glDisable(GL_TEXTURE_2D);
00220                     } else {
00221                         noTexture = false;
00222                         if (Textured)
00223                             glEnable(GL_TEXTURE_2D);
00224                     }
00225                     glBegin( renderType );
00226                 }
00227 
00228                 // Draw it.
00229                 if (Normals) mNormals[face->mNA].glNormal3f();
00230                 if (Textured) mTexCoords[face->mUVA].glTexCoord2f();
00231                 mVertices[face->mVA].glVertex3f();
00232                 
00233                 if (Normals && VertLighting) mNormals[face->mNB].glNormal3f();
00234                 if (Textured) mTexCoords[face->mUVB].glTexCoord2f();
00235                 mVertices[face->mVB].glVertex3f();
00236 
00237                 if (Normals && VertLighting) mNormals[face->mNC].glNormal3f();
00238                 if (Textured) mTexCoords[face->mUVC].glTexCoord2f();
00239                 mVertices[face->mVC].glVertex3f();
00240             } // For each face
00241 
00242             glEnd();
00243 
00244             // Disable texturing if we used it.
00245             if (pass==0 && Textured && numPasses==2) {
00246                 glDisable( GL_TEXTURE_2D );
00247                  // Forces a reset of the material
00248                 currentMaterial = tUint(-1);
00249             }
00250 
00251         } // For each pass
00252 
00253         if (iOptions & R_ShowNormals) {
00254             glDisable( GL_TEXTURE_2D );
00255             glDisable( GL_LIGHTING );
00256             glColor4f( 1.0f, 0.0f, 1.0f, 1.0f );
00257             glBegin( GL_LINES );
00258             for (tUint f=0; f<mNumValues[Header_Faces]; ++f)
00259             {
00260                 face = &(mFaces[f]);
00261                 
00262                 mVertices[face->mVA].glVertex3f();
00263                 (mVertices[face->mVA]+mNormals[face->mNA]).glVertex3f();
00264 
00265                 mVertices[face->mVB].glVertex3f();
00266                 (mVertices[face->mVB]+mNormals[face->mNB]).glVertex3f();
00267 
00268                 mVertices[face->mVC].glVertex3f();
00269                 (mVertices[face->mVC]+mNormals[face->mNC]).glVertex3f();
00270             }
00271             glEnd();
00272         }
00273 
00274         // Restore the environment
00275         glPopAttrib();
00276     }
00277 
00278     /**************************************************************************/
00279     void cRVisualTriMesh::render( const cGLTexture &iTexture ) const
00280     {
00281         assert(mFaces);
00282         assert(mNumValues[Header_Normals]);
00283 
00284         // Push all rendering attributes
00285         glPushAttrib( GL_ALL_ATTRIB_BITS );
00286 
00287         // Do the draw
00288         glEnable( GL_DEPTH_TEST );
00289         glCullFace(GL_BACK);
00290         glEnable(GL_CULL_FACE);
00291 
00292         cRTriMeshFace * face;
00293         tUint currentMaterial( tUint(-1) );
00294         
00295         glShadeModel( GL_SMOOTH );
00296         tBool smoothShading( true );
00297         tBool noTexture( false );
00298         
00299         iTexture.bind();
00300         glEnable(GL_TEXTURE_2D);
00301 
00302         glBegin( GL_TRIANGLES );
00303         
00304         for (tUint f=0; f<mNumValues[Header_Faces]; ++f)
00305         {
00306             face = &(mFaces[f]);
00307 
00308             // Map the material
00309             if (currentMaterial!=face->mMat) {
00310                 currentMaterial = face->mMat;
00311                 // You're supposed to be able to set material properties
00312                 // between begin/end, but after the NVIDIA 53.28 driver
00313                 // was released it broke.  Likely it's something I'm
00314                 // doing, but regardless, the material properties are
00315                 // completely erratic if set between begin/end.
00316                 glEnd();
00317                 mMaterials[currentMaterial].useMaterial( MatOpt_Normal );
00318                 glBegin( GL_TRIANGLES );
00319             }
00320 
00321             if (smoothShading!=(face->mFlags&FaceFlag_SmoothShading)) {
00322                 glEnd();
00323                 if (face->mFlags&FaceFlag_SmoothShading) {
00324                     smoothShading = true;
00325                     glShadeModel(GL_SMOOTH);
00326                 } else {
00327                     smoothShading = false;
00328                     glShadeModel(GL_FLAT);
00329                 }
00330                 glBegin( GL_TRIANGLES );
00331             }
00332 
00333             if (noTexture!=(face->mFlags&FaceFlag_NoTexture)) {
00334                 glEnd();
00335                 if (face->mFlags&FaceFlag_NoTexture) {
00336                     noTexture = true;
00337                     glDisable(GL_TEXTURE_2D);
00338                 } else {
00339                     noTexture = false;
00340                     glEnable(GL_TEXTURE_2D);
00341                 }
00342                 glBegin( GL_TRIANGLES );
00343             }
00344 
00345             // Draw it.
00346             mNormals[face->mNA].glNormal3f();
00347             mTexCoords[face->mUVA].glTexCoord2f();
00348             mVertices[face->mVA].glVertex3f();
00349             
00350             mNormals[face->mNB].glNormal3f();
00351             mTexCoords[face->mUVB].glTexCoord2f();
00352             mVertices[face->mVB].glVertex3f();
00353 
00354             mNormals[face->mNC].glNormal3f();
00355             mTexCoords[face->mUVC].glTexCoord2f();
00356             mVertices[face->mVC].glVertex3f();
00357         } // For each face
00358 
00359         glEnd();
00360 
00361         // Restore the environment
00362         glPopAttrib();
00363     }
00364 
00365     /**************************************************************************/
00366     void cRVisualTriMesh::clear()
00367     {
00368         if (mMaterials) 
00369             delete []mMaterials;
00370 
00371         if (mVertices) 
00372             delete []mVertices;
00373         if (mNormals) 
00374             delete []mNormals;
00375         if (mTexCoords) 
00376             delete []mTexCoords;
00377 
00378         if (mNames) 
00379             delete []mNames;
00380 
00381         if (mFaces) 
00382             delete []mFaces;
00383 
00384         mMaterials = 0;
00385         mVertices = 0;
00386         mNormals = 0;
00387         mTexCoords = 0;
00388         mNames = 0;
00389         mFaces = 0;
00390     }
00391 
00392 
00393     /**************************************************************************/
00394     cRVisualTriMesh &cRVisualTriMesh::operator =(
00395         const cRVisualTriMesh &iMesh )
00396     {
00397         // Self assign
00398         if (this == &iMesh) return *this;
00399 
00400         clear();
00401 
00402         // Copy the headers
00403         for (tUint i=0; i<Header_NumHeaders; ++i)
00404             mNumValues[i] = iMesh.mNumValues[i];
00405 
00406         if (mNumValues[Header_Vertices]) {
00407             mVertices = new tVector3f[mNumValues[Header_Vertices]];
00408             memcpy( mVertices, iMesh.mVertices,
00409                 sizeof(tVector3f)*mNumValues[Header_Vertices] );
00410         }
00411 
00412         if (mNumValues[Header_Normals]) {
00413             mNormals = new tVector3f[mNumValues[Header_Normals]];
00414             memcpy( mNormals, iMesh.mNormals,
00415                 sizeof(tVector3f)*mNumValues[Header_Normals] );
00416         }
00417 
00418         if (mNumValues[Header_TexCoords]) {
00419             mTexCoords = new tVector2f[mNumValues[Header_TexCoords]];
00420             memcpy( mTexCoords, iMesh.mTexCoords,
00421                 sizeof(tVector2f)*mNumValues[Header_TexCoords] );
00422         }
00423 
00424         if (mNumValues[Header_Materials]) {
00425             mMaterials = new cMaterial[mNumValues[Header_Materials]];
00426             for (tUint i=0; i<mNumValues[Header_Materials]; ++i)
00427                 mMaterials[i] = iMesh.mMaterials[i];
00428         }
00429 
00430         if (mNumValues[Header_Names]) {
00431             mNames = new tString[mNumValues[Header_Names]];
00432             for (tUint i=0; i<mNumValues[Header_Names]; ++i)
00433                 mNames[i] = iMesh.mNames[i];
00434         }
00435 
00436         if (mNumValues[Header_Faces]) {
00437             mFaces = new cRTriMeshFace[mNumValues[Header_Faces]];
00438             memcpy( mFaces, iMesh.mFaces,
00439                 sizeof(cRTriMeshFace)*mNumValues[Header_Faces] );
00440         }
00441 
00442 
00443         return *this;
00444     }
00445 
00446     /**************************************************************************/
00447     cMaterial &cRVisualTriMesh::material( const tString &iMaterialName )
00448     {
00449         for (tUint i=0; i!=mNumValues[Header_Materials]; ++i)
00450             if (mMaterials[i].name()==iMaterialName)
00451                 return mMaterials[i];
00452         throw cOutOfBoundsException( "cRVisualTriMesh::material",
00453             tString("No such material: \"") + iMaterialName +
00454             "\" in this mesh" );
00455     }
00456 
00457     /**************************************************************************/
00458     cMaterial &cRVisualTriMesh::material( const tUint &iIndex )
00459     {
00460         return mMaterials[iIndex];
00461     }
00462 
00463     /**************************************************************************/
00464     void cRVisualTriMesh::selectVertexListByMaterial( list<tVector3f> &oList,
00465         const tString &iMaterialName ) const
00466     {
00467         if (!mNumValues[Header_Materials]) return;
00468         cRTriMeshFace *face;
00469         for (tUint f=0; f<mNumValues[Header_Faces]; ++f) {
00470             face = &(mFaces[f]);
00471             if (mMaterials[face->mMat].name() != iMaterialName) continue;
00472             oList.push_back( mVertices[face->mVA] );
00473             oList.push_back( mVertices[face->mVB] );
00474             oList.push_back( mVertices[face->mVC] );
00475         }
00476     }
00477 
00478     /**************************************************************************/
00479     void cRVisualTriMesh::selectFaceIndexListByName( list<tUint> &oList,
00480         const tString &iName ) const
00481     {
00482         if (!mNumValues[Header_Names]) return;
00483         for (tUint f=0; f<mNumValues[Header_Faces]; ++f)
00484             if (mNames[mFaces[f].mName] == iName)
00485                 oList.push_back(f);
00486     }
00487 
00488     /**************************************************************************/
00489     void cRVisualTriMesh::selectVertexListByName( list<tVector3f> &oList,
00490         const tString &iName ) const
00491     {
00492         if (!mNumValues[Header_Names]) return;
00493         cRTriMeshFace *face;
00494         for (tUint f=0; f<mNumValues[Header_Faces]; ++f) {
00495             face = &(mFaces[f]);
00496             if (mNames[face->mName] != iName) continue;
00497             oList.push_back( mVertices[face->mVA] );
00498             oList.push_back( mVertices[face->mVB] );
00499             oList.push_back( mVertices[face->mVC] );
00500         }
00501     }
00502 
00503     /**************************************************************************/
00504     void cRVisualTriMesh::selectVertexListByContainer( 
00505         list<tVector3f> &oList, const tString &iName ) const
00506     {
00507         if (mVertexContainers.empty()) return;
00508         const tVertexContainerMap::const_iterator List =
00509             mVertexContainers.find(iName);
00510         if (List==mVertexContainers.end()) return;
00511         const vector<tUint>::const_iterator Last = List->second.end();
00512         for (vector<tUint>::const_iterator i=List->second.begin();
00513             i!=Last; ++i)
00514         {
00515             oList.push_back( mVertices[*i] );
00516         }
00517     }
00518 
00519     /**************************************************************************/
00520     void cRVisualTriMesh::selectVertexIndexListByName(
00521         list<tUint> &oList, const tString &iName ) const
00522     {
00523         if (!mNumValues[Header_Names]) return;
00524         for (tUint f=0; f<mNumValues[Header_Faces]; ++f)
00525             if (mNames[mFaces[f].mName] == iName)
00526                 oList.push_back( f );
00527     }
00528 
00529     /**************************************************************************/
00530     void cRVisualTriMesh::selectVertexIndexListByContainer(
00531         list<tUint> &oList, const tString &iName ) const
00532     {
00533         if (mVertexContainers.empty()) return;
00534         const tVertexContainerMap::const_iterator List =
00535             mVertexContainers.find(iName);
00536         if (List==mVertexContainers.end()) return;
00537         const tUint Size = List->second.size();
00538         const vector<tUint>::const_iterator Last = List->second.end();
00539         for (tUint i=0; i!=Size; ++i)
00540             oList.push_back( List->second[i] );
00541     }
00542 
00543     /**************************************************************************/
00544     void cRVisualTriMesh::selectVertexIndexListByAnyName(
00545         list<tUint> &oList, const tString &iName,
00546         const tString &iPrefix ) const
00547     {
00548         selectVertexIndexListByName( oList, iName );
00549         selectVertexIndexListByContainer( oList, iPrefix+iName );
00550     }
00551 
00552     /**************************************************************************/
00553     void cRVisualTriMesh::selectVertexListByAnyName(
00554         list<tVector3f> &oList, const tString &iName,
00555         const tString &iPrefix ) const
00556     {
00557         selectVertexListByName( oList, iName );
00558         selectVertexListByContainer( oList, iPrefix+iName );
00559     }
00560 
00561     /**************************************************************************/
00562     const tVector3f cRVisualTriMesh::dimensions() const
00563     {
00564         if (!mNumValues[Header_Vertices])
00565             return tVector3f(0,0,0);
00566 
00567         // Get the minimum and maximum values in each axis
00568         tVector3f minV(mVertices[0]), maxV(mVertices[0]);
00569         for (tUint i=1; i<mNumValues[Header_Vertices]; ++i) {
00570             minV.set( n2lMin(minV.x(), mVertices[i].x()),
00571                 n2lMin(minV.y(), mVertices[i].y()),
00572                 n2lMin(minV.z(), mVertices[i].z()) );
00573             maxV.set( n2lMax(maxV.x(), mVertices[i].x()),
00574                 n2lMax(maxV.y(), mVertices[i].y()),
00575                 n2lMax(maxV.z(), mVertices[i].z()) );
00576         }
00577         return maxV-minV;
00578     }
00579 
00580     /**************************************************************************/
00581     const tFloat cRVisualTriMesh::boundingRadius() const
00582     {
00583         tFloat radius(0);
00584         for (tUint i=0; i<mNumValues[Header_Vertices]; ++i)
00585             radius = n2lMax( radius, mVertices[i].magnitude() );
00586         return radius;
00587     }
00588 
00589     /**************************************************************************/
00590     const tFloat cRVisualTriMesh::scaledBoundingRadius(
00591         const tVector3f &iScale ) const
00592     {
00593         tFloat radius(0);
00594         for (tUint i=0; i<mNumValues[Header_Vertices]; ++i)
00595             radius = n2lMax( radius, (mVertices[i]*iScale).magnitude() );
00596         return radius;
00597     }
00598 
00599     /**************************************************************************/
00600     void cRVisualTriMesh::scale( const tVector3f &iScale )
00601     {
00602         for (tUint i=0; i<mNumValues[Header_Vertices]; ++i)
00603             mVertices[i] *= iScale;
00604     }
00605 
00606     /**************************************************************************/
00607     void cRVisualTriMesh::init()
00608     {
00609         mMaterials = 0;
00610         mNames = 0;
00611         mVertices = 0;
00612         mNormals = 0;
00613         mTexCoords = 0;
00614         mFaces = 0;
00615     }
00616 
00617     /**************************************************************************/
00618     void cRVisualTriMesh::load_serialized( const cDynVar & iDef )
00619     {
00620         cDynVar meshDef;
00621         meshDef.unserialize(tString(iDef));
00622         throw cException( "cRVisualTriMesh::load_serialized",
00623             "Not implemenmted" );
00624     }
00625 
00626     /**************************************************************************/
00627     void cRVisualTriMesh::load_n2lASCII1_0( const tString & iDef )
00628     {
00629         tString::size_type sPos(0);
00630         tString::size_type ePos(0);
00631 
00632         // Load the headers
00633         sPos = load_n2lASCII1_0_headers( iDef, 0 );
00634 
00635         // Allocating for headers
00636         mVertices = new tVector3f[ mNumValues[Header_Vertices] ];
00637         mNormals = new tVector3f[ mNumValues[Header_Normals] ];
00638 
00639         // We need SOME kind of material here
00640         if (mNumValues[Header_Materials])
00641             mMaterials = new cMaterial[ mNumValues[Header_Materials] ];
00642 
00643         if (mNumValues[Header_TexCoords])
00644             mTexCoords = new tVector2f[ mNumValues[Header_TexCoords] ];
00645 
00646         if (mNumValues[Header_Names])
00647             mNames = new tString[ mNumValues[Header_Names] ];
00648         mFaces = new cRTriMeshFace[ mNumValues[Header_Faces] ];
00649 
00650         // Load the rest of the data
00651         tUint linesLoaded = 0;
00652         tUint currentCountHeader = Header_Vertices;
00653         
00654         while ( currentCountHeader != Header_NumHeaders &&
00655                 (ePos=iDef.find('\n',sPos)) != tString::npos) {
00656             // Load the line
00657             switch (currentCountHeader)
00658             {
00659                 case Header_Vertices:
00660                     load_n2lASCII1_0_tVector3fLine( mVertices[linesLoaded],
00661                         iDef, sPos, ePos );
00662                     break;
00663 
00664                 case Header_Normals:
00665                     load_n2lASCII1_0_tVector3fLine( mNormals[linesLoaded],
00666                         iDef, sPos, ePos );
00667                     break;
00668 
00669                 case Header_TexCoords:
00670                     load_n2lASCII1_0_tVector2fLine( mTexCoords[linesLoaded],
00671                         iDef, sPos, ePos );
00672                     break;
00673 
00674                 case Header_Materials:
00675                     load_n2lASCII1_0_cMaterialLine( mMaterials[linesLoaded],
00676                         iDef, sPos, ePos );
00677                     break;
00678 
00679                 case Header_Names:
00680                     load_n2lASCII1_0_tStringLine( mNames[linesLoaded],
00681                         iDef, sPos, ePos );
00682                     break;
00683 
00684                 case Header_Faces:
00685                     load_n2lASCII1_0_cRTriMeshFaceLine( mFaces[linesLoaded],
00686                         iDef, sPos, ePos );
00687                     break;
00688 
00689                 case Header_Containers:
00690                     load_n2lASCII1_0_vertexContainerLine( mVertexContainers,
00691                         iDef, sPos, ePos );
00692             }
00693             
00694             // Check what group we're in
00695             if (++linesLoaded == mNumValues[currentCountHeader]) {
00696                 linesLoaded = 0;
00697                 ++currentCountHeader;
00698                 while ( currentCountHeader != Header_NumHeaders &&
00699                         mNumValues[currentCountHeader]==0) ++currentCountHeader;
00700             }
00701             sPos = ePos+1;
00702         }
00703         
00704     }
00705 
00706     /**************************************************************************/
00707     const tString::size_type cRVisualTriMesh::load_n2lASCII1_0_headers(
00708         const tString &iDef, const tString::size_type iSPos )
00709     {
00710         tString::size_type sPos( iSPos );
00711         tString::size_type ePos(0);
00712         const tString::size_type DefSize( iDef.size() );
00713 
00714         assert(Header_NumHeaders == 7);
00715         // @warning This character list has to match the order of the enum in the
00716         // header.  This is a seriously ugly pointy edge.
00717         const char HeaderChar[Header_NumHeaders] = {
00718             'v','n','t','m','s','f','c' };
00719         
00720         for (tUint hNum=0; hNum<Header_NumHeaders; ++hNum) {
00721             if ((ePos = iDef.find('\n', sPos)) == tString::npos ||
00722                 iDef[sPos] != HeaderChar[hNum] || ePos<(sPos+3))
00723                 throw cParsingException(
00724                     "cRVisualTriMesh::load_n2lASCII1_0_headers",
00725                     "Missing, shortfall or wrong header for: " +
00726                     tString(1,HeaderChar[hNum]) );
00727 
00728             // Advance the sPos to the data
00729             sPos+=2;
00730             mNumValues[hNum] = asUint32( iDef.substr(sPos,(ePos-sPos)) );
00731             if (HeaderChar[hNum]!='c' && HeaderChar[hNum]!='m' &&
00732                 HeaderChar[hNum]!='t' && !mNumValues[hNum])
00733                 throw cBadDataUseException(
00734                     "cRVisualTriMesh::load_n2lASCII1_0_headers",
00735                     "Mesh contains no definitions for: " +
00736                     tString(1,HeaderChar[hNum]) );
00737             // Advance
00738             sPos = ePos+1;
00739             if (sPos>=DefSize)
00740                 throw cParsingException(
00741                     "cRVisualTriMesh::load_n2lASCII1_0_headers",
00742                     "Ran out of data advancing the header" );
00743         }
00744         // Make sure there's enough of all of the required headers
00745         return sPos;
00746     }
00747 
00748     /**************************************************************************/
00749     void cRVisualTriMesh::load_n2lASCII1_0_tVector3fLine( tVector3f &oValue,
00750         const tString &iDef, const tString::size_type iSPos,
00751         const tString::size_type iEPos )
00752     {
00753         tString::size_type spaces[2];
00754         spaces[0] = iDef.find(' ',iSPos);
00755         spaces[1] = iDef.find(' ',spaces[0]+1);
00756         if (spaces[0] == tString::npos || spaces[1] == tString::npos ||
00757             spaces[0] >= iEPos  || spaces[1] >= iEPos )
00758             throw cParsingException( "load_n2lASCII1_0_tVector3fLine",
00759                 "Value missing");
00760         
00761         oValue.x( asFloat(iDef.substr(iSPos, spaces[0]-iSPos)) );
00762         ++spaces[0];
00763         oValue.y( asFloat(iDef.substr(spaces[0], spaces[1]-spaces[0])) );
00764         ++spaces[1];
00765         oValue.z( asFloat(iDef.substr(spaces[1], iEPos-spaces[0])) );
00766     }
00767 
00768     /**************************************************************************/
00769     void cRVisualTriMesh::load_n2lASCII1_0_tVector2fLine( tVector2f &oValue,
00770         const tString &iDef, const tString::size_type iSPos,
00771         const tString::size_type iEPos )
00772     {
00773         tString::size_type space;
00774         space = iDef.find(' ',iSPos);
00775         if (space == tString::npos || space >= iEPos )
00776             throw cParsingException( "load_n2lASCII1_0_tVector2fLine",
00777                 "Value missing");
00778         
00779         oValue.x( asFloat(iDef.substr(iSPos, space-iSPos)) );
00780         ++space;
00781         oValue.y( asFloat(iDef.substr(space, iEPos-space)) );
00782     }
00783 
00784     /**************************************************************************/
00785     void cRVisualTriMesh::load_n2lASCII1_0_cMaterialLine(
00786         cMaterial &oValue, const tString &iDef, const tString::size_type iSPos,
00787         const tString::size_type iEPos )
00788     {
00789         cDynVar serialDef;
00790         serialDef.unserialize( iDef, iSPos );
00791         oValue.load( serialDef );
00792     }
00793 
00794     /**************************************************************************/
00795     void cRVisualTriMesh::load_n2lASCII1_0_tStringLine( tString &oValue,
00796         const tString &iDef, const tString::size_type iSPos,
00797         const tString::size_type iEPos )
00798     {
00799         oValue = iDef.substr( iSPos, iEPos-iSPos );
00800     }
00801 
00802     /**************************************************************************/
00803     void cRVisualTriMesh::load_n2lASCII1_0_cRTriMeshFaceLine(
00804         cRTriMeshFace &oValue, const tString &iDef,
00805         const tString::size_type iSPos, const tString::size_type iEPos )
00806     {
00807         vector<tString> values;
00808         explode( iDef.substr(iSPos,iEPos-iSPos), values, ' ','\0','\0',false);
00809         if (values.size()!=12)
00810             throw cParsingException( "load_n2lASCII1_0_cRTriMeshFaceLine",
00811                 "One or more values missing (or too many) in face "
00812                 "definition: " + iDef.substr(iSPos,iEPos-iSPos) );
00813         oValue.mMat =   asUint32(values[0]);
00814         
00815         oValue.mVA =    asUint32(values[1]);
00816         oValue.mNA =    asUint32(values[2]);
00817         oValue.mUVA =   asUint32(values[3]);
00818 
00819         oValue.mVB =    asUint32(values[4]);
00820         oValue.mNB =    asUint32(values[5]);
00821         oValue.mUVB =   asUint32(values[6]);
00822 
00823         oValue.mVC =    asUint32(values[7]);
00824         oValue.mNC =    asUint32(values[8]);
00825         oValue.mUVC =   asUint32(values[9]);
00826 
00827         oValue.mFlags = asUint32(values[10]);
00828         oValue.mName =  asUint32(values[11]);
00829     }
00830 
00831     /**************************************************************************/
00832     void cRVisualTriMesh::load_n2lASCII1_0_vertexContainerLine(
00833         tVertexContainerMap &ioValue, const tString & iDef, 
00834         const tString::size_type iSPos, const tString::size_type iEPos )
00835     {
00836         vector<tString> values;
00837         explode( iDef.substr(iSPos,iEPos-iSPos), values, ' ','\0','\0',false);
00838         if (values.size()!=2)
00839             throw cParsingException("load_n2lASCII1_0_vertexContainerLine",
00840                 tString("Improper number of values in container line: ") +
00841                 iDef.substr(iSPos,iEPos-iSPos) );
00842         // Get the vertex list
00843         vector<tString> vertexIDStrs;
00844         vector<tUint> vertexIDs;
00845         explode( values[1], vertexIDStrs, ',','\0','\0',false);
00846         vertexIDs.reserve( vertexIDStrs.size() );
00847         // Convert the values and make sure they're all in range.
00848         {
00849             const vector<tString>::const_iterator Last = vertexIDStrs.end();
00850             for (vector<tString>::const_iterator i=vertexIDStrs.begin();
00851                 i!=Last; ++i)
00852             {
00853                 tUint id = asUint(*i);
00854                 if (id>=mNumValues[Header_Vertices])
00855                     throw cParsingException(
00856                         "load_n2lASCII1_0_vertexContainerLine",
00857                         "Vertex ID in container is out of range: " +
00858                         iDef.substr(iSPos,iEPos-iSPos) );
00859                 vertexIDs.push_back(id);
00860             }
00861         }
00862 
00863         tUint nameID = asUint(values[0]);
00864         if (nameID>=mNumValues[Header_Names])
00865             throw cParsingException("load_n2lASCII1_0_vertexContainerLine",
00866                 "NameID in container is out of range: " +
00867                 iDef.substr(iSPos,iEPos-iSPos) );
00868         ioValue[ mNames[nameID] ] = vertexIDs;
00869     }
00870 
00871 }
©2012 Aaron Cameron