From aeec73806dc9808863fb4e7ebd2238d8e71fd199 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sun, 24 Jan 2010 15:17:50 +0100 Subject: [PATCH] Set up a small post-processing layer to ease NIF animation handling --- nif/data.h | 33 +++++++++++++++++++-------------- nif/nif_file.cpp | 29 +++++++++++++++++++++++++++++ nif/node.h | 28 ++++++++++++++++++++++++++++ nif/record.h | 4 ++++ nif/record_ptr.h | 11 ++++++++++- nif/tests/niftool.cpp | 19 ++++++++++++++----- nifogre/ogre_nif_loader.cpp | 5 ++++- 7 files changed, 108 insertions(+), 21 deletions(-) diff --git a/nif/data.h b/nif/data.h index 2b66128b2..a3800f75d 100644 --- a/nif/data.h +++ b/nif/data.h @@ -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 diff --git a/nif/nif_file.cpp b/nif/nif_file.cpp index 7bea0637c..1e1598170 100644 --- a/nif/nif_file.cpp +++ b/nif/nif_file.cpp @@ -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; ipost(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; ifail("Oops: Missing bone! Don't know how to handle this."); + + bones[i].makeBone(i, data->bones[i]); + } } diff --git a/nif/node.h b/nif/node.h index a8722667b..39e9d9d46 100644 --- a/nif/node.h +++ b/nif/node.h @@ -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; } }; diff --git a/nif/record.h b/nif/record.h index 6dcd2c53d..3e68489bc 100644 --- a/nif/record.h +++ b/nif/record.h @@ -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 diff --git a/nif/record_ptr.h b/nif/record_ptr.h index 0da3f070d..fabec2c82 100644 --- a/nif/record_ptr.h +++ b/nif/record_ptr.h @@ -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; } }; diff --git a/nif/tests/niftool.cpp b/nif/tests/niftool.cpp index 5ff99adef..68575c303 100644 --- a/nif/tests/niftool.cpp +++ b/nif/tests/niftool.cpp @@ -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; jopen(name), name); if(nif.numRecords() < 1)