mirror of
https://github.com/OpenMW/openmw.git
synced 2025-04-01 12:36:40 +00:00
483 lines
13 KiB
C++
483 lines
13 KiB
C++
#include "particle.hpp"
|
|
#include <components/nif/exception.hpp>
|
|
|
|
namespace Nif
|
|
{
|
|
void NiParticlesData::read(NIFStream* nif)
|
|
{
|
|
bool isBS202 = nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0;
|
|
// if (nif->getVersion() < NIFFile::NIFVersion::VER_BGS)
|
|
NiGeometryData::read(nif);
|
|
|
|
// Should always match the number of vertices
|
|
if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW)
|
|
nif->read(numParticles);
|
|
|
|
float particleRadius;
|
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 0))
|
|
{
|
|
nif->read(particleRadius);
|
|
particleRadii.resize(vertices.size());
|
|
std::fill(particleRadii.begin(), particleRadii.end(), particleRadius);
|
|
}
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
{
|
|
bool hasRadii = nif->getBoolean();
|
|
// nif->read(hasRadii);
|
|
if (hasRadii && !isBS202)
|
|
nif->readVector(particleRadii, vertices.size());
|
|
}
|
|
activeCount = nif->getUShort();
|
|
|
|
// Particle sizes
|
|
bool hasSizes;
|
|
hasSizes = nif->getBoolean();
|
|
if (hasSizes && !isBS202)
|
|
nif->readVector(sizes, vertices.size());
|
|
|
|
bool hasRotations = false;
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
|
|
{
|
|
hasRotations = nif->getBoolean();
|
|
if (hasRotations && !isBS202)
|
|
{
|
|
nif->getQuaternions(mRotations, vertices.size());
|
|
}
|
|
}
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20, 0, 0, 4))
|
|
{
|
|
bool hasRotationAngles, hasRotationAxes;
|
|
|
|
// nif->read(hasRotationAngles);
|
|
hasRotationAngles = nif->getBoolean();
|
|
if (hasRotationAngles && !isBS202)
|
|
nif->readVector(mRotationAngles, vertices.size());
|
|
|
|
// nif->read(hasRotationAxes);
|
|
hasRotationAxes = nif->getBoolean();
|
|
if (hasRotationAxes && !isBS202)
|
|
{
|
|
nif->getVector3s(mRotationAxes, vertices.size());
|
|
}
|
|
}
|
|
|
|
bool hasTexIndices = false;
|
|
if (isBS202)
|
|
nif->read(hasTexIndices);
|
|
|
|
unsigned int subtexOffsetNum = 0;
|
|
if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS)
|
|
{
|
|
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
|
|
nif->read(subtexOffsetNum);
|
|
else if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3 && isBS202)
|
|
subtexOffsetNum = nif->get<char>();
|
|
}
|
|
|
|
if (isBS202)
|
|
nif->getVector4s(mSubtexOffsets, subtexOffsetNum);
|
|
|
|
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3
|
|
&& nif->getVersion() == NIFFile::NIFVersion::VER_BGS)
|
|
{
|
|
nif->read(mAspectRatio);
|
|
|
|
nif->read(mAspectFlags);
|
|
|
|
nif->read(mAspect2);
|
|
nif->read(mSpeed1);
|
|
nif->read(mSpeed2);
|
|
}
|
|
}
|
|
|
|
void NiRotatingParticlesData::read(NIFStream* nif)
|
|
{
|
|
NiParticlesData::read(nif);
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0) && nif->getBoolean())
|
|
nif->getQuaternions(mRotations, vertices.size());
|
|
}
|
|
|
|
void NiParticleInfo::read(NIFStream* nif)
|
|
{
|
|
nif->read(mVelocity);
|
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
|
|
nif->read(mRotation);
|
|
nif->read(mAge);
|
|
nif->read(mLifeSpan);
|
|
nif->read(mLastUpdate);
|
|
nif->read(mSpawnGen);
|
|
nif->read(mCode);
|
|
}
|
|
|
|
void NiPSysData::read(NIFStream* nif)
|
|
{
|
|
bool isBS202 = nif->getVersion() == NIFStream::generateVersion(20, 2, 0, 7) && nif->getBethVersion() > 0;
|
|
NiPSysDataFlag = true;
|
|
NiParticlesData::read(nif);
|
|
|
|
if (nif->getVersion() != NIFStream::generateVersion(20, 2, 0, 7))
|
|
{
|
|
mParticleInfo.resize(vertices.size());
|
|
for (unsigned long i = 0; i < vertices.size(); i++)
|
|
{
|
|
NiParticleInfo temp;
|
|
temp.read(nif);
|
|
mParticleInfo[i] = temp;
|
|
}
|
|
}
|
|
|
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76)
|
|
nif->skip(sizeof(float) * 3);
|
|
|
|
if (nif->getVersion() == NIFStream::generateVersion(20, 2, 4, 7))
|
|
nif->skip(1);
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20, 0, 0, 2))
|
|
{
|
|
bool hasRotationSpeed;
|
|
nif->read(hasRotationSpeed);
|
|
if (hasRotationSpeed && !isBS202)
|
|
{
|
|
mRotationSpeeds.resize(vertices.size());
|
|
nif->readVector(mRotationSpeeds, vertices.size());
|
|
}
|
|
}
|
|
|
|
if (!isBS202)
|
|
{
|
|
nif->read(mParticlesAddedNum);
|
|
nif->read(mParticlesBase);
|
|
}
|
|
|
|
if (nif->getVersion() == NIFStream::generateVersion(20, 2, 4, 7))
|
|
nif->skip(1);
|
|
}
|
|
|
|
void NiParticleSystem::read(NIFStream* nif)
|
|
{
|
|
NiParticleSystemFlag = true;
|
|
NiParticles::read(nif);
|
|
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_SSE)
|
|
mVertexDesc.read(nif);
|
|
|
|
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_SKY)
|
|
{
|
|
nif->read(mFarBegin);
|
|
nif->read(mFarEnd);
|
|
nif->read(mNearBegin);
|
|
nif->read(mNearEnd);
|
|
}
|
|
|
|
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_SSE)
|
|
mNiPSysData.read(nif);
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
{
|
|
nif->read(mWorldSpace);
|
|
unsigned int modifierNum;
|
|
nif->read(modifierNum);
|
|
mModifiers.resize(modifierNum);
|
|
|
|
for (auto& modifier : mModifiers)
|
|
{
|
|
modifier.read(nif);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NiParticleSystem::post(Reader& nif)
|
|
{
|
|
NiParticles::post(nif);
|
|
mNiPSysData.post(nif);
|
|
for (auto ptr : mModifiers)
|
|
{
|
|
ptr.post(nif);
|
|
}
|
|
}
|
|
|
|
void NiPSysModifier::read(NIFStream* nif)
|
|
{
|
|
mName = nif->getString();
|
|
nif->read(mOrder);
|
|
mTarget.read(nif);
|
|
nif->read(mActive);
|
|
}
|
|
|
|
void NiPSysModifier::post(Reader& nif)
|
|
{
|
|
mTarget.post(nif);
|
|
}
|
|
|
|
void NiPSysModifierCtlr::read(NIFStream* nif)
|
|
{
|
|
NiSingleInterpController::read(nif);
|
|
mModifierName = nif->getString();
|
|
}
|
|
|
|
void NiPSysEmitterCtlr::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifierCtlr::read(nif);
|
|
if (nif->getVersion() > NIFStream::generateVersion(10, 1, 0, 103))
|
|
mVisibilityInterpolator.read(nif);
|
|
// TODO: Handle pre 10.1.0.103
|
|
}
|
|
|
|
void NiPSysEmitterCtlr::post(Reader& nif)
|
|
{
|
|
NiPSysModifierCtlr::post(nif);
|
|
if (nif.getVersion() > NIFStream::generateVersion(10, 1, 0, 103))
|
|
mVisibilityInterpolator.post(nif);
|
|
}
|
|
|
|
void NiPSysAgeDeathModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
nif->read(mSpawnOnDeath);
|
|
mSpawnModifier.read(nif);
|
|
}
|
|
|
|
void NiPSysAgeDeathModifier::post(Reader& nif)
|
|
{
|
|
mSpawnModifier.post(nif);
|
|
}
|
|
|
|
void NiPSysSpawnModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
nif->read(mNumSpawnGens);
|
|
nif->read(mPercentSpawned);
|
|
nif->read(mMinSpawnNum);
|
|
nif->read(mMaxSpawnNum);
|
|
nif->read(mSpawnSpeedVariation);
|
|
nif->read(mSpawnDirVariation);
|
|
nif->read(mLifeSpan);
|
|
nif->read(mLifeSpanVariation);
|
|
}
|
|
|
|
void BSPSysLODModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
nif->read(mBeginDist);
|
|
nif->read(mEndDist);
|
|
nif->read(mEndEmitScale);
|
|
nif->read(mEndSize);
|
|
}
|
|
|
|
void NiPSysCylinderEmitter::read(NIFStream* nif)
|
|
{
|
|
NiPSysVolumeEmitter::read(nif);
|
|
|
|
nif->read(mRadius);
|
|
nif->read(mHeight);
|
|
}
|
|
|
|
void NiPSysVolumeEmitter::read(NIFStream* nif)
|
|
{
|
|
NiPSysEmitter::read(nif);
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
mEmitterObject.read(nif);
|
|
}
|
|
|
|
void NiPSysVolumeEmitter::post(Reader& nif)
|
|
{
|
|
NiPSysEmitter::post(nif);
|
|
|
|
if (nif.getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
mEmitterObject.post(nif);
|
|
}
|
|
|
|
void NiPSysEmitter::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
nif->read(mSpeed);
|
|
nif->read(mSpeedVariation);
|
|
nif->read(mDeclination);
|
|
nif->read(mDeclinationVariation);
|
|
nif->read(mPlanarAngle);
|
|
nif->read(mPlanarAngleVariation);
|
|
nif->read(mInitialColor);
|
|
nif->read(mInitialRadius);
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 4, 0, 1))
|
|
nif->read(mRadiusVariation);
|
|
nif->read(mLifespan);
|
|
nif->read(mLifespanVariation);
|
|
// nif->skip(sizeof(float) * 2);
|
|
}
|
|
|
|
void BSPSysSimpleColorModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
nif->read(mFadeInPercent);
|
|
nif->read(mFadeOutPercent);
|
|
nif->read(mColor1EndPercent);
|
|
nif->read(mColor1StartPercent);
|
|
nif->read(mColor2EndPercent);
|
|
nif->read(mColor2StartPercent);
|
|
nif->getVector4s(mColors, 3);
|
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76)
|
|
nif->skip(sizeof(unsigned short) * 26);
|
|
}
|
|
|
|
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)
|
|
throw Nif::Exception("Fallout76 is unsupported: ", nif->getFile().getFilename());
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20, 0, 0, 2))
|
|
{
|
|
nif->read(mRotationAngle);
|
|
nif->read(mRotationAngleVariation);
|
|
mRandRotSpeedSign = nif->getBoolean();
|
|
}
|
|
|
|
mRandAxis = nif->getBoolean();
|
|
nif->read(mAxis);
|
|
}
|
|
|
|
void BSPSysScaleModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
unsigned int numScales;
|
|
nif->read(numScales);
|
|
nif->readVector(mScales, numScales);
|
|
}
|
|
|
|
void NiPSysGravityModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
mGravityObject.read(nif);
|
|
nif->read(mGravityAxis);
|
|
nif->read(mDecay);
|
|
nif->read(mStrength);
|
|
nif->read(mForceType);
|
|
nif->read(mTurbulence);
|
|
nif->read(mTurbulenceScale);
|
|
|
|
if (nif->getBethVersion() > 16)
|
|
mWorldAligned = nif->getBoolean();
|
|
}
|
|
|
|
void NiPSysGravityModifier::post(Reader& nif)
|
|
{
|
|
NiPSysModifier::post(nif);
|
|
|
|
mGravityObject.post(nif);
|
|
}
|
|
|
|
void NiPSysBoundUpdateModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
nif->read(mUpdateSkip);
|
|
}
|
|
|
|
void NiPSysModifierActiveCtlr::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifierCtlr::read(nif);
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
|
mNiVisData.read(nif);
|
|
}
|
|
|
|
void NiPSysModifierActiveCtlr::post(Reader& nif)
|
|
{
|
|
NiPSysModifierCtlr::post(nif);
|
|
|
|
if (nif.getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
|
mNiVisData.post(nif);
|
|
}
|
|
|
|
void NiPSysMeshEmitter::read(NIFStream* nif)
|
|
{
|
|
NiPSysEmitter::read(nif);
|
|
|
|
unsigned int meshNum;
|
|
nif->read(meshNum);
|
|
|
|
mEmitterMeshes.resize(meshNum);
|
|
for (auto& mesh : mEmitterMeshes)
|
|
mesh.read(nif);
|
|
|
|
nif->read(mInitialVelocityType);
|
|
nif->read(mEmissionType);
|
|
nif->read(mEmissionAxis);
|
|
}
|
|
|
|
void NiPSysMeshEmitter::post(Reader& nif)
|
|
{
|
|
NiPSysEmitter::post(nif);
|
|
|
|
for (auto& mesh : mEmitterMeshes)
|
|
mesh.post(nif);
|
|
}
|
|
|
|
void BSPSysInheritVelocityModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
mInheritObject.read(nif);
|
|
nif->read(mInheritChance);
|
|
nif->read(mVelocityMult);
|
|
nif->read(mVelcoityVariation);
|
|
}
|
|
|
|
void BSPSysInheritVelocityModifier::post(Reader& nif)
|
|
{
|
|
NiPSysModifier::post(nif);
|
|
|
|
mInheritObject.post(nif);
|
|
}
|
|
|
|
void NiPSysBombModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
mBombObj.read(nif);
|
|
nif->read(mBombAxis);
|
|
nif->read(mDecay);
|
|
nif->read(mDeltaV);
|
|
nif->read(mDecayType);
|
|
nif->read(mSymmetryType);
|
|
}
|
|
|
|
void NiPSysBombModifier::post(Reader& nif)
|
|
{
|
|
NiPSysModifier::post(nif);
|
|
|
|
mBombObj.post(nif);
|
|
}
|
|
|
|
void NiPSysDragModifier::read(NIFStream* nif)
|
|
{
|
|
NiPSysModifier::read(nif);
|
|
|
|
mDragObj.read(nif);
|
|
nif->read(mDragAxis);
|
|
nif->read(mPercentage);
|
|
nif->read(mRange);
|
|
nif->read(mRangeFalloff);
|
|
}
|
|
|
|
void NiPSysDragModifier::post(Reader& nif)
|
|
{
|
|
NiPSysModifier::post(nif);
|
|
|
|
mDragObj.post(nif);
|
|
}
|
|
}
|