mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 14:45:35 +00:00
Use Ogre data streams for loading NIFs
This commit is contained in:
parent
0143cacd2b
commit
b3aa453f9a
5 changed files with 21 additions and 74 deletions
|
@ -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…
Reference in a new issue