1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-04-18 14:42:27 +00:00

Merge branch 'NiFltAnimationNode' into 'master'

Add NiFltAnimationNode support

Closes #6684

See merge request OpenMW/openmw!1732
This commit is contained in:
psi29a 2022-04-06 23:59:04 +00:00
commit 1ac7eaa6b0
9 changed files with 91 additions and 6 deletions

View File

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

View File

@ -138,11 +138,12 @@
Feature #6288: Preserve the "blocked" record flag for referenceable objects. Feature #6288: Preserve the "blocked" record flag for referenceable objects.
Feature #6380: Commas are treated as whitespace in vanilla 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 #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 #6534: Shader-based object texture blending
Feature #6541: Gloss-mapping Feature #6541: Gloss-mapping
Feature #6592: Missing support for NiTriShape particle emitters Feature #6592: Missing support for NiTriShape particle emitters
Feature #6600: Support NiSortAdjustNode Feature #6600: Support NiSortAdjustNode
Feature #6684: Support NiFltAnimationNode
Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings
Task #6264: Remove the old classes in animation.cpp Task #6264: Remove the old classes in animation.cpp
Task #6553: Simplify interpreter instruction registration Task #6553: Simplify interpreter instruction registration

View File

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

View File

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

View File

@ -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 // Abstract
struct NiAccumulator : Record struct NiAccumulator : Record
{ {

View File

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

View File

@ -8,6 +8,7 @@
#include <osg/Array> #include <osg/Array>
#include <osg/LOD> #include <osg/LOD>
#include <osg/Switch> #include <osg/Switch>
#include <osg/Sequence>
#include <osg/TexGen> #include <osg/TexGen>
#include <osg/ValueObject> #include <osg/ValueObject>
@ -416,6 +417,33 @@ namespace NifOsg
return switchNode; 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) osg::ref_ptr<osg::Image> handleSourceTexture(const Nif::NiSourceTexture* st, Resource::ImageManager* imageManager)
{ {
if (!st) if (!st)
@ -707,6 +735,12 @@ namespace NifOsg
node->addChild(lodNode); node->addChild(lodNode);
currentNode = 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); const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
if(ninode) if(ninode)
@ -727,6 +761,9 @@ namespace NifOsg
} }
} }
if (nifNode->recType == Nif::RC_NiFltAnimationNode)
activateSequenceNode(currentNode,nifNode);
return node; return node;
} }

View File

@ -23,6 +23,7 @@
#include <osg/MatrixTransform> #include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>
#include <osg/LOD> #include <osg/LOD>
#include <osg/Sequence>
#include <osg/Billboard> #include <osg/Billboard>
#include <osg/Geometry> #include <osg/Geometry>
#include <osg/Notify> #include <osg/Notify>
@ -845,7 +846,7 @@ void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes()
++pitr) ++pitr)
{ {
osg::Group* parent = *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()); parent->removeChild(nodeToRemove.get());
if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent); if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent);
@ -887,6 +888,13 @@ void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Switch& switchNode)
traverse(*switchNode.getChild(i)); 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) void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Group& group)
{ {
if (typeid(group)==typeid(osg::Group) && if (typeid(group)==typeid(osg::Group) &&
@ -1951,6 +1959,12 @@ void Optimizer::MergeGroupsVisitor::apply(osg::Switch &switchNode)
traverse(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) void Optimizer::MergeGroupsVisitor::apply(osg::Group &group)
{ {
if (group.getNumChildren() <= 1) if (group.getNumChildren() <= 1)

View File

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