diff --git a/nif/data.h b/nif/data.h index 6ea900447..2b66128b2 100644 --- a/nif/data.h +++ b/nif/data.h @@ -321,29 +321,57 @@ struct NiVisData : Record struct NiSkinData : Record { + // This is to make sure the structs are packed, ie. that the + // compiler doesn't mess them up with extra alignment bytes. +#pragma pack(push) +#pragma pack(1) + + struct BoneTrafo + { + Matrix rotation; // Rotation offset from bone? + Vector trans; // Translation + float scale; // Probably scale (always 1) + }; + + struct VertWeight + { + short vertex; + float weight; + }; +#pragma pack(pop) + + struct BoneInfo + { + const BoneTrafo *trafo; + const Vector4 *unknown; + SliceArray weights; + }; + + const BoneTrafo *trafo; + std::vector bones; + void read(NIFFile *nif) { - // Not really decoded fully. - nif->getMatrix(); // global skin rotation? - nif->getVector(); // skin translation - nif->getFloat(); // probably scale (always 1) + assert(sizeof(BoneTrafo) == 4*(9+3+1)); + assert(sizeof(VertWeight) == 6); - int bones = nif->getInt(); + trafo = nif->getPtr(); + + int boneNum = nif->getInt(); nif->getInt(); // -1 - for(int i=0;igetMatrix(); // skin rotation offset from this bone - nif->getVector(); // translation - nif->getFloat(); // scale + bones.resize(boneNum); - nif->getVector4(); + for(int i=0;igetPtr(); + bi.unknown = nif->getVector4(); // Number of vertex weights int count = nif->getShort(); - - // Each weight is a vertex index (short) and a weight (float) - nif->skip(count*6); + bi.weights = nif->getArrayLen(count); } } }; diff --git a/nif/nif_file.cpp b/nif/nif_file.cpp index 01a715847..7bea0637c 100644 --- a/nif/nif_file.cpp +++ b/nif/nif_file.cpp @@ -135,7 +135,7 @@ void NIFFile::parse() else if(rec == "NiPixelData") { r = new NiPixelData; r->recType = RC_NiPixelData; } else if(rec == "NiMorphData") { r = new NiMorphData; r->recType = RC_NiMorphData; } else if(rec == "NiKeyframeData") { r = new NiKeyframeData; r->recType = RC_NiKeyframeData; } - else if(rec == "NiSkinData") { r = new NiSkinData; r->recType = RC_NiSkindata; } + else if(rec == "NiSkinData") { r = new NiSkinData; r->recType = RC_NiSkinData; } else if(rec == "NiUVData") { r = new NiUVData; r->recType = RC_NiUVData; } else if(rec == "NiPosData") { r = new NiPosData; r->recType = RC_NiPosData; } else if(rec == "NiRotatingParticlesData") { r = new NiRotatingParticlesData; r->recType = RC_NiRotatingParticlesData; } diff --git a/nif/record.h b/nif/record.h index f0d2a031f..6dcd2c53d 100644 --- a/nif/record.h +++ b/nif/record.h @@ -72,7 +72,7 @@ enum RecordType RC_NiPixelData, RC_NiMorphData, RC_NiKeyframeData, - RC_NiSkindata, + RC_NiSkinData, RC_NiUVData, RC_NiPosData, RC_NiRotatingParticlesData, diff --git a/nif/tests/.gitignore b/nif/tests/.gitignore index d437e1928..b01c11f27 100644 --- a/nif/tests/.gitignore +++ b/nif/tests/.gitignore @@ -2,3 +2,4 @@ niftool *_test *.nif *.kf +output.txt diff --git a/nif/tests/niftool.cpp b/nif/tests/niftool.cpp index 94269c0c8..5ff99adef 100644 --- a/nif/tests/niftool.cpp +++ b/nif/tests/niftool.cpp @@ -8,11 +8,15 @@ #include "../../mangle/stream/servers/file_stream.h" #include "../node.h" #include "../controller.h" +#include "../data.h" using namespace Mangle::Stream; using namespace std; using namespace Nif; +// Display very verbose information +bool verbose = false; + void doVector(const Vector *vec) { cout << "[" @@ -21,6 +25,15 @@ void doVector(const Vector *vec) << vec->array[2] << "]\n"; } +void doVector4(const Vector4 *vec) +{ + cout << "[" + << vec->array[0] << "," + << vec->array[1] << "," + << vec->array[2] << "," + << vec->array[3] << "]\n"; +} + void doMatrix(const Matrix *mat) { cout << "Matrix:\n"; @@ -79,6 +92,54 @@ void doNode(Node *n) } } +void doNiTriShape(NiTriShape *n) +{ + doNode(n); + + cout << "Shape data: " << n->data.getIndex() << endl; + cout << "Skin instance: " << n->skin.getIndex() << endl; +} + +void doNiSkinData(NiSkinData *n) +{ + int c = n->bones.size(); + + cout << "Global transformation:\n"; + doMatrix(&n->trafo->rotation); + doVector(&n->trafo->trans); + cout << "Scale: " << n->trafo->scale << endl; + + cout << "Bone number: " << c << endl; + for(int i=0; ibones[i]; + + cout << "-- Bone " << i << ":\n"; + doMatrix(&bi.trafo->rotation); + doVector(&bi.trafo->trans); + cout << "Scale: " << bi.trafo->scale << endl; + cout << "Unknown: "; doVector4(bi.unknown); + cout << "Weight number: " << bi.weights.length << endl; + + if(verbose) + for(int j=0; jdata.getIndex() << endl; + cout << "Root: " << n->root.getIndex() << endl; + cout << "Bones:"; + for(int i=0; ibones.length(); i++) + cout << " " << n->bones.getIndex(i); + cout << endl; +} + void doNiNode(NiNode *n) { doNode(n); @@ -148,6 +209,9 @@ int main(int argc, char **args) switch(r->recType) { case RC_NiNode: doNiNode((NiNode*)r); break; + case RC_NiSkinData: doNiSkinData((NiSkinData*)r); break; + case RC_NiSkinInstance: doNiSkinInstance((NiSkinInstance*)r); break; + case RC_NiTriShape: doNiTriShape((NiTriShape*)r); break; case RC_NiStringExtraData: doNiStringExtraData((NiStringExtraData*)r); break; case RC_NiSequenceStreamHelper: doNamed((Named*)r); break; case RC_NiTextKeyExtraData: doNiTextKeyExtraData((NiTextKeyExtraData*)r); break;