From 02c895c107673ff13f51cfdcf04bb4c7ccd99ef4 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 12:31:25 +0300 Subject: [PATCH] Read all remaining Havok constraint records --- components/nif/niffile.cpp | 3 + components/nif/physics.cpp | 126 +++++++++++++++++++++++++++++++++++++ components/nif/physics.hpp | 81 ++++++++++++++++++++++++ components/nif/record.hpp | 3 + 4 files changed, 213 insertions(+) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index e0f6ee422e..06b086c089 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -395,6 +395,9 @@ namespace Nif { "bhkLimitedHingeConstraint", &construct }, { "bhkRagdollConstraint", &construct }, { "bhkStiffSpringConstraint", &construct }, + { "bhkPrismaticConstraint", &construct }, + { "bhkMalleableConstraint", &construct }, + { "bhkBreakableConstraint", &construct }, // Physics body records, Bethesda { "bhkRigidBody", &construct }, diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index f97b4b6169..24c49a77d9 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -345,6 +345,109 @@ namespace Nif nif->read(mLength); } + void bhkPrismaticConstraintCInfo::read(NIFStream* nif) + { + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + nif->read(mDataA.mPivot); + nif->read(mDataA.mRotation); + nif->read(mDataA.mPlane); + nif->read(mDataA.mSliding); + nif->read(mDataB.mSliding); + nif->read(mDataB.mPivot); + nif->read(mDataB.mRotation); + nif->read(mDataB.mPlane); + } + else + { + nif->read(mDataA.mSliding); + nif->read(mDataA.mRotation); + nif->read(mDataA.mPlane); + nif->read(mDataA.mPivot); + nif->read(mDataB.mSliding); + nif->read(mDataB.mRotation); + nif->read(mDataB.mPlane); + nif->read(mDataB.mPivot); + } + nif->read(mMinDistance); + nif->read(mMaxDistance); + nif->read(mFriction); + if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 17) + mMotor.read(nif); + } + + void bhkMalleableConstraintCInfo::read(NIFStream* nif) + { + mType = static_cast(nif->get()); + mInfo.read(nif); + switch (mType) + { + case hkConstraintType::BallAndSocket: + mBallAndSocketInfo.read(nif); + break; + case hkConstraintType::Hinge: + mHingeInfo.read(nif); + break; + case hkConstraintType::LimitedHinge: + mLimitedHingeInfo.read(nif); + break; + case hkConstraintType::Prismatic: + mPrismaticInfo.read(nif); + break; + case hkConstraintType::Ragdoll: + mRagdollInfo.read(nif); + break; + case hkConstraintType::StiffSpring: + mStiffSpringInfo.read(nif); + break; + default: + throw Nif::Exception( + "Unrecognized constraint type in bhkMalleableConstraint", nif->getFile().getFilename()); + } + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + nif->read(mTau); + nif->read(mDamping); + } + else + { + nif->read(mStrength); + } + } + + void bhkWrappedConstraintData::read(NIFStream* nif) + { + mType = static_cast(nif->get()); + mInfo.read(nif); + switch (mType) + { + case hkConstraintType::BallAndSocket: + mBallAndSocketInfo.read(nif); + break; + case hkConstraintType::Hinge: + mHingeInfo.read(nif); + break; + case hkConstraintType::LimitedHinge: + mLimitedHingeInfo.read(nif); + break; + case hkConstraintType::Prismatic: + mPrismaticInfo.read(nif); + break; + case hkConstraintType::Ragdoll: + mRagdollInfo.read(nif); + break; + case hkConstraintType::StiffSpring: + mStiffSpringInfo.read(nif); + break; + case hkConstraintType::Malleable: + mMalleableInfo.read(nif); + break; + default: + throw Nif::Exception( + "Unrecognized constraint type in bhkWrappedConstraintData", nif->getFile().getFilename()); + } + } + /// Record types void bhkCollisionObject::read(NIFStream* nif) @@ -746,4 +849,27 @@ namespace Nif mConstraint.read(nif); } + void bhkPrismaticConstraint::read(NIFStream* nif) + { + bhkConstraint::read(nif); + + mConstraint.read(nif); + } + + void bhkMalleableConstraint::read(NIFStream* nif) + { + bhkConstraint::read(nif); + + mConstraint.read(nif); + } + + void bhkBreakableConstraint::read(NIFStream* nif) + { + bhkConstraint::read(nif); + + mConstraint.read(nif); + nif->read(mThreshold); + nif->read(mRemoveWhenBroken); + } + } // Namespace diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index cdfb3cc1fb..90185d0417 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -363,6 +363,64 @@ namespace Nif void read(NIFStream* nif); }; + struct bhkPrismaticConstraintCInfo + { + struct Data + { + osg::Vec4f mSliding; + osg::Vec4f mRotation; + osg::Vec4f mPlane; + osg::Vec4f mPivot; + }; + + Data mDataA; + Data mDataB; + float mMinDistance, mMaxDistance; + float mFriction; + bhkConstraintMotorCInfo mMotor; + + void read(NIFStream* nif); + }; + + enum class hkConstraintType : uint32_t + { + BallAndSocket = 0, + Hinge = 1, + LimitedHinge = 2, + Prismatic = 6, + Ragdoll = 7, + StiffSpring = 8, + Malleable = 13, + }; + + struct bhkWrappedConstraintDataBase + { + hkConstraintType mType; + bhkConstraintCInfo mInfo; + bhkBallAndSocketConstraintCInfo mBallAndSocketInfo; + bhkHingeConstraintCInfo mHingeInfo; + bhkLimitedHingeConstraintCInfo mLimitedHingeInfo; + bhkPrismaticConstraintCInfo mPrismaticInfo; + bhkRagdollConstraintCInfo mRagdollInfo; + bhkStiffSpringConstraintCInfo mStiffSpringInfo; + }; + + struct bhkMalleableConstraintCInfo : bhkWrappedConstraintDataBase + { + float mTau; + float mDamping; + float mStrength; + + void read(NIFStream* nif); + }; + + struct bhkWrappedConstraintData : bhkWrappedConstraintDataBase + { + bhkMalleableConstraintCInfo mMalleableInfo; + + void read(NIFStream* nif); + }; + /// Record types // Abstract Bethesda Havok object @@ -713,5 +771,28 @@ namespace Nif void read(NIFStream* nif) override; }; + struct bhkPrismaticConstraint : bhkConstraint + { + bhkPrismaticConstraintCInfo mConstraint; + + void read(NIFStream* nif) override; + }; + + struct bhkMalleableConstraint : bhkConstraint + { + bhkMalleableConstraintCInfo mConstraint; + + void read(NIFStream* nif) override; + }; + + struct bhkBreakableConstraint : bhkConstraint + { + bhkWrappedConstraintData mConstraint; + float mThreshold; + bool mRemoveWhenBroken; + + void read(NIFStream* nif) override; + }; + } // Namespace #endif diff --git a/components/nif/record.hpp b/components/nif/record.hpp index ea37ad4654..e4a539e8a3 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -40,6 +40,7 @@ namespace Nif RC_bhkBlendCollisionObject, RC_bhkBlendController, RC_bhkBoxShape, + RC_bhkBreakableConstraint, RC_bhkCapsuleShape, RC_bhkCylinderShape, RC_bhkCollisionObject, @@ -52,10 +53,12 @@ namespace Nif RC_bhkHingeConstraint, RC_bhkLimitedHingeConstraint, RC_bhkListShape, + RC_bhkMalleableConstraint, RC_bhkMoppBvTreeShape, RC_bhkNiTriStripsShape, RC_bhkPackedNiTriStripsShape, RC_bhkPhysicsSystem, + RC_bhkPrismaticConstraint, RC_bhkRagdollConstraint, RC_bhkRagdollSystem, RC_bhkRigidBody,