Add support for NiRollController (feature #4675)

pull/2176/head
Andrei Kortunov 5 years ago
parent cb5a57e41b
commit 60f112d11c

@ -33,6 +33,7 @@
Feature #3610: Option to invert X axis
Feature #4209: Editor: Faction rank sub-table
Feature #4673: Weapon sheathing
Feature #4675: Support for NiRollController
Feature #4730: Native animated containers support
Feature #4812: Support NiSwitchNode
Feature #4836: Daytime node switch

@ -173,6 +173,18 @@ namespace Nif
data.post(nif);
}
void NiRollController::read(NIFStream *nif)
{
Controller::read(nif);
data.read(nif);
}
void NiRollController::post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
void NiGeomMorpherController::read(NIFStream *nif)
{
Controller::read(nif);

@ -136,6 +136,15 @@ public:
void post(NIFFile *nif);
};
class NiRollController : public Controller
{
public:
NiFloatDataPtr data;
void read(NIFStream *nif);
void post(NIFFile *nif);
};
class NiGeomMorpherController : public Controller
{
public:

@ -73,6 +73,7 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
newFactory.insert(makeEntry("NiGeomMorpherController", &construct <NiGeomMorpherController> , RC_NiGeomMorpherController ));
newFactory.insert(makeEntry("NiKeyframeController", &construct <NiKeyframeController> , RC_NiKeyframeController ));
newFactory.insert(makeEntry("NiAlphaController", &construct <NiAlphaController> , RC_NiAlphaController ));
newFactory.insert(makeEntry("NiRollController", &construct <NiRollController> , RC_NiRollController ));
newFactory.insert(makeEntry("NiUVController", &construct <NiUVController> , RC_NiUVController ));
newFactory.insert(makeEntry("NiPathController", &construct <NiPathController> , RC_NiPathController ));
newFactory.insert(makeEntry("NiMaterialColorController", &construct <NiMaterialColorController> , RC_NiMaterialColorController ));

@ -60,6 +60,7 @@ enum RecordType
RC_NiGeomMorpherController,
RC_NiKeyframeController,
RC_NiAlphaController,
RC_NiRollController,
RC_NiUVController,
RC_NiPathController,
RC_NiMaterialColorController,

@ -309,6 +309,46 @@ void VisController::operator() (osg::Node* node, osg::NodeVisitor* nv)
traverse(node, nv);
}
RollController::RollController(const Nif::NiFloatData *data)
: mData(data->mKeyList, 1.f)
{
}
RollController::RollController()
{
}
RollController::RollController(const RollController &copy, const osg::CopyOp &copyop)
: osg::NodeCallback(copy, copyop)
, Controller(copy)
, mData(copy.mData)
, mStartingTime(0)
{
}
void RollController::operator() (osg::Node* node, osg::NodeVisitor* nv)
{
traverse(node, nv);
if (hasInput())
{
double newTime = nv->getFrameStamp()->getSimulationTime();
double duration = newTime - mStartingTime;
mStartingTime = newTime;
float value = mData.interpKey(getInputValue(nv));
osg::MatrixTransform* transform = static_cast<osg::MatrixTransform*>(node);
osg::Matrix matrix = transform->getMatrix();
// Rotate around "roll" axis.
// Note: in original game rotation speed is the framerate-dependent in a very tricky way.
// Do not replicate this behaviour until we will really need it.
// For now consider controller's current value as an angular speed in radians per 1/60 seconds.
matrix = osg::Matrix::rotate(value * duration * 60.f, 0, 0, 1) * matrix;
transform->setMatrix(matrix);
}
}
AlphaController::AlphaController(const Nif::NiFloatData *data)
: mData(data->mKeyList, 1.f)
{

@ -246,6 +246,22 @@ namespace NifOsg
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
};
class RollController : public osg::NodeCallback, public SceneUtil::Controller
{
private:
FloatInterpolator mData;
double mStartingTime;
public:
RollController(const Nif::NiFloatData *data);
RollController();
RollController(const RollController& copy, const osg::CopyOp& copyop);
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
META_Object(NifOsg, RollController)
};
class AlphaController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
{
private:

@ -697,6 +697,10 @@ namespace NifOsg
{
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), transformNode, animflags);
}
else if (ctrl->recType == Nif::RC_NiRollController)
{
handleRollController(static_cast<const Nif::NiRollController*>(ctrl.getPtr()), transformNode, animflags);
}
else
Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename;
}
@ -709,6 +713,13 @@ namespace NifOsg
node->addUpdateCallback(callback);
}
void handleRollController(const Nif::NiRollController* rollctrl, osg::Node* node, int animflags)
{
osg::ref_ptr<RollController> callback(new RollController(rollctrl->data.getPtr()));
setupController(rollctrl, callback, animflags);
node->addUpdateCallback(callback);
}
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
{
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)

Loading…
Cancel
Save