Read a few more NIF types

NiFloatInterpolator, NiPoint3Interpolator, NiTransformInterpolator, NiBoolInterpolator
Update a few existing controller records
Update NiSkinInstance
pull/3030/head
Alexei Dobrohotov 4 years ago
parent ed8342ebc9
commit f3f5dcb016

@ -92,6 +92,8 @@ namespace Nif
void NiMaterialColorController::read(NIFStream *nif)
{
Controller::read(nif);
if (nif->getVersion() > NIFStream::generateVersion(10,1,0,103))
interpolator.read(nif);
// Two bits that correspond to the controlled material color.
// 00: Ambient
// 01: Diffuse
@ -101,12 +103,14 @@ namespace Nif
targetColor = nif->getUShort() & 3;
else
targetColor = (flags >> 4) & 3;
data.read(nif);
if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103))
data.read(nif);
}
void NiMaterialColorController::post(NIFFile *nif)
{
Controller::post(nif);
interpolator.post(nif);
data.post(nif);
}
@ -161,25 +165,33 @@ namespace Nif
void NiKeyframeController::read(NIFStream *nif)
{
Controller::read(nif);
data.read(nif);
if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103))
data.read(nif);
else
interpolator.read(nif);
}
void NiKeyframeController::post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
interpolator.post(nif);
}
void NiFloatInterpController::read(NIFStream *nif)
{
Controller::read(nif);
data.read(nif);
if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103))
data.read(nif);
else
interpolator.read(nif);
}
void NiFloatInterpController::post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
interpolator.post(nif);
}
void NiGeomMorpherController::read(NIFStream *nif)
@ -189,13 +201,33 @@ namespace Nif
/*bool updateNormals = !!*/nif->getUShort();
data.read(nif);
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW)
{
/*bool alwaysActive = */nif->getChar(); // Always 0
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,106))
{
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{
interpolators.read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0) && nif->getBethVersion() > 9)
{
unsigned int numUnknown = nif->getUInt();
nif->skip(4 * numUnknown);
}
}
else
{
unsigned int numInterps = nif->getUInt();
nif->skip(8 * numInterps);
}
}
}
}
void NiGeomMorpherController::post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
interpolators.post(nif);
}
void NiVisController::read(NIFStream *nif)
@ -213,6 +245,8 @@ namespace Nif
void NiFlipController::read(NIFStream *nif)
{
Controller::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0))
mInterpolator.read(nif);
mTexSlot = nif->getUInt();
if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103))
{
@ -225,6 +259,7 @@ namespace Nif
void NiFlipController::post(NIFFile *nif)
{
Controller::post(nif);
mInterpolator.post(nif);
mSources.post(nif);
}
@ -234,4 +269,59 @@ namespace Nif
nif->getUInt(); // Zero
}
void NiPoint3Interpolator::read(NIFStream *nif)
{
defaultVal = nif->getVector3();
data.read(nif);
}
void NiPoint3Interpolator::post(NIFFile *nif)
{
data.post(nif);
}
void NiBoolInterpolator::read(NIFStream *nif)
{
defaultVal = nif->getBoolean();
data.read(nif);
}
void NiBoolInterpolator::post(NIFFile *nif)
{
data.post(nif);
}
void NiFloatInterpolator::read(NIFStream *nif)
{
defaultVal = nif->getFloat();
data.read(nif);
}
void NiFloatInterpolator::post(NIFFile *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(NIFFile *nif)
{
data.post(nif);
}
}

