OpenMW
|
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