From 120223d8dff7c9547c582595aa3fda416c014c63 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Fri, 22 Sep 2023 04:42:46 +0300 Subject: [PATCH] Read even more Gamebryo/Bethesda particle records --- components/nif/niffile.cpp | 4 ++ components/nif/particle.cpp | 81 ++++++++++++++++++++++++++++++++++ components/nif/particle.hpp | 65 ++++++++++++++++++++++++--- components/nif/record.hpp | 4 ++ components/nifosg/particle.cpp | 6 +-- components/nifosg/particle.hpp | 2 +- 6 files changed, 151 insertions(+), 11 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index b60bb74594..6d29972f63 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -295,7 +295,10 @@ namespace Nif // Modifiers, Gamebryo { "NiPSysAgeDeathModifier", &construct }, { "NiPSysBoundUpdateModifier", &construct }, + { "NiPSysDragModifier", &construct }, + { "NiPSysGravityModifier", &construct }, { "NiPSysPositionModifier", &construct }, + { "NiPSysRotationModifier", &construct }, { "NiPSysSpawnModifier", &construct }, // Modifiers, Bethesda @@ -308,6 +311,7 @@ namespace Nif // Emitters { "NiPSysBoxEmitter", &construct }, { "NiPSysCylinderEmitter", &construct }, + { "NiPSysMeshEmitter", &construct }, { "NiPSysSphereEmitter", &construct }, // Modifier controllers, Gamebryo diff --git a/components/nif/particle.cpp b/components/nif/particle.cpp index f6e4ae9bc8..42ce8b57f9 100644 --- a/components/nif/particle.cpp +++ b/components/nif/particle.cpp @@ -260,6 +260,69 @@ namespace Nif nif->read(mUpdateSkip); } + void NiPSysDragModifier::read(NIFStream* nif) + { + NiPSysModifier::read(nif); + + mDragObject.read(nif); + nif->read(mDragAxis); + nif->read(mPercentage); + nif->read(mRange); + nif->read(mRangeFalloff); + } + + void NiPSysDragModifier::post(Reader& nif) + { + NiPSysModifier::post(nif); + + mDragObject.post(nif); + } + + void NiPSysGravityModifier::read(NIFStream* nif) + { + NiPSysModifier::read(nif); + + mGravityObject.read(nif); + nif->read(mGravityAxis); + nif->read(mDecay); + nif->read(mStrength); + mForceType = static_cast(nif->get()); + nif->read(mTurbulence); + nif->read(mTurbulenceScale); + + if (nif->getBethVersion() >= 17) + nif->read(mWorldAligned); + } + + void NiPSysGravityModifier::post(Reader& nif) + { + NiPSysModifier::post(nif); + + mGravityObject.post(nif); + } + + void NiPSysRotationModifier::read(NIFStream* nif) + { + NiPSysModifier::read(nif); + + nif->read(mRotationSpeed); + + if (nif->getVersion() >= NIFStream::generateVersion(20, 0, 0, 2)) + { + nif->read(mRotationSpeedVariation); + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->skip(5); // Unknown + + nif->read(mRotationAngle); + nif->read(mRotationAngleVariation); + nif->read(mRandomRotSpeedSign); + } + + nif->read(mRandomAxis); + nif->read(mAxis); + } + void NiPSysSpawnModifier::read(NIFStream* nif) { NiPSysModifier::read(nif); @@ -373,6 +436,24 @@ namespace Nif nif->read(mHeight); } + void NiPSysMeshEmitter::read(NIFStream* nif) + { + NiPSysEmitter::read(nif); + + readRecordList(nif, mEmitterMeshes); + + nif->read(mInitialVelocityType); + nif->read(mEmissionType); + nif->read(mEmissionAxis); + } + + void NiPSysMeshEmitter::post(Reader& nif) + { + NiPSysEmitter::post(nif); + + postRecordList(nif, mEmitterMeshes); + } + void NiPSysSphereEmitter::read(NIFStream* nif) { NiPSysVolumeEmitter::read(nif); diff --git a/components/nif/particle.hpp b/components/nif/particle.hpp index e887009a13..0c9379f0f9 100644 --- a/components/nif/particle.hpp +++ b/components/nif/particle.hpp @@ -34,14 +34,14 @@ namespace Nif void post(Reader& nif) override; }; + enum class ForceType : uint32_t + { + Wind = 0, // Fixed direction + Point = 1, // Fixed origin + }; + struct NiGravity : public NiParticleModifier { - enum class ForceType : uint32_t - { - Wind = 0, // Fixed direction - Point = 1, // Fixed origin - }; - float mDecay{ 0.f }; float mForce; ForceType mType; @@ -193,6 +193,46 @@ namespace Nif void read(NIFStream* nif) override; }; + struct NiPSysDragModifier : public NiPSysModifier + { + NiAVObjectPtr mDragObject; + osg::Vec3f mDragAxis; + float mPercentage; + float mRange; + float mRangeFalloff; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + + struct NiPSysGravityModifier : public NiPSysModifier + { + NiAVObjectPtr mGravityObject; + osg::Vec3f mGravityAxis; + float mDecay; + float mStrength; + ForceType mForceType; + float mTurbulence; + float mTurbulenceScale; + bool mWorldAligned; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + + struct NiPSysRotationModifier : public NiPSysModifier + { + float mRotationSpeed; + float mRotationSpeedVariation; + float mRotationAngle; + float mRotationAngleVariation; + bool mRandomRotSpeedSign; + bool mRandomAxis; + osg::Vec3f mAxis; + + void read(NIFStream* nif) override; + }; + struct NiPSysSpawnModifier : NiPSysModifier { uint16_t mNumSpawnGenerations; @@ -209,7 +249,7 @@ namespace Nif struct BSPSysInheritVelocityModifier : public NiPSysModifier { - NiObjectNETPtr mInheritObject; + NiAVObjectPtr mInheritObject; float mInheritChance; float mVelocityMult; float mVelcoityVariation; @@ -292,6 +332,17 @@ namespace Nif void read(NIFStream* nif) override; }; + struct NiPSysMeshEmitter : public NiPSysEmitter + { + NiAVObjectList mEmitterMeshes; + uint32_t mInitialVelocityType; + uint32_t mEmissionType; + osg::Vec3f mEmissionAxis; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct NiPSysSphereEmitter : public NiPSysVolumeEmitter { float mRadius; diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 770246aa08..3d5ec01bc3 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -194,6 +194,7 @@ namespace Nif RC_NiPSysBoundUpdateModifier, RC_NiPSysCylinderEmitter, RC_NiPSysData, + RC_NiPSysDragModifier, RC_NiPSysEmitterCtlr, RC_NiPSysEmitterCtlrData, RC_NiPSysEmitterDeclinationCtlr, @@ -206,13 +207,16 @@ namespace Nif RC_NiPSysFieldAttenuationCtlr, RC_NiPSysFieldMagnitudeCtlr, RC_NiPSysFieldMaxDistanceCtlr, + RC_NiPSysGravityModifier, RC_NiPSysGravityStrengthCtlr, RC_NiPSysInitialRotSpeedCtlr, RC_NiPSysInitialRotSpeedVarCtlr, RC_NiPSysInitialRotAngleCtlr, RC_NiPSysInitialRotAngleVarCtlr, + RC_NiPSysMeshEmitter, RC_NiPSysModifierActiveCtlr, RC_NiPSysPositionModifier, + RC_NiPSysRotationModifier, RC_NiPSysResetOnLoopCtlr, RC_NiPSysSpawnModifier, RC_NiPSysSphereEmitter, diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index 8be0d4ba4f..551cbfeae8 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -304,7 +304,7 @@ namespace NifOsg bool absolute = (program->getReferenceFrame() == osgParticle::ParticleProcessor::ABSOLUTE_RF); // We don't need the position for Wind gravity, except if decay is being applied - if (mType == Nif::NiGravity::ForceType::Point || mDecay != 0.f) + if (mType == Nif::ForceType::Point || mDecay != 0.f) mCachedWorldPosition = absolute ? program->transformLocalToWorld(mPosition) : mPosition; mCachedWorldDirection = absolute ? program->rotateLocalToWorld(mDirection) : mDirection; @@ -316,7 +316,7 @@ namespace NifOsg const float magic = 1.6f; switch (mType) { - case Nif::NiGravity::ForceType::Wind: + case Nif::ForceType::Wind: { float decayFactor = 1.f; if (mDecay != 0.f) @@ -330,7 +330,7 @@ namespace NifOsg break; } - case Nif::NiGravity::ForceType::Point: + case Nif::ForceType::Point: { osg::Vec3f diff = mCachedWorldPosition - particle->getPosition(); diff --git a/components/nifosg/particle.hpp b/components/nifosg/particle.hpp index a9b628f695..967531013a 100644 --- a/components/nifosg/particle.hpp +++ b/components/nifosg/particle.hpp @@ -191,7 +191,7 @@ namespace NifOsg private: float mForce{ 0.f }; - Nif::NiGravity::ForceType mType{ Nif::NiGravity::ForceType::Wind }; + Nif::ForceType mType{ Nif::ForceType::Wind }; osg::Vec3f mPosition; osg::Vec3f mDirection; float mDecay{ 0.f };