@ -83,6 +83,7 @@ using NiBSPArrayController = NiParticleSystemController;
class NiMaterialColorController : public Controller
{
public:
NiPoint3InterpolatorPtr interpolator;
NiPosDataPtr data;
unsigned int targetColor;
@ -138,6 +139,7 @@ class NiKeyframeController : public Controller
{
public:
NiKeyframeDataPtr data;
NiTransformInterpolatorPtr interpolator;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
@ -146,6 +148,7 @@ public:
struct NiFloatInterpController : public Controller
{
NiFloatDataPtr data;
NiFloatInterpolatorPtr interpolator;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
@ -158,6 +161,7 @@ class NiGeomMorpherController : public Controller
{
public:
NiMorphDataPtr data;
NiFloatInterpolatorList interpolators;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
@ -175,6 +179,7 @@ public:
class NiFlipController : public Controller
{
public:
NiFloatInterpolatorPtr mInterpolator;
int mTexSlot; // NiTexturingProperty::TextureType
float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources
NiSourceTextureList mSources;
@ -188,5 +193,42 @@ struct bhkBlendController : public Controller
void read(NIFStream *nif) override;
};
struct Interpolator : public Record { };
struct NiPoint3Interpolator : public Interpolator
{
osg::Vec3f defaultVal;
NiPosDataPtr data;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
struct NiBoolInterpolator : public Interpolator
{
bool defaultVal;
NiBoolDataPtr data;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
struct NiFloatInterpolator : public Interpolator
{
float defaultVal;
NiFloatDataPtr data;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
struct NiTransformInterpolator : public Interpolator
{
osg::Vec3f defaultPos;
osg::Quat defaultRot;
float defaultScale;
NiKeyframeDataPtr data;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
} // Namespace
#endif

@ -6,6 +6,8 @@ namespace Nif
void NiSkinInstance::read(NIFStream *nif)
{
data.read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,101))
partitions.read(nif);
root.read(nif);
bones.read(nif);
}
@ -13,6 +15,7 @@ void NiSkinInstance::read(NIFStream *nif)
void NiSkinInstance::post(NIFFile *nif)
{
data.post(nif);
partitions.post(nif);
root.post(nif);
bones.post(nif);
@ -418,7 +421,7 @@ void NiMorphData::read(NIFStream *nif)
for(int i = 0;i < morphCount;i++)
{
mMorphs[i].mKeyFrames = std::make_shared<FloatKeyMap>();
mMorphs[i].mKeyFrames->read(nif, true);
mMorphs[i].mKeyFrames->read(nif, true, /*morph*/true);
nif->getVector3s(mMorphs[i].mVertices, vertCount);
}
}

@ -122,6 +122,11 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
factory["NiTransformData"] = {&construct <NiKeyframeData> , RC_NiKeyframeData };
factory["BSFadeNode"] = {&construct <NiNode> , RC_NiNode };
factory["bhkBlendController"] = {&construct <bhkBlendController> , RC_bhkBlendController };
factory["NiFloatInterpolator"] = {&construct <NiFloatInterpolator> , RC_NiFloatInterpolator };
factory["NiBoolInterpolator"] = {&construct <NiBoolInterpolator> , RC_NiBoolInterpolator };
factory["NiPoint3Interpolator"] = {&construct <NiPoint3Interpolator> , RC_NiPoint3Interpolator };
factory["NiTransformController"] = {&construct <NiKeyframeController> , RC_NiKeyframeController };
factory["NiTransformInterpolator"] = {&construct <NiTransformInterpolator> , RC_NiTransformInterpolator };
return factory;
}

@ -52,16 +52,27 @@ struct KeyMapT {
MapType mKeys;
//Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html)
void read(NIFStream *nif, bool force=false)
void read(NIFStream *nif, bool force = false, bool morph = false)
{
assert(nif);
mInterpolationType = InterpolationType_Unknown;
if (morph && nif->getVersion() >= NIFStream::generateVersion(10,1,0,106))
nif->getString(); // Frame name
size_t count = nif->getUInt();
if(count == 0 && !force)
if (count == 0 && !force && !morph)
return;
if (morph && nif->getVersion() > NIFStream::generateVersion(10,1,0,0))
{
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,104) &&
nif->getVersion() <= NIFStream::generateVersion(20,1,0,2) && nif->getBethVersion() < 10)
nif->getFloat(); // Legacy weight
return;
}
mKeys.clear();
mInterpolationType = nif->getUInt();

@ -115,7 +115,11 @@ enum RecordType
RC_NiSkinPartition,
RC_BSXFlags,
RC_BSBound,
RC_bhkBlendController
RC_bhkBlendController,
RC_NiFloatInterpolator,
RC_NiPoint3Interpolator,
RC_NiBoolInterpolator,
RC_NiTransformInterpolator,
};
/// Base class for all records

@ -145,6 +145,9 @@ struct NiParticleModifier;
struct NiLinesData;
struct NiBoolData;
struct NiSkinPartition;
struct NiFloatInterpolator;
struct NiPoint3Interpolator;
struct NiTransformInterpolator;
using NodePtr = RecordPtrT<Node>;
using ExtraPtr = RecordPtrT<Extra>;
@ -170,11 +173,15 @@ using NiPalettePtr = RecordPtrT<NiPalette>;
using NiParticleModifierPtr = RecordPtrT<NiParticleModifier>;
using NiBoolDataPtr = RecordPtrT<NiBoolData>;
using NiSkinPartitionPtr = RecordPtrT<NiSkinPartition>;
using NiFloatInterpolatorPtr = RecordPtrT<NiFloatInterpolator>;
using NiPoint3InterpolatorPtr = RecordPtrT<NiPoint3Interpolator>;
using NiTransformInterpolatorPtr = RecordPtrT<NiTransformInterpolator>;
using NodeList = RecordListT<Node>;
using PropertyList = RecordListT<Property>;
using ExtraList = RecordListT<Extra>;
using NiSourceTextureList = RecordListT<NiSourceTexture>;
using NiFloatInterpolatorList = RecordListT<NiFloatInterpolator>;
} // Namespace
#endif

@ -92,6 +92,26 @@ KeyframeController::KeyframeController(const Nif::NiKeyframeData *data)
{
}
KeyframeController::KeyframeController(const Nif::NiTransformInterpolator* interpolator)
: mRotations(interpolator->data->mRotations, interpolator->defaultRot)
, mXRotations(interpolator->data->mXRotations, 0.f)
, mYRotations(interpolator->data->mYRotations, 0.f)
, mZRotations(interpolator->data->mZRotations, 0.f)
, mTranslations(interpolator->data->mTranslations, interpolator->defaultPos)
, mScales(interpolator->data->mScales, interpolator->defaultScale)
{
}
KeyframeController::KeyframeController(const float scale, const osg::Vec3f& pos, const osg::Quat& rot)
: mRotations(Nif::QuaternionKeyMapPtr(), rot)
, mXRotations(Nif::FloatKeyMapPtr(), 0.f)
, mYRotations(Nif::FloatKeyMapPtr(), 0.f)
, mZRotations(Nif::FloatKeyMapPtr(), 0.f)
, mTranslations(Nif::Vector3KeyMapPtr(), pos)
, mScales(Nif::FloatKeyMapPtr(), scale)
{
}
osg::Quat KeyframeController::getXYZRotation(float time) const
{
float xrot = 0, yrot = 0, zrot = 0;
@ -313,6 +333,11 @@ RollController::RollController(const Nif::NiFloatData *data)
{
}
RollController::RollController(const Nif::NiFloatInterpolator* interpolator)
: mData(interpolator)
{
}
RollController::RollController(const RollController &copy, const osg::CopyOp &copyop)
: osg::NodeCallback(copy, copyop)
, Controller(copy)
@ -344,6 +369,10 @@ void RollController::operator() (osg::Node* node, osg::NodeVisitor* nv)
}
}
AlphaController::AlphaController()
{
}
AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial)
: mData(data->mKeyList, 1.f)
, mBaseMaterial(baseMaterial)
@ -351,7 +380,9 @@ AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Materi
}
AlphaController::AlphaController()
AlphaController::AlphaController(const Nif::NiFloatInterpolator* interpolator, const osg::Material* baseMaterial)
: mData(interpolator)
, mBaseMaterial(baseMaterial)
{
}
@ -379,6 +410,10 @@ void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
}
}
MaterialColorController::MaterialColorController()
{
}
MaterialColorController::MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial)
: mData(data->mKeyList, osg::Vec3f(1,1,1))
, mTargetColor(color)
@ -386,7 +421,10 @@ MaterialColorController::MaterialColorController(const Nif::NiPosData *data, Tar
{
}
MaterialColorController::MaterialColorController()
MaterialColorController::MaterialColorController(const Nif::NiPoint3Interpolator* interpolator, TargetColor color, const osg::Material* baseMaterial)
: mData(interpolator)
, mTargetColor(color)
, mBaseMaterial(baseMaterial)
{
}
@ -448,6 +486,8 @@ FlipController::FlipController(const Nif::NiFlipController *ctrl, const std::vec
, mDelta(ctrl->mDelta)
, mTextures(textures)
{
if (!ctrl->mInterpolator.empty())
mData = ctrl->mInterpolator.getPtr();
}
FlipController::FlipController(int texSlot, float delta, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures)
@ -463,14 +503,19 @@ FlipController::FlipController(const FlipController &copy, const osg::CopyOp &co
, mTexSlot(copy.mTexSlot)
, mDelta(copy.mDelta)
, mTextures(copy.mTextures)
, mData(copy.mData)
{
}
void FlipController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
{
if (hasInput() && mDelta != 0 && !mTextures.empty())
if (hasInput() && !mTextures.empty())
{
int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size();
int curTexture = 0;
if (mDelta != 0)
curTexture = int(getInputValue(nv) / mDelta) % mTextures.size();
else
curTexture = int(mData.interpKey(getInputValue(nv))) % mTextures.size();
stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]);
}
}

@ -58,6 +58,8 @@ namespace NifOsg
using ValueT = typename MapT::ValueType;
ValueInterpolator() = default;
ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) = delete;
ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) = delete;
ValueInterpolator(std::shared_ptr<const MapT> keys, ValueT defaultVal = ValueT())
: mKeys(keys)
@ -161,6 +163,34 @@ namespace NifOsg
using Vec3Interpolator = ValueInterpolator<Nif::Vector3KeyMap>;
using Vec4Interpolator = ValueInterpolator<Nif::Vector4KeyMap>;
template<>
inline FloatInterpolator::ValueInterpolator(const Nif::NiFloatInterpolator* interpolator)
: mDefaultVal(interpolator->defaultVal)
{
if (interpolator->data.empty())
return;
mKeys = interpolator->data->mKeyList;
if (mKeys)
{
mLastLowKey = mKeys->mKeys.end();
mLastHighKey = mKeys->mKeys.end();
}
}
template<>
inline Vec3Interpolator::ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator)
: mDefaultVal(interpolator->defaultVal)
{
if (interpolator->data.empty())
return;
mKeys = interpolator->data->mKeyList;
if (mKeys)
{
mLastLowKey = mKeys->mKeys.end();
mLastHighKey = mKeys->mKeys.end();
}
}
class ControllerFunction : public SceneUtil::ControllerFunction
{
private:
@ -203,7 +233,14 @@ namespace NifOsg
class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller
{
public:
// This is used if there's no interpolator but there is data (Morrowind meshes).
KeyframeController(const Nif::NiKeyframeData *data);
// This is used if the interpolator has data.
KeyframeController(const Nif::NiTransformInterpolator* interpolator);
// This is used if there are default values available (e.g. from a data-less interpolator).
// If there's neither keyframe data nor an interpolator a KeyframeController must not be created.
KeyframeController(const float scale, const osg::Vec3f& pos, const osg::Quat& rot);
KeyframeController();
KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop);
@ -272,6 +309,7 @@ namespace NifOsg
public:
RollController(const Nif::NiFloatData *data);
RollController(const Nif::NiFloatInterpolator* interpolator);
RollController() = default;
RollController(const RollController& copy, const osg::CopyOp& copyop);
@ -287,6 +325,7 @@ namespace NifOsg
osg::ref_ptr<const osg::Material> mBaseMaterial;
public:
AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial);
AlphaController(const Nif::NiFloatInterpolator* interpolator, const osg::Material* baseMaterial);
AlphaController();
AlphaController(const AlphaController& copy, const osg::CopyOp& copyop);
@ -308,6 +347,7 @@ namespace NifOsg
Emissive = 3
};
MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial);
MaterialColorController(const Nif::NiPoint3Interpolator* interpolator, TargetColor color, const osg::Material* baseMaterial);
MaterialColorController();
MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop);
@ -329,6 +369,7 @@ namespace NifOsg
int mTexSlot{0};
float mDelta{0.f};
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
FloatInterpolator mData;
public:
FlipController(const Nif::NiFlipController* ctrl, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures);

