mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 07:23:51 +00:00
Merge commit 'ape/master'
This commit is contained in:
commit
e69a924036
4 changed files with 706 additions and 531 deletions
|
@ -14,6 +14,11 @@ IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||||
SET(ICONV_FIND_QUIETLY TRUE)
|
SET(ICONV_FIND_QUIETLY TRUE)
|
||||||
ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||||
|
|
||||||
|
IF(WIN32)
|
||||||
|
SET(ICONV_INCLUDE_DIR $ENV{ICONV_INCLUDE_DIR})
|
||||||
|
SET(ICONV_LIBRARIES $ENV{ICONV_LIBRARIES})
|
||||||
|
ENDIF(WIN32)
|
||||||
|
|
||||||
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
|
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
|
||||||
|
|
||||||
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c)
|
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c)
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef __WIN32__
|
||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <libs/mangle/stream/stream.hpp>
|
#include <libs/mangle/stream/stream.hpp>
|
||||||
#include <libs/mangle/stream/servers/file_stream.hpp>
|
#include <libs/mangle/stream/servers/file_stream.hpp>
|
||||||
|
@ -621,6 +624,9 @@ public:
|
||||||
// Convert a string from the encoding used by Morrowind to UTF-8
|
// Convert a string from the encoding used by Morrowind to UTF-8
|
||||||
std::string convertToUTF8 (std::string input)
|
std::string convertToUTF8 (std::string input)
|
||||||
{
|
{
|
||||||
|
#ifdef __WIN32__
|
||||||
|
return input;
|
||||||
|
#else
|
||||||
std::string output = "";
|
std::string output = "";
|
||||||
|
|
||||||
//create convert description
|
//create convert description
|
||||||
|
@ -701,6 +707,7 @@ public:
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void skip(int bytes) { esm->seek(esm->tell()+bytes); }
|
void skip(int bytes) { esm->seek(esm->tell()+bytes); }
|
||||||
uint64_t getOffset() { return esm->tell(); }
|
uint64_t getOffset() { return esm->tell(); }
|
||||||
|
|
|
@ -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,43 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 NIFLoader::convertVector3(const Nif::Vector& vec)
|
||||||
|
{
|
||||||
|
return Ogre::Vector3(vec.array);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion NIFLoader::convertRotation(const Nif::Matrix& rot)
|
||||||
|
{
|
||||||
|
Real matrix[3][3];
|
||||||
|
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
for (int j=0; j<3; j++)
|
||||||
|
matrix[i][j] = rot.v[i].array[j];
|
||||||
|
|
||||||
|
return Quaternion(Matrix3(matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper class that computes the bounding box and of a mesh
|
// Helper class that computes the bounding box and of a mesh
|
||||||
|
@ -126,12 +148,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 +211,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 +220,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 +230,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 +289,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 +305,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 +321,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::createOgreSubMesh(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,21 +407,33 @@ 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
|
|
||||||
VertexBoneAssignment v;
|
|
||||||
v.boneIndex = ((Bone*)bone)->getHandle();
|
|
||||||
v.weight = 1.0;
|
|
||||||
|
|
||||||
std::cerr << "+ Assigning bone index " << v.boneIndex << "\n";
|
// assigning bones if skindata is not empty
|
||||||
|
if (!shape->skin.empty())
|
||||||
for(int i=0; i < numVerts; i++)
|
|
||||||
{
|
{
|
||||||
v.vertexIndex = i;
|
NodeList *boneList = &shape->skin->bones;
|
||||||
sub->addBoneAssignment(v);
|
|
||||||
|
for (int i=0; i<boneList->length(); i++)
|
||||||
|
{
|
||||||
|
if (boneList->has(i))
|
||||||
|
{
|
||||||
|
Nif::Node *bone = &(*boneList)[i];
|
||||||
|
|
||||||
|
SkeletonPtr skel = SkeletonManager::getSingleton().getByName(getSkeletonName());
|
||||||
|
|
||||||
|
VertexBoneAssignment vba;
|
||||||
|
vba.boneIndex = skel->getBone(bone->name.toString())->getHandle();
|
||||||
|
vba.weight = 1.0;
|
||||||
|
|
||||||
|
for (unsigned int j=0; j<sub->vertexData->vertexCount; j++) //assing every vertex
|
||||||
|
{
|
||||||
|
vba.vertexIndex = j;
|
||||||
|
sub->addBoneAssignment(vba);
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper math functions. Reinventing linear algebra for the win!
|
// Helper math functions. Reinventing linear algebra for the win!
|
||||||
|
@ -432,7 +479,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(NiTriShape *shape, int flags, BoundsFinder &bounds)
|
||||||
{
|
{
|
||||||
assert(shape != NULL);
|
assert(shape != NULL);
|
||||||
|
|
||||||
|
@ -451,7 +498,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
|
||||||
|
@ -596,12 +646,12 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFin
|
||||||
bounds.add(optr, numVerts);
|
bounds.add(optr, numVerts);
|
||||||
|
|
||||||
// Create the submesh
|
// Create the submesh
|
||||||
createOgreMesh(mesh, shape, material);
|
createOgreSubMesh(shape, material);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleNode(Mesh* mesh, Nif::Node *node, int flags,
|
void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
const Transformation *trafo, BoundsFinder &bounds)
|
const Transformation *trafo, BoundsFinder &bounds, Bone *parentBone)
|
||||||
{
|
{
|
||||||
// Accumulate the flags from all the child nodes. This works for all
|
// Accumulate the flags from all the child nodes. This works for all
|
||||||
// the flags we currently use, at least.
|
// the flags we currently use, at least.
|
||||||
|
@ -632,6 +682,36 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bone *bone = 0;
|
||||||
|
|
||||||
|
// create skeleton or add bones
|
||||||
|
if (node->recType == RC_NiNode)
|
||||||
|
{
|
||||||
|
if (node->name == "Bip01") //root node, create a skeleton
|
||||||
|
{
|
||||||
|
skel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skel.isNull()) //if there is a skeleton
|
||||||
|
{
|
||||||
|
bone = skel->createBone(node->name.toString());
|
||||||
|
|
||||||
|
if (parentBone)
|
||||||
|
parentBone->addChild(bone);
|
||||||
|
|
||||||
|
bone->setInheritOrientation(true);
|
||||||
|
bone->setPosition(convertVector3(node->trafo->pos));
|
||||||
|
bone->setOrientation(convertRotation(node->trafo->rotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
//output for debuging purpose
|
||||||
|
// Ogre::Vector3 vec(node->trafo->pos.array);
|
||||||
|
// Ogre::Quaternion q = convertRotation(node->trafo->rotation);
|
||||||
|
// std::cout << node->name.toString() << ": " << vec.x << " " << vec.y << " " << vec.z << "\n";
|
||||||
|
// std::cout << " Y: " << q.getYaw().valueDegrees() << " P: " << q.getPitch().valueDegrees() << " R: " << q.getRoll().valueDegrees() << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Apply the parent transformation to this node. We overwrite the
|
// Apply the parent transformation to this node. We overwrite the
|
||||||
// existing data with the final transformation.
|
// existing data with the final transformation.
|
||||||
if (trafo)
|
if (trafo)
|
||||||
|
@ -661,27 +741,31 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags,
|
||||||
for (int i=0; i<n; i++)
|
for (int i=0; i<n; i++)
|
||||||
{
|
{
|
||||||
if (list.has(i))
|
if (list.has(i))
|
||||||
handleNode(mesh, &list[i], flags, node->trafo, bounds);
|
handleNode(&list[i], flags, node->trafo, bounds, bone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->recType == RC_NiTriShape)
|
else if (node->recType == RC_NiTriShape)
|
||||||
// For shapes
|
// For shapes
|
||||||
handleNiTriShape(mesh, dynamic_cast<NiTriShape*>(node), flags, bounds);
|
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFLoader::loadResource(Resource *resource)
|
void NIFLoader::loadResource(Resource *resource)
|
||||||
{
|
{
|
||||||
|
resourceName = "";
|
||||||
|
mesh = 0;
|
||||||
|
skel.setNull();
|
||||||
|
|
||||||
// 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 = dynamic_cast<Mesh*>(resource);
|
||||||
assert(mesh);
|
assert(mesh);
|
||||||
|
|
||||||
// Look it up
|
// Look it up
|
||||||
const String &name = mesh->getName();
|
resourceName = mesh->getName();
|
||||||
errName = name; // Set name for error messages
|
|
||||||
if(!vfs->isFile(name))
|
if (!vfs->isFile(resourceName))
|
||||||
{
|
{
|
||||||
warn("File not found.");
|
warn("File not found.");
|
||||||
return;
|
return;
|
||||||
|
@ -694,7 +778,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(name), name);
|
NIFFile nif(vfs->open(resourceName), resourceName);
|
||||||
|
|
||||||
if (nif.numRecords() < 1)
|
if (nif.numRecords() < 1)
|
||||||
{
|
{
|
||||||
|
@ -716,7 +800,11 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the node
|
// Handle the node
|
||||||
handleNode(mesh, node, 0, NULL, bounds);
|
handleNode(node, 0, NULL, bounds, 0);
|
||||||
|
|
||||||
|
//set skeleton
|
||||||
|
if (!skel.isNull())
|
||||||
|
mesh->setSkeletonName(getSkeletonName());
|
||||||
|
|
||||||
// Finally, set the bounding value.
|
// Finally, set the bounding value.
|
||||||
if (bounds.isValid())
|
if (bounds.isValid())
|
||||||
|
@ -738,7 +826,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
|
||||||
|
|
|
@ -27,6 +27,27 @@
|
||||||
#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;
|
||||||
|
class Matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +64,66 @@
|
||||||
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");
|
||||||
|
|
||||||
|
Ogre::Vector3 convertVector3(const Nif::Vector& vec);
|
||||||
|
Ogre::Quaternion convertRotation(const Nif::Matrix& rot);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NIFLoader() : resourceGroup("General") {}
|
||||||
|
NIFLoader(NIFLoader& n) {}
|
||||||
|
|
||||||
|
void warn(std::string msg);
|
||||||
|
void fail(std::string msg);
|
||||||
|
|
||||||
|
void handleNode( Nif::Node *node, int flags,
|
||||||
|
const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone);
|
||||||
|
|
||||||
|
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
|
||||||
|
|
||||||
|
void createOgreSubMesh(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);
|
||||||
|
|
||||||
|
//returns the skeleton name of this mesh
|
||||||
|
std::string getSkeletonName()
|
||||||
|
{
|
||||||
|
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 resourceName;
|
||||||
|
std::string resourceGroup;
|
||||||
|
|
||||||
|
// pointer to the ogre mesh which is currently build
|
||||||
|
Ogre::Mesh *mesh;
|
||||||
|
Ogre::SkeletonPtr skel;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue