Merge branch 'NiFltAnimationNode' into 'master'

Add NiFltAnimationNode support

Closes #6684

See merge request OpenMW/openmw!1732
pull/3226/head
psi29a 3 years ago
commit 1ac7eaa6b0

@ -164,6 +164,7 @@ Programmers
Nialsy
Nick Crawford (nighthawk469)
Nikolay Kasyanov (corristo)
Noah Gooder
nobrakal
Nolan Poe (nopoe)
Nurivan Gomez (Nuri-G)
@ -228,14 +229,14 @@ Programmers
viadanna
Vincent Heuken
Vladimir Panteleev (CyberShadow)
vocollapse
Wang Ryu (bzzt)
Will Herrmann (Thunderforge)
vocollapse
Wolfgang Lieff
xyzz
Yohaulticetl
Yuri Krupenin
zelurker
Noah Gooder
Documentation
-------------

@ -138,11 +138,12 @@
Feature #6288: Preserve the "blocked" record flag for referenceable objects.
Feature #6380: Commas are treated as whitespace in vanilla
Feature #6419: Topics shouldn't be greyed out if they can produce another topic reference
Feature #6443: NiStencilProperty is not fully supported
Feature #6443: Support NiStencilProperty
Feature #6534: Shader-based object texture blending
Feature #6541: Gloss-mapping
Feature #6592: Missing support for NiTriShape particle emitters
Feature #6600: Support NiSortAdjustNode
Feature #6684: Support NiFltAnimationNode
Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings
Task #6264: Remove the old classes in animation.cpp
Task #6553: Simplify interpreter instruction registration

@ -2,9 +2,9 @@
#include <unordered_map>
#include <osg/Version>
#include <osg/LOD>
#include <osg/Switch>
#include <osg/Sequence>
#include <osg/MatrixTransform>
#include <osg/Material>
#include <osgUtil/IncrementalCompileOperation>
@ -65,7 +65,7 @@ namespace MWRender
case ESM::REC_CONT:
return store.get<ESM::Container>().searchStatic(id)->mModel;
default:
return std::string();
return {};
}
}
@ -152,6 +152,13 @@ namespace MWRender
n->setDataVariance(osg::Object::STATIC);
return n;
}
if (const osg::Sequence* sq = dynamic_cast<const osg::Sequence*>(node))
{
osg::Group* n = new osg::Group;
n->addChild(operator()(sq->getChild(sq->getValue() != -1 ? sq->getValue() : 0)));
n->setDataVariance(osg::Object::STATIC);
return n;
}
mNodePath.push_back(node);
@ -301,6 +308,11 @@ namespace MWRender
traverse(*lod->getChild(i));
return;
}
if (osg::Sequence* sq = dynamic_cast<osg::Sequence*>(&node))
{
traverse(*sq->getChild(sq->getValue() != -1 ? sq->getValue() : 0));
return;
}
traverse(node);
}

@ -36,6 +36,7 @@ static std::map<std::string, CreateRecord> makeFactory()
{"NiNode" , &construct <NiNode , RC_NiNode >},
{"NiSwitchNode" , &construct <NiSwitchNode , RC_NiSwitchNode >},
{"NiLODNode" , &construct <NiLODNode , RC_NiLODNode >},
{"NiFltAnimationNode" , &construct <NiFltAnimationNode , RC_NiFltAnimationNode >},
{"AvoidNode" , &construct <NiNode , RC_AvoidNode >},
{"NiCollisionSwitch" , &construct <NiNode , RC_NiCollisionSwitch >},
{"NiBSParticleNode" , &construct <NiNode , RC_NiBSParticleNode >},

@ -431,6 +431,22 @@ struct NiLODNode : public NiSwitchNode
}
};
struct NiFltAnimationNode : public NiSwitchNode
{
float mDuration;
enum Flags
{
Flag_Swing = 0x40
};
void read(NIFStream *nif) override
{
NiSwitchNode::read(nif);
mDuration = nif->getFloat();
}
};
// Abstract
struct NiAccumulator : Record
{

@ -38,6 +38,7 @@ enum RecordType
RC_NiNode,
RC_NiSwitchNode,
RC_NiLODNode,
RC_NiFltAnimationNode,
RC_NiBillboardNode,
RC_AvoidNode,
RC_NiCollisionSwitch,

@ -8,6 +8,7 @@
#include <osg/Array>
#include <osg/LOD>
#include <osg/Switch>
#include <osg/Sequence>
#include <osg/TexGen>
#include <osg/ValueObject>
@ -416,6 +417,33 @@ namespace NifOsg
return switchNode;
}
static osg::ref_ptr<osg::Sequence> prepareSequenceNode(const Nif::Node* nifNode)
{
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
osg::ref_ptr<osg::Sequence> sequenceNode (new osg::Sequence);
sequenceNode->setName(niFltAnimationNode->name);
if (niFltAnimationNode->children.length()!=0)
{
if (niFltAnimationNode->flags & Nif::NiFltAnimationNode::Flag_Swing)
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration/(niFltAnimationNode->children.length()*2));
else
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration/niFltAnimationNode->children.length());
}
return sequenceNode;
}
static void activateSequenceNode(osg::Group* osgNode, const Nif::Node* nifNode)
{
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
osg::Sequence* sequenceNode = static_cast<osg::Sequence*>(osgNode);
if (niFltAnimationNode->flags & Nif::NiFltAnimationNode::Flag_Swing)
sequenceNode->setInterval(osg::Sequence::SWING, 0,-1);
else
sequenceNode->setInterval(osg::Sequence::LOOP, 0,-1);
sequenceNode->setDuration(1.0f, -1);
sequenceNode->setMode(osg::Sequence::START);
}
osg::ref_ptr<osg::Image> handleSourceTexture(const Nif::NiSourceTexture* st, Resource::ImageManager* imageManager)
{
if (!st)
@ -707,6 +735,12 @@ namespace NifOsg
node->addChild(lodNode);
currentNode = lodNode;
}
else if (nifNode->recType == Nif::RC_NiFltAnimationNode)
{
osg::ref_ptr<osg::Sequence> sequenceNode = prepareSequenceNode(nifNode);
node->addChild(sequenceNode);
currentNode = sequenceNode;
}
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
if(ninode)
@ -727,6 +761,9 @@ namespace NifOsg
}
}
if (nifNode->recType == Nif::RC_NiFltAnimationNode)
activateSequenceNode(currentNode,nifNode);
return node;
}

@ -23,6 +23,7 @@
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/LOD>
#include <osg/Sequence>
#include <osg/Billboard>
#include <osg/Geometry>
#include <osg/Notify>
@ -845,7 +846,7 @@ void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes()
++pitr)
{
osg::Group* parent = *pitr;
if (!parent->asSwitch() && !dynamic_cast<osg::LOD*>(parent))
if (!parent->asSwitch() && !dynamic_cast<osg::LOD*>(parent) && !dynamic_cast<osg::Sequence*>(parent))
{
parent->removeChild(nodeToRemove.get());
if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent);
@ -887,6 +888,13 @@ void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Switch& switchNode)
traverse(*switchNode.getChild(i));
}
void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Sequence& sequenceNode)
{
// We should keep all sequence child nodes since they reflect different sequence states.
for (unsigned int i=0; i<sequenceNode.getNumChildren(); ++i)
traverse(*sequenceNode.getChild(i));
}
void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Group& group)
{
if (typeid(group)==typeid(osg::Group) &&
@ -1951,6 +1959,12 @@ void Optimizer::MergeGroupsVisitor::apply(osg::Switch &switchNode)
traverse(switchNode);
}
void Optimizer::MergeGroupsVisitor::apply(osg::Sequence &sequenceNode)
{
// We should keep all sequence child nodes since they reflect different sequence states.
traverse(sequenceNode);
}
void Optimizer::MergeGroupsVisitor::apply(osg::Group &group)
{
if (group.getNumChildren() <= 1)

@ -362,6 +362,7 @@ class Optimizer
void apply(osg::Transform& transform) override;
void apply(osg::LOD& lod) override;
void apply(osg::Switch& switchNode) override;
void apply(osg::Sequence& sequenceNode) override;
void apply(osg::Geometry&) override { }
bool isOperationPermissible(osg::Node& node);
@ -385,6 +386,7 @@ class Optimizer
void apply(osg::Group& group) override;
void apply(osg::LOD& lod) override;
void apply(osg::Switch& switchNode) override;
void apply(osg::Sequence& sequenceNode) override;
};
class MergeGeometryVisitor : public BaseOptimizerVisitor

Loading…
Cancel
Save