Moved functions from niffile.cpp to where they belong.

Also cleaned up some #includes

Removed a few asserts.  Vector already throws an out_of_range error.
deque
Arthur Moore 10 years ago
parent 45c0be8f62
commit 8be6aefd95

@ -19,7 +19,7 @@ add_component_dir (bsa
)
add_component_dir (nif
controlled effect niftypes record controller extra node record_ptr data niffile property
controlled effect niftypes record controller extra node record_ptr data niffile property nifkey data node
)
add_component_dir (nifcache

@ -0,0 +1,29 @@
#include "data.hpp"
#include "node.hpp"
namespace Nif
{
void NiSkinInstance::post(NIFFile *nif)
{
data.post(nif);
root.post(nif);
bones.post(nif);
if(data.empty() || root.empty())
nif->fail("NiSkinInstance missing root or data");
size_t bnum = bones.length();
if(bnum != data->bones.size())
nif->fail("Mismatch in NiSkinData bone count");
root->makeRootBone(&data->trafo);
for(size_t i=0; i<bnum; i++)
{
if(bones[i].empty())
nif->fail("Oops: Missing bone! Don't know how to handle this.");
bones[i]->makeBone(i, data->bones[i]);
}
}
} // Namespace

@ -25,9 +25,8 @@
#define OPENMW_COMPONENTS_NIF_DATA_HPP
#include "controlled.hpp"
#include <OgreQuaternion.h>
#include <OgreVector3.h>
#include "nifstream.hpp"
#include "nifkey.hpp"
namespace Nif
{

@ -1,39 +1,7 @@
/*
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.cpp) 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/ .
*/
#include "niffile.hpp"
#include "record.hpp"
#include "components/misc/stringops.hpp"
#include "extra.hpp"
#include "controlled.hpp"
#include "node.hpp"
#include "property.hpp"
#include "data.hpp"
#include "effect.hpp"
#include "controller.hpp"
#include <iostream>
#include <OgreResourceGroupManager.h>
namespace Nif
{
@ -204,15 +172,6 @@ void NIFFile::parse()
r->recIndex = i;
records[i] = r;
r->read(&nif);
// Discard tranformations for the root node, otherwise some meshes
// occasionally get wrong orientation. Only for NiNode-s for now, but
// can be expanded if needed.
// This should be rewritten when the method is cleaned up.
if (0 == i && rec == "NiNode")
{
static_cast<Nif::Node*>(r)->trafo = Nif::Transformation::getIdentity();
}
}
size_t rootNum = nif.getUInt();
@ -229,81 +188,4 @@ void NIFFile::parse()
records[i]->post(this);
}
/// \todo move to the write cpp file
void NiSkinInstance::post(NIFFile *nif)
{
data.post(nif);
root.post(nif);
bones.post(nif);
if(data.empty() || root.empty())
nif->fail("NiSkinInstance missing root or data");
size_t bnum = bones.length();
if(bnum != data->bones.size())
nif->fail("Mismatch in NiSkinData bone count");
root->makeRootBone(&data->trafo);
for(size_t i=0; i<bnum; i++)
{
if(bones[i].empty())
nif->fail("Oops: Missing bone! Don't know how to handle this.");
bones[i]->makeBone(i, data->bones[i]);
}
}
void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
const Nif::NiMaterialProperty *&matprop,
const Nif::NiAlphaProperty *&alphaprop,
const Nif::NiVertexColorProperty *&vertprop,
const Nif::NiZBufferProperty *&zprop,
const Nif::NiSpecularProperty *&specprop,
const Nif::NiWireframeProperty *&wireprop) const
{
if(parent)
parent->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop);
for(size_t i = 0;i < props.length();i++)
{
// Entries may be empty
if(props[i].empty())
continue;
const Nif::Property *pr = props[i].getPtr();
if(pr->recType == Nif::RC_NiTexturingProperty)
texprop = static_cast<const Nif::NiTexturingProperty*>(pr);
else if(pr->recType == Nif::RC_NiMaterialProperty)
matprop = static_cast<const Nif::NiMaterialProperty*>(pr);
else if(pr->recType == Nif::RC_NiAlphaProperty)
alphaprop = static_cast<const Nif::NiAlphaProperty*>(pr);
else if(pr->recType == Nif::RC_NiVertexColorProperty)
vertprop = static_cast<const Nif::NiVertexColorProperty*>(pr);
else if(pr->recType == Nif::RC_NiZBufferProperty)
zprop = static_cast<const Nif::NiZBufferProperty*>(pr);
else if(pr->recType == Nif::RC_NiSpecularProperty)
specprop = static_cast<const Nif::NiSpecularProperty*>(pr);
else if(pr->recType == Nif::RC_NiWireframeProperty)
wireprop = static_cast<const Nif::NiWireframeProperty*>(pr);
else
std::cerr<< "Unhandled property type: "<<pr->recName <<std::endl;
}
}
Ogre::Matrix4 Node::getLocalTransform() const
{
Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY);
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
return mat4;
}
Ogre::Matrix4 Node::getWorldTransform() const
{
if(parent != NULL)
return parent->getWorldTransform() * getLocalTransform();
return getLocalTransform();
}
}

