AaronCameron.net
I care not for your petty politics.
Not a Member? - Login or Create an Account
Sunday the 5th of February 2012 @ 04:29pm
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cRMd2.cpp

Go 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
©2012 Aaron Cameron