mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-20 21:11:33 +00:00
Merge branch 'nif' into 'master'
Modernize NIF loader, part 4 See merge request OpenMW/openmw!3427
This commit is contained in:
commit
64e4a33400
20 changed files with 648 additions and 697 deletions
|
@ -20,7 +20,7 @@ namespace Nif::Testing
|
||||||
{
|
{
|
||||||
value.mExtra = ExtraPtr(nullptr);
|
value.mExtra = ExtraPtr(nullptr);
|
||||||
value.mExtraList = ExtraList();
|
value.mExtraList = ExtraList();
|
||||||
value.mController = ControllerPtr(nullptr);
|
value.mController = NiTimeControllerPtr(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void init(NiAVObject& value)
|
inline void init(NiAVObject& value)
|
||||||
|
@ -55,15 +55,15 @@ namespace Nif::Testing
|
||||||
value.mRoot = NiAVObjectPtr(nullptr);
|
value.mRoot = NiAVObjectPtr(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void init(Controller& value)
|
inline void init(NiTimeController& value)
|
||||||
{
|
{
|
||||||
value.next = ControllerPtr(nullptr);
|
value.mNext = NiTimeControllerPtr(nullptr);
|
||||||
value.flags = 0;
|
value.mFlags = 0;
|
||||||
value.frequency = 0;
|
value.mFrequency = 0;
|
||||||
value.phase = 0;
|
value.mPhase = 0;
|
||||||
value.timeStart = 0;
|
value.mTimeStart = 0;
|
||||||
value.timeStop = 0;
|
value.mTimeStop = 0;
|
||||||
value.target = NiObjectNETPtr(nullptr);
|
value.mTarget = NiObjectNETPtr(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ namespace
|
||||||
Nif::NiStringExtraData mNiStringExtraData;
|
Nif::NiStringExtraData mNiStringExtraData;
|
||||||
Nif::NiStringExtraData mNiStringExtraData2;
|
Nif::NiStringExtraData mNiStringExtraData2;
|
||||||
Nif::NiIntegerExtraData mNiIntegerExtraData;
|
Nif::NiIntegerExtraData mNiIntegerExtraData;
|
||||||
Nif::Controller mController;
|
Nif::NiTimeController mController;
|
||||||
btTransform mTransform{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(1, 2, 3) };
|
btTransform mTransform{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(1, 2, 3) };
|
||||||
btTransform mTransformScale2{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(2, 4, 6) };
|
btTransform mTransformScale2{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(2, 4, 6) };
|
||||||
btTransform mTransformScale3{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(3, 6, 9) };
|
btTransform mTransformScale3{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(3, 6, 9) };
|
||||||
|
@ -817,11 +817,11 @@ namespace
|
||||||
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_animated_shape)
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_animated_shape)
|
||||||
{
|
{
|
||||||
mController.recType = Nif::RC_NiKeyframeController;
|
mController.recType = Nif::RC_NiKeyframeController;
|
||||||
mController.flags |= Nif::Controller::Flag_Active;
|
mController.mFlags |= Nif::NiTimeController::Flag_Active;
|
||||||
copy(mTransform, mNiTriShape.mTransform);
|
copy(mTransform, mNiTriShape.mTransform);
|
||||||
mNiTriShape.mTransform.mScale = 3;
|
mNiTriShape.mTransform.mScale = 3;
|
||||||
mNiTriShape.mParents.push_back(&mNiNode);
|
mNiTriShape.mParents.push_back(&mNiNode);
|
||||||
mNiTriShape.mController = Nif::ControllerPtr(&mController);
|
mNiTriShape.mController = Nif::NiTimeControllerPtr(&mController);
|
||||||
mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
|
mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
|
||||||
mNiNode.mTransform.mScale = 4;
|
mNiNode.mTransform.mScale = 4;
|
||||||
|
|
||||||
|
@ -847,14 +847,14 @@ namespace
|
||||||
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_nodes_where_one_with_controller_should_return_animated_shape)
|
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_nodes_where_one_with_controller_should_return_animated_shape)
|
||||||
{
|
{
|
||||||
mController.recType = Nif::RC_NiKeyframeController;
|
mController.recType = Nif::RC_NiKeyframeController;
|
||||||
mController.flags |= Nif::Controller::Flag_Active;
|
mController.mFlags |= Nif::NiTimeController::Flag_Active;
|
||||||
copy(mTransform, mNiTriShape.mTransform);
|
copy(mTransform, mNiTriShape.mTransform);
|
||||||
mNiTriShape.mTransform.mScale = 3;
|
mNiTriShape.mTransform.mScale = 3;
|
||||||
mNiTriShape.mParents.push_back(&mNiNode);
|
mNiTriShape.mParents.push_back(&mNiNode);
|
||||||
copy(mTransform, mNiTriShape2.mTransform);
|
copy(mTransform, mNiTriShape2.mTransform);
|
||||||
mNiTriShape2.mTransform.mScale = 3;
|
mNiTriShape2.mTransform.mScale = 3;
|
||||||
mNiTriShape2.mParents.push_back(&mNiNode);
|
mNiTriShape2.mParents.push_back(&mNiNode);
|
||||||
mNiTriShape2.mController = Nif::ControllerPtr(&mController);
|
mNiTriShape2.mController = Nif::NiTimeControllerPtr(&mController);
|
||||||
mNiNode.mChildren = Nif::NiAVObjectList{
|
mNiNode.mChildren = Nif::NiAVObjectList{
|
||||||
Nif::NiAVObjectPtr(&mNiTriShape),
|
Nif::NiAVObjectPtr(&mNiTriShape),
|
||||||
Nif::NiAVObjectPtr(&mNiTriShape2),
|
Nif::NiAVObjectPtr(&mNiTriShape2),
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Nif
|
||||||
void post(Reader& nif) override { mNext.post(nif); }
|
void post(Reader& nif) override { mNext.post(nif); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Controller : public Record
|
struct NiTimeController : public Record
|
||||||
{
|
{
|
||||||
enum Flags
|
enum Flags
|
||||||
{
|
{
|
||||||
|
@ -36,17 +36,17 @@ namespace Nif
|
||||||
Mask = 6
|
Mask = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
ControllerPtr next;
|
NiTimeControllerPtr mNext;
|
||||||
int flags;
|
uint16_t mFlags;
|
||||||
float frequency, phase;
|
float mFrequency, mPhase;
|
||||||
float timeStart, timeStop;
|
float mTimeStart, mTimeStop;
|
||||||
NiObjectNETPtr target;
|
NiObjectNETPtr mTarget;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
||||||
bool isActive() const { return flags & Flag_Active; }
|
bool isActive() const { return mFlags & Flag_Active; }
|
||||||
ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(flags & Mask); }
|
ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(mFlags & Mask); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract object that has a name, extra data and controllers
|
/// Abstract object that has a name, extra data and controllers
|
||||||
|
@ -55,7 +55,7 @@ namespace Nif
|
||||||
std::string mName;
|
std::string mName;
|
||||||
ExtraPtr mExtra;
|
ExtraPtr mExtra;
|
||||||
ExtraList mExtraList;
|
ExtraList mExtraList;
|
||||||
ControllerPtr mController;
|
NiTimeControllerPtr mController;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "controller.hpp"
|
#include "controller.hpp"
|
||||||
|
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
#include "particle.hpp"
|
#include "particle.hpp"
|
||||||
#include "texture.hpp"
|
#include "texture.hpp"
|
||||||
|
@ -8,25 +9,22 @@
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
void Controller::read(NIFStream* nif)
|
void NiTimeController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
next.read(nif);
|
mNext.read(nif);
|
||||||
|
nif->read(mFlags);
|
||||||
flags = nif->getUShort();
|
nif->read(mFrequency);
|
||||||
|
nif->read(mPhase);
|
||||||
frequency = nif->getFloat();
|
nif->read(mTimeStart);
|
||||||
phase = nif->getFloat();
|
nif->read(mTimeStop);
|
||||||
timeStart = nif->getFloat();
|
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
|
||||||
timeStop = nif->getFloat();
|
mTarget.read(nif);
|
||||||
|
|
||||||
target.read(nif);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::post(Reader& nif)
|
void NiTimeController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Record::post(nif);
|
mNext.post(nif);
|
||||||
next.post(nif);
|
mTarget.post(nif);
|
||||||
target.post(nif);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlledBlock::read(NIFStream* nif)
|
void ControlledBlock::read(NIFStream* nif)
|
||||||
|
@ -44,28 +42,28 @@ namespace Nif
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 110))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 110))
|
||||||
{
|
{
|
||||||
mBlendInterpolator.read(nif);
|
mBlendInterpolator.read(nif);
|
||||||
mBlendIndex = nif->getUShort();
|
nif->read(mBlendIndex);
|
||||||
}
|
}
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106) && nif->getBethVersion() > 0)
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106) && nif->getBethVersion() > 0)
|
||||||
mPriority = nif->getChar();
|
nif->read(mPriority);
|
||||||
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0)
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0)
|
||||||
&& nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0))
|
&& nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0))
|
||||||
{
|
{
|
||||||
mStringPalette.read(nif);
|
mStringPalette.read(nif);
|
||||||
mNodeNameOffset = nif->getUInt();
|
nif->read(mNodeNameOffset);
|
||||||
mPropertyTypeOffset = nif->getUInt();
|
nif->read(mPropertyTypeOffset);
|
||||||
mControllerTypeOffset = nif->getUInt();
|
nif->read(mControllerTypeOffset);
|
||||||
mControllerIdOffset = nif->getUInt();
|
nif->read(mControllerIdOffset);
|
||||||
mInterpolatorIdOffset = nif->getUInt();
|
nif->read(mInterpolatorIdOffset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mNodeName = nif->getString();
|
nif->read(mNodeName);
|
||||||
mPropertyType = nif->getString();
|
nif->read(mPropertyType);
|
||||||
mControllerType = nif->getString();
|
nif->read(mControllerType);
|
||||||
mControllerId = nif->getString();
|
nif->read(mControllerId);
|
||||||
mInterpolatorId = nif->getString();
|
nif->read(mInterpolatorId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,16 +78,15 @@ namespace Nif
|
||||||
|
|
||||||
void NiSequence::read(NIFStream* nif)
|
void NiSequence::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
mName = nif->getString();
|
nif->read(mName);
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
{
|
{
|
||||||
mAccumRootName = nif->getString();
|
nif->read(mAccumRootName);
|
||||||
mTextKeys.read(nif);
|
mTextKeys.read(nif);
|
||||||
}
|
}
|
||||||
size_t numControlledBlocks = nif->getUInt();
|
mControlledBlocks.resize(nif->get<uint32_t>());
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106))
|
||||||
mArrayGrowBy = nif->getUInt();
|
nif->read(mArrayGrowBy);
|
||||||
mControlledBlocks.resize(numControlledBlocks);
|
|
||||||
for (ControlledBlock& block : mControlledBlocks)
|
for (ControlledBlock& block : mControlledBlocks)
|
||||||
block.read(nif);
|
block.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -104,28 +101,30 @@ namespace Nif
|
||||||
void NiControllerSequence::read(NIFStream* nif)
|
void NiControllerSequence::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiSequence::read(nif);
|
NiSequence::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mWeight = nif->getFloat();
|
nif->read(mWeight);
|
||||||
mTextKeys.read(nif);
|
mTextKeys.read(nif);
|
||||||
mExtrapolationMode = static_cast<Controller::ExtrapolationMode>(nif->getUInt());
|
mExtrapolationMode = static_cast<NiTimeController::ExtrapolationMode>(nif->get<uint32_t>());
|
||||||
mFrequency = nif->getFloat();
|
nif->read(mFrequency);
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
|
||||||
mPhase = nif->getFloat();
|
nif->read(mPhase);
|
||||||
mStartTime = nif->getFloat();
|
nif->read(mStartTime);
|
||||||
mStopTime = nif->getFloat();
|
nif->read(mStopTime);
|
||||||
mPlayBackwards = nif->getVersion() == NIFStream::generateVersion(10, 1, 0, 106) && nif->getBoolean();
|
if (nif->getVersion() == NIFStream::generateVersion(10, 1, 0, 106))
|
||||||
|
nif->read(mPlayBackwards);
|
||||||
mManager.read(nif);
|
mManager.read(nif);
|
||||||
mAccumRootName = nif->getString();
|
nif->read(mAccumRootName);
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 113)
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 113)
|
||||||
&& nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0))
|
&& nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0))
|
||||||
mStringPalette.read(nif);
|
mStringPalette.read(nif);
|
||||||
else if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 24)
|
else if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 24)
|
||||||
{
|
{
|
||||||
size_t numAnimNotes = 1;
|
uint16_t numAnimNotes = 1;
|
||||||
if (nif->getBethVersion() >= 29)
|
if (nif->getBethVersion() >= 29)
|
||||||
numAnimNotes = nif->getUShort();
|
nif->read(numAnimNotes);
|
||||||
|
|
||||||
nif->skip(4 * numAnimNotes); // BSAnimNotes links
|
nif->skip(4 * numAnimNotes); // BSAnimNotes links
|
||||||
}
|
}
|
||||||
|
@ -134,21 +133,24 @@ namespace Nif
|
||||||
void NiControllerSequence::post(Reader& nif)
|
void NiControllerSequence::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiSequence::post(nif);
|
NiSequence::post(nif);
|
||||||
|
|
||||||
mManager.post(nif);
|
mManager.post(nif);
|
||||||
mStringPalette.post(nif);
|
mStringPalette.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiInterpController::read(NIFStream* nif)
|
void NiInterpController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104)
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104)
|
||||||
&& nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 108))
|
&& nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 108))
|
||||||
mManagerControlled = nif->getBoolean();
|
nif->read(mManagerControlled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiSingleInterpController::read(NIFStream* nif)
|
void NiSingleInterpController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiInterpController::read(nif);
|
NiInterpController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104))
|
||||||
mInterpolator.read(nif);
|
mInterpolator.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -156,83 +158,86 @@ namespace Nif
|
||||||
void NiSingleInterpController::post(Reader& nif)
|
void NiSingleInterpController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiInterpController::post(nif);
|
NiInterpController::post(nif);
|
||||||
|
|
||||||
mInterpolator.post(nif);
|
mInterpolator.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NiParticleInfo::read(NIFStream* nif)
|
||||||
|
{
|
||||||
|
nif->read(mVelocity);
|
||||||
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
|
||||||
|
nif->read(mRotationAxis);
|
||||||
|
nif->read(mAge);
|
||||||
|
nif->read(mLifespan);
|
||||||
|
nif->read(mLastUpdate);
|
||||||
|
nif->read(mSpawnGeneration);
|
||||||
|
nif->read(mCode);
|
||||||
|
}
|
||||||
|
|
||||||
void NiParticleSystemController::read(NIFStream* nif)
|
void NiParticleSystemController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
|
|
||||||
velocity = nif->getFloat();
|
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
|
||||||
velocityRandom = nif->getFloat();
|
nif->read(mSpeed);
|
||||||
verticalDir = nif->getFloat();
|
nif->read(mSpeedVariation);
|
||||||
verticalAngle = nif->getFloat();
|
nif->read(mDeclination);
|
||||||
horizontalDir = nif->getFloat();
|
nif->read(mDeclinationVariation);
|
||||||
horizontalAngle = nif->getFloat();
|
nif->read(mPlanarAngle);
|
||||||
/*normal?*/ nif->getVector3();
|
nif->read(mPlanarAngleVariation);
|
||||||
color = nif->getVector4();
|
nif->read(mInitialNormal);
|
||||||
size = nif->getFloat();
|
nif->read(mInitialColor);
|
||||||
startTime = nif->getFloat();
|
nif->read(mInitialSize);
|
||||||
stopTime = nif->getFloat();
|
nif->read(mEmitStartTime);
|
||||||
nif->getChar();
|
nif->read(mEmitStopTime);
|
||||||
emitRate = nif->getFloat();
|
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
|
||||||
lifetime = nif->getFloat();
|
|
||||||
lifetimeRandom = nif->getFloat();
|
|
||||||
|
|
||||||
emitFlags = nif->getUShort();
|
|
||||||
offsetRandom = nif->getVector3();
|
|
||||||
|
|
||||||
emitter.read(nif);
|
|
||||||
|
|
||||||
/* Unknown Short, 0?
|
|
||||||
* Unknown Float, 1.0?
|
|
||||||
* Unknown Int, 1?
|
|
||||||
* Unknown Int, 0?
|
|
||||||
* Unknown Short, 0?
|
|
||||||
*/
|
|
||||||
nif->skip(16);
|
|
||||||
|
|
||||||
numParticles = nif->getUShort();
|
|
||||||
activeCount = nif->getUShort();
|
|
||||||
|
|
||||||
particles.resize(numParticles);
|
|
||||||
for (size_t i = 0; i < particles.size(); i++)
|
|
||||||
{
|
{
|
||||||
particles[i].velocity = nif->getVector3();
|
mResetParticleSystem = nif->get<uint8_t>() != 0;
|
||||||
nif->getVector3(); /* unknown */
|
nif->read(mBirthRate);
|
||||||
particles[i].lifetime = nif->getFloat();
|
|
||||||
particles[i].lifespan = nif->getFloat();
|
|
||||||
particles[i].timestamp = nif->getFloat();
|
|
||||||
nif->getUShort(); /* unknown */
|
|
||||||
particles[i].vertex = nif->getUShort();
|
|
||||||
}
|
}
|
||||||
|
nif->read(mLifetime);
|
||||||
nif->getUInt(); /* -1? */
|
nif->read(mLifetimeVariation);
|
||||||
affectors.read(nif);
|
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
|
||||||
colliders.read(nif);
|
nif->read(mEmitFlags);
|
||||||
nif->getChar();
|
nif->read(mEmitterDimensions);
|
||||||
|
mEmitter.read(nif);
|
||||||
|
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
|
||||||
|
{
|
||||||
|
nif->read(mNumSpawnGenerations);
|
||||||
|
nif->read(mPercentageSpawned);
|
||||||
|
nif->read(mSpawnMultiplier);
|
||||||
|
nif->read(mSpawnSpeedChaos);
|
||||||
|
nif->read(mSpawnDirChaos);
|
||||||
|
mParticles.resize(nif->get<uint16_t>());
|
||||||
|
nif->read(mNumValid);
|
||||||
|
for (NiParticleInfo& particle : mParticles)
|
||||||
|
particle.read(nif);
|
||||||
|
nif->skip(4); // NiEmitterModifier link
|
||||||
|
}
|
||||||
|
mModifier.read(nif);
|
||||||
|
mCollider.read(nif);
|
||||||
|
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 15))
|
||||||
|
nif->read(mStaticTargetBound);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiParticleSystemController::post(Reader& nif)
|
void NiParticleSystemController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
NiTimeController::post(nif);
|
||||||
emitter.post(nif);
|
|
||||||
affectors.post(nif);
|
mEmitter.post(nif);
|
||||||
colliders.post(nif);
|
mModifier.post(nif);
|
||||||
|
mCollider.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiMaterialColorController::read(NIFStream* nif)
|
void NiMaterialColorController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiPoint3InterpController::read(nif);
|
NiPoint3InterpController::read(nif);
|
||||||
// Two bits that correspond to the controlled material color.
|
|
||||||
// 00: Ambient
|
|
||||||
// 01: Diffuse
|
|
||||||
// 10: Specular
|
|
||||||
// 11: Emissive
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
||||||
mTargetColor = nif->getUShort() & 3;
|
mTargetColor = static_cast<TargetColor>(nif->get<uint16_t>() & 3);
|
||||||
else
|
else
|
||||||
mTargetColor = (flags >> 4) & 3;
|
mTargetColor = static_cast<TargetColor>((mFlags >> 4) & 3);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -240,60 +245,70 @@ namespace Nif
|
||||||
void NiMaterialColorController::post(Reader& nif)
|
void NiMaterialColorController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiPoint3InterpController::post(nif);
|
NiPoint3InterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiLookAtController::read(NIFStream* nif)
|
void NiLookAtController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
||||||
lookAtFlags = nif->getUShort();
|
nif->read(mLookAtFlags);
|
||||||
target.read(nif);
|
mLookAt.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiLookAtController::post(Reader& nif)
|
void NiLookAtController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
NiTimeController::post(nif);
|
||||||
target.post(nif);
|
|
||||||
|
mLookAt.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPathController::read(NIFStream* nif)
|
void NiPathController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
|
|
||||||
bankDir = nif->getInt();
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
||||||
maxBankAngle = nif->getFloat();
|
nif->read(mPathFlags);
|
||||||
smoothing = nif->getFloat();
|
else
|
||||||
followAxis = nif->getShort();
|
mPathFlags = (mFlags >> 4);
|
||||||
posData.read(nif);
|
|
||||||
floatData.read(nif);
|
nif->read(mBankDirection);
|
||||||
|
nif->read(mMaxBankAngle);
|
||||||
|
nif->read(mSmoothing);
|
||||||
|
nif->read(mFollowAxis);
|
||||||
|
mPathData.read(nif);
|
||||||
|
mPercentData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPathController::post(Reader& nif)
|
void NiPathController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
NiTimeController::post(nif);
|
||||||
|
|
||||||
posData.post(nif);
|
mPathData.post(nif);
|
||||||
floatData.post(nif);
|
mPercentData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiUVController::read(NIFStream* nif)
|
void NiUVController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
|
|
||||||
uvSet = nif->getUShort();
|
nif->read(mUvSet);
|
||||||
data.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiUVController::post(Reader& nif)
|
void NiUVController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
NiTimeController::post(nif);
|
||||||
data.post(nif);
|
|
||||||
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiKeyframeController::read(NIFStream* nif)
|
void NiKeyframeController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiSingleInterpController::read(nif);
|
NiSingleInterpController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -301,29 +316,30 @@ namespace Nif
|
||||||
void NiKeyframeController::post(Reader& nif)
|
void NiKeyframeController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiSingleInterpController::post(nif);
|
NiSingleInterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiMultiTargetTransformController::read(NIFStream* nif)
|
void NiMultiTargetTransformController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiInterpController::read(nif);
|
NiInterpController::read(nif);
|
||||||
size_t numTargets = nif->getUShort();
|
|
||||||
std::vector<NiAVObjectPtr> targets;
|
mExtraTargets.resize(nif->get<uint16_t>());
|
||||||
targets.resize(numTargets);
|
for (NiAVObjectPtr& extraTarget : mExtraTargets)
|
||||||
for (size_t i = 0; i < targets.size(); i++)
|
extraTarget.read(nif);
|
||||||
targets[i].read(nif);
|
|
||||||
mExtraTargets = targets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiMultiTargetTransformController::post(Reader& nif)
|
void NiMultiTargetTransformController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiInterpController::post(nif);
|
NiInterpController::post(nif);
|
||||||
|
|
||||||
postRecordList(nif, mExtraTargets);
|
postRecordList(nif, mExtraTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiAlphaController::read(NIFStream* nif)
|
void NiAlphaController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::read(nif);
|
NiFloatInterpController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -331,12 +347,14 @@ namespace Nif
|
||||||
void NiAlphaController::post(Reader& nif)
|
void NiAlphaController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::post(nif);
|
NiFloatInterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiRollController::read(NIFStream* nif)
|
void NiRollController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiSingleInterpController::read(nif);
|
NiSingleInterpController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -344,49 +362,47 @@ namespace Nif
|
||||||
void NiRollController::post(Reader& nif)
|
void NiRollController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiSingleInterpController::post(nif);
|
NiSingleInterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiGeomMorpherController::read(NIFStream* nif)
|
void NiGeomMorpherController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiInterpController::read(nif);
|
NiInterpController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD)
|
if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD)
|
||||||
mUpdateNormals = nif->getUShort() & 1;
|
mUpdateNormals = nif->get<uint16_t>() & 1;
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW)
|
|
||||||
|
if (nif->getVersion() < NIFFile::NIFVersion::VER_MW)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mAlwaysActive = nif->get<uint8_t>() != 0;
|
||||||
|
|
||||||
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 105))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||||
{
|
{
|
||||||
mAlwaysActive = nif->getChar();
|
readRecordList(nif, mInterpolators);
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() >= 10)
|
||||||
{
|
nif->skip(4 * nif->get<uint32_t>()); // Unknown
|
||||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
return;
|
||||||
{
|
}
|
||||||
readRecordList(nif, mInterpolators);
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() > 9)
|
mInterpolators.resize(nif->get<uint32_t>());
|
||||||
{
|
mWeights.resize(mInterpolators.size());
|
||||||
unsigned int numUnknown = nif->getUInt();
|
for (size_t i = 0; i < mInterpolators.size(); i++)
|
||||||
nif->skip(4 * numUnknown);
|
{
|
||||||
}
|
mInterpolators[i].read(nif);
|
||||||
}
|
nif->read(mWeights[i]);
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<NiInterpolatorPtr> interpolators;
|
|
||||||
size_t numInterps = nif->getUInt();
|
|
||||||
interpolators.resize(numInterps);
|
|
||||||
mWeights.resize(numInterps);
|
|
||||||
for (size_t i = 0; i < numInterps; i++)
|
|
||||||
{
|
|
||||||
interpolators[i].read(nif);
|
|
||||||
mWeights[i] = nif->getFloat();
|
|
||||||
}
|
|
||||||
mInterpolators = interpolators;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiGeomMorpherController::post(Reader& nif)
|
void NiGeomMorpherController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiInterpController::post(nif);
|
NiInterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
postRecordList(nif, mInterpolators);
|
postRecordList(nif, mInterpolators);
|
||||||
}
|
}
|
||||||
|
@ -394,6 +410,7 @@ namespace Nif
|
||||||
void NiVisController::read(NIFStream* nif)
|
void NiVisController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiBoolInterpController::read(nif);
|
NiBoolInterpController::read(nif);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
@ -401,17 +418,19 @@ namespace Nif
|
||||||
void NiVisController::post(Reader& nif)
|
void NiVisController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiBoolInterpController::post(nif);
|
NiBoolInterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiFlipController::read(NIFStream* nif)
|
void NiFlipController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::read(nif);
|
NiFloatInterpController::read(nif);
|
||||||
mTexSlot = nif->getUInt();
|
|
||||||
|
mTexSlot = static_cast<NiTexturingProperty::TextureType>(nif->get<uint32_t>());
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
{
|
{
|
||||||
timeStart = nif->getFloat();
|
nif->read(mTimeStart);
|
||||||
mDelta = nif->getFloat();
|
nif->read(mDelta);
|
||||||
}
|
}
|
||||||
readRecordList(nif, mSources);
|
readRecordList(nif, mSources);
|
||||||
}
|
}
|
||||||
|
@ -419,14 +438,16 @@ namespace Nif
|
||||||
void NiFlipController::post(Reader& nif)
|
void NiFlipController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::post(nif);
|
NiFloatInterpController::post(nif);
|
||||||
|
|
||||||
postRecordList(nif, mSources);
|
postRecordList(nif, mSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiTextureTransformController::read(NIFStream* nif)
|
void NiTextureTransformController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::read(nif);
|
NiFloatInterpController::read(nif);
|
||||||
mShaderMap = nif->getBoolean();
|
|
||||||
nif->read(mTexSlot);
|
nif->read(mShaderMap);
|
||||||
|
mTexSlot = static_cast<NiTexturingProperty::TextureType>(nif->get<uint32_t>());
|
||||||
nif->read(mTransformMember);
|
nif->read(mTransformMember);
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
|
@ -435,176 +456,113 @@ namespace Nif
|
||||||
void NiTextureTransformController::post(Reader& nif)
|
void NiTextureTransformController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::post(nif);
|
NiFloatInterpController::post(nif);
|
||||||
|
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkBlendController::read(NIFStream* nif)
|
void bhkBlendController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
nif->getUInt(); // Zero
|
|
||||||
|
uint32_t numKeys;
|
||||||
|
nif->read(numKeys);
|
||||||
|
// Is this possible?
|
||||||
|
if (numKeys != 0)
|
||||||
|
throw Nif::Exception(
|
||||||
|
"Unsupported keys in bhkBlendController " + std::to_string(recIndex), nif->getFile().getFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSEffectShaderPropertyFloatController::read(NIFStream* nif)
|
void BSEffectShaderPropertyFloatController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::read(nif);
|
NiFloatInterpController::read(nif);
|
||||||
|
|
||||||
nif->read(mControlledVariable);
|
nif->read(mControlledVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSEffectShaderPropertyColorController::read(NIFStream* nif)
|
void BSEffectShaderPropertyColorController::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiPoint3InterpController::read(nif);
|
NiPoint3InterpController::read(nif);
|
||||||
|
|
||||||
nif->read(mControlledColor);
|
nif->read(mControlledColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiControllerManager::read(NIFStream* nif)
|
void NiControllerManager::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
NiTimeController::read(nif);
|
||||||
mCumulative = nif->getBoolean();
|
|
||||||
|
nif->read(mCumulative);
|
||||||
readRecordList(nif, mSequences);
|
readRecordList(nif, mSequences);
|
||||||
mObjectPalette.read(nif);
|
mObjectPalette.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiControllerManager::post(Reader& nif)
|
void NiControllerManager::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
NiTimeController::post(nif);
|
||||||
|
|
||||||
postRecordList(nif, mSequences);
|
postRecordList(nif, mSequences);
|
||||||
mObjectPalette.post(nif);
|
mObjectPalette.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPoint3Interpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
defaultVal = nif->getVector3();
|
|
||||||
data.read(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiPoint3Interpolator::post(Reader& nif)
|
|
||||||
{
|
|
||||||
data.post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiBoolInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
defaultVal = nif->getBoolean();
|
|
||||||
data.read(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiBoolInterpolator::post(Reader& nif)
|
|
||||||
{
|
|
||||||
data.post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiFloatInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
defaultVal = nif->getFloat();
|
|
||||||
data.read(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiFloatInterpolator::post(Reader& nif)
|
|
||||||
{
|
|
||||||
data.post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiTransformInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
defaultPos = nif->getVector3();
|
|
||||||
defaultRot = nif->getQuaternion();
|
|
||||||
defaultScale = nif->getFloat();
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
|
||||||
{
|
|
||||||
if (!nif->getBoolean())
|
|
||||||
defaultPos = osg::Vec3f();
|
|
||||||
if (!nif->getBoolean())
|
|
||||||
defaultRot = osg::Quat();
|
|
||||||
if (!nif->getBoolean())
|
|
||||||
defaultScale = 1.f;
|
|
||||||
}
|
|
||||||
data.read(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiTransformInterpolator::post(Reader& nif)
|
|
||||||
{
|
|
||||||
data.post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiColorInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
defaultVal = nif->getVector4();
|
|
||||||
data.read(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiColorInterpolator::post(Reader& nif)
|
|
||||||
{
|
|
||||||
data.post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiBlendInterpolator::read(NIFStream* nif)
|
void NiBlendInterpolator::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112))
|
||||||
mManagerControlled = nif->getChar() & 1;
|
|
||||||
size_t numInterps = 0;
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
|
||||||
{
|
{
|
||||||
numInterps = nif->getUShort();
|
nif->read(mFlags);
|
||||||
mArrayGrowBy = nif->getUShort();
|
mItems.resize(nif->get<uint8_t>());
|
||||||
}
|
nif->read(mWeightThreshold);
|
||||||
else
|
if (!(mFlags & Flag_ManagerControlled))
|
||||||
{
|
|
||||||
numInterps = nif->getChar();
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112))
|
|
||||||
{
|
{
|
||||||
mWeightThreshold = nif->getFloat();
|
mInterpCount = nif->get<uint8_t>();
|
||||||
if (!mManagerControlled)
|
mSingleIndex = nif->get<uint8_t>();
|
||||||
{
|
mHighPriority = nif->get<int8_t>();
|
||||||
mInterpCount = nif->getChar();
|
mNextHighPriority = nif->get<int8_t>();
|
||||||
mSingleIndex = nif->getChar();
|
nif->read(mSingleTime);
|
||||||
mHighPriority = nif->getChar();
|
nif->read(mHighWeightsSum);
|
||||||
mNextHighPriority = nif->getChar();
|
nif->read(mNextHighWeightsSum);
|
||||||
mSingleTime = nif->getFloat();
|
nif->read(mHighEaseSpinner);
|
||||||
mHighWeightsSum = nif->getFloat();
|
for (Item& item : mItems)
|
||||||
mNextHighWeightsSum = nif->getFloat();
|
item.read(nif);
|
||||||
mHighEaseSpinner = nif->getFloat();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mManagerControlled)
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 110))
|
||||||
{
|
{
|
||||||
mItems.resize(numInterps);
|
mItems.resize(nif->get<uint8_t>());
|
||||||
for (Item& item : mItems)
|
for (Item& item : mItems)
|
||||||
item.read(nif);
|
item.read(nif);
|
||||||
|
if (nif->get<bool>())
|
||||||
|
mFlags |= Flag_ManagerControlled;
|
||||||
|
nif->read(mWeightThreshold);
|
||||||
|
if (nif->get<bool>())
|
||||||
|
mFlags |= Flag_OnlyUseHighestWeight;
|
||||||
|
mInterpCount = nif->get<uint8_t>();
|
||||||
|
mSingleIndex = nif->get<uint8_t>();
|
||||||
|
mSingleInterpolator.read(nif);
|
||||||
|
nif->read(mSingleTime);
|
||||||
|
mHighPriority = nif->get<int8_t>();
|
||||||
|
mNextHighPriority = nif->get<int8_t>();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 111))
|
mItems.resize(nif->get<uint16_t>());
|
||||||
|
nif->read(mArrayGrowBy);
|
||||||
|
for (Item& item : mItems)
|
||||||
|
item.read(nif);
|
||||||
|
if (nif->get<bool>())
|
||||||
|
mFlags |= Flag_ManagerControlled;
|
||||||
|
nif->read(mWeightThreshold);
|
||||||
|
if (nif->get<bool>())
|
||||||
|
mFlags |= Flag_OnlyUseHighestWeight;
|
||||||
|
nif->read(mInterpCount);
|
||||||
|
nif->read(mSingleIndex);
|
||||||
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 108))
|
||||||
{
|
{
|
||||||
mManagerControlled = nif->getBoolean();
|
mSingleInterpolator.read(nif);
|
||||||
mWeightThreshold = nif->getFloat();
|
nif->read(mSingleTime);
|
||||||
mOnlyUseHighestWeight = nif->getBoolean();
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
|
||||||
{
|
|
||||||
mInterpCount = nif->getUShort();
|
|
||||||
mSingleIndex = nif->getUShort();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mInterpCount = nif->getChar();
|
|
||||||
mSingleIndex = nif->getChar();
|
|
||||||
}
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 108))
|
|
||||||
{
|
|
||||||
mSingleInterpolator.read(nif);
|
|
||||||
mSingleTime = nif->getFloat();
|
|
||||||
}
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
|
||||||
{
|
|
||||||
mHighPriority = nif->getInt();
|
|
||||||
mNextHighPriority = nif->getInt();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mHighPriority = nif->getChar();
|
|
||||||
mNextHighPriority = nif->getChar();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
nif->read(mHighPriority);
|
||||||
|
nif->read(mNextHighPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiBlendInterpolator::post(Reader& nif)
|
void NiBlendInterpolator::post(Reader& nif)
|
||||||
|
@ -617,13 +575,13 @@ namespace Nif
|
||||||
void NiBlendInterpolator::Item::read(NIFStream* nif)
|
void NiBlendInterpolator::Item::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
mInterpolator.read(nif);
|
mInterpolator.read(nif);
|
||||||
mWeight = nif->getFloat();
|
nif->read(mWeight);
|
||||||
mNormalizedWeight = nif->getFloat();
|
nif->read(mNormalizedWeight);
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 110))
|
||||||
mPriority = nif->getInt();
|
mPriority = nif->get<int8_t>();
|
||||||
else
|
else
|
||||||
mPriority = nif->getChar();
|
nif->read(mPriority);
|
||||||
mEaseSpinner = nif->getFloat();
|
nif->read(mEaseSpinner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiBlendInterpolator::Item::post(Reader& nif)
|
void NiBlendInterpolator::Item::post(Reader& nif)
|
||||||
|
@ -631,38 +589,4 @@ namespace Nif
|
||||||
mInterpolator.post(nif);
|
mInterpolator.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiBlendBoolInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
NiBlendInterpolator::read(nif);
|
|
||||||
mValue = nif->getChar() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiBlendFloatInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
NiBlendInterpolator::read(nif);
|
|
||||||
mValue = nif->getFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiBlendPoint3Interpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
NiBlendInterpolator::read(nif);
|
|
||||||
mValue = nif->getVector3();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NiBlendTransformInterpolator::read(NIFStream* nif)
|
|
||||||
{
|
|
||||||
NiBlendInterpolator::read(nif);
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
|
||||||
{
|
|
||||||
mPosValue = nif->getVector3();
|
|
||||||
mRotValue = nif->getQuaternion();
|
|
||||||
mScaleValue = nif->getFloat();
|
|
||||||
if (!nif->getBoolean())
|
|
||||||
mPosValue = osg::Vec3f();
|
|
||||||
if (!nif->getBoolean())
|
|
||||||
mRotValue = osg::Quat();
|
|
||||||
if (!nif->getBoolean())
|
|
||||||
mScaleValue = 1.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,8 @@
|
||||||
/*
|
|
||||||
OpenMW - The completely unofficial reimplementation of Morrowind
|
|
||||||
Copyright (C) 2008-2010 Nicolay Korslund
|
|
||||||
Email: < korslund@gmail.com >
|
|
||||||
WWW: https://openmw.org/
|
|
||||||
|
|
||||||
This file (controller.h) is part of the OpenMW package.
|
|
||||||
|
|
||||||
OpenMW is distributed as free software: you can redistribute it
|
|
||||||
and/or modify it under the terms of the GNU General Public License
|
|
||||||
version 3, as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
version 3 along with this program. If not, see
|
|
||||||
https://www.gnu.org/licenses/ .
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OPENMW_COMPONENTS_NIF_CONTROLLER_HPP
|
#ifndef OPENMW_COMPONENTS_NIF_CONTROLLER_HPP
|
||||||
#define OPENMW_COMPONENTS_NIF_CONTROLLER_HPP
|
#define OPENMW_COMPONENTS_NIF_CONTROLLER_HPP
|
||||||
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
|
#include "niftypes.hpp"
|
||||||
#include "property.hpp"
|
#include "property.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
|
@ -34,16 +12,16 @@ namespace Nif
|
||||||
{
|
{
|
||||||
std::string mTargetName;
|
std::string mTargetName;
|
||||||
NiInterpolatorPtr mInterpolator;
|
NiInterpolatorPtr mInterpolator;
|
||||||
ControllerPtr mController;
|
NiTimeControllerPtr mController;
|
||||||
NiBlendInterpolatorPtr mBlendInterpolator;
|
NiBlendInterpolatorPtr mBlendInterpolator;
|
||||||
unsigned short mBlendIndex;
|
uint16_t mBlendIndex;
|
||||||
unsigned char mPriority;
|
uint8_t mPriority;
|
||||||
NiStringPalettePtr mStringPalette;
|
NiStringPalettePtr mStringPalette;
|
||||||
size_t mNodeNameOffset;
|
uint32_t mNodeNameOffset;
|
||||||
size_t mPropertyTypeOffset;
|
uint32_t mPropertyTypeOffset;
|
||||||
size_t mControllerTypeOffset;
|
uint32_t mControllerTypeOffset;
|
||||||
size_t mControllerIdOffset;
|
uint32_t mControllerIdOffset;
|
||||||
size_t mInterpolatorIdOffset;
|
uint32_t mInterpolatorIdOffset;
|
||||||
std::string mNodeName;
|
std::string mNodeName;
|
||||||
std::string mPropertyType;
|
std::string mPropertyType;
|
||||||
std::string mControllerType;
|
std::string mControllerType;
|
||||||
|
@ -60,7 +38,7 @@ namespace Nif
|
||||||
std::string mName;
|
std::string mName;
|
||||||
std::string mAccumRootName;
|
std::string mAccumRootName;
|
||||||
ExtraPtr mTextKeys;
|
ExtraPtr mTextKeys;
|
||||||
unsigned int mArrayGrowBy;
|
uint32_t mArrayGrowBy;
|
||||||
std::vector<ControlledBlock> mControlledBlocks;
|
std::vector<ControlledBlock> mControlledBlocks;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
|
@ -71,7 +49,7 @@ namespace Nif
|
||||||
struct NiControllerSequence : public NiSequence
|
struct NiControllerSequence : public NiSequence
|
||||||
{
|
{
|
||||||
float mWeight{ 1.f };
|
float mWeight{ 1.f };
|
||||||
Controller::ExtrapolationMode mExtrapolationMode{ Controller::ExtrapolationMode::Constant };
|
NiTimeController::ExtrapolationMode mExtrapolationMode{ NiTimeController::ExtrapolationMode::Constant };
|
||||||
float mFrequency{ 1.f };
|
float mFrequency{ 1.f };
|
||||||
float mPhase{ 1.f };
|
float mPhase{ 1.f };
|
||||||
float mStartTime, mStopTime;
|
float mStartTime, mStopTime;
|
||||||
|
@ -84,7 +62,7 @@ namespace Nif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base class for controllers that use NiInterpolators to animate objects.
|
// Base class for controllers that use NiInterpolators to animate objects.
|
||||||
struct NiInterpController : public Controller
|
struct NiInterpController : public NiTimeController
|
||||||
{
|
{
|
||||||
// Usually one of the flags.
|
// Usually one of the flags.
|
||||||
bool mManagerControlled{ false };
|
bool mManagerControlled{ false };
|
||||||
|
@ -116,7 +94,20 @@ namespace Nif
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiParticleSystemController : public Controller
|
struct NiParticleInfo
|
||||||
|
{
|
||||||
|
osg::Vec3f mVelocity;
|
||||||
|
osg::Vec3f mRotationAxis;
|
||||||
|
float mAge;
|
||||||
|
float mLifespan;
|
||||||
|
float mLastUpdate;
|
||||||
|
uint16_t mSpawnGeneration;
|
||||||
|
uint16_t mCode;
|
||||||
|
|
||||||
|
void read(NIFStream* nif);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NiParticleSystemController : public NiTimeController
|
||||||
{
|
{
|
||||||
enum BSPArrayController
|
enum BSPArrayController
|
||||||
{
|
{
|
||||||
|
@ -124,104 +115,113 @@ namespace Nif
|
||||||
BSPArrayController_AtVertex = 0x10
|
BSPArrayController_AtVertex = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Particle
|
|
||||||
{
|
|
||||||
osg::Vec3f velocity;
|
|
||||||
float lifetime;
|
|
||||||
float lifespan;
|
|
||||||
float timestamp;
|
|
||||||
unsigned short vertex;
|
|
||||||
};
|
|
||||||
|
|
||||||
float velocity;
|
|
||||||
float velocityRandom;
|
|
||||||
|
|
||||||
float verticalDir; // 0=up, pi/2=horizontal, pi=down
|
|
||||||
float verticalAngle;
|
|
||||||
float horizontalDir;
|
|
||||||
float horizontalAngle;
|
|
||||||
|
|
||||||
osg::Vec4f color;
|
|
||||||
float size;
|
|
||||||
float startTime;
|
|
||||||
float stopTime;
|
|
||||||
|
|
||||||
float emitRate;
|
|
||||||
float lifetime;
|
|
||||||
float lifetimeRandom;
|
|
||||||
|
|
||||||
enum EmitFlags
|
enum EmitFlags
|
||||||
{
|
{
|
||||||
EmitFlag_NoAutoAdjust = 0x1 // If this flag is set, we use the emitRate value. Otherwise,
|
EmitFlag_NoAutoAdjust = 0x1 // If this flag is set, we use the emitRate value. Otherwise,
|
||||||
// we calculate an emit rate so that the maximum number of particles
|
// we calculate an emit rate so that the maximum number of particles
|
||||||
// in the system (numParticles) is never exceeded.
|
// in the system (numParticles) is never exceeded.
|
||||||
};
|
};
|
||||||
int emitFlags;
|
|
||||||
|
|
||||||
osg::Vec3f offsetRandom;
|
float mSpeed;
|
||||||
|
float mSpeedVariation;
|
||||||
NiAVObjectPtr emitter;
|
float mDeclination;
|
||||||
|
float mDeclinationVariation;
|
||||||
int numParticles;
|
float mPlanarAngle;
|
||||||
int activeCount;
|
float mPlanarAngleVariation;
|
||||||
std::vector<Particle> particles;
|
osg::Vec3f mInitialNormal;
|
||||||
|
osg::Vec4f mInitialColor;
|
||||||
NiParticleModifierPtr affectors;
|
float mInitialSize;
|
||||||
NiParticleModifierPtr colliders;
|
float mEmitStartTime;
|
||||||
|
float mEmitStopTime;
|
||||||
|
bool mResetParticleSystem{ false };
|
||||||
|
float mBirthRate;
|
||||||
|
float mLifetime;
|
||||||
|
float mLifetimeVariation;
|
||||||
|
uint16_t mEmitFlags{ 0 };
|
||||||
|
osg::Vec3f mEmitterDimensions;
|
||||||
|
NiAVObjectPtr mEmitter;
|
||||||
|
uint16_t mNumSpawnGenerations;
|
||||||
|
float mPercentageSpawned;
|
||||||
|
uint16_t mSpawnMultiplier;
|
||||||
|
float mSpawnSpeedChaos;
|
||||||
|
float mSpawnDirChaos;
|
||||||
|
uint16_t mNumParticles;
|
||||||
|
uint16_t mNumValid;
|
||||||
|
std::vector<NiParticleInfo> mParticles;
|
||||||
|
NiParticleModifierPtr mModifier;
|
||||||
|
NiParticleModifierPtr mCollider;
|
||||||
|
uint8_t mStaticTargetBound;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
||||||
bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; }
|
bool noAutoAdjust() const { return mEmitFlags & EmitFlag_NoAutoAdjust; }
|
||||||
bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; }
|
bool emitAtVertex() const { return mFlags & BSPArrayController_AtVertex; }
|
||||||
};
|
};
|
||||||
using NiBSPArrayController = NiParticleSystemController;
|
using NiBSPArrayController = NiParticleSystemController;
|
||||||
|
|
||||||
struct NiMaterialColorController : public NiPoint3InterpController
|
struct NiMaterialColorController : public NiPoint3InterpController
|
||||||
{
|
{
|
||||||
NiPosDataPtr mData;
|
enum class TargetColor
|
||||||
unsigned int mTargetColor;
|
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
void post(Reader& nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiPathController : public Controller
|
|
||||||
{
|
|
||||||
NiPosDataPtr posData;
|
|
||||||
NiFloatDataPtr floatData;
|
|
||||||
|
|
||||||
enum Flags
|
|
||||||
{
|
{
|
||||||
Flag_OpenCurve = 0x020,
|
Ambient = 0,
|
||||||
Flag_AllowFlip = 0x040,
|
Diffuse = 1,
|
||||||
Flag_Bank = 0x080,
|
Specular = 2,
|
||||||
Flag_ConstVelocity = 0x100,
|
Emissive = 3,
|
||||||
Flag_Follow = 0x200,
|
|
||||||
Flag_FlipFollowAxis = 0x400
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int bankDir;
|
NiPosDataPtr mData;
|
||||||
float maxBankAngle, smoothing;
|
TargetColor mTargetColor;
|
||||||
short followAxis;
|
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiLookAtController : public Controller
|
struct NiPathController : public NiTimeController
|
||||||
{
|
{
|
||||||
NiAVObjectPtr target;
|
enum Flags
|
||||||
unsigned short lookAtFlags{ 0 };
|
{
|
||||||
|
Flag_CVDataNeedsUpdate = 0x01,
|
||||||
|
Flag_OpenCurve = 0x02,
|
||||||
|
Flag_AllowFlip = 0x04,
|
||||||
|
Flag_Bank = 0x08,
|
||||||
|
Flag_ConstVelocity = 0x10,
|
||||||
|
Flag_Follow = 0x20,
|
||||||
|
Flag_FlipFollowAxis = 0x40,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t mPathFlags;
|
||||||
|
int32_t mBankDirection;
|
||||||
|
float mMaxBankAngle;
|
||||||
|
float mSmoothing;
|
||||||
|
uint16_t mFollowAxis;
|
||||||
|
NiPosDataPtr mPathData;
|
||||||
|
NiFloatDataPtr mPercentData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiUVController : public Controller
|
struct NiLookAtController : public NiTimeController
|
||||||
{
|
{
|
||||||
NiUVDataPtr data;
|
enum Flags
|
||||||
unsigned int uvSet;
|
{
|
||||||
|
Flag_Flip = 0x1,
|
||||||
|
Flag_LookYAxis = 0x2,
|
||||||
|
Flag_LookZAxis = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t mLookAtFlags{ 0 };
|
||||||
|
NiAVObjectPtr mLookAt;
|
||||||
|
|
||||||
|
void read(NIFStream* nif) override;
|
||||||
|
void post(Reader& nif) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NiUVController : public NiTimeController
|
||||||
|
{
|
||||||
|
NiUVDataPtr mData;
|
||||||
|
uint16_t mUvSet;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
|
@ -281,7 +281,7 @@ namespace Nif
|
||||||
|
|
||||||
struct NiFlipController : public NiFloatInterpController
|
struct NiFlipController : public NiFloatInterpController
|
||||||
{
|
{
|
||||||
int mTexSlot; // NiTexturingProperty::TextureType
|
NiTexturingProperty::TextureType mTexSlot;
|
||||||
float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources
|
float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources
|
||||||
NiSourceTextureList mSources;
|
NiSourceTextureList mSources;
|
||||||
|
|
||||||
|
@ -292,110 +292,95 @@ namespace Nif
|
||||||
struct NiTextureTransformController : public NiFloatInterpController
|
struct NiTextureTransformController : public NiFloatInterpController
|
||||||
{
|
{
|
||||||
bool mShaderMap;
|
bool mShaderMap;
|
||||||
int mTexSlot; // NiTexturingProperty::TextureType
|
NiTexturingProperty::TextureType mTexSlot;
|
||||||
unsigned int mTransformMember;
|
uint32_t mTransformMember;
|
||||||
NiFloatDataPtr mData;
|
NiFloatDataPtr mData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bhkBlendController : public Controller
|
struct bhkBlendController : public NiTimeController
|
||||||
{
|
{
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSEffectShaderPropertyFloatController : public NiFloatInterpController
|
struct BSEffectShaderPropertyFloatController : public NiFloatInterpController
|
||||||
{
|
{
|
||||||
unsigned int mControlledVariable;
|
uint32_t mControlledVariable;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSEffectShaderPropertyColorController : public NiPoint3InterpController
|
struct BSEffectShaderPropertyColorController : public NiPoint3InterpController
|
||||||
{
|
{
|
||||||
unsigned int mControlledColor;
|
uint32_t mControlledColor;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiControllerManager : public Controller
|
struct NiControllerManager : public NiTimeController
|
||||||
{
|
{
|
||||||
bool mCumulative;
|
bool mCumulative;
|
||||||
NiControllerSequenceList mSequences;
|
NiControllerSequenceList mSequences;
|
||||||
NiDefaultAVObjectPalettePtr mObjectPalette;
|
NiDefaultAVObjectPalettePtr mObjectPalette;
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
void post(Reader& nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiInterpolator : public Record
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiPoint3Interpolator : public NiInterpolator
|
|
||||||
{
|
|
||||||
osg::Vec3f defaultVal;
|
|
||||||
NiPosDataPtr data;
|
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
void post(Reader& nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiBoolInterpolator : public NiInterpolator
|
|
||||||
{
|
|
||||||
char defaultVal;
|
|
||||||
NiBoolDataPtr data;
|
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
void post(Reader& nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiFloatInterpolator : public NiInterpolator
|
|
||||||
{
|
|
||||||
float defaultVal;
|
|
||||||
NiFloatDataPtr data;
|
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
void post(Reader& nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiTransformInterpolator : public NiInterpolator
|
|
||||||
{
|
|
||||||
osg::Vec3f defaultPos;
|
|
||||||
osg::Quat defaultRot;
|
|
||||||
float defaultScale;
|
|
||||||
NiKeyframeDataPtr data;
|
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
void post(Reader& nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NiColorInterpolator : public NiInterpolator
|
|
||||||
{
|
|
||||||
osg::Vec4f defaultVal;
|
|
||||||
NiColorDataPtr data;
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Abstract
|
||||||
|
struct NiInterpolator : public Record
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class DataPtr>
|
||||||
|
struct TypedNiInterpolator : public NiInterpolator
|
||||||
|
{
|
||||||
|
T mDefaultValue;
|
||||||
|
DataPtr mData;
|
||||||
|
|
||||||
|
void read(NIFStream* nif) override
|
||||||
|
{
|
||||||
|
nif->read(mDefaultValue);
|
||||||
|
mData.read(nif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void post(Reader& nif) override { mData.post(nif); }
|
||||||
|
};
|
||||||
|
|
||||||
|
using NiPoint3Interpolator = TypedNiInterpolator<osg::Vec3f, NiPosDataPtr>;
|
||||||
|
using NiBoolInterpolator = TypedNiInterpolator<bool, NiBoolDataPtr>;
|
||||||
|
using NiFloatInterpolator = TypedNiInterpolator<float, NiFloatDataPtr>;
|
||||||
|
using NiTransformInterpolator = TypedNiInterpolator<NiQuatTransform, NiKeyframeDataPtr>;
|
||||||
|
using NiColorInterpolator = TypedNiInterpolator<osg::Vec4f, NiColorDataPtr>;
|
||||||
|
|
||||||
// Abstract
|
// Abstract
|
||||||
struct NiBlendInterpolator : public NiInterpolator
|
struct NiBlendInterpolator : public NiInterpolator
|
||||||
{
|
{
|
||||||
|
enum Flags
|
||||||
|
{
|
||||||
|
Flag_ManagerControlled = 0x1,
|
||||||
|
Flag_OnlyUseHighestWeight = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
NiInterpolatorPtr mInterpolator;
|
NiInterpolatorPtr mInterpolator;
|
||||||
float mWeight, mNormalizedWeight;
|
float mWeight, mNormalizedWeight;
|
||||||
int mPriority;
|
int32_t mPriority;
|
||||||
float mEaseSpinner;
|
float mEaseSpinner;
|
||||||
|
|
||||||
void read(NIFStream* nif);
|
void read(NIFStream* nif);
|
||||||
void post(Reader& nif);
|
void post(Reader& nif);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mManagerControlled{ false };
|
uint8_t mFlags{ 0 };
|
||||||
bool mOnlyUseHighestWeight{ false };
|
uint16_t mArrayGrowBy{ 0 };
|
||||||
unsigned short mArrayGrowBy{ 0 };
|
|
||||||
float mWeightThreshold;
|
float mWeightThreshold;
|
||||||
unsigned short mInterpCount;
|
uint16_t mInterpCount;
|
||||||
unsigned short mSingleIndex;
|
uint16_t mSingleIndex;
|
||||||
int mHighPriority, mNextHighPriority;
|
int32_t mHighPriority, mNextHighPriority;
|
||||||
float mSingleTime;
|
float mSingleTime;
|
||||||
float mHighWeightsSum, mNextHighWeightsSum;
|
float mHighWeightsSum, mNextHighWeightsSum;
|
||||||
float mHighEaseSpinner;
|
float mHighEaseSpinner;
|
||||||
|
@ -406,31 +391,37 @@ namespace Nif
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiBlendBoolInterpolator : public NiBlendInterpolator
|
template <typename T>
|
||||||
|
struct TypedNiBlendInterpolator : public NiBlendInterpolator
|
||||||
{
|
{
|
||||||
char mValue;
|
T mValue;
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
|
void read(NIFStream* nif) override
|
||||||
|
{
|
||||||
|
NiBlendInterpolator::read(nif);
|
||||||
|
|
||||||
|
nif->read(mValue);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiBlendFloatInterpolator : public NiBlendInterpolator
|
template <>
|
||||||
|
struct TypedNiBlendInterpolator<NiQuatTransform> : public NiBlendInterpolator
|
||||||
{
|
{
|
||||||
float mValue;
|
NiQuatTransform mValue;
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
|
void read(NIFStream* nif) override
|
||||||
|
{
|
||||||
|
NiBlendInterpolator::read(nif);
|
||||||
|
|
||||||
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109))
|
||||||
|
nif->read(mValue);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiBlendPoint3Interpolator : public NiBlendInterpolator
|
using NiBlendBoolInterpolator = TypedNiBlendInterpolator<uint8_t>;
|
||||||
{
|
using NiBlendFloatInterpolator = TypedNiBlendInterpolator<float>;
|
||||||
osg::Vec3f mValue;
|
using NiBlendPoint3Interpolator = TypedNiBlendInterpolator<osg::Vec3f>;
|
||||||
void read(NIFStream* nif) override;
|
using NiBlendTransformInterpolator = TypedNiBlendInterpolator<NiQuatTransform>;
|
||||||
};
|
|
||||||
|
|
||||||
struct NiBlendTransformInterpolator : public NiBlendInterpolator
|
}
|
||||||
{
|
|
||||||
osg::Vec3f mPosValue;
|
|
||||||
osg::Quat mRotValue;
|
|
||||||
float mScaleValue;
|
|
||||||
void read(NIFStream* nif) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Namespace
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -528,7 +528,7 @@ namespace Nif
|
||||||
|
|
||||||
void NiBoolData::read(NIFStream* nif)
|
void NiBoolData::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
mKeyList = std::make_shared<ByteKeyMap>();
|
mKeyList = std::make_shared<BoolKeyMap>();
|
||||||
mKeyList->read(nif);
|
mKeyList->read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ namespace Nif
|
||||||
|
|
||||||
struct NiVisData : public Record
|
struct NiVisData : public Record
|
||||||
{
|
{
|
||||||
// TODO: investigate possible use of ByteKeyMap
|
// TODO: investigate possible use of BoolKeyMap
|
||||||
std::shared_ptr<std::map<float, bool>> mKeys;
|
std::shared_ptr<std::map<float, bool>> mKeys;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
|
@ -357,7 +357,8 @@ namespace Nif
|
||||||
|
|
||||||
struct NiBoolData : public Record
|
struct NiBoolData : public Record
|
||||||
{
|
{
|
||||||
ByteKeyMapPtr mKeyList;
|
BoolKeyMapPtr mKeyList;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -152,13 +152,13 @@ namespace Nif
|
||||||
using Vector3KeyMap = KeyMapT<osg::Vec3f, &NIFStream::get<osg::Vec3f>>;
|
using Vector3KeyMap = KeyMapT<osg::Vec3f, &NIFStream::get<osg::Vec3f>>;
|
||||||
using Vector4KeyMap = KeyMapT<osg::Vec4f, &NIFStream::get<osg::Vec4f>>;
|
using Vector4KeyMap = KeyMapT<osg::Vec4f, &NIFStream::get<osg::Vec4f>>;
|
||||||
using QuaternionKeyMap = KeyMapT<osg::Quat, &NIFStream::get<osg::Quat>>;
|
using QuaternionKeyMap = KeyMapT<osg::Quat, &NIFStream::get<osg::Quat>>;
|
||||||
using ByteKeyMap = KeyMapT<char, &NIFStream::get<char>>;
|
using BoolKeyMap = KeyMapT<bool, &NIFStream::get<bool>>;
|
||||||
|
|
||||||
using FloatKeyMapPtr = std::shared_ptr<FloatKeyMap>;
|
using FloatKeyMapPtr = std::shared_ptr<FloatKeyMap>;
|
||||||
using Vector3KeyMapPtr = std::shared_ptr<Vector3KeyMap>;
|
using Vector3KeyMapPtr = std::shared_ptr<Vector3KeyMap>;
|
||||||
using Vector4KeyMapPtr = std::shared_ptr<Vector4KeyMap>;
|
using Vector4KeyMapPtr = std::shared_ptr<Vector4KeyMap>;
|
||||||
using QuaternionKeyMapPtr = std::shared_ptr<QuaternionKeyMap>;
|
using QuaternionKeyMapPtr = std::shared_ptr<QuaternionKeyMap>;
|
||||||
using ByteKeyMapPtr = std::shared_ptr<ByteKeyMap>;
|
using BoolKeyMapPtr = std::shared_ptr<BoolKeyMap>;
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
||||||
|
|
|
@ -137,6 +137,22 @@ namespace Nif
|
||||||
read(transform.mScale);
|
read(transform.mScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void NIFStream::read<NiQuatTransform>(NiQuatTransform& transform)
|
||||||
|
{
|
||||||
|
read(transform.mTranslation);
|
||||||
|
read(transform.mRotation);
|
||||||
|
read(transform.mScale);
|
||||||
|
if (getVersion() >= generateVersion(10, 1, 0, 110))
|
||||||
|
return;
|
||||||
|
if (!get<bool>())
|
||||||
|
transform.mTranslation = osg::Vec3f();
|
||||||
|
if (!get<bool>())
|
||||||
|
transform.mRotation = osg::Quat();
|
||||||
|
if (!get<bool>())
|
||||||
|
transform.mScale = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void NIFStream::read<bool>(bool& data)
|
void NIFStream::read<bool>(bool& data)
|
||||||
{
|
{
|
||||||
|
@ -197,6 +213,12 @@ namespace Nif
|
||||||
readRange(*this, dest, size);
|
readRange(*this, dest, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void NIFStream::read<NiQuatTransform>(NiQuatTransform* dest, size_t size)
|
||||||
|
{
|
||||||
|
readRange(*this, dest, size);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void NIFStream::read<bool>(bool* dest, size_t size)
|
void NIFStream::read<bool>(bool* dest, size_t size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -149,7 +149,6 @@ namespace Nif
|
||||||
|
|
||||||
/// DEPRECATED: Use read() or get()
|
/// DEPRECATED: Use read() or get()
|
||||||
char getChar() { return get<char>(); }
|
char getChar() { return get<char>(); }
|
||||||
short getShort() { return get<short>(); }
|
|
||||||
unsigned short getUShort() { return get<unsigned short>(); }
|
unsigned short getUShort() { return get<unsigned short>(); }
|
||||||
int getInt() { return get<int>(); }
|
int getInt() { return get<int>(); }
|
||||||
unsigned int getUInt() { return get<unsigned int>(); }
|
unsigned int getUInt() { return get<unsigned int>(); }
|
||||||
|
@ -157,10 +156,6 @@ namespace Nif
|
||||||
osg::Vec2f getVector2() { return get<osg::Vec2f>(); }
|
osg::Vec2f getVector2() { return get<osg::Vec2f>(); }
|
||||||
osg::Vec3f getVector3() { return get<osg::Vec3f>(); }
|
osg::Vec3f getVector3() { return get<osg::Vec3f>(); }
|
||||||
osg::Vec4f getVector4() { return get<osg::Vec4f>(); }
|
osg::Vec4f getVector4() { return get<osg::Vec4f>(); }
|
||||||
Matrix3 getMatrix3() { return get<Matrix3>(); }
|
|
||||||
osg::Quat getQuaternion() { return get<osg::Quat>(); }
|
|
||||||
bool getBoolean() { return get<bool>(); }
|
|
||||||
std::string getString() { return get<std::string>(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -178,6 +173,8 @@ namespace Nif
|
||||||
template <>
|
template <>
|
||||||
void NIFStream::read<NiTransform>(NiTransform& transform);
|
void NIFStream::read<NiTransform>(NiTransform& transform);
|
||||||
template <>
|
template <>
|
||||||
|
void NIFStream::read<NiQuatTransform>(NiQuatTransform& transform);
|
||||||
|
template <>
|
||||||
void NIFStream::read<bool>(bool& data);
|
void NIFStream::read<bool>(bool& data);
|
||||||
template <>
|
template <>
|
||||||
void NIFStream::read<std::string>(std::string& str);
|
void NIFStream::read<std::string>(std::string& str);
|
||||||
|
@ -197,6 +194,8 @@ namespace Nif
|
||||||
template <>
|
template <>
|
||||||
void NIFStream::read<NiTransform>(NiTransform* dest, size_t size);
|
void NIFStream::read<NiTransform>(NiTransform* dest, size_t size);
|
||||||
template <>
|
template <>
|
||||||
|
void NIFStream::read<NiQuatTransform>(NiQuatTransform* dest, size_t size);
|
||||||
|
template <>
|
||||||
void NIFStream::read<bool>(bool* dest, size_t size);
|
void NIFStream::read<bool>(bool* dest, size_t size);
|
||||||
template <>
|
template <>
|
||||||
void NIFStream::read<std::string>(std::string* dest, size_t size);
|
void NIFStream::read<std::string>(std::string* dest, size_t size);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define OPENMW_COMPONENTS_NIF_NIFTYPES_HPP
|
#define OPENMW_COMPONENTS_NIF_NIFTYPES_HPP
|
||||||
|
|
||||||
#include <osg/Matrixf>
|
#include <osg/Matrixf>
|
||||||
|
#include <osg/Quat>
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
// Common types used in NIF files
|
// Common types used in NIF files
|
||||||
|
@ -80,5 +81,30 @@ namespace Nif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NiQuatTransform
|
||||||
|
{
|
||||||
|
osg::Vec3f mTranslation;
|
||||||
|
osg::Quat mRotation;
|
||||||
|
float mScale;
|
||||||
|
|
||||||
|
osg::Matrixf toMatrix() const
|
||||||
|
{
|
||||||
|
osg::Matrixf transform(mRotation);
|
||||||
|
transform.setTrans(mTranslation);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
transform(i, i) *= mScale;
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIdentity() const { return mTranslation == osg::Vec3f() && mRotation == osg::Quat() && mScale == 1.f; }
|
||||||
|
|
||||||
|
static const NiQuatTransform& getIdentity()
|
||||||
|
{
|
||||||
|
static const NiQuatTransform identity = { osg::Vec3f(), osg::Quat(), 1.f };
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Nif
|
||||||
case BOX_BV:
|
case BOX_BV:
|
||||||
{
|
{
|
||||||
box.center = nif->getVector3();
|
box.center = nif->getVector3();
|
||||||
box.axes = nif->getMatrix3();
|
nif->read(box.axes);
|
||||||
box.extents = nif->getVector3();
|
box.extents = nif->getVector3();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -153,8 +153,8 @@ namespace Nif
|
||||||
if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0))
|
if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0))
|
||||||
return;
|
return;
|
||||||
unsigned int num = 0;
|
unsigned int num = 0;
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 3))
|
if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 3) && nif->get<bool>())
|
||||||
num = nif->getBoolean(); // Has Shader
|
num = 1;
|
||||||
else if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
|
else if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
|
||||||
num = nif->getUInt();
|
num = nif->getUInt();
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ namespace Nif
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
|
if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
|
||||||
active = nif->getUInt();
|
active = nif->getUInt();
|
||||||
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
|
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
|
||||||
needsUpdate = nif->getBoolean();
|
nif->read(needsUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiGeometry::read(NIFStream* nif)
|
void NiGeometry::read(NIFStream* nif)
|
||||||
|
@ -210,7 +210,7 @@ namespace Nif
|
||||||
nearDist = nif->getFloat();
|
nearDist = nif->getFloat();
|
||||||
farDist = nif->getFloat();
|
farDist = nif->getFloat();
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
||||||
orthographic = nif->getBoolean();
|
nif->read(orthographic);
|
||||||
vleft = nif->getFloat();
|
vleft = nif->getFloat();
|
||||||
vright = nif->getFloat();
|
vright = nif->getFloat();
|
||||||
vtop = nif->getFloat();
|
vtop = nif->getFloat();
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Nif
|
||||||
struct NiParticleModifier : public Record
|
struct NiParticleModifier : public Record
|
||||||
{
|
{
|
||||||
NiParticleModifierPtr mNext;
|
NiParticleModifierPtr mNext;
|
||||||
ControllerPtr mController;
|
NiTimeControllerPtr mController;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Nif
|
||||||
|
|
||||||
void NiTexturingProperty::Texture::read(NIFStream* nif)
|
void NiTexturingProperty::Texture::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
inUse = nif->getBoolean();
|
nif->read(inUse);
|
||||||
if (!inUse)
|
if (!inUse)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace Nif
|
||||||
nif->skip(2); // Unknown short
|
nif->skip(2); // Unknown short
|
||||||
else if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
else if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
||||||
{
|
{
|
||||||
if (nif->getBoolean()) // Has texture transform
|
if (nif->get<bool>()) // Has texture transform
|
||||||
{
|
{
|
||||||
nif->getVector2(); // UV translation
|
nif->getVector2(); // UV translation
|
||||||
nif->getVector2(); // UV scale
|
nif->getVector2(); // UV scale
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace Nif
|
||||||
* 5 - Bump map texture
|
* 5 - Bump map texture
|
||||||
* 6 - Decal texture
|
* 6 - Decal texture
|
||||||
*/
|
*/
|
||||||
enum TextureType
|
enum TextureType : uint32_t
|
||||||
{
|
{
|
||||||
BaseTexture = 0,
|
BaseTexture = 0,
|
||||||
DarkTexture = 1,
|
DarkTexture = 1,
|
||||||
|
|
|
@ -116,7 +116,7 @@ namespace Nif
|
||||||
struct NiUVData;
|
struct NiUVData;
|
||||||
struct NiPosData;
|
struct NiPosData;
|
||||||
struct NiVisData;
|
struct NiVisData;
|
||||||
struct Controller;
|
struct NiTimeController;
|
||||||
struct NiObjectNET;
|
struct NiObjectNET;
|
||||||
struct NiSkinData;
|
struct NiSkinData;
|
||||||
struct NiFloatData;
|
struct NiFloatData;
|
||||||
|
@ -157,7 +157,7 @@ namespace Nif
|
||||||
using NiUVDataPtr = RecordPtrT<NiUVData>;
|
using NiUVDataPtr = RecordPtrT<NiUVData>;
|
||||||
using NiPosDataPtr = RecordPtrT<NiPosData>;
|
using NiPosDataPtr = RecordPtrT<NiPosData>;
|
||||||
using NiVisDataPtr = RecordPtrT<NiVisData>;
|
using NiVisDataPtr = RecordPtrT<NiVisData>;
|
||||||
using ControllerPtr = RecordPtrT<Controller>;
|
using NiTimeControllerPtr = RecordPtrT<NiTimeController>;
|
||||||
using NiObjectNETPtr = RecordPtrT<NiObjectNET>;
|
using NiObjectNETPtr = RecordPtrT<NiObjectNET>;
|
||||||
using NiSkinDataPtr = RecordPtrT<NiSkinData>;
|
using NiSkinDataPtr = RecordPtrT<NiSkinData>;
|
||||||
using NiMorphDataPtr = RecordPtrT<NiMorphData>;
|
using NiMorphDataPtr = RecordPtrT<NiMorphData>;
|
||||||
|
|
|
@ -255,7 +255,7 @@ namespace NifBullet
|
||||||
if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive())
|
if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (Nif::ControllerPtr ctrl = node.mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = node.mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (args.mAnimated)
|
if (args.mAnimated)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
namespace NifOsg
|
namespace NifOsg
|
||||||
{
|
{
|
||||||
|
|
||||||
ControllerFunction::ControllerFunction(const Nif::Controller* ctrl)
|
ControllerFunction::ControllerFunction(const Nif::NiTimeController* ctrl)
|
||||||
: mFrequency(ctrl->frequency)
|
: mFrequency(ctrl->mFrequency)
|
||||||
, mPhase(ctrl->phase)
|
, mPhase(ctrl->mPhase)
|
||||||
, mStartTime(ctrl->timeStart)
|
, mStartTime(ctrl->mTimeStart)
|
||||||
, mStopTime(ctrl->timeStop)
|
, mStopTime(ctrl->mTimeStop)
|
||||||
, mExtrapolationMode(ctrl->extrapolationMode())
|
, mExtrapolationMode(ctrl->extrapolationMode())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace NifOsg
|
||||||
return time;
|
return time;
|
||||||
switch (mExtrapolationMode)
|
switch (mExtrapolationMode)
|
||||||
{
|
{
|
||||||
case Nif::Controller::ExtrapolationMode::Cycle:
|
case Nif::NiTimeController::ExtrapolationMode::Cycle:
|
||||||
{
|
{
|
||||||
float delta = mStopTime - mStartTime;
|
float delta = mStopTime - mStartTime;
|
||||||
if (delta <= 0)
|
if (delta <= 0)
|
||||||
|
@ -40,7 +40,7 @@ namespace NifOsg
|
||||||
float remainder = (cycles - std::floor(cycles)) * delta;
|
float remainder = (cycles - std::floor(cycles)) * delta;
|
||||||
return mStartTime + remainder;
|
return mStartTime + remainder;
|
||||||
}
|
}
|
||||||
case Nif::Controller::ExtrapolationMode::Reverse:
|
case Nif::NiTimeController::ExtrapolationMode::Reverse:
|
||||||
{
|
{
|
||||||
float delta = mStopTime - mStartTime;
|
float delta = mStopTime - mStartTime;
|
||||||
if (delta <= 0)
|
if (delta <= 0)
|
||||||
|
@ -55,7 +55,7 @@ namespace NifOsg
|
||||||
|
|
||||||
return mStopTime - remainder;
|
return mStopTime - remainder;
|
||||||
}
|
}
|
||||||
case Nif::Controller::ExtrapolationMode::Constant:
|
case Nif::NiTimeController::ExtrapolationMode::Constant:
|
||||||
default:
|
default:
|
||||||
return std::clamp(time, mStartTime, mStopTime);
|
return std::clamp(time, mStartTime, mStopTime);
|
||||||
}
|
}
|
||||||
|
@ -90,21 +90,23 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
const Nif::NiTransformInterpolator* interp
|
const Nif::NiTransformInterpolator* interp
|
||||||
= static_cast<const Nif::NiTransformInterpolator*>(keyctrl->mInterpolator.getPtr());
|
= static_cast<const Nif::NiTransformInterpolator*>(keyctrl->mInterpolator.getPtr());
|
||||||
if (!interp->data.empty())
|
const Nif::NiQuatTransform& defaultTransform = interp->mDefaultValue;
|
||||||
|
if (!interp->mData.empty())
|
||||||
{
|
{
|
||||||
mRotations = QuaternionInterpolator(interp->data->mRotations, interp->defaultRot);
|
mRotations = QuaternionInterpolator(interp->mData->mRotations, defaultTransform.mRotation);
|
||||||
mXRotations = FloatInterpolator(interp->data->mXRotations);
|
mXRotations = FloatInterpolator(interp->mData->mXRotations);
|
||||||
mYRotations = FloatInterpolator(interp->data->mYRotations);
|
mYRotations = FloatInterpolator(interp->mData->mYRotations);
|
||||||
mZRotations = FloatInterpolator(interp->data->mZRotations);
|
mZRotations = FloatInterpolator(interp->mData->mZRotations);
|
||||||
mTranslations = Vec3Interpolator(interp->data->mTranslations, interp->defaultPos);
|
mTranslations = Vec3Interpolator(interp->mData->mTranslations, defaultTransform.mTranslation);
|
||||||
mScales = FloatInterpolator(interp->data->mScales, interp->defaultScale);
|
mScales = FloatInterpolator(interp->mData->mScales, defaultTransform.mScale);
|
||||||
mAxisOrder = interp->data->mAxisOrder;
|
|
||||||
|
mAxisOrder = interp->mData->mAxisOrder;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mRotations = QuaternionInterpolator(Nif::QuaternionKeyMapPtr(), interp->defaultRot);
|
mRotations = QuaternionInterpolator(Nif::QuaternionKeyMapPtr(), defaultTransform.mRotation);
|
||||||
mTranslations = Vec3Interpolator(Nif::Vector3KeyMapPtr(), interp->defaultPos);
|
mTranslations = Vec3Interpolator(Nif::Vector3KeyMapPtr(), defaultTransform.mTranslation);
|
||||||
mScales = FloatInterpolator(Nif::FloatKeyMapPtr(), interp->defaultScale);
|
mScales = FloatInterpolator(Nif::FloatKeyMapPtr(), defaultTransform.mScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +119,7 @@ namespace NifOsg
|
||||||
mZRotations = FloatInterpolator(keydata->mZRotations);
|
mZRotations = FloatInterpolator(keydata->mZRotations);
|
||||||
mTranslations = Vec3Interpolator(keydata->mTranslations);
|
mTranslations = Vec3Interpolator(keydata->mTranslations);
|
||||||
mScales = FloatInterpolator(keydata->mScales, 1.f);
|
mScales = FloatInterpolator(keydata->mScales, 1.f);
|
||||||
|
|
||||||
mAxisOrder = keydata->mAxisOrder;
|
mAxisOrder = keydata->mAxisOrder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,11 +180,11 @@ namespace NifOsg
|
||||||
else
|
else
|
||||||
node->setRotation(node->mRotationScale);
|
node->setRotation(node->mRotationScale);
|
||||||
|
|
||||||
if (!mScales.empty())
|
|
||||||
node->setScale(mScales.interpKey(time));
|
|
||||||
|
|
||||||
if (!mTranslations.empty())
|
if (!mTranslations.empty())
|
||||||
node->setTranslation(mTranslations.interpKey(time));
|
node->setTranslation(mTranslations.interpKey(time));
|
||||||
|
|
||||||
|
if (!mScales.empty())
|
||||||
|
node->setScale(mScales.interpKey(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
|
@ -251,9 +254,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UVController::UVController() {}
|
UVController::UVController(const Nif::NiUVData* data, const std::set<unsigned int>& textureUnits)
|
||||||
|
|
||||||
UVController::UVController(const Nif::NiUVData* data, const std::set<int>& textureUnits)
|
|
||||||
: mUTrans(data->mKeyList[0], 0.f)
|
: mUTrans(data->mKeyList[0], 0.f)
|
||||||
, mVTrans(data->mKeyList[1], 0.f)
|
, mVTrans(data->mKeyList[1], 0.f)
|
||||||
, mUScale(data->mKeyList[2], 1.f)
|
, mUScale(data->mKeyList[2], 1.f)
|
||||||
|
@ -277,8 +278,8 @@ namespace NifOsg
|
||||||
void UVController::setDefaults(osg::StateSet* stateset)
|
void UVController::setDefaults(osg::StateSet* stateset)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::TexMat> texMat(new osg::TexMat);
|
osg::ref_ptr<osg::TexMat> texMat(new osg::TexMat);
|
||||||
for (std::set<int>::const_iterator it = mTextureUnits.begin(); it != mTextureUnits.end(); ++it)
|
for (unsigned int unit : mTextureUnits)
|
||||||
stateset->setTextureAttributeAndModes(*it, texMat, osg::StateAttribute::ON);
|
stateset->setTextureAttributeAndModes(unit, texMat, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UVController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
|
void UVController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
|
||||||
|
@ -314,9 +315,10 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
if (!ctrl->mInterpolator.empty())
|
if (!ctrl->mInterpolator.empty())
|
||||||
{
|
{
|
||||||
if (ctrl->mInterpolator->recType == Nif::RC_NiBoolInterpolator)
|
if (ctrl->mInterpolator->recType != Nif::RC_NiBoolInterpolator)
|
||||||
mInterpolator
|
return;
|
||||||
= ByteInterpolator(static_cast<const Nif::NiBoolInterpolator*>(ctrl->mInterpolator.getPtr()));
|
|
||||||
|
mInterpolator = { static_cast<const Nif::NiBoolInterpolator*>(ctrl->mInterpolator.getPtr()) };
|
||||||
}
|
}
|
||||||
else if (!ctrl->mData.empty())
|
else if (!ctrl->mData.empty())
|
||||||
mData = ctrl->mData->mKeys;
|
mData = ctrl->mData->mKeys;
|
||||||
|
@ -444,7 +446,7 @@ namespace NifOsg
|
||||||
|
|
||||||
MaterialColorController::MaterialColorController(
|
MaterialColorController::MaterialColorController(
|
||||||
const Nif::NiMaterialColorController* ctrl, const osg::Material* baseMaterial)
|
const Nif::NiMaterialColorController* ctrl, const osg::Material* baseMaterial)
|
||||||
: mTargetColor(static_cast<MaterialColorController::TargetColor>(ctrl->mTargetColor))
|
: mTargetColor(ctrl->mTargetColor)
|
||||||
, mBaseMaterial(baseMaterial)
|
, mBaseMaterial(baseMaterial)
|
||||||
{
|
{
|
||||||
if (!ctrl->mInterpolator.empty())
|
if (!ctrl->mInterpolator.empty())
|
||||||
|
@ -477,30 +479,31 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
osg::Vec3f value = mData.interpKey(getInputValue(nv));
|
osg::Vec3f value = mData.interpKey(getInputValue(nv));
|
||||||
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
||||||
|
using TargetColor = Nif::NiMaterialColorController::TargetColor;
|
||||||
switch (mTargetColor)
|
switch (mTargetColor)
|
||||||
{
|
{
|
||||||
case Diffuse:
|
case TargetColor::Diffuse:
|
||||||
{
|
{
|
||||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||||
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
||||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Specular:
|
case TargetColor::Specular:
|
||||||
{
|
{
|
||||||
osg::Vec4f specular = mat->getSpecular(osg::Material::FRONT_AND_BACK);
|
osg::Vec4f specular = mat->getSpecular(osg::Material::FRONT_AND_BACK);
|
||||||
specular.set(value.x(), value.y(), value.z(), specular.a());
|
specular.set(value.x(), value.y(), value.z(), specular.a());
|
||||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, specular);
|
mat->setSpecular(osg::Material::FRONT_AND_BACK, specular);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Emissive:
|
case TargetColor::Emissive:
|
||||||
{
|
{
|
||||||
osg::Vec4f emissive = mat->getEmission(osg::Material::FRONT_AND_BACK);
|
osg::Vec4f emissive = mat->getEmission(osg::Material::FRONT_AND_BACK);
|
||||||
emissive.set(value.x(), value.y(), value.z(), emissive.a());
|
emissive.set(value.x(), value.y(), value.z(), emissive.a());
|
||||||
mat->setEmission(osg::Material::FRONT_AND_BACK, emissive);
|
mat->setEmission(osg::Material::FRONT_AND_BACK, emissive);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Ambient:
|
case TargetColor::Ambient:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
osg::Vec4f ambient = mat->getAmbient(osg::Material::FRONT_AND_BACK);
|
osg::Vec4f ambient = mat->getAmbient(osg::Material::FRONT_AND_BACK);
|
||||||
|
@ -552,14 +555,8 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleSystemController::ParticleSystemController(const Nif::NiParticleSystemController* ctrl)
|
ParticleSystemController::ParticleSystemController(const Nif::NiParticleSystemController* ctrl)
|
||||||
: mEmitStart(ctrl->startTime)
|
: mEmitStart(ctrl->mEmitStartTime)
|
||||||
, mEmitStop(ctrl->stopTime)
|
, mEmitStop(ctrl->mEmitStopTime)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticleSystemController::ParticleSystemController()
|
|
||||||
: mEmitStart(0.f)
|
|
||||||
, mEmitStop(0.f)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,9 +591,9 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
PathController::PathController(const Nif::NiPathController* ctrl)
|
PathController::PathController(const Nif::NiPathController* ctrl)
|
||||||
: mPath(ctrl->posData->mKeyList, osg::Vec3f())
|
: mPath(ctrl->mPathData->mKeyList, osg::Vec3f())
|
||||||
, mPercent(ctrl->floatData->mKeyList, 1.f)
|
, mPercent(ctrl->mPercentData->mKeyList, 1.f)
|
||||||
, mFlags(ctrl->flags)
|
, mFlags(ctrl->mPathFlags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,18 +63,17 @@ namespace NifOsg
|
||||||
ValueInterpolator() = default;
|
ValueInterpolator() = default;
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
typename
|
typename = std::enable_if_t<
|
||||||
= std::enable_if_t<std::conjunction_v<std::disjunction<std::is_same<ValueT, float>,
|
std::conjunction_v<std::disjunction<std::is_same<ValueT, float>, std::is_same<ValueT, osg::Vec3f>,
|
||||||
std::is_same<ValueT, osg::Vec3f>, std::is_same<ValueT, bool>,
|
std::is_same<ValueT, bool>, std::is_same<ValueT, osg::Vec4f>>,
|
||||||
std::is_same<ValueT, osg::Vec4f>, std::is_same<ValueT, char>>,
|
std::is_same<decltype(T::mDefaultValue), ValueT>>,
|
||||||
std::is_same<decltype(T::defaultVal), ValueT>>,
|
|
||||||
T>>
|
T>>
|
||||||
ValueInterpolator(const T* interpolator)
|
ValueInterpolator(const T* interpolator)
|
||||||
: mDefaultVal(interpolator->defaultVal)
|
: mDefaultVal(interpolator->mDefaultValue)
|
||||||
{
|
{
|
||||||
if (interpolator->data.empty())
|
if (interpolator->mData.empty())
|
||||||
return;
|
return;
|
||||||
mKeys = interpolator->data->mKeyList;
|
mKeys = interpolator->mData->mKeyList;
|
||||||
if (mKeys)
|
if (mKeys)
|
||||||
{
|
{
|
||||||
mLastLowKey = mKeys->mKeys.end();
|
mLastLowKey = mKeys->mKeys.end();
|
||||||
|
@ -182,7 +181,7 @@ namespace NifOsg
|
||||||
using FloatInterpolator = ValueInterpolator<Nif::FloatKeyMap>;
|
using FloatInterpolator = ValueInterpolator<Nif::FloatKeyMap>;
|
||||||
using Vec3Interpolator = ValueInterpolator<Nif::Vector3KeyMap>;
|
using Vec3Interpolator = ValueInterpolator<Nif::Vector3KeyMap>;
|
||||||
using Vec4Interpolator = ValueInterpolator<Nif::Vector4KeyMap>;
|
using Vec4Interpolator = ValueInterpolator<Nif::Vector4KeyMap>;
|
||||||
using ByteInterpolator = ValueInterpolator<Nif::ByteKeyMap>;
|
using BoolInterpolator = ValueInterpolator<Nif::BoolKeyMap>;
|
||||||
|
|
||||||
class ControllerFunction : public SceneUtil::ControllerFunction
|
class ControllerFunction : public SceneUtil::ControllerFunction
|
||||||
{
|
{
|
||||||
|
@ -191,10 +190,10 @@ namespace NifOsg
|
||||||
float mPhase;
|
float mPhase;
|
||||||
float mStartTime;
|
float mStartTime;
|
||||||
float mStopTime;
|
float mStopTime;
|
||||||
Nif::Controller::ExtrapolationMode mExtrapolationMode;
|
Nif::NiTimeController::ExtrapolationMode mExtrapolationMode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ControllerFunction(const Nif::Controller* ctrl);
|
ControllerFunction(const Nif::NiTimeController* ctrl);
|
||||||
|
|
||||||
float calculate(float value) const override;
|
float calculate(float value) const override;
|
||||||
|
|
||||||
|
@ -262,9 +261,9 @@ namespace NifOsg
|
||||||
class UVController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
class UVController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UVController();
|
UVController() = default;
|
||||||
UVController(const UVController&, const osg::CopyOp&);
|
UVController(const UVController&, const osg::CopyOp&);
|
||||||
UVController(const Nif::NiUVData* data, const std::set<int>& textureUnits);
|
UVController(const Nif::NiUVData* data, const std::set<unsigned int>& textureUnits);
|
||||||
|
|
||||||
META_Object(NifOsg, UVController)
|
META_Object(NifOsg, UVController)
|
||||||
|
|
||||||
|
@ -276,14 +275,14 @@ namespace NifOsg
|
||||||
FloatInterpolator mVTrans;
|
FloatInterpolator mVTrans;
|
||||||
FloatInterpolator mUScale;
|
FloatInterpolator mUScale;
|
||||||
FloatInterpolator mVScale;
|
FloatInterpolator mVScale;
|
||||||
std::set<int> mTextureUnits;
|
std::set<unsigned int> mTextureUnits;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VisController : public SceneUtil::NodeCallback<VisController>, public SceneUtil::Controller
|
class VisController : public SceneUtil::NodeCallback<VisController>, public SceneUtil::Controller
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<std::map<float, bool>> mData;
|
std::shared_ptr<std::map<float, bool>> mData;
|
||||||
ByteInterpolator mInterpolator;
|
BoolInterpolator mInterpolator;
|
||||||
unsigned int mMask{ 0u };
|
unsigned int mMask{ 0u };
|
||||||
|
|
||||||
bool calculate(float time) const;
|
bool calculate(float time) const;
|
||||||
|
@ -336,13 +335,6 @@ namespace NifOsg
|
||||||
class MaterialColorController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
class MaterialColorController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum TargetColor
|
|
||||||
{
|
|
||||||
Ambient = 0,
|
|
||||||
Diffuse = 1,
|
|
||||||
Specular = 2,
|
|
||||||
Emissive = 3
|
|
||||||
};
|
|
||||||
MaterialColorController(const Nif::NiMaterialColorController* ctrl, const osg::Material* baseMaterial);
|
MaterialColorController(const Nif::NiMaterialColorController* ctrl, const osg::Material* baseMaterial);
|
||||||
MaterialColorController();
|
MaterialColorController();
|
||||||
MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop);
|
MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop);
|
||||||
|
@ -355,7 +347,7 @@ namespace NifOsg
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vec3Interpolator mData;
|
Vec3Interpolator mData;
|
||||||
TargetColor mTargetColor = Ambient;
|
Nif::NiMaterialColorController::TargetColor mTargetColor;
|
||||||
osg::ref_ptr<const osg::Material> mBaseMaterial;
|
osg::ref_ptr<const osg::Material> mBaseMaterial;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -386,7 +378,7 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ParticleSystemController(const Nif::NiParticleSystemController* ctrl);
|
ParticleSystemController(const Nif::NiParticleSystemController* ctrl);
|
||||||
ParticleSystemController();
|
ParticleSystemController() = default;
|
||||||
ParticleSystemController(const ParticleSystemController& copy, const osg::CopyOp& copyop);
|
ParticleSystemController(const ParticleSystemController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
META_Object(NifOsg, ParticleSystemController)
|
META_Object(NifOsg, ParticleSystemController)
|
||||||
|
@ -394,8 +386,8 @@ namespace NifOsg
|
||||||
void operator()(osgParticle::ParticleProcessor* node, osg::NodeVisitor* nv);
|
void operator()(osgParticle::ParticleProcessor* node, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mEmitStart;
|
float mEmitStart{ 0.f };
|
||||||
float mEmitStop;
|
float mEmitStop{ 0.f };
|
||||||
};
|
};
|
||||||
|
|
||||||
class PathController : public SceneUtil::NodeCallback<PathController, NifOsg::MatrixTransform*>,
|
class PathController : public SceneUtil::NodeCallback<PathController, NifOsg::MatrixTransform*>,
|
||||||
|
|
|
@ -293,8 +293,8 @@ namespace NifOsg
|
||||||
auto textKeyExtraData = static_cast<const Nif::NiTextKeyExtraData*>(extraList[0].getPtr());
|
auto textKeyExtraData = static_cast<const Nif::NiTextKeyExtraData*>(extraList[0].getPtr());
|
||||||
extractTextKeys(textKeyExtraData, target.mTextKeys);
|
extractTextKeys(textKeyExtraData, target.mTextKeys);
|
||||||
|
|
||||||
Nif::ControllerPtr ctrl = seq->mController;
|
Nif::NiTimeControllerPtr ctrl = seq->mController;
|
||||||
for (size_t i = 1; i < extraList.size() && !ctrl.empty(); i++, (ctrl = ctrl->next))
|
for (size_t i = 1; i < extraList.size() && !ctrl.empty(); i++, (ctrl = ctrl->mNext))
|
||||||
{
|
{
|
||||||
Nif::ExtraPtr extra = extraList[i];
|
Nif::ExtraPtr extra = extraList[i];
|
||||||
if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController)
|
if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController)
|
||||||
|
@ -449,7 +449,7 @@ namespace NifOsg
|
||||||
animflags, hasStencilProperty);
|
animflags, hasStencilProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setupController(const Nif::Controller* ctrl, SceneUtil::Controller* toSetup, int animflags)
|
static void setupController(const Nif::NiTimeController* ctrl, SceneUtil::Controller* toSetup, int animflags)
|
||||||
{
|
{
|
||||||
bool autoPlay = animflags & Nif::NiNode::AnimFlag_AutoPlay;
|
bool autoPlay = animflags & Nif::NiNode::AnimFlag_AutoPlay;
|
||||||
if (autoPlay)
|
if (autoPlay)
|
||||||
|
@ -725,7 +725,7 @@ namespace NifOsg
|
||||||
if (nifNode->isHidden())
|
if (nifNode->isHidden())
|
||||||
{
|
{
|
||||||
bool hasVisController = false;
|
bool hasVisController = false;
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
hasVisController |= (ctrl->recType == Nif::RC_NiVisController);
|
hasVisController |= (ctrl->recType == Nif::RC_NiVisController);
|
||||||
if (hasVisController)
|
if (hasVisController)
|
||||||
|
@ -858,25 +858,24 @@ namespace NifOsg
|
||||||
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
|
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
|
||||||
int animflags)
|
int animflags)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (!ctrl->isActive())
|
if (!ctrl->isActive())
|
||||||
continue;
|
continue;
|
||||||
if (ctrl->recType == Nif::RC_NiUVController)
|
if (ctrl->recType == Nif::RC_NiUVController)
|
||||||
{
|
{
|
||||||
const Nif::NiUVController* niuvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
const Nif::NiUVController* niuvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
||||||
if (niuvctrl->data.empty())
|
if (niuvctrl->mData.empty())
|
||||||
continue;
|
continue;
|
||||||
const unsigned int uvSet = niuvctrl->uvSet;
|
std::set<unsigned int> texUnits;
|
||||||
std::set<int> texUnits;
|
// UVController should only work for textures which use the given UV Set.
|
||||||
// UVController should work only for textures which use a given UV Set, usually 0.
|
|
||||||
for (unsigned int i = 0; i < boundTextures.size(); ++i)
|
for (unsigned int i = 0; i < boundTextures.size(); ++i)
|
||||||
{
|
{
|
||||||
if (boundTextures[i] == uvSet)
|
if (boundTextures[i] == niuvctrl->mUvSet)
|
||||||
texUnits.insert(i);
|
texUnits.insert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<UVController> uvctrl = new UVController(niuvctrl->data.getPtr(), texUnits);
|
osg::ref_ptr<UVController> uvctrl = new UVController(niuvctrl->mData.getPtr(), texUnits);
|
||||||
setupController(niuvctrl, uvctrl, animflags);
|
setupController(niuvctrl, uvctrl, animflags);
|
||||||
composite->addController(uvctrl);
|
composite->addController(uvctrl);
|
||||||
}
|
}
|
||||||
|
@ -885,7 +884,7 @@ namespace NifOsg
|
||||||
|
|
||||||
void handleNodeControllers(const Nif::NiAVObject* nifNode, osg::Node* node, int animflags, bool& isAnimated)
|
void handleNodeControllers(const Nif::NiAVObject* nifNode, osg::Node* node, int animflags, bool& isAnimated)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (!ctrl->isActive())
|
if (!ctrl->isActive())
|
||||||
continue;
|
continue;
|
||||||
|
@ -908,7 +907,7 @@ namespace NifOsg
|
||||||
else if (ctrl->recType == Nif::RC_NiPathController)
|
else if (ctrl->recType == Nif::RC_NiPathController)
|
||||||
{
|
{
|
||||||
const Nif::NiPathController* path = static_cast<const Nif::NiPathController*>(ctrl.getPtr());
|
const Nif::NiPathController* path = static_cast<const Nif::NiPathController*>(ctrl.getPtr());
|
||||||
if (path->posData.empty() || path->floatData.empty())
|
if (path->mPathData.empty() || path->mPercentData.empty())
|
||||||
continue;
|
continue;
|
||||||
osg::ref_ptr<PathController> callback(new PathController(path));
|
osg::ref_ptr<PathController> callback(new PathController(path));
|
||||||
setupController(path, callback, animflags);
|
setupController(path, callback, animflags);
|
||||||
|
@ -963,7 +962,7 @@ namespace NifOsg
|
||||||
void handleMaterialControllers(const Nif::Property* materialProperty,
|
void handleMaterialControllers(const Nif::Property* materialProperty,
|
||||||
SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial)
|
SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (!ctrl->isActive())
|
if (!ctrl->isActive())
|
||||||
continue;
|
continue;
|
||||||
|
@ -988,18 +987,16 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
const Nif::NiMaterialColorController* matctrl
|
const Nif::NiMaterialColorController* matctrl
|
||||||
= static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
|
= static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
|
||||||
if (matctrl->mData.empty() && matctrl->mInterpolator.empty())
|
Nif::NiInterpolatorPtr interp = matctrl->mInterpolator;
|
||||||
|
if (matctrl->mData.empty() && interp.empty())
|
||||||
continue;
|
continue;
|
||||||
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->mTargetColor);
|
|
||||||
if (mVersion <= Nif::NIFFile::VER_MW
|
if (mVersion <= Nif::NIFFile::VER_MW
|
||||||
&& targetColor == MaterialColorController::TargetColor::Specular)
|
&& matctrl->mTargetColor == Nif::NiMaterialColorController::TargetColor::Specular)
|
||||||
continue;
|
continue;
|
||||||
if (!matctrl->mInterpolator.empty()
|
if (!interp.empty() && interp->recType != Nif::RC_NiPoint3Interpolator)
|
||||||
&& matctrl->mInterpolator->recType != Nif::RC_NiPoint3Interpolator)
|
|
||||||
{
|
{
|
||||||
Log(Debug::Error)
|
Log(Debug::Error) << "Unsupported interpolator type for NiMaterialColorController "
|
||||||
<< "Unsupported interpolator type for NiMaterialColorController " << matctrl->recIndex
|
<< matctrl->recIndex << " in " << mFilename << ": " << interp->recName;
|
||||||
<< " in " << mFilename << ": " << matctrl->mInterpolator->recName;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
osg::ref_ptr<MaterialColorController> osgctrl = new MaterialColorController(matctrl, baseMaterial);
|
osg::ref_ptr<MaterialColorController> osgctrl = new MaterialColorController(matctrl, baseMaterial);
|
||||||
|
@ -1014,7 +1011,7 @@ namespace NifOsg
|
||||||
void handleTextureControllers(const Nif::Property* texProperty, SceneUtil::CompositeStateSetUpdater* composite,
|
void handleTextureControllers(const Nif::Property* texProperty, SceneUtil::CompositeStateSetUpdater* composite,
|
||||||
Resource::ImageManager* imageManager, osg::StateSet* stateset, int animflags)
|
Resource::ImageManager* imageManager, osg::StateSet* stateset, int animflags)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (!ctrl->isActive())
|
if (!ctrl->isActive())
|
||||||
continue;
|
continue;
|
||||||
|
@ -1063,7 +1060,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleParticlePrograms(Nif::NiParticleModifierPtr affectors, Nif::NiParticleModifierPtr colliders,
|
void handleParticlePrograms(Nif::NiParticleModifierPtr modifier, Nif::NiParticleModifierPtr collider,
|
||||||
osg::Group* attachTo, osgParticle::ParticleSystem* partsys,
|
osg::Group* attachTo, osgParticle::ParticleSystem* partsys,
|
||||||
osgParticle::ParticleProcessor::ReferenceFrame rf)
|
osgParticle::ParticleProcessor::ReferenceFrame rf)
|
||||||
{
|
{
|
||||||
|
@ -1071,50 +1068,50 @@ namespace NifOsg
|
||||||
attachTo->addChild(program);
|
attachTo->addChild(program);
|
||||||
program->setParticleSystem(partsys);
|
program->setParticleSystem(partsys);
|
||||||
program->setReferenceFrame(rf);
|
program->setReferenceFrame(rf);
|
||||||
for (; !affectors.empty(); affectors = affectors->mNext)
|
for (; !modifier.empty(); modifier = modifier->mNext)
|
||||||
{
|
{
|
||||||
if (affectors->recType == Nif::RC_NiParticleGrowFade)
|
if (modifier->recType == Nif::RC_NiParticleGrowFade)
|
||||||
{
|
{
|
||||||
const Nif::NiParticleGrowFade* gf = static_cast<const Nif::NiParticleGrowFade*>(affectors.getPtr());
|
const Nif::NiParticleGrowFade* gf = static_cast<const Nif::NiParticleGrowFade*>(modifier.getPtr());
|
||||||
program->addOperator(new GrowFadeAffector(gf->mGrowTime, gf->mFadeTime));
|
program->addOperator(new GrowFadeAffector(gf->mGrowTime, gf->mFadeTime));
|
||||||
}
|
}
|
||||||
else if (affectors->recType == Nif::RC_NiGravity)
|
else if (modifier->recType == Nif::RC_NiGravity)
|
||||||
{
|
{
|
||||||
const Nif::NiGravity* gr = static_cast<const Nif::NiGravity*>(affectors.getPtr());
|
const Nif::NiGravity* gr = static_cast<const Nif::NiGravity*>(modifier.getPtr());
|
||||||
program->addOperator(new GravityAffector(gr));
|
program->addOperator(new GravityAffector(gr));
|
||||||
}
|
}
|
||||||
else if (affectors->recType == Nif::RC_NiParticleColorModifier)
|
else if (modifier->recType == Nif::RC_NiParticleColorModifier)
|
||||||
{
|
{
|
||||||
const Nif::NiParticleColorModifier* cl
|
const Nif::NiParticleColorModifier* cl
|
||||||
= static_cast<const Nif::NiParticleColorModifier*>(affectors.getPtr());
|
= static_cast<const Nif::NiParticleColorModifier*>(modifier.getPtr());
|
||||||
if (cl->mData.empty())
|
if (cl->mData.empty())
|
||||||
continue;
|
continue;
|
||||||
const Nif::NiColorData* clrdata = cl->mData.getPtr();
|
const Nif::NiColorData* clrdata = cl->mData.getPtr();
|
||||||
program->addOperator(new ParticleColorAffector(clrdata));
|
program->addOperator(new ParticleColorAffector(clrdata));
|
||||||
}
|
}
|
||||||
else if (affectors->recType == Nif::RC_NiParticleRotation)
|
else if (modifier->recType == Nif::RC_NiParticleRotation)
|
||||||
{
|
{
|
||||||
// unused
|
// unused
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Log(Debug::Info) << "Unhandled particle modifier " << affectors->recName << " in " << mFilename;
|
Log(Debug::Info) << "Unhandled particle modifier " << modifier->recName << " in " << mFilename;
|
||||||
}
|
}
|
||||||
for (; !colliders.empty(); colliders = colliders->mNext)
|
for (; !collider.empty(); collider = collider->mNext)
|
||||||
{
|
{
|
||||||
if (colliders->recType == Nif::RC_NiPlanarCollider)
|
if (collider->recType == Nif::RC_NiPlanarCollider)
|
||||||
{
|
{
|
||||||
const Nif::NiPlanarCollider* planarcollider
|
const Nif::NiPlanarCollider* planarcollider
|
||||||
= static_cast<const Nif::NiPlanarCollider*>(colliders.getPtr());
|
= static_cast<const Nif::NiPlanarCollider*>(collider.getPtr());
|
||||||
program->addOperator(new PlanarCollider(planarcollider));
|
program->addOperator(new PlanarCollider(planarcollider));
|
||||||
}
|
}
|
||||||
else if (colliders->recType == Nif::RC_NiSphericalCollider)
|
else if (collider->recType == Nif::RC_NiSphericalCollider)
|
||||||
{
|
{
|
||||||
const Nif::NiSphericalCollider* sphericalcollider
|
const Nif::NiSphericalCollider* sphericalcollider
|
||||||
= static_cast<const Nif::NiSphericalCollider*>(colliders.getPtr());
|
= static_cast<const Nif::NiSphericalCollider*>(collider.getPtr());
|
||||||
program->addOperator(new SphericalCollider(sphericalcollider));
|
program->addOperator(new SphericalCollider(sphericalcollider));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Log(Debug::Info) << "Unhandled particle collider " << colliders->recName << " in " << mFilename;
|
Log(Debug::Info) << "Unhandled particle collider " << collider->recName << " in " << mFilename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,7 +1123,7 @@ namespace NifOsg
|
||||||
auto particleNode = static_cast<const Nif::NiParticles*>(nifNode);
|
auto particleNode = static_cast<const Nif::NiParticles*>(nifNode);
|
||||||
if (particleNode->data.empty() || particleNode->data->recType != Nif::RC_NiParticlesData)
|
if (particleNode->data.empty() || particleNode->data->recType != Nif::RC_NiParticlesData)
|
||||||
{
|
{
|
||||||
partsys->setQuota(partctrl->numParticles);
|
partsys->setQuota(partctrl->mParticles.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1136,35 +1133,35 @@ namespace NifOsg
|
||||||
osg::BoundingBox box;
|
osg::BoundingBox box;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& particle : partctrl->particles)
|
for (const auto& particle : partctrl->mParticles)
|
||||||
{
|
{
|
||||||
if (i++ >= particledata->mActiveCount)
|
if (i++ >= particledata->mActiveCount)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (particle.lifespan <= 0)
|
if (particle.mLifespan <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (particle.vertex >= particledata->mVertices.size())
|
if (particle.mCode >= particledata->mVertices.size())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ParticleAgeSetter particletemplate(std::max(0.f, particle.lifetime));
|
ParticleAgeSetter particletemplate(std::max(0.f, particle.mAge));
|
||||||
|
|
||||||
osgParticle::Particle* created = partsys->createParticle(&particletemplate);
|
osgParticle::Particle* created = partsys->createParticle(&particletemplate);
|
||||||
created->setLifeTime(particle.lifespan);
|
created->setLifeTime(particle.mLifespan);
|
||||||
|
|
||||||
// Note this position and velocity is not correct for a particle system with absolute reference frame,
|
// Note this position and velocity is not correct for a particle system with absolute reference frame,
|
||||||
// which can not be done in this loader since we are not attached to the scene yet. Will be fixed up
|
// which can not be done in this loader since we are not attached to the scene yet. Will be fixed up
|
||||||
// post-load in the SceneManager.
|
// post-load in the SceneManager.
|
||||||
created->setVelocity(particle.velocity);
|
created->setVelocity(particle.mVelocity);
|
||||||
const osg::Vec3f& position = particledata->mVertices[particle.vertex];
|
const osg::Vec3f& position = particledata->mVertices[particle.mCode];
|
||||||
created->setPosition(position);
|
created->setPosition(position);
|
||||||
|
|
||||||
created->setColorRange(osgParticle::rangev4(partctrl->color, partctrl->color));
|
created->setColorRange(osgParticle::rangev4(partctrl->mInitialColor, partctrl->mInitialColor));
|
||||||
created->setAlphaRange(osgParticle::rangef(1.f, 1.f));
|
created->setAlphaRange(osgParticle::rangef(1.f, 1.f));
|
||||||
|
|
||||||
float size = partctrl->size;
|
float size = partctrl->mInitialSize;
|
||||||
if (particle.vertex < particledata->mSizes.size())
|
if (particle.mCode < particledata->mSizes.size())
|
||||||
size *= particledata->mSizes[particle.vertex];
|
size *= particledata->mSizes[particle.mCode];
|
||||||
|
|
||||||
created->setSizeRange(osgParticle::rangef(size, size));
|
created->setSizeRange(osgParticle::rangef(size, size));
|
||||||
box.expandBy(osg::BoundingSphere(position, size));
|
box.expandBy(osg::BoundingSphere(position, size));
|
||||||
|
@ -1181,39 +1178,39 @@ namespace NifOsg
|
||||||
std::vector<int> targets;
|
std::vector<int> targets;
|
||||||
if (partctrl->recType == Nif::RC_NiBSPArrayController && !partctrl->emitAtVertex())
|
if (partctrl->recType == Nif::RC_NiBSPArrayController && !partctrl->emitAtVertex())
|
||||||
{
|
{
|
||||||
getAllNiNodes(partctrl->emitter.getPtr(), targets);
|
getAllNiNodes(partctrl->mEmitter.getPtr(), targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<Emitter> emitter = new Emitter(targets);
|
osg::ref_ptr<Emitter> emitter = new Emitter(targets);
|
||||||
|
|
||||||
osgParticle::ConstantRateCounter* counter = new osgParticle::ConstantRateCounter;
|
osgParticle::ConstantRateCounter* counter = new osgParticle::ConstantRateCounter;
|
||||||
if (partctrl->noAutoAdjust())
|
if (partctrl->noAutoAdjust())
|
||||||
counter->setNumberOfParticlesPerSecondToCreate(partctrl->emitRate);
|
counter->setNumberOfParticlesPerSecondToCreate(partctrl->mBirthRate);
|
||||||
else if (partctrl->lifetime == 0 && partctrl->lifetimeRandom == 0)
|
else if (partctrl->mLifetime == 0 && partctrl->mLifetimeVariation == 0)
|
||||||
counter->setNumberOfParticlesPerSecondToCreate(0);
|
counter->setNumberOfParticlesPerSecondToCreate(0);
|
||||||
else
|
else
|
||||||
counter->setNumberOfParticlesPerSecondToCreate(
|
counter->setNumberOfParticlesPerSecondToCreate(
|
||||||
partctrl->numParticles / (partctrl->lifetime + partctrl->lifetimeRandom / 2));
|
partctrl->mParticles.size() / (partctrl->mLifetime + partctrl->mLifetimeVariation / 2));
|
||||||
|
|
||||||
emitter->setCounter(counter);
|
emitter->setCounter(counter);
|
||||||
|
|
||||||
ParticleShooter* shooter = new ParticleShooter(partctrl->velocity - partctrl->velocityRandom * 0.5f,
|
ParticleShooter* shooter = new ParticleShooter(partctrl->mSpeed - partctrl->mSpeedVariation * 0.5f,
|
||||||
partctrl->velocity + partctrl->velocityRandom * 0.5f, partctrl->horizontalDir,
|
partctrl->mSpeed + partctrl->mSpeedVariation * 0.5f, partctrl->mPlanarAngle,
|
||||||
partctrl->horizontalAngle, partctrl->verticalDir, partctrl->verticalAngle, partctrl->lifetime,
|
partctrl->mPlanarAngleVariation, partctrl->mDeclination, partctrl->mDeclinationVariation,
|
||||||
partctrl->lifetimeRandom);
|
partctrl->mLifetime, partctrl->mLifetimeVariation);
|
||||||
emitter->setShooter(shooter);
|
emitter->setShooter(shooter);
|
||||||
emitter->setFlags(partctrl->flags);
|
emitter->setFlags(partctrl->mFlags);
|
||||||
|
|
||||||
if (partctrl->recType == Nif::RC_NiBSPArrayController && partctrl->emitAtVertex())
|
if (partctrl->recType == Nif::RC_NiBSPArrayController && partctrl->emitAtVertex())
|
||||||
{
|
{
|
||||||
emitter->setGeometryEmitterTarget(partctrl->emitter->recIndex);
|
emitter->setGeometryEmitterTarget(partctrl->mEmitter->recIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osgParticle::BoxPlacer* placer = new osgParticle::BoxPlacer;
|
osgParticle::BoxPlacer* placer = new osgParticle::BoxPlacer;
|
||||||
placer->setXRange(-partctrl->offsetRandom.x() / 2.f, partctrl->offsetRandom.x() / 2.f);
|
placer->setXRange(-partctrl->mEmitterDimensions.x() / 2.f, partctrl->mEmitterDimensions.x() / 2.f);
|
||||||
placer->setYRange(-partctrl->offsetRandom.y() / 2.f, partctrl->offsetRandom.y() / 2.f);
|
placer->setYRange(-partctrl->mEmitterDimensions.y() / 2.f, partctrl->mEmitterDimensions.y() / 2.f);
|
||||||
placer->setZRange(-partctrl->offsetRandom.z() / 2.f, partctrl->offsetRandom.z() / 2.f);
|
placer->setZRange(-partctrl->mEmitterDimensions.z() / 2.f, partctrl->mEmitterDimensions.z() / 2.f);
|
||||||
emitter->setPlacer(placer);
|
emitter->setPlacer(placer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1254,7 +1251,7 @@ namespace NifOsg
|
||||||
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
||||||
|
|
||||||
const Nif::NiParticleSystemController* partctrl = nullptr;
|
const Nif::NiParticleSystemController* partctrl = nullptr;
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (!ctrl->isActive())
|
if (!ctrl->isActive())
|
||||||
continue;
|
continue;
|
||||||
|
@ -1282,11 +1279,13 @@ namespace NifOsg
|
||||||
|
|
||||||
handleParticleInitialState(nifNode, partsys, partctrl);
|
handleParticleInitialState(nifNode, partsys, partctrl);
|
||||||
|
|
||||||
partsys->getDefaultParticleTemplate().setSizeRange(osgParticle::rangef(partctrl->size, partctrl->size));
|
partsys->getDefaultParticleTemplate().setSizeRange(
|
||||||
partsys->getDefaultParticleTemplate().setColorRange(osgParticle::rangev4(partctrl->color, partctrl->color));
|
osgParticle::rangef(partctrl->mInitialSize, partctrl->mInitialSize));
|
||||||
|
partsys->getDefaultParticleTemplate().setColorRange(
|
||||||
|
osgParticle::rangev4(partctrl->mInitialColor, partctrl->mInitialColor));
|
||||||
partsys->getDefaultParticleTemplate().setAlphaRange(osgParticle::rangef(1.f, 1.f));
|
partsys->getDefaultParticleTemplate().setAlphaRange(osgParticle::rangef(1.f, 1.f));
|
||||||
|
|
||||||
if (!partctrl->emitter.empty())
|
if (!partctrl->mEmitter.empty())
|
||||||
{
|
{
|
||||||
osg::ref_ptr<Emitter> emitter = handleParticleEmitter(partctrl);
|
osg::ref_ptr<Emitter> emitter = handleParticleEmitter(partctrl);
|
||||||
emitter->setParticleSystem(partsys);
|
emitter->setParticleSystem(partsys);
|
||||||
|
@ -1295,7 +1294,7 @@ namespace NifOsg
|
||||||
// The emitter node may not actually be handled yet, so let's delay attaching the emitter to a later
|
// The emitter node may not actually be handled yet, so let's delay attaching the emitter to a later
|
||||||
// moment. If the emitter node is placed later than the particle node, it'll have a single frame delay
|
// moment. If the emitter node is placed later than the particle node, it'll have a single frame delay
|
||||||
// in particle processing. But that shouldn't be a game-breaking issue.
|
// in particle processing. But that shouldn't be a game-breaking issue.
|
||||||
mEmitterQueue.emplace_back(partctrl->emitter->recIndex, emitter);
|
mEmitterQueue.emplace_back(partctrl->mEmitter->recIndex, emitter);
|
||||||
|
|
||||||
osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl));
|
osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl));
|
||||||
setupController(partctrl, callback, animflags);
|
setupController(partctrl, callback, animflags);
|
||||||
|
@ -1312,16 +1311,16 @@ namespace NifOsg
|
||||||
partsys->update(0.0, nv);
|
partsys->update(0.0, nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// affectors should be attached *after* the emitter in the scene graph for correct update order
|
// modifiers should be attached *after* the emitter in the scene graph for correct update order
|
||||||
// attach to same node as the ParticleSystem, we need osgParticle Operators to get the correct
|
// attach to same node as the ParticleSystem, we need osgParticle Operators to get the correct
|
||||||
// localToWorldMatrix for transforming to particle space
|
// localToWorldMatrix for transforming to particle space
|
||||||
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
|
handleParticlePrograms(partctrl->mModifier, partctrl->mCollider, parentNode, partsys.get(), rf);
|
||||||
|
|
||||||
std::vector<const Nif::Property*> drawableProps;
|
std::vector<const Nif::Property*> drawableProps;
|
||||||
collectDrawableProperties(nifNode, parent, drawableProps);
|
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||||
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
||||||
|
|
||||||
// particle system updater (after the emitters and affectors in the scene graph)
|
// particle system updater (after the emitters and modifiers in the scene graph)
|
||||||
// I think for correct culling needs to be *before* the ParticleSystem, though osg examples do it the other
|
// I think for correct culling needs to be *before* the ParticleSystem, though osg examples do it the other
|
||||||
// way
|
// way
|
||||||
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater = new osgParticle::ParticleSystemUpdater;
|
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater = new osgParticle::ParticleSystemUpdater;
|
||||||
|
@ -1485,7 +1484,7 @@ namespace NifOsg
|
||||||
if (geom->empty())
|
if (geom->empty())
|
||||||
return;
|
return;
|
||||||
osg::ref_ptr<osg::Drawable> drawable;
|
osg::ref_ptr<osg::Drawable> drawable;
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||||
{
|
{
|
||||||
if (!ctrl->isActive())
|
if (!ctrl->isActive())
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue