From d0487461461f5f8284b8168b783e35397316d924 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 10:41:24 +0300 Subject: [PATCH 1/7] Read BSMasterParticleSystem, BSParentVelocityModifier, NiLookAtInterpolator --- components/nif/controller.cpp | 20 ++++++++++++++++++++ components/nif/controller.hpp | 15 +++++++++++++++ components/nif/niffile.cpp | 3 +++ components/nif/particle.cpp | 22 ++++++++++++++++++++++ components/nif/particle.hpp | 16 ++++++++++++++++ components/nif/record.hpp | 2 ++ 6 files changed, 78 insertions(+) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index a3033357ec..3f4d5a6380 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -600,6 +600,26 @@ namespace Nif mPercentData.post(nif); } + void NiLookAtInterpolator::read(NIFStream* nif) + { + nif->read(mLookAtFlags); + mLookAt.read(nif); + nif->read(mLookAtName); + if (nif->getVersion() <= NIFStream::generateVersion(20, 4, 0, 12)) + nif->read(mTransform); + mTranslation.read(nif); + mRoll.read(nif); + mScale.read(nif); + } + + void NiLookAtInterpolator::post(Reader& nif) + { + mLookAt.post(nif); + mTranslation.post(nif); + mRoll.post(nif); + mScale.post(nif); + } + void NiBlendInterpolator::read(NIFStream* nif) { if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 8a7d306a85..97f948167b 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -419,6 +419,21 @@ namespace Nif void post(Reader& nif) override; }; + struct NiLookAtInterpolator : NiInterpolator + { + // Uses the same flags as NiLookAtController + uint16_t mLookAtFlags{ 0 }; + NiAVObjectPtr mLookAt; + std::string mLookAtName; + NiQuatTransform mTransform; + NiInterpolatorPtr mTranslation; + NiInterpolatorPtr mRoll; + NiInterpolatorPtr mScale; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + // Abstract struct NiBlendInterpolator : public NiInterpolator { diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index f526c1e3d4..10a53234f1 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -72,6 +72,7 @@ namespace Nif { "BSDebrisNode", &construct }, { "BSFadeNode", &construct }, { "BSLeafAnimNode", &construct }, + { "BSMasterParticleSystem", &construct }, { "BSMultiBoundNode", &construct }, { "BSOrderedNode", &construct }, { "BSRangeNode", &construct }, @@ -164,6 +165,7 @@ namespace Nif { "NiBoolTimelineInterpolator", &construct }, { "NiColorInterpolator", &construct }, { "NiFloatInterpolator", &construct }, + { "NiLookAtInterpolator", &construct }, { "NiPathInterpolator", &construct }, { "NiPoint3Interpolator", &construct }, { "NiTransformInterpolator", &construct }, @@ -305,6 +307,7 @@ namespace Nif { "NiPSysSpawnModifier", &construct }, // Modifiers, Bethesda + { "BSParentVelocityModifier", &construct }, { "BSPSysInheritVelocityModifier", &construct }, { "BSPSysLODModifier", &construct }, diff --git a/components/nif/particle.cpp b/components/nif/particle.cpp index 0d3545acd5..63eff520b3 100644 --- a/components/nif/particle.cpp +++ b/components/nif/particle.cpp @@ -150,6 +150,21 @@ namespace Nif nif->readVector(mRotations, mNumVertices); } + void BSMasterParticleSystem::read(NIFStream* nif) + { + NiNode::read(nif); + + nif->read(mMaxEmitters); + readRecordList(nif, mParticleSystems); + } + + void BSMasterParticleSystem::post(Reader& nif) + { + NiNode::post(nif); + + postRecordList(nif, mParticleSystems); + } + void NiParticleSystem::read(NIFStream* nif) { // Weird loading to account for inheritance differences starting from SSE @@ -383,6 +398,13 @@ namespace Nif nif->read(mLifespanVariation); } + void BSParentVelocityModifier::read(NIFStream* nif) + { + NiPSysModifier::read(nif); + + nif->read(mDamping); + } + void BSPSysInheritVelocityModifier::read(NIFStream* nif) { NiPSysModifier::read(nif); diff --git a/components/nif/particle.hpp b/components/nif/particle.hpp index 8fc24ee407..732649fabe 100644 --- a/components/nif/particle.hpp +++ b/components/nif/particle.hpp @@ -115,6 +115,15 @@ namespace Nif void read(NIFStream* nif) override; }; + struct BSMasterParticleSystem : NiNode + { + uint16_t mMaxEmitters; + NiAVObjectList mParticleSystems; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct NiParticleSystem : NiParticles { osg::BoundingSpheref mBoundingSphere; @@ -279,6 +288,13 @@ namespace Nif void read(NIFStream* nif) override; }; + struct BSParentVelocityModifier : NiPSysModifier + { + float mDamping; + + void read(NIFStream* nif) override; + }; + struct BSPSysInheritVelocityModifier : NiPSysModifier { NiAVObjectPtr mInheritObject; diff --git a/components/nif/record.hpp b/components/nif/record.hpp index f7bb4fa648..d0a51581c4 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -94,6 +94,7 @@ namespace Nif RC_BSMultiBoundSphere, RC_BSNiAlphaPropertyTestRefController, RC_BSPackedAdditionalGeometryData, + RC_BSParentVelocityModifier, RC_BSPSysArrayEmitter, RC_BSPSysInheritVelocityModifier, RC_BSPSysLODModifier, @@ -172,6 +173,7 @@ namespace Nif RC_NiLinesData, RC_NiLODNode, RC_NiLookAtController, + RC_NiLookAtInterpolator, RC_NiMaterialColorController, RC_NiMaterialProperty, RC_NiMorphData, From 3296dadf60aaca9d5b60edd92e35d9612cfeae5b Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 11:27:18 +0300 Subject: [PATCH 2/7] Read BSPSysMultiTargetEmitterCtlr and bone LOD controllers --- components/nif/controller.cpp | 44 +++++++++++++++++++++++++++++++++++ components/nif/controller.hpp | 18 ++++++++++++++ components/nif/niffile.cpp | 5 ++++ components/nif/particle.cpp | 15 ++++++++++++ components/nif/particle.hpp | 9 +++++++ components/nif/record.hpp | 2 ++ components/nif/recordptr.hpp | 5 ++++ 7 files changed, 98 insertions(+) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 3f4d5a6380..6a48ea1e4f 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -460,6 +460,50 @@ namespace Nif mData.post(nif); } + void NiBoneLODController::read(NIFStream* nif) + { + NiTimeController::read(nif); + + nif->read(mLOD); + mNodeGroups.resize(nif->get()); + nif->read(mNumNodeGroups); + for (NiAVObjectList& group : mNodeGroups) + readRecordList(nif, group); + + if (nif->getBethVersion() != 0 || nif->getVersion() < NIFStream::generateVersion(4, 2, 2, 0)) + return; + + mSkinnedShapeGroups.resize(nif->get()); + for (std::vector& group : mSkinnedShapeGroups) + { + group.resize(nif->get()); + for (SkinInfo& info : group) + { + info.mShape.read(nif); + info.mSkin.read(nif); + } + } + readRecordList(nif, mShapeGroups); + } + + void NiBoneLODController::post(Reader& nif) + { + NiTimeController::post(nif); + + for (NiAVObjectList& group : mNodeGroups) + postRecordList(nif, group); + + for (std::vector& group : mSkinnedShapeGroups) + { + for (SkinInfo& info : group) + { + info.mShape.post(nif); + info.mSkin.post(nif); + } + } + postRecordList(nif, mShapeGroups); + } + void bhkBlendController::read(NIFStream* nif) { NiTimeController::read(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 97f948167b..b6c71e1548 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -300,6 +300,24 @@ namespace Nif void post(Reader& nif) override; }; + struct NiBoneLODController : NiTimeController + { + struct SkinInfo + { + NiTriBasedGeomPtr mShape; + NiSkinInstancePtr mSkin; + }; + + uint32_t mLOD; + uint32_t mNumNodeGroups; + std::vector mNodeGroups; + std::vector> mSkinnedShapeGroups; + NiTriBasedGeomList mShapeGroups; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct bhkBlendController : public NiTimeController { void read(NIFStream* nif) override; diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 10a53234f1..e0f6ee422e 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -118,6 +118,7 @@ namespace Nif { "NiVisController", &construct }, // Gamebryo + { "NiBoneLODController", &construct }, { "NiControllerManager", &construct }, { "NiLightDimmerController", &construct }, { "NiTransformController", &construct }, @@ -154,6 +155,7 @@ namespace Nif { "BSLightingShaderPropertyFloatController", &construct }, { "bhkBlendController", &construct }, + { "NiBSBoneLODController", &construct }, // Interpolators, Gamebryo { "NiBlendBoolInterpolator", &construct }, @@ -353,6 +355,9 @@ namespace Nif { "NiPSysInitialRotAngleVarCtlr", &construct }, { "NiPSysModifierActiveCtlr", &construct }, + // Modifier controllers, Bethesda + { "BSPSysMultiTargetEmitterCtlr", &construct }, + // Modifier controller data, Gamebryo { "NiPSysEmitterCtlrData", &construct }, diff --git a/components/nif/particle.cpp b/components/nif/particle.cpp index 63eff520b3..95440af26b 100644 --- a/components/nif/particle.cpp +++ b/components/nif/particle.cpp @@ -597,6 +597,21 @@ namespace Nif mVisInterpolator.post(nif); } + void BSPSysMultiTargetEmitterCtlr::read(NIFStream* nif) + { + NiPSysEmitterCtlr::read(nif); + + nif->read(mMaxEmitters); + mMasterPSys.read(nif); + } + + void BSPSysMultiTargetEmitterCtlr::post(Reader& nif) + { + NiPSysEmitterCtlr::post(nif); + + mMasterPSys.post(nif); + } + void NiPSysEmitterCtlrData::read(NIFStream* nif) { mFloatKeyList = std::make_shared(); diff --git a/components/nif/particle.hpp b/components/nif/particle.hpp index 732649fabe..a2b0567b3b 100644 --- a/components/nif/particle.hpp +++ b/components/nif/particle.hpp @@ -476,6 +476,15 @@ namespace Nif void post(Reader& nif) override; }; + struct BSPSysMultiTargetEmitterCtlr : NiPSysEmitterCtlr + { + uint16_t mMaxEmitters; + BSMasterParticleSystemPtr mMasterPSys; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct NiPSysEmitterCtlrData : Record { FloatKeyMapPtr mFloatKeyList; diff --git a/components/nif/record.hpp b/components/nif/record.hpp index d0a51581c4..ea37ad4654 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -98,6 +98,7 @@ namespace Nif RC_BSPSysArrayEmitter, RC_BSPSysInheritVelocityModifier, RC_BSPSysLODModifier, + RC_BSPSysMultiTargetEmitterCtlr, RC_BSPSysRecycleBoundModifier, RC_BSPSysScaleModifier, RC_BSPSysSimpleColorModifier, @@ -130,6 +131,7 @@ namespace Nif RC_NiBlendFloatInterpolator, RC_NiBlendPoint3Interpolator, RC_NiBlendTransformInterpolator, + RC_NiBoneLODController, RC_NiBoolData, RC_NiBooleanExtraData, RC_NiBoolInterpolator, diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 50d16d5eac..0a7bd0ccbd 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -129,6 +129,7 @@ namespace Nif struct NiSourceTexture; struct NiPalette; struct NiParticleModifier; + struct BSMasterParticleSystem; struct NiParticleSystem; struct NiPSysCollider; struct NiPSysColliderManager; @@ -138,6 +139,7 @@ namespace Nif struct NiBoolData; struct NiSkinPartition; struct BSShaderTextureSet; + struct NiTriBasedGeom; struct NiGeometryData; struct BSShaderProperty; struct NiAlphaProperty; @@ -177,6 +179,7 @@ namespace Nif using NiSourceTexturePtr = RecordPtrT; using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; + using BSMasterParticleSystemPtr = RecordPtrT; using NiParticleSystemPtr = RecordPtrT; using NiPSysColliderPtr = RecordPtrT; using NiPSysColliderManagerPtr = RecordPtrT; @@ -185,6 +188,7 @@ namespace Nif using NiBoolDataPtr = RecordPtrT; using NiSkinPartitionPtr = RecordPtrT; using BSShaderTextureSetPtr = RecordPtrT; + using NiTriBasedGeomPtr = RecordPtrT; using NiGeometryDataPtr = RecordPtrT; using BSShaderPropertyPtr = RecordPtrT; using NiAlphaPropertyPtr = RecordPtrT; @@ -216,6 +220,7 @@ namespace Nif using bhkEntityList = RecordListT; using NiControllerSequenceList = RecordListT; using NiPSysModifierList = RecordListT; + using NiTriBasedGeomList = RecordListT; } // Namespace #endif From 02c895c107673ff13f51cfdcf04bb4c7ccd99ef4 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 12:31:25 +0300 Subject: [PATCH 3/7] 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, From 285eafbf66069955e4eaebc9aa3cbfaccbd77674 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 13:52:37 +0300 Subject: [PATCH 4/7] Read bhkBallSocketConstraintChain and BSProceduralLightingController --- components/nif/controller.cpp | 43 +++++++++++++++++++++++++++++++++++ components/nif/controller.hpp | 28 +++++++++++++++++++++++ components/nif/niffile.cpp | 3 +++ components/nif/physics.cpp | 32 ++++++++++++++++++++++++++ components/nif/physics.hpp | 22 ++++++++++++++++++ components/nif/record.hpp | 2 ++ components/nif/recordptr.hpp | 3 +++ 7 files changed, 133 insertions(+) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 6a48ea1e4f..903cf7710c 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -553,6 +553,49 @@ namespace Nif nif->read(mMaximumDistance); } + void BSProceduralLightningController::read(NIFStream* nif) + { + NiTimeController::read(nif); + + mGenerationInterp.read(nif); + mMutationInterp.read(nif); + mSubdivisionInterp.read(nif); + mNumBranchesInterp.read(nif); + mNumBranchesVarInterp.read(nif); + mLengthInterp.read(nif); + mLengthVarInterp.read(nif); + mWidthInterp.read(nif); + mArcOffsetInterp.read(nif); + nif->read(mSubdivisions); + nif->read(mNumBranches); + nif->read(mNumBranchesVar); + nif->read(mLength); + nif->read(mLengthVar); + nif->read(mWidth); + nif->read(mChildWidthMult); + nif->read(mArcOffset); + nif->read(mFadeMainBolt); + nif->read(mFadeChildBolts); + nif->read(mAnimateArcOffset); + mShaderProperty.read(nif); + } + + void BSProceduralLightningController::post(Reader& nif) + { + NiTimeController::post(nif); + + mGenerationInterp.post(nif); + mMutationInterp.post(nif); + mSubdivisionInterp.post(nif); + mNumBranchesInterp.post(nif); + mNumBranchesVarInterp.post(nif); + mLengthInterp.post(nif); + mLengthVarInterp.post(nif); + mWidthInterp.post(nif); + mArcOffsetInterp.post(nif); + mShaderProperty.post(nif); + } + void NiControllerManager::read(NIFStream* nif) { NiTimeController::read(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index b6c71e1548..33c04a6d35 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -354,6 +354,34 @@ namespace Nif void read(NIFStream* nif) override; }; + struct BSProceduralLightningController : NiTimeController + { + NiInterpolatorPtr mGenerationInterp; + NiInterpolatorPtr mMutationInterp; + NiInterpolatorPtr mSubdivisionInterp; + NiInterpolatorPtr mNumBranchesInterp; + NiInterpolatorPtr mNumBranchesVarInterp; + NiInterpolatorPtr mLengthInterp; + NiInterpolatorPtr mLengthVarInterp; + NiInterpolatorPtr mWidthInterp; + NiInterpolatorPtr mArcOffsetInterp; + uint16_t mSubdivisions; + uint16_t mNumBranches; + uint16_t mNumBranchesVar; + float mLength; + float mLengthVar; + float mWidth; + float mChildWidthMult; + float mArcOffset; + bool mFadeMainBolt; + bool mFadeChildBolts; + bool mAnimateArcOffset; + BSShaderPropertyPtr mShaderProperty; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct NiControllerManager : public NiTimeController { bool mCumulative; diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 06b086c089..fb403bccb4 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -138,6 +138,8 @@ namespace Nif { "BSFrustumFOVController", &construct }, { "BSKeyframeController", &construct }, { "BSLagBoneController", &construct }, + { "BSProceduralLightningController", + &construct }, { "BSMaterialEmittanceMultController", &construct }, { "BSNiAlphaPropertyTestRefController", @@ -391,6 +393,7 @@ namespace Nif // Constraint records, Bethesda { "bhkBallAndSocketConstraint", &construct }, + { "bhkBallSocketConstraintChain", &construct }, { "bhkHingeConstraint", &construct }, { "bhkLimitedHingeConstraint", &construct }, { "bhkRagdollConstraint", &construct }, diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index 24c49a77d9..4eaf77f510 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -448,6 +448,17 @@ namespace Nif } } + void bhkConstraintChainCInfo::read(NIFStream* nif) + { + readRecordList(nif, mEntities); + mInfo.read(nif); + } + + void bhkConstraintChainCInfo::post(Reader& nif) + { + postRecordList(nif, mEntities); + } + /// Record types void bhkCollisionObject::read(NIFStream* nif) @@ -842,6 +853,27 @@ namespace Nif mConstraint.read(nif); } + void bhkBallSocketConstraintChain::read(NIFStream* nif) + { + uint32_t numPivots = nif->get(); + if (numPivots % 2 != 0) + throw Nif::Exception( + "Invalid number of constraints in bhkBallSocketConstraintChain", nif->getFile().getFilename()); + mConstraints.resize(numPivots / 2); + for (bhkBallAndSocketConstraintCInfo& info : mConstraints) + info.read(nif); + nif->read(mTau); + nif->read(mDamping); + nif->read(mConstraintForceMixing); + nif->read(mMaxErrorDistance); + mConstraintChainInfo.read(nif); + } + + void bhkBallSocketConstraintChain::post(Reader& nif) + { + mConstraintChainInfo.post(nif); + } + void bhkStiffSpringConstraint::read(NIFStream* nif) { bhkConstraint::read(nif); diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index 90185d0417..d4eaccfc94 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -421,6 +421,15 @@ namespace Nif void read(NIFStream* nif); }; + struct bhkConstraintChainCInfo + { + bhkRigidBodyList mEntities; + bhkConstraintCInfo mInfo; + + void read(NIFStream* nif); + void post(Reader& nif); + }; + /// Record types // Abstract Bethesda Havok object @@ -764,6 +773,19 @@ namespace Nif void read(NIFStream* nif) override; }; + struct bhkBallSocketConstraintChain : bhkSerializable + { + std::vector mConstraints; + float mTau; + float mDamping; + float mConstraintForceMixing; + float mMaxErrorDistance; + bhkConstraintChainCInfo mConstraintChainInfo; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct bhkStiffSpringConstraint : bhkConstraint { bhkStiffSpringConstraintCInfo mConstraint; diff --git a/components/nif/record.hpp b/components/nif/record.hpp index e4a539e8a3..1b6ea1e99b 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -37,6 +37,7 @@ namespace Nif RC_MISSING = 0, RC_AvoidNode, RC_bhkBallAndSocketConstraint, + RC_bhkBallSocketConstraintChain, RC_bhkBlendCollisionObject, RC_bhkBlendController, RC_bhkBoxShape, @@ -98,6 +99,7 @@ namespace Nif RC_BSNiAlphaPropertyTestRefController, RC_BSPackedAdditionalGeometryData, RC_BSParentVelocityModifier, + RC_BSProceduralLightningController, RC_BSPSysArrayEmitter, RC_BSPSysInheritVelocityModifier, RC_BSPSysLODModifier, diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 0a7bd0ccbd..209ee010d6 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -150,6 +150,7 @@ namespace Nif struct bhkSerializable; struct bhkEntity; struct bhkConvexShape; + struct bhkRigidBody; struct hkPackedNiTriStripsData; struct NiAccumulator; struct NiInterpolator; @@ -198,6 +199,7 @@ namespace Nif using bhkShapePtr = RecordPtrT; using bhkEntityPtr = RecordPtrT; using bhkConvexShapePtr = RecordPtrT; + using bhkRigidBodyPtr = RecordPtrT; using hkPackedNiTriStripsDataPtr = RecordPtrT; using NiAccumulatorPtr = RecordPtrT; using NiInterpolatorPtr = RecordPtrT; @@ -218,6 +220,7 @@ namespace Nif using bhkShapeList = RecordListT; using bhkSerializableList = RecordListT; using bhkEntityList = RecordListT; + using bhkRigidBodyList = RecordListT; using NiControllerSequenceList = RecordListT; using NiPSysModifierList = RecordListT; using NiTriBasedGeomList = RecordListT; From 7c11d9acbcc6d059440f818db5c43a16bd8d2071 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 14:52:48 +0300 Subject: [PATCH 5/7] Read NiMeshPSysData and related modifiers --- components/nif/data.cpp | 2 +- components/nif/niffile.cpp | 3 +++ components/nif/particle.cpp | 48 ++++++++++++++++++++++++++++++++++++ components/nif/particle.hpp | 27 ++++++++++++++++++++ components/nif/record.hpp | 3 +++ components/nif/recordptr.hpp | 1 + 6 files changed, 83 insertions(+), 1 deletion(-) diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 9aa61b4db7..62a2a9cce3 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -19,7 +19,7 @@ namespace Nif switch (recType) { case RC_NiPSysData: - // case RC_NiMeshPSysData: + case RC_NiMeshPSysData: case RC_BSStripPSysData: isPSysData = true; break; diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index fb403bccb4..6ed6b8fc08 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -287,6 +287,7 @@ namespace Nif { "NiParticleSystem", &construct }, { "NiMeshParticleSystem", &construct }, { "NiPSysData", &construct }, + { "NiMeshPSysData", &construct }, // Geometry, Bethesda { "BSStripParticleSystem", &construct }, @@ -309,9 +310,11 @@ namespace Nif { "NiPSysPositionModifier", &construct }, { "NiPSysRotationModifier", &construct }, { "NiPSysSpawnModifier", &construct }, + { "NiPSysMeshUpdateModifier", &construct }, // Modifiers, Bethesda { "BSParentVelocityModifier", &construct }, + { "BSPSysHavokUpdateModifier", &construct }, { "BSPSysInheritVelocityModifier", &construct }, { "BSPSysLODModifier", &construct }, diff --git a/components/nif/particle.cpp b/components/nif/particle.cpp index 95440af26b..d74473f468 100644 --- a/components/nif/particle.cpp +++ b/components/nif/particle.cpp @@ -230,6 +230,26 @@ namespace Nif } } + void NiMeshPSysData::read(NIFStream* nif) + { + NiPSysData::read(nif); + + if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0)) + { + nif->read(mDefaultPoolSize); + nif->read(mFillPoolsOnLoad); + nif->readVector(mGenerations, nif->get()); + } + mParticleMeshes.read(nif); + } + + void NiMeshPSysData::post(Reader& nif) + { + NiPSysData::post(nif); + + mParticleMeshes.post(nif); + } + void BSStripPSysData::read(NIFStream* nif) { NiPSysData::read(nif); @@ -362,6 +382,20 @@ namespace Nif nif->read(mBaseScale); } + void NiPSysMeshUpdateModifier::read(NIFStream* nif) + { + NiPSysModifier::read(nif); + + readRecordList(nif, mMeshes); + } + + void NiPSysMeshUpdateModifier::post(Reader& nif) + { + NiPSysModifier::post(nif); + + postRecordList(nif, mMeshes); + } + void NiPSysRotationModifier::read(NIFStream* nif) { NiPSysModifier::read(nif); @@ -405,6 +439,20 @@ namespace Nif nif->read(mDamping); } + void BSPSysHavokUpdateModifier::read(NIFStream* nif) + { + NiPSysMeshUpdateModifier::read(nif); + + mModifier.read(nif); + } + + void BSPSysHavokUpdateModifier::post(Reader& nif) + { + NiPSysMeshUpdateModifier::post(nif); + + mModifier.post(nif); + } + void BSPSysInheritVelocityModifier::read(NIFStream* nif) { NiPSysModifier::read(nif); diff --git a/components/nif/particle.hpp b/components/nif/particle.hpp index a2b0567b3b..45b6296891 100644 --- a/components/nif/particle.hpp +++ b/components/nif/particle.hpp @@ -147,6 +147,17 @@ namespace Nif void read(NIFStream* nif) override; }; + struct NiMeshPSysData : NiPSysData + { + uint32_t mDefaultPoolSize; + bool mFillPoolsOnLoad; + std::vector mGenerations; + NiAVObjectPtr mParticleMeshes; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct BSStripPSysData : NiPSysData { uint16_t mMaxPointCount; @@ -261,6 +272,14 @@ namespace Nif void read(NIFStream* nif) override; }; + struct NiPSysMeshUpdateModifier : NiPSysModifier + { + NiAVObjectList mMeshes; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct NiPSysRotationModifier : NiPSysModifier { float mRotationSpeed; @@ -295,6 +314,14 @@ namespace Nif void read(NIFStream* nif) override; }; + struct BSPSysHavokUpdateModifier : NiPSysMeshUpdateModifier + { + NiPSysModifierPtr mModifier; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct BSPSysInheritVelocityModifier : NiPSysModifier { NiAVObjectPtr mInheritObject; diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 1b6ea1e99b..332647a661 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -101,6 +101,7 @@ namespace Nif RC_BSParentVelocityModifier, RC_BSProceduralLightningController, RC_BSPSysArrayEmitter, + RC_BSPSysHavokUpdateModifier, RC_BSPSysInheritVelocityModifier, RC_BSPSysLODModifier, RC_BSPSysMultiTargetEmitterCtlr, @@ -183,6 +184,7 @@ namespace Nif RC_NiLookAtInterpolator, RC_NiMaterialColorController, RC_NiMaterialProperty, + RC_NiMeshPSysData, RC_NiMorphData, RC_NiMultiTargetTransformController, RC_NiNode, @@ -232,6 +234,7 @@ namespace Nif RC_NiPSysInitialRotAngleCtlr, RC_NiPSysInitialRotAngleVarCtlr, RC_NiPSysMeshEmitter, + RC_NiPSysMeshUpdateModifier, RC_NiPSysModifierActiveCtlr, RC_NiPSysPlanarCollider, RC_NiPSysPositionModifier, diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 209ee010d6..b847f609a4 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -185,6 +185,7 @@ namespace Nif using NiPSysColliderPtr = RecordPtrT; using NiPSysColliderManagerPtr = RecordPtrT; using NiPSysEmitterCtlrDataPtr = RecordPtrT; + using NiPSysModifierPtr = RecordPtrT; using NiPSysSpawnModifierPtr = RecordPtrT; using NiBoolDataPtr = RecordPtrT; using NiSkinPartitionPtr = RecordPtrT; From 6b28f07537fb2cb77aad106469e793e2be6beb92 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 15:42:10 +0300 Subject: [PATCH 6/7] Read bhkPlaneShape and bhkMultiSphereShape --- components/nif/niffile.cpp | 2 ++ components/nif/physics.cpp | 23 +++++++++++++++++++++++ components/nif/physics.hpp | 28 ++++++++++++++++++++++++++++ components/nif/record.hpp | 2 ++ 4 files changed, 55 insertions(+) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 6ed6b8fc08..682fef1987 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -421,9 +421,11 @@ namespace Nif { "bhkConvexVerticesShape", &construct }, { "bhkListShape", &construct }, { "bhkMoppBvTreeShape", &construct }, + { "bhkMultiSphereShape", &construct }, { "bhkNiTriStripsShape", &construct }, { "bhkPackedNiTriStripsShape", &construct }, { "hkPackedNiTriStripsData", &construct }, + { "bhkPlaneShape", &construct }, { "bhkSimpleShapePhantom", &construct }, { "bhkSphereShape", &construct }, { "bhkTransformShape", &construct }, diff --git a/components/nif/physics.cpp b/components/nif/physics.cpp index 4eaf77f510..4969bf2cb9 100644 --- a/components/nif/physics.cpp +++ b/components/nif/physics.cpp @@ -716,6 +716,29 @@ namespace Nif nif->skip(12); // Unused } + void bhkHeightfieldShape::read(NIFStream* nif) + { + mHavokMaterial.read(nif); + } + + void bhkPlaneShape::read(NIFStream* nif) + { + bhkHeightfieldShape::read(nif); + + nif->skip(12); // Unused + mPlane = osg::Plane(nif->get()); + nif->read(mExtents); + nif->read(mCenter); + } + + void bhkMultiSphereShape::read(NIFStream* nif) + { + bhkSphereRepShape::read(nif); + + mShapeProperty.read(nif); + nif->readVector(mSpheres, nif->get()); + } + void bhkListShape::read(NIFStream* nif) { readRecordList(nif, mSubshapes); diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index d4eaccfc94..a14d1d55f6 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -6,6 +6,7 @@ #include "recordptr.hpp" #include +#include #include #include @@ -676,9 +677,36 @@ namespace Nif void read(NIFStream* nif) override; }; + // Abstract shape that can collide with an array of spheres + struct bhkHeightfieldShape : bhkShape + { + HavokMaterial mHavokMaterial; + + void read(NIFStream* nif) override; + }; + + // A plane bounded by an AABB + struct bhkPlaneShape : bhkHeightfieldShape + { + osg::Plane mPlane; + osg::Vec4f mExtents; + osg::Vec4f mCenter; + + void read(NIFStream* nif) override; + }; + // A sphere using bhkSphereShape = bhkConvexShape; + // Multiple spheres + struct bhkMultiSphereShape : bhkSphereRepShape + { + bhkWorldObjCInfoProperty mShapeProperty; + std::vector mSpheres; + + void read(NIFStream* nif) override; + }; + // A list of shapes struct bhkListShape : public bhkShapeCollection { diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 332647a661..331c2ff645 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -56,8 +56,10 @@ namespace Nif RC_bhkListShape, RC_bhkMalleableConstraint, RC_bhkMoppBvTreeShape, + RC_bhkMultiSphereShape, RC_bhkNiTriStripsShape, RC_bhkPackedNiTriStripsShape, + RC_bhkPlaneShape, RC_bhkPhysicsSystem, RC_bhkPrismaticConstraint, RC_bhkRagdollConstraint, From 01cd7e715b9cc473a9fb8df4478d6ea3ad01b306 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Sep 2023 16:43:40 +0300 Subject: [PATCH 7/7] Fix formatting --- components/nif/niffile.cpp | 6 ++++-- components/nif/physics.hpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 682fef1987..0106f47e2f 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -361,7 +361,8 @@ namespace Nif { "NiPSysModifierActiveCtlr", &construct }, // Modifier controllers, Bethesda - { "BSPSysMultiTargetEmitterCtlr", &construct }, + { "BSPSysMultiTargetEmitterCtlr", + &construct }, // Modifier controller data, Gamebryo { "NiPSysEmitterCtlrData", &construct }, @@ -396,7 +397,8 @@ namespace Nif // Constraint records, Bethesda { "bhkBallAndSocketConstraint", &construct }, - { "bhkBallSocketConstraintChain", &construct }, + { "bhkBallSocketConstraintChain", + &construct }, { "bhkHingeConstraint", &construct }, { "bhkLimitedHingeConstraint", &construct }, { "bhkRagdollConstraint", &construct }, diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index a14d1d55f6..6f7b14f1ee 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -5,8 +5,8 @@ #include "record.hpp" #include "recordptr.hpp" -#include #include +#include #include #include