Use Ogre data streams for loading NIFs

actorid
Chris Robinson 13 years ago
parent 0143cacd2b
commit b3aa453f9a

@ -24,9 +24,8 @@
#ifndef _NIF_FILE_H_ #ifndef _NIF_FILE_H_
#define _NIF_FILE_H_ #define _NIF_FILE_H_
#include <libs/mangle/stream/stream.hpp> #include <OgreResourceGroupManager.h>
#include <libs/mangle/stream/filters/buffer_stream.hpp> #include <OgreDataStream.h>
#include <components/misc/slice_array.hpp>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
@ -36,8 +35,6 @@
#include "record.hpp" #include "record.hpp"
#include "nif_types.hpp" #include "nif_types.hpp"
using namespace Mangle::Stream;
namespace Nif namespace Nif
{ {
@ -51,7 +48,7 @@ class NIFFile
int ver; int ver;
/// Input stream /// Input stream
StreamPtr inp; Ogre::DataStreamPtr inp;
/// File name, used for error messages /// File name, used for error messages
std::string filename; std::string filename;
@ -72,22 +69,10 @@ public:
} }
/// Open a NIF stream. The name is used for error messages. /// Open a NIF stream. The name is used for error messages.
NIFFile(StreamPtr nif, const std::string &name) NIFFile(const std::string &name)
: filename(name) : filename(name)
{ {
/* Load the entire file into memory. This allows us to use inp = Ogre::ResourceGroupManager::getSingleton().openResource(name);
direct pointers to the data arrays in the NIF, instead of
individually allocating and copying each one.
The NIF data is only stored temporarily in memory, since once
the mesh data is loaded it is siphoned into OGRE and
deleted. For that reason, we might improve this further and
use a shared region/pool based allocation scheme in the
future, especially since only one NIFFile will ever be loaded
at any given time.
*/
inp = StreamPtr(new BufferStream(nif));
parse(); parse();
} }
@ -112,11 +97,14 @@ public:
Parser functions Parser functions
****************************************************/ ****************************************************/
void skip(size_t size) { inp->getPtr(size); } void skip(size_t size) { inp->skip(size); }
template<class X> X getType() template<class X> X getType()
{ {
return *(const X*)inp->getPtr(sizeof(X)); X obj;
if(inp->read(&obj, sizeof(X)) != sizeof(X))
fail("Failed to read from NIF");
return obj;
} }
unsigned short getShort() { return getType<unsigned short>(); } unsigned short getShort() { return getType<unsigned short>(); }
int getInt() { return getType<int>(); } int getInt() { return getType<int>(); }
@ -127,7 +115,8 @@ public:
std::vector<X> getArrayLen(int num) std::vector<X> getArrayLen(int num)
{ {
std::vector<X> v(num); std::vector<X> v(num);
memcpy(&v[0], inp->getPtr(num*sizeof(X)), num*sizeof(X)); if(inp->read(&v[0], num*sizeof(X)) != num*sizeof(X))
fail("Failed to read from NIF");
return v; return v;
} }
@ -151,7 +140,8 @@ public:
{ {
std::string str; std::string str;
str.resize(size); str.resize(size);
memcpy(&str[0], inp->getPtr(size), size); if(inp->read(&str[0], size) != size)
fail("Failed to read from NIF");
return str.substr(0, str.find('\0')); return str.substr(0, str.find('\0'));
} }
std::string getString() std::string getString()

@ -25,7 +25,6 @@ http://www.gnu.org/licenses/ .
#include <Ogre.h> #include <Ogre.h>
#include <stdio.h> #include <stdio.h>
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
#include "../nif/nif_file.hpp" #include "../nif/nif_file.hpp"
#include "../nif/node.hpp" #include "../nif/node.hpp"
#include "../nif/data.hpp" #include "../nif/data.hpp"
@ -47,13 +46,11 @@ typedef unsigned char ubyte;
using namespace std; using namespace std;
using namespace Ogre; using namespace Ogre;
using namespace Nif; using namespace Nif;
using namespace Mangle::VFS;
using namespace NifBullet; using namespace NifBullet;
ManualBulletShapeLoader::~ManualBulletShapeLoader() ManualBulletShapeLoader::~ManualBulletShapeLoader()
{ {
delete vfs;
} }
Ogre::Matrix3 ManualBulletShapeLoader::getMatrix(Nif::Transformation* tr) Ogre::Matrix3 ManualBulletShapeLoader::getMatrix(Nif::Transformation* tr)
@ -94,20 +91,11 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
mTriMesh = new btTriangleMesh(); mTriMesh = new btTriangleMesh();
if (!vfs) vfs = new OgreVFS(resourceGroup);
if (!vfs->isFile(resourceName))
{
warn("File not found.");
return;
}
// Load the NIF. TODO: Wrap this in a try-catch block once we're out // Load the NIF. TODO: Wrap this in a try-catch block once we're out
// of the early stages of development. Right now we WANT to catch // of the early stages of development. Right now we WANT to catch
// every error as early and intrusively as possible, as it's most // every error as early and intrusively as possible, as it's most
// likely a sign of incomplete code rather than faulty input. // likely a sign of incomplete code rather than faulty input.
Nif::NIFFile nif(vfs->open(resourceName), resourceName); Nif::NIFFile nif(resourceName);
if (nif.numRecords() < 1) if (nif.numRecords() < 1)
{ {
warn("Found no records in NIF."); warn("Found no records in NIF.");

@ -50,14 +50,6 @@ namespace Nif
class Matrix; class Matrix;
} }
namespace Mangle
{
namespace VFS
{
class OgreVFS;
}
}
namespace NifBullet namespace NifBullet
{ {
@ -68,7 +60,7 @@ class ManualBulletShapeLoader : public BulletShapeLoader
{ {
public: public:
ManualBulletShapeLoader():resourceGroup("General"){vfs = 0;} ManualBulletShapeLoader():resourceGroup("General"){}
virtual ~ManualBulletShapeLoader(); virtual ~ManualBulletShapeLoader();
void warn(std::string msg) void warn(std::string msg)
@ -119,8 +111,6 @@ private:
*/ */
void handleNiTriShape(Nif::NiTriShape *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScales,bool raycastingOnly); void handleNiTriShape(Nif::NiTriShape *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScales,bool raycastingOnly);
Mangle::VFS::OgreVFS *vfs;
std::string resourceName; std::string resourceName;
std::string resourceGroup; std::string resourceGroup;

@ -379,16 +379,12 @@ String NIFLoader::getUniqueName(const String &input)
// is lost in that case. // is lost in that case.
void NIFLoader::findRealTexture(String &texName) void NIFLoader::findRealTexture(String &texName)
{ {
assert(vfs); if(Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName))
if (vfs->isFile(texName)) return; return;
int len = texName.size();
if (len < 4) return;
// Change texture extension to .dds // Change texture extension to .dds
texName[len-3] = 'd'; String::size_type pos = texName.rfind('.');
texName[len-2] = 'd'; texName.replace(pos, texName.length(), ".dds");
texName[len-1] = 's';
} }
//Handle node at top //Handle node at top
@ -1290,9 +1286,6 @@ void NIFLoader::loadResource(Resource *resource)
{ {
calculateTransform(); calculateTransform();
} }
// Set up the VFS if it hasn't been done already
if (!vfs) vfs = new OgreVFS(resourceGroup);
// Get the mesh // Get the mesh
mesh = dynamic_cast<Mesh*>(resource); mesh = dynamic_cast<Mesh*>(resource);
assert(mesh); assert(mesh);
@ -1301,12 +1294,6 @@ void NIFLoader::loadResource(Resource *resource)
resourceName = mesh->getName(); resourceName = mesh->getName();
//std::cout << resourceName << "\n"; //std::cout << resourceName << "\n";
if (!vfs->isFile(resourceName))
{
warn("File "+resourceName+" not found.");
return;
}
// Helper that computes bounding boxes for us. // Helper that computes bounding boxes for us.
BoundsFinder bounds; BoundsFinder bounds;
@ -1314,8 +1301,7 @@ void NIFLoader::loadResource(Resource *resource)
// of the early stages of development. Right now we WANT to catch // of the early stages of development. Right now we WANT to catch
// every error as early and intrusively as possible, as it's most // every error as early and intrusively as possible, as it's most
// likely a sign of incomplete code rather than faulty input. // likely a sign of incomplete code rather than faulty input.
NIFFile nif(vfs->open(resourceName), resourceName); NIFFile nif(resourceName);
if (nif.numRecords() < 1) if (nif.numRecords() < 1)
{ {
warn("Found no records in NIF."); warn("Found no records in NIF.");

@ -154,13 +154,6 @@ class NIFLoader : Ogre::ManualResourceLoader
return resourceName + ".skel"; return resourceName + ".skel";
} }
// This is the interface to the Ogre resource system. It allows us to
// load NIFs from BSAs, in the file system and in any other place we
// tell Ogre to look (eg. in zip or rar files.) It's also used to
// check for the existence of texture files, so we can exchange the
// extension from .tga to .dds if the texture is missing.
Mangle::VFS::OgreVFS *vfs;
std::string verbosePath; std::string verbosePath;
std::string resourceName; std::string resourceName;
std::string resourceGroup; std::string resourceGroup;

Loading…
Cancel
Save