![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cRVisualTriMesh.cppGo 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 } |