OpenMW
components/nif/niffile.hpp
Go to the documentation of this file.
00001 /*
00002   OpenMW - The completely unofficial reimplementation of Morrowind
00003   Copyright (C) 2008-2010  Nicolay Korslund
00004   Email: < korslund@gmail.com >
00005   WWW: http://openmw.sourceforge.net/
00006 
00007   This file (nif_file.h) is part of the OpenMW package.
00008 
00009   OpenMW is distributed as free software: you can redistribute it
00010   and/or modify it under the terms of the GNU General Public License
00011   version 3, as published by the Free Software Foundation.
00012 
00013   This program is distributed in the hope that it will be useful, but
00014   WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016   General Public License for more details.
00017 
00018   You should have received a copy of the GNU General Public License
00019   version 3 along with this program. If not, see
00020   http://www.gnu.org/licenses/ .
00021 
00022  */
00023 
00024 #ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP
00025 #define OPENMW_COMPONENTS_NIF_NIFFILE_HPP
00026 
00027 #include <OgreResourceGroupManager.h>
00028 #include <OgreDataStream.h>
00029 #include <OgreVector2.h>
00030 #include <OgreVector3.h>
00031 #include <OgreVector4.h>
00032 #include <OgreMatrix3.h>
00033 #include <OgreQuaternion.h>
00034 #include <OgreStringConverter.h>
00035 
00036 #include <stdexcept>
00037 #include <vector>
00038 #include <cassert>
00039 
00040 #include <boost/weak_ptr.hpp>
00041 #include <boost/shared_ptr.hpp>
00042 #include <boost/make_shared.hpp>
00043 #include <boost/detail/endian.hpp>
00044 
00045 #include <libs/platform/stdint.h>
00046 
00047 #include "record.hpp"
00048 #include "niftypes.hpp"
00049 #include "nifstream.hpp"
00050 
00051 namespace Nif
00052 {
00053 
00054 class NIFFile
00055 {
00056     enum NIFVersion {
00057         VER_MW    = 0x04000002    // Morrowind NIFs
00058     };
00059 
00061     int ver;
00062 
00064     std::string filename;
00065 
00067     std::vector<Record*> records;
00068 
00070     std::vector<Record*> roots;
00071 
00073     void parse();
00074 
00075     class LoadedCache;
00076     friend class LoadedCache;
00077 
00078     // attempt to protect NIFFile from misuse...
00079     struct psudo_private_modifier {}; // this dirty little trick should optimize out
00080     NIFFile (NIFFile const &);
00081     void operator = (NIFFile const &);
00082 
00083 public:
00085     void fail(const std::string &msg)
00086     {
00087         std::string err = "NIFFile Error: " + msg;
00088         err += "\nFile: " + filename;
00089         throw std::runtime_error(err);
00090     }
00091 
00092     void warn(const std::string &msg)
00093     {
00094         std::cerr << "NIFFile Warning: " << msg <<std::endl
00095                   << "File: " << filename <<std::endl;
00096     }
00097 
00098     typedef boost::shared_ptr <NIFFile> ptr;
00099 
00101     NIFFile(const std::string &name, psudo_private_modifier);
00102     ~NIFFile();
00103 
00104     static ptr create (const std::string &name);
00105     static void lockCache ();
00106     static void unlockCache ();
00107 
00108     struct CacheLock
00109     {
00110         CacheLock () { lockCache (); }
00111         ~CacheLock () { unlockCache (); }
00112     };
00113 
00115     Record *getRecord(size_t index)
00116     {
00117         Record *res = records.at(index);
00118         assert(res != NULL);
00119         return res;
00120     }
00122     size_t numRecords() { return records.size(); }
00123 
00125     Record *getRoot(size_t index=0)
00126     {
00127         Record *res = roots.at(index);
00128         assert(res != NULL);
00129         return res;
00130     }
00132     size_t numRoots() { return roots.size(); }
00133 };
00134 
00135 
00136 template<typename T>
00137 struct KeyT {
00138     float mTime;
00139     T mValue;
00140     T mForwardValue;  // Only for Quadratic interpolation
00141     T mBackwardValue; // Only for Quadratic interpolation
00142     float mTension;    // Only for TBC interpolation
00143     float mBias;       // Only for TBC interpolation
00144     float mContinuity; // Only for TBC interpolation
00145 };
00146 typedef KeyT<float> FloatKey;
00147 typedef KeyT<Ogre::Vector3> Vector3Key;
00148 typedef KeyT<Ogre::Vector4> Vector4Key;
00149 typedef KeyT<Ogre::Quaternion> QuaternionKey;
00150 
00151 template<typename T, T (NIFStream::*getValue)()>
00152 struct KeyListT {
00153     typedef std::vector< KeyT<T> > VecType;
00154 
00155     static const int sLinearInterpolation = 1;
00156     static const int sQuadraticInterpolation = 2;
00157     static const int sTBCInterpolation = 3;
00158 
00159     int mInterpolationType;
00160     VecType mKeys;
00161 
00162     void read(NIFStream *nif, bool force=false)
00163     {
00164         size_t count = nif->getInt();
00165         if(count == 0 && !force)
00166             return;
00167 
00168         mInterpolationType = nif->getInt();
00169         mKeys.resize(count);
00170         if(mInterpolationType == sLinearInterpolation)
00171         {
00172             for(size_t i = 0;i < count;i++)
00173             {
00174                 KeyT<T> &key = mKeys[i];
00175                 key.mTime = nif->getFloat();
00176                 key.mValue = (nif->*getValue)();
00177             }
00178         }
00179         else if(mInterpolationType == sQuadraticInterpolation)
00180         {
00181             for(size_t i = 0;i < count;i++)
00182             {
00183                 KeyT<T> &key = mKeys[i];
00184                 key.mTime = nif->getFloat();
00185                 key.mValue = (nif->*getValue)();
00186                 key.mForwardValue = (nif->*getValue)();
00187                 key.mBackwardValue = (nif->*getValue)();
00188             }
00189         }
00190         else if(mInterpolationType == sTBCInterpolation)
00191         {
00192             for(size_t i = 0;i < count;i++)
00193             {
00194                 KeyT<T> &key = mKeys[i];
00195                 key.mTime = nif->getFloat();
00196                 key.mValue = (nif->*getValue)();
00197                 key.mTension = nif->getFloat();
00198                 key.mBias = nif->getFloat();
00199                 key.mContinuity = nif->getFloat();
00200             }
00201         }
00202         else
00203             nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType));
00204     }
00205 };
00206 typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList;
00207 typedef KeyListT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyList;
00208 typedef KeyListT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyList;
00209 typedef KeyListT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyList;
00210 
00211 } // Namespace
00212 #endif