1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 19:15:41 +00:00

Further controller updates

Correct NiMaterialColorController base class
Load everything in NiGeomMorpherController
Make a guess at how weighted interpolators might be supposed to work like
This commit is contained in:
Alexei Kotov 2022-09-16 23:45:54 +03:00
parent cd8b20439e
commit 7aee22be91
6 changed files with 60 additions and 38 deletions

View file

@ -113,7 +113,7 @@ namespace Nif
void NiMaterialColorController::read(NIFStream *nif) void NiMaterialColorController::read(NIFStream *nif)
{ {
NiSingleInterpController::read(nif); NiPoint3InterpController::read(nif);
// Two bits that correspond to the controlled material color. // Two bits that correspond to the controlled material color.
// 00: Ambient // 00: Ambient
// 01: Diffuse // 01: Diffuse
@ -129,7 +129,7 @@ namespace Nif
void NiMaterialColorController::post(NIFFile *nif) void NiMaterialColorController::post(NIFFile *nif)
{ {
NiSingleInterpController::post(nif); NiPoint3InterpController::post(nif);
mData.post(nif); mData.post(nif);
} }
@ -241,16 +241,16 @@ namespace Nif
{ {
NiInterpController::read(nif); NiInterpController::read(nif);
if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD) if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD)
/*bool updateNormals = !!*/nif->getUShort(); mUpdateNormals = nif->getUShort() & 1;
data.read(nif); mData.read(nif);
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW)
{ {
/*bool alwaysActive = */nif->getChar(); // Always 0 mAlwaysActive = nif->getChar();
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,106))
{ {
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{ {
interpolators.read(nif); mInterpolators.read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0) && nif->getBethVersion() > 9) if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0) && nif->getBethVersion() > 9)
{ {
unsigned int numUnknown = nif->getUInt(); unsigned int numUnknown = nif->getUInt();
@ -259,9 +259,16 @@ namespace Nif
} }
else else
{ {
// TODO: handle weighted interpolators std::vector<NiInterpolatorPtr> interpolators;
unsigned int numInterps = nif->getUInt(); size_t numInterps = nif->getUInt();
nif->skip(8 * numInterps); interpolators.resize(numInterps);
mWeights.resize(numInterps);
for (size_t i = 0; i < numInterps; i++)
{
interpolators[i].read(nif);
mWeights[i] = nif->getFloat();
}
mInterpolators = interpolators;
} }
} }
} }
@ -270,8 +277,8 @@ namespace Nif
void NiGeomMorpherController::post(NIFFile *nif) void NiGeomMorpherController::post(NIFFile *nif)
{ {
NiInterpController::post(nif); NiInterpController::post(nif);
data.post(nif); mData.post(nif);
interpolators.post(nif); mInterpolators.post(nif);
} }
void NiVisController::read(NIFStream *nif) void NiVisController::read(NIFStream *nif)

View file

