diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 1bd4821395..5eb55e10d1 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -144,6 +144,9 @@ static std::map makeFactory() factory["BSDismemberSkinInstance"] = {&construct , RC_BSDismemberSkinInstance }; factory["NiControllerManager"] = {&construct , RC_NiControllerManager }; factory["bhkMoppBvTreeShape"] = {&construct , RC_bhkMoppBvTreeShape }; + factory["bhkNiTriStripsShape"] = {&construct , RC_bhkNiTriStripsShape }; + factory["bhkPackedNiTriStripsShape"] = {&construct , RC_bhkPackedNiTriStripsShape }; + factory["hkPackedNiTriStripsData"] = {&construct , RC_hkPackedNiTriStripsData }; return factory; } diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index 3c43c160cd..e447bc65df 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -60,6 +60,15 @@ namespace Nif mProcessContactDelay = nif->getUShort(); } + void TriangleData::read(NIFStream *nif) + { + for (int i = 0; i < 3; i++) + mTriangle[i] = nif->getUShort(); + mWeldingInfo = nif->getUShort(); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + mNormal = nif->getVector3(); + } + /// Record types void bhkCollisionObject::read(NIFStream *nif) @@ -107,4 +116,67 @@ namespace Nif mMopp.read(nif); } + void bhkNiTriStripsShape::read(NIFStream *nif) + { + mHavokMaterial.read(nif); + mRadius = nif->getFloat(); + nif->skip(20); // Unused + mGrowBy = nif->getUInt(); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + mScale = nif->getVector4(); + mData.read(nif); + unsigned int numFilters = nif->getUInt(); + nif->getUInts(mFilters, numFilters); + } + + void bhkNiTriStripsShape::post(NIFFile *nif) + { + mData.post(nif); + } + + void bhkPackedNiTriStripsShape::read(NIFStream *nif) + { + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + mSubshapes.resize(nif->getUShort()); + for (hkSubPartData& subshape : mSubshapes) + subshape.read(nif); + } + mUserData = nif->getUInt(); + nif->skip(4); // Unused + mRadius = nif->getFloat(); + nif->skip(4); // Unused + mScale = nif->getVector4(); + nif->skip(20); // Duplicates of the two previous fields + mData.read(nif); + } + + void bhkPackedNiTriStripsShape::post(NIFFile *nif) + { + mData.post(nif); + } + + void hkPackedNiTriStripsData::read(NIFStream *nif) + { + unsigned int numTriangles = nif->getUInt(); + mTriangles.resize(numTriangles); + for (unsigned int i = 0; i < numTriangles; i++) + mTriangles[i].read(nif); + + unsigned int numVertices = nif->getUInt(); + bool compressed = false; + if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS) + compressed = nif->getBoolean(); + if (!compressed) + nif->getVector3s(mVertices, numVertices); + else + nif->skip(6 * numVertices); // Half-precision vectors are not currently supported + if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS) + { + mSubshapes.resize(nif->getUShort()); + for (hkSubPartData& subshape : mSubshapes) + subshape.read(nif); + } + } + } // Namespace \ No newline at end of file diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index 190cb42b1d..6c9fe685ef 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -77,6 +77,14 @@ struct hkpMoppCode void read(NIFStream *nif); }; +struct TriangleData +{ + unsigned short mTriangle[3]; + unsigned short mWeldingInfo; + osg::Vec3f mNormal; + void read(NIFStream *nif); +}; + /// Record types // Abstract Bethesda Havok object @@ -155,5 +163,40 @@ struct bhkMoppBvTreeShape : public bhkBvTreeShape void read(NIFStream *nif) override; }; +// Bethesda triangle strip-based Havok shape collection +struct bhkNiTriStripsShape : public bhkShape +{ + HavokMaterial mHavokMaterial; + float mRadius; + unsigned int mGrowBy; + osg::Vec4f mScale{1.f, 1.f, 1.f, 0.f}; + NiTriStripsDataList mData; + std::vector mFilters; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +// Bethesda packed triangle strip-based Havok shape collection +struct bhkPackedNiTriStripsShape : public bhkShapeCollection +{ + std::vector mSubshapes; + unsigned int mUserData; + float mRadius; + osg::Vec4f mScale; + hkPackedNiTriStripsDataPtr mData; + + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +// bhkPackedNiTriStripsShape data block +struct hkPackedNiTriStripsData : public bhkShapeCollection +{ + std::vector mTriangles; + std::vector mVertices; + std::vector mSubshapes; + void read(NIFStream *nif) override; +}; + } // Namespace #endif \ No newline at end of file diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 47ce14969f..804b13262d 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -131,7 +131,10 @@ enum RecordType RC_bhkCollisionObject, RC_BSDismemberSkinInstance, RC_NiControllerManager, - RC_bhkMoppBvTreeShape + RC_bhkMoppBvTreeShape, + RC_bhkNiTriStripsShape, + RC_bhkPackedNiTriStripsShape, + RC_hkPackedNiTriStripsData }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index c97957c95a..cc62d7b2e0 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -152,6 +152,7 @@ struct NiCollisionObject; struct bhkWorldObject; struct bhkShape; struct bhkSerializable; +struct hkPackedNiTriStripsData; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -182,6 +183,7 @@ using NiAlphaPropertyPtr = RecordPtrT; using NiCollisionObjectPtr = RecordPtrT; using bhkWorldObjectPtr = RecordPtrT; using bhkShapePtr = RecordPtrT; +using hkPackedNiTriStripsDataPtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT;