diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 4df464fdf5..6bbab97863 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -320,7 +320,7 @@ void NiSkinData::read(NIFStream *nif) int boneNum = nif->getInt(); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFStream::generateVersion(10,1,0,0)) - nif->skip(4); // NiSkinPartition link + partitions.read(nif); // Has vertex weights flag if (nif->getVersion() > NIFStream::generateVersion(4,2,1,0) && !nif->getBoolean()) @@ -345,6 +345,69 @@ void NiSkinData::read(NIFStream *nif) } } +void NiSkinData::post(NIFFile *nif) +{ + partitions.post(nif); +} + +void NiSkinPartition::read(NIFStream *nif) +{ + unsigned int num = nif->getUInt(); + data.resize(num); + for (auto& partition : data) + partition.read(nif); +} + +void NiSkinPartition::Partition::read(NIFStream *nif) +{ + unsigned short numVertices = nif->getUShort(); + unsigned short numTriangles = nif->getUShort(); + unsigned short numBones = nif->getUShort(); + unsigned short numStrips = nif->getUShort(); + unsigned short bonesPerVertex = nif->getUShort(); + if (numBones) + nif->getUShorts(bones, numBones); + + bool hasVertexMap = true; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + hasVertexMap = nif->getBoolean(); + if (hasVertexMap && numVertices) + nif->getUShorts(vertexMap, numVertices); + + bool hasVertexWeights = true; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + hasVertexWeights = nif->getBoolean(); + if (hasVertexWeights && numVertices && bonesPerVertex) + nif->getFloats(weights, numVertices * bonesPerVertex); + + std::vector stripLengths; + if (numStrips) + nif->getUShorts(stripLengths, numStrips); + + bool hasFaces = true; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + hasFaces = nif->getBoolean(); + if (hasFaces) + { + if (numStrips) + { + strips.resize(numStrips); + for (unsigned short i = 0; i < numStrips; i++) + nif->getUShorts(strips[i], stripLengths[i]); + } + else if (numTriangles) + nif->getUShorts(triangles, numTriangles * 3); + } + bool hasBoneIndices = nif->getChar() != 0; + if (hasBoneIndices && numVertices && bonesPerVertex) + nif->getChars(boneIndices, numVertices * bonesPerVertex); + if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3) + { + nif->getChar(); // LOD level + nif->getBoolean(); // Global VB + } +} + void NiMorphData::read(NIFStream *nif) { int morphCount = nif->getInt(); diff --git a/components/nif/data.hpp b/components/nif/data.hpp index d0ea150e0b..4d13afb9d0 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -174,6 +174,7 @@ class NiSkinInstance : public Record { public: NiSkinDataPtr data; + NiSkinPartitionPtr partitions; NodePtr root; NodeList bones; @@ -200,6 +201,25 @@ public: Transformation trafo; std::vector bones; + NiSkinPartitionPtr partitions; + + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiSkinPartition : public Record +{ + struct Partition + { + std::vector bones; + std::vector vertexMap; + std::vector weights; + std::vector> strips; + std::vector triangles; + std::vector boneIndices; + void read(NIFStream *nif); + }; + std::vector data; void read(NIFStream *nif) override; }; diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index b50b602d57..04cac535c0 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -118,6 +118,7 @@ static std::map makeFactory() factory["NiFloatsExtraData"] = {&construct , RC_NiFloatsExtraData }; factory["NiStringPalette"] = {&construct , RC_NiStringPalette }; factory["NiBoolData"] = {&construct , RC_NiBoolData }; + factory["NiSkinPartition"] = {&construct , RC_NiSkinPartition }; return factory; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 0e8b80ffa7..2a6be58e22 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -111,7 +111,8 @@ enum RecordType RC_NiFloatExtraData, RC_NiFloatsExtraData, RC_NiStringPalette, - RC_NiBoolData + RC_NiBoolData, + RC_NiSkinPartition }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index d0b3d00ab8..2748f40736 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -144,6 +144,7 @@ class NiPalette; struct NiParticleModifier; struct NiLinesData; struct NiBoolData; +struct NiSkinPartition; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -168,6 +169,7 @@ using NiAutoNormalParticlesDataPtr = RecordPtrT; using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; using NiBoolDataPtr = RecordPtrT; +using NiSkinPartitionPtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT;