restructured ogre nif code (struct -> class with singleton), formated code

This commit is contained in:
Armin Preiml 2010-08-08 17:20:55 +02:00
parent fa077ccdc4
commit 181b538e4a
2 changed files with 547 additions and 461 deletions

View File

@ -26,11 +26,11 @@
#include <stdio.h> #include <stdio.h>
#include <libs/mangle/vfs/servers/ogre_vfs.hpp> #include <libs/mangle/vfs/servers/ogre_vfs.hpp>
#include "components/nif/nif_file.hpp" #include "../nif/nif_file.hpp"
#include "components/nif/node.hpp" #include "../nif/node.hpp"
#include "components/nif/data.hpp" #include "../nif/data.hpp"
#include "components/nif/property.hpp" #include "../nif/property.hpp"
#include "libs/platform/strings.h" #include <libs/platform/strings.h>
// For warning messages // For warning messages
#include <iostream> #include <iostream>
@ -45,21 +45,27 @@ using namespace Ogre;
using namespace Nif; using namespace Nif;
using namespace Mangle::VFS; using namespace Mangle::VFS;
// This is the interface to the Ogre resource system. It allows us to NIFLoader& NIFLoader::getSingleton()
// 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.
static OgreVFS *vfs;
// Singleton instance used by load()
static NIFLoader g_sing;
// Makeshift error reporting system
static string errName;
static void warn(const string &msg)
{ {
cout << "WARNING (NIF:" << errName << "): " << msg << endl; static NIFLoader instance;
return instance;
}
NIFLoader* NIFLoader::getSingletonPtr()
{
return &getSingleton();
}
void NIFLoader::warn(string msg)
{
std::cerr << "NIFLoader: Warn:" << msg << "\n";
}
void NIFLoader::fail(string msg)
{
std::cerr << "NIFLoader: Fail: "<< msg << std::endl;
assert(1);
} }
// Helper class that computes the bounding box and of a mesh // Helper class that computes the bounding box and of a mesh
@ -126,12 +132,24 @@ public:
return sqrt(X.getMaxSquared() + Y.getMaxSquared() + Z.getMaxSquared()); return sqrt(X.getMaxSquared() + Y.getMaxSquared() + Z.getMaxSquared());
} }
float minX() { return X.min; } float minX() {
float maxX() { return X.max; } return X.min;
float minY() { return Y.min; } }
float maxY() { return Y.max; } float maxX() {
float minZ() { return Z.min; } return X.max;
float maxZ() { return Z.max; } }
float minY() {
return Y.min;
}
float maxY() {
return Y.max;
}
float minZ() {
return Z.min;
}
float maxZ() {
return Z.max;
}
}; };
// Conversion of blend / test mode from NIF -> OGRE. // Conversion of blend / test mode from NIF -> OGRE.
@ -177,7 +195,7 @@ static CompareFunction getTestMode(int mode)
} }
*/ */
static void createMaterial(const String &name, void NIFLoader::createMaterial(const String &name,
const Vector &ambient, const Vector &ambient,
const Vector &diffuse, const Vector &diffuse,
const Vector &specular, const Vector &specular,
@ -186,7 +204,7 @@ static void createMaterial(const String &name,
float alphaFlags, float alphaTest, float alphaFlags, float alphaTest,
const String &texName) const String &texName)
{ {
MaterialPtr material = MaterialManager::getSingleton().create(name, "General"); MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup);
// This assigns the texture to this material. If the texture name is // This assigns the texture to this material. If the texture name is
// a file name, and this file exists (in a resource directory), it // a file name, and this file exists (in a resource directory), it
@ -196,7 +214,8 @@ static void createMaterial(const String &name,
if (!texName.empty()) if (!texName.empty())
{ {
Pass *pass = material->getTechnique(0)->getPass(0); Pass *pass = material->getTechnique(0)->getPass(0);
/*TextureUnitState *txt =*/ pass->createTextureUnitState(texName); /*TextureUnitState *txt =*/
pass->createTextureUnitState(texName);
/* As of yet UNTESTED code from Chris: /* As of yet UNTESTED code from Chris:
pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
@ -254,7 +273,7 @@ static void createMaterial(const String &name,
// Takes a name and adds a unique part to it. This is just used to // Takes a name and adds a unique part to it. This is just used to
// make sure that all materials are given unique names. // make sure that all materials are given unique names.
static String getUniqueName(const String &input) String NIFLoader::getUniqueName(const String &input)
{ {
static int addon = 0; static int addon = 0;
static char buf[8]; static char buf[8];
@ -270,7 +289,7 @@ static String getUniqueName(const String &input)
// does not, change the string IN PLACE to say .dds instead and try // does not, change the string IN PLACE to say .dds instead and try
// that. The texture may still not exist, but no information of value // that. The texture may still not exist, but no information of value
// is lost in that case. // is lost in that case.
static void findRealTexture(String &texName) void NIFLoader::findRealTexture(String &texName)
{ {
assert(vfs); assert(vfs);
if (vfs->isFile(texName)) return; if (vfs->isFile(texName)) return;
@ -286,7 +305,7 @@ static void findRealTexture(String &texName)
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given // Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given
// mesh. // mesh.
static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material) void NIFLoader::createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material)
{ {
NiTriShapeData *data = shape->data.getPtr(); NiTriShapeData *data = shape->data.getPtr();
SubMesh *sub = mesh->createSubMesh(shape->name.toString()); SubMesh *sub = mesh->createSubMesh(shape->name.toString());
@ -372,9 +391,10 @@ static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material
// Set material if one was given // Set material if one was given
if (!material.empty()) sub->setMaterialName(material); if (!material.empty()) sub->setMaterialName(material);
/* Old commented D code. Might be useful when reimplementing
animation.
// Assign this submesh to the given bone // Assign this submesh to the given bone
//TODO: Must use niskininstance!
/*if (bone)
{
VertexBoneAssignment v; VertexBoneAssignment v;
v.boneIndex = ((Bone*)bone)->getHandle(); v.boneIndex = ((Bone*)bone)->getHandle();
v.weight = 1.0; v.weight = 1.0;
@ -386,7 +406,8 @@ static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material
v.vertexIndex = i; v.vertexIndex = i;
sub->addBoneAssignment(v); sub->addBoneAssignment(v);
} }
*/ }*/
} }
// Helper math functions. Reinventing linear algebra for the win! // Helper math functions. Reinventing linear algebra for the win!
@ -432,7 +453,7 @@ static void vectorMul(const Matrix &A, float *C)
C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2]; C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2];
} }
static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFinder &bounds) void NIFLoader::handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFinder &bounds)
{ {
assert(shape != NULL); assert(shape != NULL);
@ -451,7 +472,10 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFin
// If the object was marked "NCO" earlier, it shouldn't collide with // If the object was marked "NCO" earlier, it shouldn't collide with
// anything. // anything.
if (flags & 0x800) if (flags & 0x800)
{ collide = false; bbcollide = false; } {
collide = false;
bbcollide = false;
}
if (!collide && !bbcollide && hidden) if (!collide && !bbcollide && hidden)
// This mesh apparently isn't being used for anything, so don't // This mesh apparently isn't being used for anything, so don't
@ -600,7 +624,7 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFin
} }
} }
static void handleNode(Mesh* mesh, Nif::Node *node, int flags, void NIFLoader::handleNode(Mesh* mesh, Nif::Node *node, int flags,
const Transformation *trafo, BoundsFinder &bounds) const Transformation *trafo, BoundsFinder &bounds)
{ {
// Accumulate the flags from all the child nodes. This works for all // Accumulate the flags from all the child nodes. This works for all
@ -656,6 +680,8 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags,
// For NiNodes, loop through children // For NiNodes, loop through children
if (node->recType == RC_NiNode) if (node->recType == RC_NiNode)
{ {
NodeList &list = ((NiNode*)node)->children; NodeList &list = ((NiNode*)node)->children;
int n = list.length(); int n = list.length();
for (int i=0; i<n; i++) for (int i=0; i<n; i++)
@ -672,7 +698,7 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags,
void NIFLoader::loadResource(Resource *resource) void NIFLoader::loadResource(Resource *resource)
{ {
// Set up the VFS if it hasn't been done already // Set up the VFS if it hasn't been done already
if(!vfs) vfs = new OgreVFS("General"); if (!vfs) vfs = new OgreVFS(resourceGroup);
// Get the mesh // Get the mesh
Mesh *mesh = dynamic_cast<Mesh*>(resource); Mesh *mesh = dynamic_cast<Mesh*>(resource);
@ -680,7 +706,7 @@ void NIFLoader::loadResource(Resource *resource)
// Look it up // Look it up
const String &name = mesh->getName(); const String &name = mesh->getName();
errName = name; // Set name for error messages
if (!vfs->isFile(name)) if (!vfs->isFile(name))
{ {
warn("File not found."); warn("File not found.");
@ -738,7 +764,7 @@ MeshPtr NIFLoader::load(const std::string &name,
return MeshPtr(ptr); return MeshPtr(ptr);
// Nope, create a new one. // Nope, create a new one.
return MeshManager::getSingleton().createManual(name, group, &g_sing); return MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
} }
/* More code currently not in use, from the old D source. This was /* More code currently not in use, from the old D source. This was

View File

@ -27,6 +27,26 @@
#include <OgreResource.h> #include <OgreResource.h>
#include <OgreMesh.h> #include <OgreMesh.h>
#include <assert.h> #include <assert.h>
#include <string>
class BoundsFinder;
namespace Nif
{
class Node;
class Transformation;
class NiTriShape;
class Vector;
}
namespace Mangle
{
namespace VFS
{
class OgreVFS;
}
}
/** Manual resource loader for NIF meshes. This is the main class /** Manual resource loader for NIF meshes. This is the main class
responsible for translating the internal NIF mesh structure into responsible for translating the internal NIF mesh structure into
@ -43,12 +63,52 @@
very resource intensive, and can safely be done for a large number very resource intensive, and can safely be done for a large number
of meshes at load time. of meshes at load time.
*/ */
struct NIFLoader : Ogre::ManualResourceLoader class NIFLoader : Ogre::ManualResourceLoader
{ {
void loadResource(Ogre::Resource *resource); public:
static NIFLoader& getSingleton();
static NIFLoader* getSingletonPtr();
virtual void loadResource(Ogre::Resource *resource);
static Ogre::MeshPtr load(const std::string &name, static Ogre::MeshPtr load(const std::string &name,
const std::string &group="General"); const std::string &group="General");
private:
NIFLoader() : resourceGroup("General") {}
NIFLoader(NIFLoader& n) {}
void warn(std::string msg);
void fail(std::string msg);
void handleNode(Ogre::Mesh* mesh, Nif::Node *node, int flags,
const Nif::Transformation *trafo, BoundsFinder &bounds);
void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
void createOgreMesh(Ogre::Mesh *mesh, Nif::NiTriShape *shape, const Ogre::String &material);
void createMaterial(const Ogre::String &name,
const Nif::Vector &ambient,
const Nif::Vector &diffuse,
const Nif::Vector &specular,
const Nif::Vector &emissive,
float glossiness, float alpha,
float alphaFlags, float alphaTest,
const Ogre::String &texName);
void findRealTexture(Ogre::String &texName);
Ogre::String getUniqueName(const Ogre::String &input);
// 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 resourceGroup;
}; };
#endif #endif