md2.h

00001 /*--License:
00002         Lilith 3D Engine
00003         Copyright Lee Thomason (Grinning Lizard Software) 2002-2007
00004         www.grinninglizard.com/lilith
00005 
00006         This program is free software; you can redistribute it and/or
00007         modify it under the terms of the GNU General Public License
00008         as published by the Free Software Foundation; either version 2
00009         of the License, or (at your option) any later version.
00010 
00011         This program is distributed in the hope that it will be useful,
00012         but WITHOUT ANY WARRANTY; without even the implied warranty of
00013         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014         GNU General Public License for more details.
00015 
00016         You should have received a copy of the GNU General Public License
00017         along with this program; if not, write to the Free Software
00018         Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020         The full text of the license can be found in license.txt
00021 */
00022 
00023 #ifndef LILITH_MD2_INCLUDED
00024 #define LILITH_MD2_INCLUDED
00025 
00026 #include "animated.h"
00027 #include "../grinliz/glvector.h"
00028 
00029 namespace lilith3d
00030 {
00031         
00032 enum {
00033         MD2_STAND,
00034         MD2_RUN,
00035         MD2_ATTACK,
00036         MD2_PAIN0,
00037         MD2_PAIN1,
00038         MD2_PAIN2,
00039         MD2_JUMP,
00040         MD2_FLIP,
00041         MD2_SALUTE,
00042         MD2_TAUNT,              
00043         MD2_WAVE,               
00044         MD2_POINT,              
00045         MD2_CRSTAND,    
00046         MD2_CRWALK,             
00047         MD2_CRATTACK,   
00048         MD2_CRPAIN,             
00049         MD2_CRDEATH,    
00050         MD2_DEATH0,
00051         MD2_DEATH1,
00052         MD2_DEATH2,
00053         MD2_COUNT,
00054 
00055         MD2_PAIN = MD2_PAIN0,
00056         MD2_DEATH = MD2_DEATH0,
00057 };
00058 
00059 struct LMD2Vertex
00060 {
00061         grinliz::Vector3F       pos;
00062         grinliz::Vector3F       normal;
00063 };
00064 
00065 // 0 model, 1 weapon
00066 struct LMD2RenderIn
00067 {
00068         U32 actionID;
00069         U32 time;
00070 };
00071 
00072 struct LMD2RenderOut
00073 {
00074         // 0 for model, 1 for weapon
00075         U32 nVertex[2];
00076         const Texture*  texture[2];
00077 
00078         // Each array needs to be at least 2048 in length.
00079         LMD2Vertex* vertex[2];
00080 };
00081 
00086 class MD2Resource : public AnimatedResource
00087 {
00088   public:
00089         MD2Resource( const std::string& name );
00090         virtual ~MD2Resource();
00091         virtual const MD2Resource* ToMD2() const        { return this; }
00092 
00093         enum {
00094                 SPRITE, 
00095                 WEAPON
00096         };
00097 
00102         bool Load( const std::string& filename, int type );
00103 
00105         void SetTexture( const Texture* tex, int type ) { 
00106                 if ( type == SPRITE )
00107                         sprite.texture = tex;
00108                 else if ( type == WEAPON )
00109                         weapon.texture = tex;
00110         }
00111 
00112         U32 AnimationLength( int action ) const;
00113         
00115         void SetMelee( bool _melee )    { this->melee = _melee; }
00117         bool Melee() const                      { return melee; }
00119         bool Ranged() const                     { return !melee; }
00120 
00121         // NOTE: this runs in world space, unlike the StaticMesh
00122         int IntersectRay(       const LMD2RenderOut& out, const grinliz::Matrix4& m,
00123                 const grinliz::Vector3F& point, const grinliz::Vector3F& dir, grinliz::Vector3F* intersection ) const;
00124 
00125         const grinliz::Vector3F& WeaponOrigin() const { return weaponOrigin; }
00126         const grinliz::Matrix4& ResXForm() const { return resXForm; }
00127         void GenerateVertex( const LMD2RenderIn& in, LMD2RenderOut* out ) const;
00128         void StreamOutMD2(  int i, const LMD2RenderOut& out ) const;
00129         void StreamOutShadowMD2( ShadowVolumeCache* cache, const LMD2RenderOut& out, const grinliz::Matrix4& mat ) const;
00130         bool IsLooping( int action ) const;
00131 
00132   private:
00133 
00134         //int ActionToMD2Id( int action, bool* looping ) const;
00135 
00136         static grinliz::Vector3F normals[256];
00137         static bool normalsFlipped;
00138 
00139         struct MD2Header
00140         {
00141                 U32 magic;          // magic number: "IDP2"
00142                 U32 version;        // version: must be 8
00143 
00144                 U32 textureWidth;   // not used by lilith
00145                 U32 textureHeight;  // not used by lilith
00146 
00147                 U32 frameSize;      // the size of the frame in bytes
00148 
00149                 U32 numSkins;           
00150                 U32 numVertices;        // number of vertices per frame
00151                 U32 numST;                      // number of texture coordinates
00152                 U32 numTri;                     // number of triangles
00153                 U32 numGlCmds;          //
00154                 U32 numFrames;          // number of frames
00155 
00156                 U32 offsetSkins;        // offset skin data
00157                 U32 offsetST;           // offset texture coordinate data
00158                 U32 offsetTris;         // offset triangle data
00159                 U32 offsetFrames;       // offset frame data 
00160                 U32 offsetGlCmds;       // offset OpenGL command data
00161                 U32 offsetEnd;          // offset end of file
00162         };
00163 
00164         struct MD2Tri
00165         {
00166                 U16 vertexIndex[3];
00167                 U16 textureIndex[3];
00168         };
00169 
00170         // MD2 texture coordinates.
00171         // Texture coordinates are stored in a structure as short integers. 
00172         // To get the true texture coordinates, you have to divide s by skinwidth and t by skinheight
00173         struct MD2TexST
00174         {
00175                 S16 s;
00176                 S16 t;
00177         };
00178 
00179         // Vertices are composed of "compressed" 3D coordinates, which are stored in one byte for 
00180         // each coordinate, and of a normal vector index. 
00181         struct MD2Vertex
00182         {
00183                 U8 x, y, z;
00184                 U8 normal;
00185         };
00186 
00187         struct MD2Frame
00188         {
00189                 grinliz::Vector3F       scale;
00190                 grinliz::Vector3F       translate;
00191                 char                            name[16];
00192                 MD2Vertex                       md2Vertex[2048];        // Note it will be 2048 OR LESS
00193         };
00194 
00195         struct Action
00196         {
00197                 U32                                     numFrames;
00198                 U32                                     startFrame;
00199                 U32                                     msecPerFrame;
00200         };
00201 
00202         struct LObject
00203         {
00204                 const MD2Header* header;
00205                 const Texture*   texture;
00206 
00207                 enum { MAX_INDEX = 4096*3 };
00208                 mutable U16 index[MAX_INDEX];
00209                 mutable bool hasIndex;
00210                 grinliz::Vector2F st[2048];
00211 
00212                 #ifdef DEBUG
00213                 void* memStart;
00214                 void* memEnd;
00215                 #endif
00216         
00217                 const MD2Frame* GetFrame( int i ) const {
00218                         const size_t FRAME_SIZE = sizeof(float)*6 + sizeof(char)*16 + 4*header->numVertices;
00219 
00220                         const MD2Frame* frame = (const MD2Frame*)((U8*)header + header->offsetFrames + FRAME_SIZE*i );
00221                         GLASSERT( frame > memStart );
00222                         GLASSERT( frame < memEnd );
00223                         return frame;
00224                 }
00225                 const MD2TexST* GetTexST() const  {
00226                         const MD2TexST* texst = (const MD2TexST*)((U8*)header + header->offsetST );
00227                         GLASSERT( texst > memStart );
00228                         GLASSERT( texst < memEnd );
00229                         return texst;
00230                 }
00231                 const MD2Tri* GetTri() const {
00232                         const MD2Tri* tri = (const MD2Tri*)((U8*)header + header->offsetTris );
00233                         GLASSERT( tri > memStart );
00234                         GLASSERT( tri < memEnd );
00235                         return tri;
00236                 }
00237         };
00238 
00239         void GenerateObjectVertex(      const LObject* obj,                                     
00240                                                                 int frameId,
00241                                                                 float frame,
00242                                                                 LMD2Vertex* vertex,
00243                                                                 U32 *nVertex ) const;
00244 
00245         bool LoadInner( FILE* fp, LObject* obj, int type );
00246 
00247         inline static void Transform(   const MD2Vertex& md2Vertex, 
00248                                                                         const MD2Frame* frame,
00249                                                                         grinliz::Vector3F* out )
00250         {
00251                 out->x =  (frame->scale.x * (float)md2Vertex.x + frame->translate.x);
00252                 out->y = -(frame->scale.y * (float)md2Vertex.y + frame->translate.y);
00253                 out->z =  (frame->scale.z * (float)md2Vertex.z + frame->translate.z);           
00254         }
00255 
00256         LObject                         sprite, 
00257                                                 weapon;
00258 
00259         float                           allScale;                       // Scale factor for converting from size in MD2
00260                                                                                         // coordinates to Lilith coordinates.
00261         float                           deltaZ;                         // Offset in Lilith coordinates to move feet 
00262                                                                                         // to the ground.
00263 
00264         Action                          actions[ MD2_COUNT ];   
00265         grinliz::Vector3F       weaponOrigin;
00266         bool                            melee;
00267         grinliz::Matrix4        resXForm;
00268 };
00269 
00270 
00273 class MD2Mesh : public AnimatedMesh
00274 {
00275   public:
00276         MD2Mesh( const MD2Resource* meshResource );
00277         virtual ~MD2Mesh();
00278 
00280         void SetAction( int action );
00282         int GetAction();
00283 
00289         bool ActionOkay( int newAction );
00290 
00291         void StreamOutMesh( ELightPass light, EPass pass );
00292 
00293         #ifdef SHADOW_VOLUME
00294         virtual void StreamOutShadow( ShadowVolumeCache* cache );
00295         #endif
00296 
00297         //virtual void UpdateZ( float z );
00298         //virtual void SetPosV( const grinliz::Vector3F& pos, const grinliz::Matrix4& rotation );
00299 
00301         void CalcWeaponOrigin( grinliz::Vector3F* origin ) const;
00302 
00304         const MD2Resource* GetMD2Resource() const { return md2Resource; }
00305 
00306         virtual void IntersectRay(      int flags, 
00307                                                                 const grinliz::Vector3F& point, 
00308                                                                 const grinliz::Vector3F& dir, 
00309                                                                 LilithObjectList* vec );
00310 
00311   protected:
00312         void VertexCacheCurrent();
00313 
00314         const MD2Resource* md2Resource;
00315         int action;
00316         U32 actionStart;
00317         U32 lastAttack;         // There is a minimum time between attacks.
00318 
00319         LMD2RenderIn  renderIn;
00320         LMD2RenderOut renderOut;
00321         bool texGen;
00322 
00323         LMD2Vertex vertex0[2048];
00324         LMD2Vertex vertex1[2048];
00325 };
00326 
00327 
00328 };      // namespace lilith3d
00329 #endif

Generated on Fri Mar 23 19:36:22 2007 for Lilith3D by  doxygen 1.5.1-p1