From 723f5c58e1ae258cf7b2062d8d8813d852a1b818 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 15 Jul 2023 05:21:51 +0300 Subject: [PATCH 1/4] Add bhkConstraint --- components/nif/physics.cpp | 26 ++++++++++++++++++++++++++ components/nif/physics.hpp | 24 ++++++++++++++++++++++++ components/nif/recordptr.hpp | 2 ++ 3 files changed, 52 insertions(+) diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index 9636ec22da..2d1abeff58 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -187,6 +187,21 @@ namespace Nif nif->skip(12); // Unused } + void bhkConstraintCInfo::read(NIFStream* nif) + { + nif->get(); // Number of entities, unused + mEntities.resize(2); // Hardcoded + for (auto& entity : mEntities) + entity.read(nif); + + mPriority = static_cast(nif->get()); + } + + void bhkConstraintCInfo::post(Reader& nif) + { + postRecordList(nif, mEntities); + } + /// Record types void bhkCollisionObject::read(NIFStream* nif) @@ -448,4 +463,15 @@ namespace Nif nif->readArray(mat); mTransform.set(mat.data()); } + + void bhkConstraint::read(NIFStream* nif) + { + mInfo.read(nif); + } + + void bhkConstraint::post(Reader& nif) + { + mInfo.post(nif); + } + } // Namespace diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index 3124e05692..bf1ca4c011 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -210,6 +210,21 @@ namespace Nif void read(NIFStream* nif); }; + enum class ConstraintPriority : uint32_t + { + Priority_Invalid = 0, + Priority_PhysicsTime = 1, + Priority_TimeOfImpact = 3 + }; + + struct bhkConstraintCInfo + { + bhkEntityList mEntities; + ConstraintPriority mPriority; + void read(NIFStream* nif); + void post(Reader& nif); + }; + /// Record types // Abstract Bethesda Havok object @@ -431,5 +446,14 @@ namespace Nif osg::Matrixf mTransform; void read(NIFStream* nif) override; }; + + // Abstract constraint + struct bhkConstraint : public bhkSerializable + { + bhkConstraintCInfo mInfo; + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + } // Namespace #endif diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 7025063213..3c22502145 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -137,6 +137,7 @@ namespace Nif struct bhkWorldObject; struct bhkShape; struct bhkSerializable; + struct bhkEntity; struct hkPackedNiTriStripsData; struct NiAccumulator; struct NiInterpolator; @@ -194,6 +195,7 @@ namespace Nif using NiTriStripsDataList = RecordListT; using bhkShapeList = RecordListT; using bhkSerializableList = RecordListT; + using bhkEntityList = RecordListT; using NiControllerSequenceList = RecordListT; } // Namespace From 83be42893d8be7e0261aa1af866f915a0eac2631 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 15 Jul 2023 06:09:34 +0300 Subject: [PATCH 2/4] Read bhkRagdollConstraint --- components/nif/niffile.cpp | 1 + components/nif/physics.cpp | 88 ++++++++++++++++++++++++++++++++++++++ components/nif/physics.hpp | 71 ++++++++++++++++++++++++++++++ components/nif/record.hpp | 1 + 4 files changed, 161 insertions(+) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 4fc624d609..71ad075704 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -179,6 +179,7 @@ namespace Nif { "bhkListShape", &construct }, { "bhkRigidBody", &construct }, { "bhkRigidBodyT", &construct }, + { "bhkRagdollConstraint", &construct }, { "BSLightingShaderProperty", &construct }, { "BSEffectShaderProperty", &construct }, { "NiSortAdjustNode", &construct }, diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index 2d1abeff58..3d2da2fb39 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -202,6 +202,88 @@ namespace Nif postRecordList(nif, mEntities); } + void bhkPositionConstraintMotor::read(NIFStream* nif) + { + nif->read(mMinForce); + nif->read(mMaxForce); + nif->read(mTau); + nif->read(mDamping); + nif->read(mProportionalRecoveryVelocity); + nif->read(mConstantRecoveryVelocity); + mEnabled = nif->getBoolean(); + } + + void bhkVelocityConstraintMotor::read(NIFStream* nif) + { + nif->read(mMinForce); + nif->read(mMaxForce); + nif->read(mTau); + nif->read(mTargetVelocity); + mUseVelocityTarget = nif->getBoolean(); + mEnabled = nif->getBoolean(); + } + + void bhkSpringDamperConstraintMotor::read(NIFStream* nif) + { + nif->read(mMinForce); + nif->read(mMaxForce); + nif->read(mSpringConstant); + nif->read(mSpringDamping); + mEnabled = nif->getBoolean(); + } + + void bhkConstraintMotorCInfo::read(NIFStream* nif) + { + mType = static_cast(nif->get()); + switch (mType) + { + case hkMotorType::Motor_Position: + mPositionMotor.read(nif); + break; + case hkMotorType::Motor_Velocity: + mVelocityMotor.read(nif); + break; + case hkMotorType::Motor_SpringDamper: + mSpringDamperMotor.read(nif); + break; + case hkMotorType::Motor_None: + default: + break; + } + } + + void bhkRagdollConstraintCInfo::read(NIFStream* nif) + { + mEntityData.resize(2); // Hardcoded by the format + if (nif->getBethVersion() <= 16) + { + for (EntityData& data: mEntityData) + { + nif->read(data.mPivot); + nif->read(data.mPlane); + nif->read(data.mTwist); + } + } + else + { + for (EntityData& data: mEntityData) + { + nif->read(data.mTwist); + nif->read(data.mPlane); + nif->read(data.mMotor); + nif->read(data.mPivot); + } + } + nif->read(mConeMaxAngle); + nif->read(mPlaneMinAngle); + nif->read(mPlaneMaxAngle); + nif->read(mTwistMinAngle); + nif->read(mTwistMaxAngle); + nif->read(mMaxFriction); + if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 16) + mMotor.read(nif); + } + /// Record types void bhkCollisionObject::read(NIFStream* nif) @@ -474,4 +556,10 @@ namespace Nif mInfo.post(nif); } + void bhkRagdollConstraint::read(NIFStream* nif) + { + bhkConstraint::read(nif); + mConstraint.read(nif); + } + } // Namespace diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index bf1ca4c011..f6f4e7490b 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -225,6 +225,71 @@ namespace Nif void post(Reader& nif); }; + enum class hkMotorType : uint8_t + { + Motor_None = 0, + Motor_Position = 1, + Motor_Velocity = 2, + Motor_SpringDamper = 3 + }; + + struct bhkPositionConstraintMotor + { + float mMinForce, mMaxForce; + float mTau; + float mDamping; + float mProportionalRecoveryVelocity; + float mConstantRecoveryVelocity; + bool mEnabled; + void read(NIFStream* nif); + }; + + struct bhkVelocityConstraintMotor + { + float mMinForce, mMaxForce; + float mTau; + float mTargetVelocity; + bool mUseVelocityTarget; + bool mEnabled; + void read(NIFStream* nif); + }; + + struct bhkSpringDamperConstraintMotor + { + float mMinForce, mMaxForce; + float mSpringConstant; + float mSpringDamping; + bool mEnabled; + void read(NIFStream* nif); + }; + + struct bhkConstraintMotorCInfo + { + hkMotorType mType; + bhkPositionConstraintMotor mPositionMotor; + bhkVelocityConstraintMotor mVelocityMotor; + bhkSpringDamperConstraintMotor mSpringDamperMotor; + void read(NIFStream* nif); + }; + + struct bhkRagdollConstraintCInfo + { + struct EntityData + { + osg::Vec4f mPivot; + osg::Vec4f mPlane; + osg::Vec4f mTwist; + osg::Vec4f mMotor; + }; + std::vector mEntityData; + float mConeMaxAngle; + float mPlaneMinAngle, mPlaneMaxAngle; + float mTwistMinAngle, mTwistMaxAngle; + float mMaxFriction; + bhkConstraintMotorCInfo mMotor; + void read(NIFStream* nif); + }; + /// Record types // Abstract Bethesda Havok object @@ -455,5 +520,11 @@ namespace Nif void post(Reader& nif) override; }; + struct bhkRagdollConstraint : public bhkConstraint + { + bhkRagdollConstraintCInfo mConstraint; + void read(NIFStream* nif) override; + }; + } // Namespace #endif diff --git a/components/nif/record.hpp b/components/nif/record.hpp index b5319d2b2f..22a4b6acd8 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -145,6 +145,7 @@ namespace Nif RC_bhkListShape, RC_bhkRigidBody, RC_bhkRigidBodyT, + RC_bhkRagdollConstraint, RC_BSLightingShaderProperty, RC_BSEffectShaderProperty, RC_NiClusterAccumulator, From eb3e762c508356c6ce14b1b65b4a6d05c9af3ac3 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 15 Jul 2023 06:33:21 +0300 Subject: [PATCH 3/4] Read bhkHingeConstraint --- components/nif/niffile.cpp | 1 + components/nif/physics.cpp | 28 ++++++++++++++++++++++++++++ components/nif/physics.hpp | 20 ++++++++++++++++++++ components/nif/record.hpp | 1 + 4 files changed, 50 insertions(+) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 71ad075704..c381eb50e1 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -180,6 +180,7 @@ namespace Nif { "bhkRigidBody", &construct }, { "bhkRigidBodyT", &construct }, { "bhkRagdollConstraint", &construct }, + { "bhkHingeConstraint", &construct }, { "BSLightingShaderProperty", &construct }, { "BSEffectShaderProperty", &construct }, { "NiSortAdjustNode", &construct }, diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index 3d2da2fb39..cd6c9bbabb 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -284,6 +284,28 @@ namespace Nif mMotor.read(nif); } + void bhkHingeConstraintCInfo::read(NIFStream* nif) + { + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + nif->read(mDataA.mPivot); + nif->read(mDataA.mPerpAxis1); + nif->read(mDataA.mPerpAxis2); + nif->read(mDataB.mPivot); + nif->read(mDataB.mAxis); + } + else + { + nif->read(mDataA.mAxis); + nif->read(mDataA.mPerpAxis1); + nif->read(mDataA.mPerpAxis2); + nif->read(mDataA.mPivot); + nif->read(mDataB.mAxis); + nif->read(mDataB.mPerpAxis1); + nif->read(mDataB.mPerpAxis2); + nif->read(mDataB.mPivot); + } + } /// Record types void bhkCollisionObject::read(NIFStream* nif) @@ -562,4 +584,10 @@ namespace Nif mConstraint.read(nif); } + void bhkHingeConstraint::read(NIFStream* nif) + { + bhkConstraint::read(nif); + mConstraint.read(nif); + } + } // Namespace diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index f6f4e7490b..5367b8a2b9 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -290,6 +290,20 @@ namespace Nif void read(NIFStream* nif); }; + struct bhkHingeConstraintCInfo + { + struct HingeData + { + osg::Vec4f mPivot; + osg::Vec4f mAxis; + osg::Vec4f mPerpAxis1; + osg::Vec4f mPerpAxis2; + }; + HingeData mDataA; + HingeData mDataB; + void read(NIFStream* nif); + }; + /// Record types // Abstract Bethesda Havok object @@ -526,5 +540,11 @@ namespace Nif void read(NIFStream* nif) override; }; + struct bhkHingeConstraint : public bhkConstraint + { + bhkHingeConstraintCInfo mConstraint; + void read(NIFStream* nif) override; + }; + } // Namespace #endif diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 22a4b6acd8..24f0695719 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -146,6 +146,7 @@ namespace Nif RC_bhkRigidBody, RC_bhkRigidBodyT, RC_bhkRagdollConstraint, + RC_bhkHingeConstraint, RC_BSLightingShaderProperty, RC_BSEffectShaderProperty, RC_NiClusterAccumulator, From ed8fd81714180040c08f3ab22fecb57ccfa79a9c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 15 Jul 2023 06:59:22 +0300 Subject: [PATCH 4/4] Don't mess with A/B hardcoding in constraints --- components/nif/physics.cpp | 36 ++++++++++++++++++------------------ components/nif/physics.hpp | 8 +++++--- components/nif/recordptr.hpp | 1 + 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index cd6c9bbabb..af4a573707 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -190,16 +190,16 @@ namespace Nif void bhkConstraintCInfo::read(NIFStream* nif) { nif->get(); // Number of entities, unused - mEntities.resize(2); // Hardcoded - for (auto& entity : mEntities) - entity.read(nif); + mEntityA.read(nif); + mEntityB.read(nif); mPriority = static_cast(nif->get()); } void bhkConstraintCInfo::post(Reader& nif) { - postRecordList(nif, mEntities); + mEntityA.post(nif); + mEntityB.post(nif); } void bhkPositionConstraintMotor::read(NIFStream* nif) @@ -254,25 +254,25 @@ namespace Nif void bhkRagdollConstraintCInfo::read(NIFStream* nif) { - mEntityData.resize(2); // Hardcoded by the format if (nif->getBethVersion() <= 16) { - for (EntityData& data: mEntityData) - { - nif->read(data.mPivot); - nif->read(data.mPlane); - nif->read(data.mTwist); - } + nif->read(mDataA.mPivot); + nif->read(mDataA.mPlane); + nif->read(mDataA.mTwist); + nif->read(mDataB.mPivot); + nif->read(mDataB.mPlane); + nif->read(mDataB.mTwist); } else { - for (EntityData& data: mEntityData) - { - nif->read(data.mTwist); - nif->read(data.mPlane); - nif->read(data.mMotor); - nif->read(data.mPivot); - } + nif->read(mDataA.mTwist); + nif->read(mDataA.mPlane); + nif->read(mDataA.mMotor); + nif->read(mDataA.mPivot); + nif->read(mDataB.mTwist); + nif->read(mDataB.mPlane); + nif->read(mDataB.mMotor); + nif->read(mDataB.mPivot); } nif->read(mConeMaxAngle); nif->read(mPlaneMinAngle); diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index 5367b8a2b9..14eab4efa2 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -219,7 +219,8 @@ namespace Nif struct bhkConstraintCInfo { - bhkEntityList mEntities; + bhkEntityPtr mEntityA; + bhkEntityPtr mEntityB; ConstraintPriority mPriority; void read(NIFStream* nif); void post(Reader& nif); @@ -274,14 +275,15 @@ namespace Nif struct bhkRagdollConstraintCInfo { - struct EntityData + struct Data { osg::Vec4f mPivot; osg::Vec4f mPlane; osg::Vec4f mTwist; osg::Vec4f mMotor; }; - std::vector mEntityData; + Data mDataA; + Data mDataB; float mConeMaxAngle; float mPlaneMinAngle, mPlaneMaxAngle; float mTwistMinAngle, mTwistMaxAngle; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 3c22502145..e2836d458d 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -176,6 +176,7 @@ namespace Nif using NiCollisionObjectPtr = RecordPtrT; using bhkWorldObjectPtr = RecordPtrT; using bhkShapePtr = RecordPtrT; + using bhkEntityPtr = RecordPtrT; using hkPackedNiTriStripsDataPtr = RecordPtrT; using NiAccumulatorPtr = RecordPtrT; using NiInterpolatorPtr = RecordPtrT;