@ -1,53 +1,13 @@
/*
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/ .
*/
///Main header for reading .nif files
#ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP
#define OPENMW_COMPONENTS_NIF_NIFFILE_HPP
#include <OgreResourceGroupManager.h>
#include <OgreDataStream.h>
#include <OgreVector2.h>
#include <OgreVector3.h>
#include <OgreVector4.h>
#include <OgreMatrix3.h>
#include <OgreQuaternion.h>
#include <OgreStringConverter.h>
#include <stdexcept>
#include <vector>
#include <cassert>
#include <typeinfo>
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/detail/endian.hpp>
#include <stdint.h>
#include <iostream>
#include "record.hpp"
#include "niftypes.hpp"
#include "nifstream.hpp"
namespace Nif
{
@ -61,37 +21,39 @@ class NIFFile
/// Nif file version
int ver;
/// File name, used for error messages
/// File name, used for error messages and opening the file
std::string filename;
/// Record list
std::vector<Record*> records;
/// Root list
/// Root list. This is a select portion of the pointers from records
std::vector<Record*> roots;
/// Parse the file
void parse();
///Private Copy Constructor
NIFFile (NIFFile const &);
///\overload
void operator = (NIFFile const &);
public:
/// Used for error handling
/// Used if file parsing fails
void fail(const std::string &msg)
{
std::string err = "NIFFile Error: " + msg;
err += "\nFile: " + filename;
throw std::runtime_error(err);
}
/// Used when something goes wrong, but not catastrophically so
void warn(const std::string &msg)
{
std::cerr << "NIFFile Warning: " << msg <<std::endl
<< "File: " << filename <<std::endl;
}
/// Open a NIF stream. The name is used for error messages.
/// Open a NIF stream. The name is used for error messages and opening the file.
NIFFile(const std::string &name);
~NIFFile();
@ -99,7 +61,6 @@ public:
Record *getRecord(size_t index) const
{
Record *res = records.at(index);
assert(res != NULL);
return res;
}
/// Number of records
@ -109,7 +70,6 @@ public:
Record *getRoot(size_t index=0) const
{
Record *res = roots.at(index);
assert(res != NULL);
return res;
}
/// Number of roots
@ -117,131 +77,6 @@ public:
};
template<typename T>
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<float> FloatKey;
typedef KeyT<Ogre::Vector3> Vector3Key;
typedef KeyT<Ogre::Vector4> Vector4Key;
typedef KeyT<Ogre::Quaternion> QuaternionKey;
template<typename T, T (NIFStream::*getValue)()>
struct KeyListT {
typedef std::vector< KeyT<T> > 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<T> 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<T> &key)
{
key.mTime = nif.getFloat();
key.mValue = (nif.*getValue)();
}
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
{
readTimeAndValue(nif, key);
}
template <typename U>
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
{
readTimeAndValue(nif, key);
key.mForwardValue = (nif.*getValue)();
key.mBackwardValue = (nif.*getValue)();
}
static void readTBC(NIFStream &nif, KeyT<T> &key)
{
readTimeAndValue(nif, key);
key.mTension = nif.getFloat();
key.mBias = nif.getFloat();
key.mContinuity = nif.getFloat();
}
};
typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList;
typedef KeyListT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyList;
typedef KeyListT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyList;
typedef KeyListT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyList;
} // Namespace
#endif

@ -0,0 +1,140 @@
///File to handle keys used by nif file records
#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
#define OPENMW_COMPONENTS_NIF_NIFKEY_HPP
#include <OgreStringConverter.h>
#include "nifstream.hpp"
namespace Nif
{
template<typename T>
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<float> FloatKey;
typedef KeyT<Ogre::Vector3> Vector3Key;
typedef KeyT<Ogre::Vector4> Vector4Key;
typedef KeyT<Ogre::Quaternion> QuaternionKey;
template<typename T, T (NIFStream::*getValue)()>
struct KeyListT {
typedef std::vector< KeyT<T> > 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<T> 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<T> &key)
{
key.mTime = nif.getFloat();
key.mValue = (nif.*getValue)();
}
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
{
readTimeAndValue(nif, key);
}
template <typename U>
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
{
readTimeAndValue(nif, key);
key.mForwardValue = (nif.*getValue)();
key.mBackwardValue = (nif.*getValue)();
}
static void readTBC(NIFStream &nif, KeyT<T> &key)
{
readTimeAndValue(nif, key);
key.mTension = nif.getFloat();
key.mBias = nif.getFloat();
key.mContinuity = nif.getFloat();
}
};
typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList;
typedef KeyListT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyList;
typedef KeyListT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyList;
typedef KeyListT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyList;
} // Namespace
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP

@ -1,6 +1,20 @@
///Functions used to read raw binary data from .nif files
#ifndef OPENMW_COMPONENTS_NIF_NIFSTREAM_HPP
#define OPENMW_COMPONENTS_NIF_NIFSTREAM_HPP
#include <stdint.h>
#include <stdexcept>
#include <OgreDataStream.h>
#include <OgreVector2.h>
#include <OgreVector3.h>
#include <OgreVector4.h>
#include <OgreMatrix3.h>
#include <OgreQuaternion.h>
#include "niftypes.hpp"
namespace Nif
{

@ -0,0 +1,57 @@
#include "node.hpp"
namespace Nif
{
void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
const Nif::NiMaterialProperty *&matprop,
const Nif::NiAlphaProperty *&alphaprop,
const Nif::NiVertexColorProperty *&vertprop,
const Nif::NiZBufferProperty *&zprop,
const Nif::NiSpecularProperty *&specprop,
const Nif::NiWireframeProperty *&wireprop) const
{
if(parent)
parent->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop);
for(size_t i = 0;i < props.length();i++)
{
// Entries may be empty
if(props[i].empty())
continue;
const Nif::Property *pr = props[i].getPtr();
if(pr->recType == Nif::RC_NiTexturingProperty)
texprop = static_cast<const Nif::NiTexturingProperty*>(pr);
else if(pr->recType == Nif::RC_NiMaterialProperty)
matprop = static_cast<const Nif::NiMaterialProperty*>(pr);
else if(pr->recType == Nif::RC_NiAlphaProperty)
alphaprop = static_cast<const Nif::NiAlphaProperty*>(pr);
else if(pr->recType == Nif::RC_NiVertexColorProperty)
vertprop = static_cast<const Nif::NiVertexColorProperty*>(pr);
else if(pr->recType == Nif::RC_NiZBufferProperty)
zprop = static_cast<const Nif::NiZBufferProperty*>(pr);
else if(pr->recType == Nif::RC_NiSpecularProperty)
specprop = static_cast<const Nif::NiSpecularProperty*>(pr);
else if(pr->recType == Nif::RC_NiWireframeProperty)
wireprop = static_cast<const Nif::NiWireframeProperty*>(pr);
else
std::cerr<< "Unhandled property type: "<<pr->recName <<std::endl;
}
}
Ogre::Matrix4 Node::getLocalTransform() const
{
Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY);
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
return mat4;
}
Ogre::Matrix4 Node::getWorldTransform() const
{
if(parent != NULL)
return parent->getWorldTransform() * getLocalTransform();
return getLocalTransform();
}
}

@ -1,26 +1,3 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/
This file (node.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_NODE_HPP
#define OPENMW_COMPONENTS_NIF_NODE_HPP
@ -29,6 +6,7 @@
#include "controlled.hpp"
#include "data.hpp"
#include "property.hpp"
#include "niftypes.hpp"
namespace Nif
{
@ -149,6 +127,14 @@ struct NiNode : Node
Node::read(nif);
children.read(nif);
effects.read(nif);
// Discard tranformations for the root node, otherwise some meshes
// occasionally get wrong orientation. Only for NiNode-s for now, but
// can be expanded if needed.
if (0 == recIndex)
{
static_cast<Nif::Node*>(this)->trafo = Nif::Transformation::getIdentity();
}
}
void post(NIFFile *nif)

@ -1,30 +1,8 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/
This file (record_ptr.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_RECORDPTR_HPP
#define OPENMW_COMPONENTS_NIF_RECORDPTR_HPP
#include "niffile.hpp"
#include "nifstream.hpp"
#include <vector>
namespace Nif

@ -5,6 +5,8 @@
#include <boost/shared_ptr.hpp>
#include <map>
namespace Nif
{

Loading…
Cancel
Save