Disabled loading skins.nif. NifLoader builds now a skeleton (if available)

actorid
Armin Preiml 15 years ago
parent 181b538e4a
commit d8f8bd12d3

@ -52,9 +52,6 @@ void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRef<ESM::NPC, MWWorld::R
cellRender.insertBegin(liveRef.ref); cellRender.insertBegin(liveRef.ref);
cellRender.insertMesh(headModel); cellRender.insertMesh(headModel);
//TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the right place
cellRender.insertMesh("meshes\\" + store.bodyParts.find(bodyRaceID + "chest")->model);
liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled()));
} }

@ -68,6 +68,22 @@ void NIFLoader::fail(string msg)
assert(1); 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
class BoundsFinder class BoundsFinder
{ {
@ -305,7 +321,7 @@ void NIFLoader::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.
void NIFLoader::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());
@ -391,22 +407,32 @@ void NIFLoader::createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &mate
// Set material if one was given // Set material if one was given
if (!material.empty()) sub->setMaterialName(material); if (!material.empty()) sub->setMaterialName(material);
// Assign this submesh to the given bone
//TODO: Must use niskininstance!
/*if (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())
{
NodeList *boneList = &shape->skin->bones;
for(int i=0; i < numVerts; i++) for (int i=0; i<boneList->length(); i++)
{ {
v.vertexIndex = i; if (boneList->has(i))
sub->addBoneAssignment(v); {
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);
}
}
} }
}*/ }
} }
@ -453,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];
} }
void NIFLoader::handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFinder &bounds) void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds)
{ {
assert(shape != NULL); assert(shape != NULL);
@ -620,12 +646,12 @@ void NIFLoader::handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, Bound
bounds.add(optr, numVerts); bounds.add(optr, numVerts);
// Create the submesh // Create the submesh
createOgreMesh(mesh, shape, material); createOgreSubMesh(shape, material);
} }
} }
void NIFLoader::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.
@ -656,6 +682,36 @@ void NIFLoader::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)
@ -680,34 +736,36 @@ void NIFLoader::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++)
{ {
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(resourceGroup); 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();
if (!vfs->isFile(name)) if (!vfs->isFile(resourceName))
{ {
warn("File not found."); warn("File not found.");
return; return;
@ -720,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)
{ {
@ -742,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())

@ -38,6 +38,7 @@ namespace Nif
class Transformation; class Transformation;
class NiTriShape; class NiTriShape;
class Vector; class Vector;
class Matrix;
} }
namespace Mangle namespace Mangle
@ -74,6 +75,9 @@ class NIFLoader : Ogre::ManualResourceLoader
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: private:
NIFLoader() : resourceGroup("General") {} NIFLoader() : resourceGroup("General") {}
NIFLoader(NIFLoader& n) {} NIFLoader(NIFLoader& n) {}
@ -81,12 +85,12 @@ class NIFLoader : Ogre::ManualResourceLoader
void warn(std::string msg); void warn(std::string msg);
void fail(std::string msg); void fail(std::string msg);
void handleNode(Ogre::Mesh* mesh, Nif::Node *node, int flags, void handleNode( Nif::Node *node, int flags,
const Nif::Transformation *trafo, BoundsFinder &bounds); const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone);
void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape *shape, int flags, BoundsFinder &bounds); void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
void createOgreMesh(Ogre::Mesh *mesh, Nif::NiTriShape *shape, const Ogre::String &material); void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material);
void createMaterial(const Ogre::String &name, void createMaterial(const Ogre::String &name,
const Nif::Vector &ambient, const Nif::Vector &ambient,
@ -100,6 +104,12 @@ class NIFLoader : Ogre::ManualResourceLoader
void findRealTexture(Ogre::String &texName); void findRealTexture(Ogre::String &texName);
Ogre::String getUniqueName(const Ogre::String &input); 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 // 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 // load NIFs from BSAs, in the file system and in any other place we
@ -108,7 +118,12 @@ class NIFLoader : Ogre::ManualResourceLoader
// extension from .tga to .dds if the texture is missing. // extension from .tga to .dds if the texture is missing.
Mangle::VFS::OgreVFS *vfs; Mangle::VFS::OgreVFS *vfs;
std::string resourceName;
std::string resourceGroup; std::string resourceGroup;
// pointer to the ogre mesh which is currently build
Ogre::Mesh *mesh;
Ogre::SkeletonPtr skel;
}; };
#endif #endif

Loading…
Cancel
Save