Set up a small post-processing layer to ease NIF animation handling

actorid
Nicolay Korslund 15 years ago
parent ef69584793
commit aeec73806d

@ -319,6 +319,25 @@ struct NiVisData : Record
}
};
struct NiSkinInstance : Record
{
NiSkinDataPtr data;
NodePtr root;
NodeList bones;
void read(NIFFile *nif)
{
data.read(nif);
root.read(nif);
bones.read(nif);
if(data.empty() || root.empty())
nif->fail("NiSkinInstance missing root or data");
}
void post(NIFFile *nif);
};
struct NiSkinData : Record
{
// This is to make sure the structs are packed, ie. that the
@ -461,19 +480,5 @@ struct NiKeyframeData : Record
}
};
struct NiSkinInstance : Record
{
NiSkinDataPtr data;
NodePtr root;
NodeList bones;
void read(NIFFile *nif)
{
data.read(nif);
root.read(nif);
bones.read(nif);
}
};
} // Namespace
#endif

@ -37,6 +37,11 @@
using namespace std;
using namespace Nif;
/* This file implements functions from the NIFFile class. It is also
where we stash all the functions we couldn't add as inline
definitions in the record types.
*/
void NIFFile::parse()
{
// Check the header string
@ -161,4 +166,28 @@ void NIFFile::parse()
ints following it. This might be a list of the root nodes in the
tree, but for the moment we ignore it.
*/
// TODO: Set up kf file here first, if applicable. It needs its own
// code to link it up with the main NIF structure.
// Once parsing is done, do post-processing.
for(int i=0; i<recNum; i++)
records[i]->post(this);
}
void NiSkinInstance::post(NIFFile *nif)
{
int bnum = bones.length();
if(bnum != data->bones.size())
nif->fail("Mismatch in NiSkinData bone count");
root->makeRootBone(data->trafo);
for(int i=0; i<bnum; i++)
{
if(!bones.has(i))
nif->fail("Oops: Missing bone! Don't know how to handle this.");
bones[i].makeBone(i, data->bones[i]);
}
}

@ -25,6 +25,7 @@
#define _NIF_NODE_H_
#include "controlled.h"
#include "data.h"
namespace Nif
{
@ -62,6 +63,33 @@ struct Node : Named
boundRot = nif->getMatrix();
boundXYZ = nif->getVector();
}
boneTrafo = NULL;
boneIndex = -1;
}
// Bone transformation. If set, node is a part of a skeleton.
const NiSkinData::BoneTrafo *boneTrafo;
// Bone weight info, from NiSkinData
const NiSkinData::BoneInfo *boneInfo;
// Bone index. If -1, this node is either not a bone, or the root
// bone in the skeleton.
short boneIndex;
// Make this the root animation bone
void makeRootBone(const NiSkinData::BoneTrafo *tr)
{
boneTrafo = tr;
boneIndex = -1;
}
void makeBone(short ind, const NiSkinData::BoneInfo &bi)
{
boneInfo = &bi;
boneTrafo = bi.trafo;
boneIndex = ind;
}
};

@ -91,8 +91,12 @@ struct Record
Record() : recType(RC_NONE) {}
/// Parses the record from file
virtual void read(NIFFile *nif) = 0;
/// Does post-processing, after the entire tree is loaded
virtual void post(NIFFile *nif) {}
/*
Use these later if you want custom allocation of all NIF objects

@ -58,6 +58,15 @@ class RecordPtrT
index = nif->getInt();
}
/** Set the pointer explicitly. May be used when you are pointing to
records in another file, eg. when you have a .nif / .kf pair.
*/
void set(X *p)
{
ptr = p;
index = -1;
}
/// Look up the actual object from the index
X* getPtr()
{
@ -80,7 +89,7 @@ class RecordPtrT
X& get() { return *getPtr(); }
/// Pointers are allowed to be empty
bool empty() { return index == -1; }
bool empty() { return index == -1 && ptr == NULL; }
int getIndex() { return index; }
};

@ -90,6 +90,15 @@ void doNode(Node *n)
doMatrix(n->boundRot);
doVector(n->boundXYZ);
}
if(n->boneTrafo)
{
cout << "This is a bone: ";
if(n->boneIndex == -1)
cout << "root bone\n";
else
cout << "index " << n->boneIndex << endl;
}
}
void doNiTriShape(NiTriShape *n)
@ -122,11 +131,11 @@ void doNiSkinData(NiSkinData *n)
cout << "Weight number: " << bi.weights.length << endl;
if(verbose)
for(int j=0; j<bi.weights.length; j++)
{
const NiSkinData::VertWeight &w = bi.weights.ptr[j];
cout << " vert:" << w.vertex << " weight:" << w.weight << endl;
}
for(int j=0; j<bi.weights.length; j++)
{
const NiSkinData::VertWeight &w = bi.weights.ptr[j];
cout << " vert:" << w.vertex << " weight:" << w.weight << endl;
}
}
}

@ -521,7 +521,10 @@ void NIFLoader::loadResource(Resource *resource)
return;
}
// Load the NIF
// 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
// every error as early and intrusively as possible, as it's most
// likely a sign of incomplete code rather than faulty input.
NIFFile nif(vfs->open(name), name);
if(nif.numRecords() < 1)

Loading…
Cancel
Save