@ -281,10 +281,10 @@ namespace NifOsg
const Nif::NiStringExtraData *strdata = static_cast<const Nif::NiStringExtraData*>(extra.getPtr());
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
if(key->data.empty())
if (key->data.empty() && key->interpolator.empty())
continue;
osg::ref_ptr<NifOsg::KeyframeController> callback(new NifOsg::KeyframeController(key->data.getPtr()));
osg::ref_ptr<NifOsg::KeyframeController> callback(handleKeyframeController(key));
callback->setFunction(std::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(key)));
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
@ -725,6 +725,24 @@ namespace NifOsg
}
}
static osg::ref_ptr<KeyframeController> handleKeyframeController(const Nif::NiKeyframeController* keyctrl)
{
osg::ref_ptr<NifOsg::KeyframeController> ctrl;
if (!keyctrl->interpolator.empty())
{
const Nif::NiTransformInterpolator* interp = keyctrl->interpolator.getPtr();
if (!interp->data.empty())
ctrl = new NifOsg::KeyframeController(interp);
else
ctrl = new NifOsg::KeyframeController(interp->defaultScale, interp->defaultPos, interp->defaultRot);
}
else if (!keyctrl->data.empty())
{
ctrl = new NifOsg::KeyframeController(keyctrl->data.getPtr());
}
return ctrl;
}
void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated)
{
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
@ -734,9 +752,9 @@ namespace NifOsg
if (ctrl->recType == Nif::RC_NiKeyframeController)
{
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
if (key->data.empty())
if (key->data.empty() && key->interpolator.empty())
continue;
osg::ref_ptr<KeyframeController> callback(new KeyframeController(key->data.getPtr()));
osg::ref_ptr<KeyframeController> callback(handleKeyframeController(key));
setupController(key, callback, animflags);
node->addUpdateCallback(callback);
isAnimated = true;
@ -763,9 +781,13 @@ namespace NifOsg
else if (ctrl->recType == Nif::RC_NiRollController)
{
const Nif::NiRollController *rollctrl = static_cast<const Nif::NiRollController*>(ctrl.getPtr());
if (rollctrl->data.empty())
if (rollctrl->data.empty() && rollctrl->interpolator.empty())
continue;
osg::ref_ptr<RollController> callback(new RollController(rollctrl->data.getPtr()));
osg::ref_ptr<RollController> callback;
if (!rollctrl->interpolator.empty())
callback = new RollController(rollctrl->interpolator.getPtr());
else // if (!rollctrl->data.empty())
callback = new RollController(rollctrl->data.getPtr());
setupController(rollctrl, callback, animflags);
node->addUpdateCallback(callback);
isAnimated = true;
@ -791,19 +813,27 @@ namespace NifOsg
if (ctrl->recType == Nif::RC_NiAlphaController)
{
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
if (alphactrl->data.empty())
if (alphactrl->data.empty() && alphactrl->interpolator.empty())
continue;
osg::ref_ptr<AlphaController> osgctrl(new AlphaController(alphactrl->data.getPtr(), baseMaterial));
osg::ref_ptr<AlphaController> osgctrl;
if (!alphactrl->interpolator.empty())
osgctrl = new AlphaController(alphactrl->interpolator.getPtr(), baseMaterial);
else // if (!alphactrl->data.empty())
osgctrl = new AlphaController(alphactrl->data.getPtr(), baseMaterial);
setupController(alphactrl, osgctrl, animflags);
composite->addController(osgctrl);
}
else if (ctrl->recType == Nif::RC_NiMaterialColorController)
{
const Nif::NiMaterialColorController* matctrl = static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
if (matctrl->data.empty())
if (matctrl->data.empty() && matctrl->interpolator.empty())
continue;
osg::ref_ptr<MaterialColorController> osgctrl;
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->targetColor);
osg::ref_ptr<MaterialColorController> osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial));
if (!matctrl->interpolator.empty())
osgctrl = new MaterialColorController(matctrl->interpolator.getPtr(), targetColor, baseMaterial);
else // if (!matctrl->data.empty())
osgctrl = new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial);
setupController(matctrl, osgctrl, animflags);
composite->addController(osgctrl);
}

Loading…
Cancel
Save