![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cRMd2.cppGo to the documentation of this file.00001 /************************************************************************ 00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library 00003 Copyright (C) 2003 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 00026 #include "cRMd2.h" 00027 00028 #include "n2l/vfs.h" 00029 #include "n2l/materials.h" 00030 00031 #include <GL/gl.h> 00032 00033 using namespace std; 00034 00035 namespace n2l 00036 { 00037 00038 const tSint cRMd2::Md2MagicNumber = 0x32504449; 00039 const tSint cRMd2::Md2VersionNumber = 8; 00040 00041 00042 00043 /* ************************************************************ */ 00044 cRMd2::cRMd2( const cVfsNodeInterface & iFile ) : 00045 mSkins(0), 00046 mTriangles(0), 00047 mCurrentFrame(0), 00048 mTexture(0) 00049 { 00050 load(iFile); 00051 } 00052 00053 /* ************************************************************ */ 00054 cRMd2::~cRMd2() 00055 { 00056 00057 } 00058 00059 00060 /* ************************************************************ */ 00061 void cRMd2::load( const cVfsNodeInterface & iFile ) 00062 { 00063 const tVfsFileBuffer & buffer = iFile.buffer(); 00064 const tUint BufferSize(buffer.size()); 00065 // Fill out the header. 00066 if (BufferSize<=sizeof(tHeader)) 00067 throw cParsingException("cRMd2::load", 00068 "Size shortfall, not even a full header" ); 00069 memcpy( (void*)(&mHeader), (void*)(buffer.data()), sizeof(tHeader) ); 00070 // Check the header for information we know 00071 if (mHeader.mMagic != Md2MagicNumber) 00072 throw cParsingException("cRMd2::load", 00073 "Magic number did not match" ); 00074 if (mHeader.mVersion != Md2VersionNumber) 00075 throw cParsingException("cRMd2::load", 00076 "Version number did not match" ); 00077 00078 if (BufferSize<=tUint(mHeader.mFrameSize*mHeader.mNumFrames+mHeader.mOffsetFrames)) 00079 throw cParsingException("cRMd2::load", 00080 "Buffer too small for suggested frames"); 00081 00082 // Read the frames. 00083 tUint frameOffset(mHeader.mOffsetFrames); 00084 for (tSint i=0; i<mHeader.mNumFrames; ++i,frameOffset+=mHeader.mFrameSize) { 00085 mFrames.push_back( new cFrame( mHeader.mNumVertices ) ); 00086 mFrames[i]->readFrom( (tUint8*)(buffer.data())+frameOffset, 00087 mHeader.mNumVertices ); 00088 } 00089 00090 // Load skins 00091 if (mHeader.mNumSkins) { 00092 mSkins = new tSkin[mHeader.mNumSkins]; 00093 if (BufferSize<=(sizeof(tSkin)*mHeader.mNumSkins+mHeader.mOffsetSkins)) 00094 throw cParsingException("cRMd2::load", 00095 "Buffer too small for suggested skins"); 00096 memcpy( (void*)(mSkins), 00097 (void*)((tUint8*)(buffer.data())+mHeader.mOffsetSkins), 00098 sizeof(tSkin)*mHeader.mNumSkins ); 00099 } // if (mHeader.mNumSkins) 00100 00101 // Load texture coordinates 00102 // First we'll load them into a structure in their original 'short' 00103 // formats, then we'll scale them here and keep the scaled versions 00104 // instead, dropping the shorts. 00105 if (BufferSize<=(sizeof(tRawTextureCoordinate)*mHeader.mNumTexCoords + 00106 mHeader.mOffsetTexCoords)) 00107 throw cParsingException("cRMd2::load", 00108 "Buffer too small for suggested texture coordinates"); 00109 tRawTextureCoordinate * rawTexCoords; 00110 rawTexCoords = new tRawTextureCoordinate[mHeader.mNumTexCoords]; 00111 memcpy( (void*)(rawTexCoords), 00112 (void*)((tUint8*)(buffer.data())+mHeader.mOffsetTexCoords), 00113 sizeof(tRawTextureCoordinate)*mHeader.mNumTexCoords ); 00114 00115 mTextureCoords = new tTextureCoordinate[mHeader.mNumTexCoords]; 00116 for (tSint i=0; i<mHeader.mNumTexCoords; ++i) { 00117 mTextureCoords[i].mS = rawTexCoords[i].mS/tFloat(mHeader.mSkinWidth); 00118 mTextureCoords[i].mT = rawTexCoords[i].mT/tFloat(mHeader.mSkinHeight); 00119 } 00120 delete []rawTexCoords; 00121 00122 00123 // Load Triangles 00124 if (BufferSize<=(sizeof(tTriangle)*mHeader.mNumTriangles + 00125 mHeader.mOffsetTriangles)) 00126 throw cParsingException("cRMd2::load", 00127 "Buffer too small for suggested triangles"); 00128 mTriangles = new tTriangle[mHeader.mNumTriangles]; 00129 memcpy( (void*)(mTriangles), 00130 (void*)((tUint8*)(buffer.data())+mHeader.mOffsetTriangles), 00131 sizeof(tTriangle)*mHeader.mNumTriangles ); 00132 00133 } 00134 00135 /* ************************************************************ */ 00136 void cRMd2::selectFrame( const tUint iFrameNum ) 00137 { 00138 if (iFrameNum>mFrames.size()) 00139 throw cOutOfBoundsException("cRMd2::selectFrame", 00140 "No such frame"); 00141 mCurrentFrame = iFrameNum; 00142 } 00143 00144 /* ************************************************************ */ 00145 void cRMd2::render( const cAutoPtr<const cGLTexture> & i_iTexture, 00146 const tRenderOptions iOptions ) const 00147 { 00148 glEnable(GL_CULL_FACE); 00149 glCullFace(GL_FRONT); 00150 glEnable( GL_DEPTH_TEST ); 00151 00152 const tBool Textured( !(iOptions & R_NoTextures) && (i_iTexture || mTexture) ); 00153 00154 if (Textured) { 00155 glEnable( GL_TEXTURE_2D ); 00156 if (i_iTexture) i_iTexture->bind(); 00157 else mTexture->bind(); 00158 } 00159 // Find the vertices we're using for the two frames 00160 tTriangleVertex * vList = mFrames[mCurrentFrame]->mVertices; 00161 tUint vIndex; 00162 tUint tIndex; 00163 00164 // Let's draw the thing. 00165 if (iOptions & R_Wireframe) 00166 glBegin( GL_LINE_STRIP ); 00167 else glBegin( GL_TRIANGLES ); 00168 00169 for (tSint i=0; i<mHeader.mNumTriangles; ++i) 00170 for (tUint vi=0; vi<3; ++vi) { 00171 vIndex = mTriangles[i].mVertexIndices[vi]; 00172 tIndex = mTriangles[i].mTextureIndices[vi]; 00173 if (Textured) 00174 glTexCoord2f(mTextureCoords[tIndex].mS,mTextureCoords[tIndex].mT); 00175 glVertex3f( vList[vIndex].mVertex[0], 00176 vList[vIndex].mVertex[1], 00177 vList[vIndex].mVertex[2] ); 00178 } 00179 glEnd(); 00180 00181 glDisable( GL_DEPTH_TEST ); 00182 glDisable(GL_CULL_FACE); 00183 if (Textured) glDisable( GL_TEXTURE_2D ); 00184 } 00185 00186 00187 /* ************************************************************ */ 00188 void cRMd2::renderInter( const tUint iFrameNum, 00189 const tFloat iFraction, 00190 const cAutoPtr<const cGLTexture> & i_iTexture, 00191 const tRenderOptions iOptions ) const 00192 { 00193 if (iFrameNum+1>=mFrames.size()) return; 00194 glEnable(GL_CULL_FACE); 00195 glCullFace(GL_FRONT); 00196 glEnable( GL_DEPTH_TEST ); 00197 if (mTexture) { 00198 glEnable( GL_TEXTURE_2D ); 00199 mTexture->bind(); 00200 } 00201 // Find the vertices we're using for the two frames 00202 tTriangleVertex * vList[2] = { 00203 mFrames[iFrameNum]->mVertices, 00204 mFrames[iFrameNum+1]->mVertices 00205 }; 00206 tFloat vert[2][3]; 00207 tUint vIndex; 00208 tUint tIndex; 00209 // Let's draw the thing. 00210 00211 glBegin( GL_TRIANGLES ); 00212 for (tSint i=0; i<mHeader.mNumTriangles; ++i) 00213 for (tUint vi=0; vi<3; ++vi) { 00214 vIndex = mTriangles[i].mVertexIndices[vi]; 00215 tIndex = mTriangles[i].mTextureIndices[vi]; 00216 vert[0][0] = vList[0][vIndex].mVertex[0]; 00217 vert[0][1] = vList[0][vIndex].mVertex[1]; 00218 vert[0][2] = vList[0][vIndex].mVertex[2]; 00219 vert[1][0] = vList[1][vIndex].mVertex[0]; 00220 vert[1][1] = vList[1][vIndex].mVertex[1]; 00221 vert[1][2] = vList[1][vIndex].mVertex[2]; 00222 if (mTexture) 00223 glTexCoord2f(mTextureCoords[tIndex].mS,mTextureCoords[tIndex].mT); 00224 glVertex3f( vert[0][0] + iFraction*(vert[1][0]-vert[0][0]), 00225 vert[0][1] + iFraction*(vert[1][1]-vert[0][1]), 00226 vert[0][2] + iFraction*(vert[1][2]-vert[0][2]) ); 00227 } 00228 glEnd(); 00229 00230 glDisable( GL_DEPTH_TEST ); 00231 glDisable(GL_CULL_FACE); 00232 if (mTexture) glDisable( GL_TEXTURE_2D ); 00233 } 00234 00235 00236 /******************************************************************/ 00237 void cRMd2::centerAroundOrigin() 00238 { 00239 // I have no idea how to implement this, since it's animated. 00240 // If I center each frame individually, it'll jitter when 00241 // animated, and centering the whole animation strip could cause 00242 // position to be odd for many frames 00243 } 00244 00245 00246 /* ************************************************************ */ 00247 const tString cRMd2::dump() const 00248 { 00249 tString temp( "cRMd2(\n" ); 00250 temp += "\tMagic:\t\t"; 00251 temp += asString(mHeader.mMagic) + "\n"; 00252 temp += "\tVersion:\t"; 00253 temp += asString(mHeader.mVersion) + "\n"; 00254 temp += "\tSkinW:\t\t"; 00255 temp += asString(mHeader.mSkinWidth) + "\n"; 00256 temp += "\tSkinH:\t\t"; 00257 temp += asString(mHeader.mSkinHeight) + "\n"; 00258 temp += "\tFrameS:\t\t"; 00259 temp += asString(mHeader.mFrameSize) + "\n"; 00260 temp += "\tNumSkins:\t"; 00261 temp += asString(mHeader.mNumSkins) + "\n"; 00262 temp += "\tNumVert:\t"; 00263 temp += asString(mHeader.mNumVertices) + "\n"; 00264 temp += "\tNumTexCord:\t"; 00265 temp += asString(mHeader.mNumTexCoords) + "\n"; 00266 temp += "\tNumTri:\t\t"; 00267 temp += asString(mHeader.mNumTriangles) + "\n"; 00268 temp += "\tNumGLCom:\t"; 00269 temp += asString(mHeader.mNumGlCommands) + "\n"; 00270 temp += "\tNumFrames:\t"; 00271 temp += asString(mHeader.mNumFrames) + "\n"; 00272 temp += "\tOffSkins:\t"; 00273 temp += asString(mHeader.mOffsetSkins) + "\n"; 00274 temp += "\tOffTexCord:\t"; 00275 temp += asString(mHeader.mOffsetTexCoords) + "\n"; 00276 temp += "\tOffTri:\t\t"; 00277 temp += asString(mHeader.mOffsetTriangles) + "\n"; 00278 temp += "\tOffFrames:\t"; 00279 temp += asString(mHeader.mOffsetFrames) + "\n"; 00280 temp += "\tOffGLCom:\t"; 00281 temp += asString(mHeader.mOffsetGlCommands) + "\n"; 00282 temp += "\tOffEnd:\t\t"; 00283 temp += asString(mHeader.mOffsetEnd) + "\n"; 00284 temp += ")"; 00285 return temp; 00286 } 00287 00288 00289 /* ************************************************************ */ 00290 const tString cRMd2::dumpFrames() const 00291 { 00292 tString temp( "cRMd2 frames(" ); 00293 vector<cFrame*>::const_iterator frame = mFrames.begin(); 00294 const vector<cFrame*>::const_iterator EndFrame = mFrames.end(); 00295 for (; frame<EndFrame; ++frame) 00296 temp += tString("\n\t") + (*frame)->mName; 00297 temp += "\n)"; 00298 return temp; 00299 } 00300 00301 00302 /* ************************************************************ */ 00303 void cRMd2::cFrame::readFrom( const tUint8 * iBuffer, 00304 const tUint iNumVert ) 00305 { 00306 free(); 00307 tUint offset(0); 00308 memcpy( (void*)(mScale), (void*)(iBuffer), sizeof(mScale) ); 00309 offset += sizeof(mScale); 00310 00311 memcpy( (void*)(mTranslate), (void*)(iBuffer+offset), 00312 sizeof(mTranslate) ); 00313 offset += sizeof(mTranslate); 00314 00315 memcpy( (void*)(mName), (void*)(iBuffer+offset), 00316 sizeof(mName) ); 00317 offset += sizeof(mName); 00318 00319 // Load the unscaled vertices first, then scale them 00320 // and keep those instead 00321 tRawTriangleVertex * rawVertices; 00322 rawVertices = new tRawTriangleVertex[iNumVert]; 00323 memcpy( (void*)(rawVertices), (void*)(iBuffer+offset), 00324 sizeof(tRawTriangleVertex)*iNumVert ); 00325 00326 mVertices = new tTriangleVertex[iNumVert]; 00327 for (tUint i=0; i<iNumVert; ++i) { 00328 mVertices[i].mVertex[0] = rawVertices[i].mVertex[0]*mScale[0]+mTranslate[0]; 00329 mVertices[i].mVertex[1] = rawVertices[i].mVertex[2]*mScale[2]+mTranslate[2]; 00330 mVertices[i].mVertex[2] = -1*(rawVertices[i].mVertex[1]*mScale[1]+mTranslate[1]); 00331 } 00332 delete []rawVertices; 00333 } 00334 00335 00336 /******************************************************************/ 00337 const tString & cRMd2::vfsType() const 00338 { 00339 return VfsFileType_MD2; 00340 } 00341 00342 /* ************************************************************ */ 00343 void cRMd2::cFrame::free() 00344 { 00345 if (!mVertices) return; 00346 delete []mVertices; 00347 mVertices = 0; 00348 } 00349 00350 } // namespace |