@ -47,6 +47,15 @@ struct NiSingleInterpController : public NiInterpController
void post(NIFFile* nif) override; void post(NIFFile* nif) override;
}; };
// Base class for controllers that use a NiFloatInterpolator to animate their target.
struct NiFloatInterpController : public NiSingleInterpController { };
// Ditto for NiBoolInterpolator.
struct NiBoolInterpController : public NiSingleInterpController { };
// Ditto for NiPoint3Interpolator.
struct NiPoint3InterpController : public NiSingleInterpController { };
struct NiParticleSystemController : public Controller struct NiParticleSystemController : public Controller
{ {
enum BSPArrayController { enum BSPArrayController {
@ -106,7 +115,7 @@ struct NiParticleSystemController : public Controller
}; };
using NiBSPArrayController = NiParticleSystemController; using NiBSPArrayController = NiParticleSystemController;
struct NiMaterialColorController : public NiSingleInterpController struct NiMaterialColorController : public NiPoint3InterpController
{ {
NiPosDataPtr mData; NiPosDataPtr mData;
unsigned int mTargetColor; unsigned int mTargetColor;
@ -172,12 +181,6 @@ struct NiMultiTargetTransformController : public NiInterpController
void post(NIFFile *nif) override; void post(NIFFile *nif) override;
}; };
// Base class for controllers that use a NiFloatInterpolator to animate their target.
struct NiFloatInterpController : public NiSingleInterpController { };
// Ditto for NiBoolInterpolator.
struct NiBoolInterpController : public NiSingleInterpController { };
struct NiAlphaController : public NiFloatInterpController struct NiAlphaController : public NiFloatInterpController
{ {
NiFloatDataPtr mData; NiFloatDataPtr mData;
@ -196,8 +199,11 @@ struct NiRollController : public NiSingleInterpController
struct NiGeomMorpherController : public NiInterpController struct NiGeomMorpherController : public NiInterpController
{ {
NiMorphDataPtr data; bool mUpdateNormals{false};
NiFloatInterpolatorList interpolators; bool mAlwaysActive{false};
NiMorphDataPtr mData;
NiInterpolatorList mInterpolators;
std::vector<float> mWeights;
void read(NIFStream *nif) override; void read(NIFStream *nif) override;
void post(NIFFile *nif) override; void post(NIFFile *nif) override;

View file

@ -152,7 +152,6 @@ struct bhkSerializable;
struct hkPackedNiTriStripsData; struct hkPackedNiTriStripsData;
struct NiAccumulator; struct NiAccumulator;
struct NiInterpolator; struct NiInterpolator;
struct NiFloatInterpolator;
using NodePtr = RecordPtrT<Node>; using NodePtr = RecordPtrT<Node>;
using ExtraPtr = RecordPtrT<Extra>; using ExtraPtr = RecordPtrT<Extra>;
@ -188,7 +187,7 @@ using NodeList = RecordListT<Node>;
using PropertyList = RecordListT<Property>; using PropertyList = RecordListT<Property>;
using ExtraList = RecordListT<Extra>; using ExtraList = RecordListT<Extra>;
using NiSourceTextureList = RecordListT<NiSourceTexture>; using NiSourceTextureList = RecordListT<NiSourceTexture>;
using NiFloatInterpolatorList = RecordListT<NiFloatInterpolator>; using NiInterpolatorList = RecordListT<NiInterpolator>;
using NiTriStripsDataList = RecordListT<NiTriStripsData>; using NiTriStripsDataList = RecordListT<NiTriStripsData>;
using bhkShapeList = RecordListT<bhkShape>; using bhkShapeList = RecordListT<bhkShape>;
using bhkSerializableList = RecordListT<bhkSerializable>; using bhkSerializableList = RecordListT<bhkSerializable>;

View file

@ -196,26 +196,31 @@ GeomMorpherController::GeomMorpherController(const GeomMorpherController &copy,
: Controller(copy) : Controller(copy)
, SceneUtil::NodeCallback<GeomMorpherController, SceneUtil::MorphGeometry*>(copy, copyop) , SceneUtil::NodeCallback<GeomMorpherController, SceneUtil::MorphGeometry*>(copy, copyop)
, mKeyFrames(copy.mKeyFrames) , mKeyFrames(copy.mKeyFrames)
, mWeights(copy.mWeights)
{ {
} }
GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl) GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl)
{ {
if (ctrl->interpolators.length() == 0) if (ctrl->mInterpolators.length() == 0)
{ {
if (ctrl->data.empty()) if (!ctrl->mData.empty())
return;
for (const auto& morph : ctrl->data->mMorphs)
mKeyFrames.emplace_back(morph.mKeyFrames);
}
else
{
for (size_t i = 0; i < ctrl->interpolators.length(); ++i)
{ {
if (!ctrl->interpolators[i].empty()) for (const auto& morph : ctrl->mData->mMorphs)
mKeyFrames.emplace_back(ctrl->interpolators[i].getPtr()); mKeyFrames.emplace_back(morph.mKeyFrames);
else }
mKeyFrames.emplace_back(); return;
}
mKeyFrames.resize(ctrl->mInterpolators.length());
mWeights = ctrl->mWeights;
for (size_t i = 0; i < ctrl->mInterpolators.length(); ++i)
{
if (!ctrl->mInterpolators[i].empty() && ctrl->mInterpolators[i]->recType == Nif::RC_NiFloatInterpolator)
{
auto interpolator = static_cast<const Nif::NiFloatInterpolator*>(ctrl->mInterpolators[i].getPtr());
mKeyFrames[i] = FloatInterpolator(interpolator);
} }
} }
} }
@ -227,12 +232,16 @@ void GeomMorpherController::operator()(SceneUtil::MorphGeometry* node, osg::Node
if (mKeyFrames.size() <= 1) if (mKeyFrames.size() <= 1)
return; return;
float input = getInputValue(nv); float input = getInputValue(nv);
int i = 1; size_t i = 1;
for (std::vector<FloatInterpolator>::iterator it = mKeyFrames.begin()+1; it != mKeyFrames.end(); ++it,++i) for (std::vector<FloatInterpolator>::iterator it = mKeyFrames.begin()+1; it != mKeyFrames.end(); ++it,++i)
{ {
float val = 0; float val = 0;
if (!(*it).empty()) if (!(*it).empty())
{
val = it->interpKey(input); val = it->interpKey(input);
if (i < mWeights.size())
val *= mWeights[i];
}
SceneUtil::MorphGeometry::MorphTarget& target = node->getMorphTarget(i); SceneUtil::MorphGeometry::MorphTarget& target = node->getMorphTarget(i);
if (target.getWeight() != val) if (target.getWeight() != val)

View file

@ -225,6 +225,7 @@ namespace NifOsg
private: private:
std::vector<FloatInterpolator> mKeyFrames; std::vector<FloatInterpolator> mKeyFrames;
std::vector<float> mWeights;
}; };
#ifdef _MSC_VER #ifdef _MSC_VER

View file

@ -1357,7 +1357,7 @@ namespace NifOsg
if(ctrl->recType == Nif::RC_NiGeomMorpherController) if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{ {
const Nif::NiGeomMorpherController* nimorphctrl = static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr()); const Nif::NiGeomMorpherController* nimorphctrl = static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr());
if (nimorphctrl->data.empty()) if (nimorphctrl->mData.empty())
continue; continue;
drawable = handleMorphGeometry(nimorphctrl, geom, parentNode, composite, boundTextures, animflags); drawable = handleMorphGeometry(nimorphctrl, geom, parentNode, composite, boundTextures, animflags);
@ -1378,7 +1378,7 @@ namespace NifOsg
osg::ref_ptr<SceneUtil::MorphGeometry> morphGeom = new SceneUtil::MorphGeometry; osg::ref_ptr<SceneUtil::MorphGeometry> morphGeom = new SceneUtil::MorphGeometry;
morphGeom->setSourceGeometry(sourceGeometry); morphGeom->setSourceGeometry(sourceGeometry);
const std::vector<Nif::NiMorphData::MorphData>& morphs = morpher->data.getPtr()->mMorphs; const std::vector<Nif::NiMorphData::MorphData>& morphs = morpher->mData.getPtr()->mMorphs;
if (morphs.empty()) if (morphs.empty())
return morphGeom; return morphGeom;
if (morphs[0].mVertices.size() != static_cast<const osg::Vec3Array*>(sourceGeometry->getVertexArray())->size()) if (morphs[0].mVertices.size() != static_cast<const osg::Vec3Array*>(sourceGeometry->getVertexArray())->size())