/* OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > WWW: http://openmw.sourceforge.net/ This file (nif_file.h) is part of the OpenMW package. OpenMW is distributed as free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License version 3 along with this program. If not, see http://www.gnu.org/licenses/ . */ #ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP #define OPENMW_COMPONENTS_NIF_NIFFILE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "record.hpp" #include "niftypes.hpp" #include "nifstream.hpp" namespace Nif { class NIFFile { enum NIFVersion { VER_MW = 0x04000002 // Morrowind NIFs }; /// Nif file version int ver; /// File name, used for error messages std::string filename; /// Record list std::vector records; /// Root list std::vector roots; /// Parse the file void parse(); NIFFile (NIFFile const &); void operator = (NIFFile const &); public: /// Used for error handling void fail(const std::string &msg) { std::string err = "NIFFile Error: " + msg; err += "\nFile: " + filename; throw std::runtime_error(err); } void warn(const std::string &msg) { std::cerr << "NIFFile Warning: " << msg < struct KeyT { float mTime; T mValue; T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList float mTension; // Only for TBC interpolation float mBias; // Only for TBC interpolation float mContinuity; // Only for TBC interpolation }; typedef KeyT FloatKey; typedef KeyT Vector3Key; typedef KeyT Vector4Key; typedef KeyT QuaternionKey; template struct KeyListT { typedef std::vector< KeyT > VecType; static const unsigned int sLinearInterpolation = 1; static const unsigned int sQuadraticInterpolation = 2; static const unsigned int sTBCInterpolation = 3; static const unsigned int sXYZInterpolation = 4; unsigned int mInterpolationType; VecType mKeys; KeyListT() : mInterpolationType(sLinearInterpolation) {} //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) void read(NIFStream *nif, bool force=false) { assert(nif); mInterpolationType = 0; size_t count = nif->getUInt(); if(count == 0 && !force) return; //If we aren't forcing things, make sure that read clears any previous keys if(!force) mKeys.clear(); mInterpolationType = nif->getUInt(); KeyT key; NIFStream &nifReference = *nif; if(mInterpolationType == sLinearInterpolation) { for(size_t i = 0;i < count;i++) { readTimeAndValue(nifReference, key); mKeys.push_back(key); } } else if(mInterpolationType == sQuadraticInterpolation) { for(size_t i = 0;i < count;i++) { readQuadratic(nifReference, key); mKeys.push_back(key); } } else if(mInterpolationType == sTBCInterpolation) { for(size_t i = 0;i < count;i++) { readTBC(nifReference, key); mKeys.push_back(key); } } //XYZ keys aren't actually read here. //data.hpp sees that the last type read was sXYZInterpolation and: // Eats a floating point number, then // Re-runs the read function 3 more times, with force enabled so that the previous values aren't cleared. // When it does that it's reading in a bunch of sLinearInterpolation keys, not sXYZInterpolation. else if(mInterpolationType == sXYZInterpolation) { //Don't try to read XYZ keys into the wrong part if ( count != 1 ) nif->file->fail("XYZ_ROTATION_KEY count should always be '1' . Retrieved Value: "+Ogre::StringConverter::toString(count)); } else if (0 == mInterpolationType) { if (count != 0) nif->file->fail("Interpolation type 0 doesn't work with keys"); } else nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } private: static void readTimeAndValue(NIFStream &nif, KeyT &key) { key.mTime = nif.getFloat(); key.mValue = (nif.*getValue)(); } static void readQuadratic(NIFStream &nif, KeyT &key) { readTimeAndValue(nif, key); } template static void readQuadratic(NIFStream &nif, KeyT &key) { readTimeAndValue(nif, key); key.mForwardValue = (nif.*getValue)(); key.mBackwardValue = (nif.*getValue)(); } static void readTBC(NIFStream &nif, KeyT &key) { readTimeAndValue(nif, key); key.mTension = nif.getFloat(); key.mBias = nif.getFloat(); key.mContinuity = nif.getFloat(); } }; typedef KeyListT FloatKeyList; typedef KeyListT Vector3KeyList; typedef KeyListT Vector4KeyList; typedef KeyListT QuaternionKeyList; } // Namespace #endif