Replace NodeUserData with a custom transform node

pull/2962/head
Capostrophic 5 years ago
parent 4c9cefefdd
commit a61267f57d

@ -59,7 +59,7 @@ add_component_dir (nif
)
add_component_dir (nifosg
nifloader controller particle userdata
nifloader controller particle matrixtransform
)
add_component_dir (nifbullet

@ -4,14 +4,13 @@
#include <osg/TexMat>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/UserDataContainer>
#include <osgParticle/Emitter>
#include <components/nif/data.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include "userdata.hpp"
#include "matrixtransform.hpp"
namespace NifOsg
{
@ -119,13 +118,12 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv)
{
if (hasInput())
{
osg::MatrixTransform* trans = static_cast<osg::MatrixTransform*>(node);
NifOsg::MatrixTransform* trans = static_cast<NifOsg::MatrixTransform*>(node);
osg::Matrix mat = trans->getMatrix();
float time = getInputValue(nv);
NodeUserData* userdata = static_cast<NodeUserData*>(trans->getUserDataContainer()->getUserObject(0));
Nif::Matrix3& rot = userdata->mRotationScale;
Nif::Matrix3& rot = trans->mRotationScale;
bool setRot = false;
if(!mRotations.empty())
@ -140,18 +138,18 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv)
}
else
{
// no rotation specified, use the previous value from the UserData
// no rotation specified, use the previous value
for (int i=0;i<3;++i)
for (int j=0;j<3;++j)
mat(j,i) = rot.mValues[i][j]; // NB column/row major difference
}
if (setRot) // copy the new values back to the UserData
if (setRot) // copy the new values back
for (int i=0;i<3;++i)
for (int j=0;j<3;++j)
rot.mValues[i][j] = mat(j,i); // NB column/row major difference
float& scale = userdata->mScale;
float& scale = trans->mScale;
if(!mScales.empty())
scale = mScales.interpKey(time);

@ -9,11 +9,9 @@
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/statesetupdater.hpp>
#include <set> //UVController
#include <set>
// FlipController
#include <osg/Texture2D>
#include <osg/ref_ptr>
#include <osg/StateSet>
#include <osg/NodeCallback>
@ -22,8 +20,6 @@
namespace osg
{
class Node;
class StateSet;
class Material;
}

@ -0,0 +1,20 @@
#include "matrixtransform.hpp"
namespace NifOsg
{
MatrixTransform::MatrixTransform(int recordIndex, const Nif::Transformation &trafo)
: osg::MatrixTransform(trafo.toMatrix())
, mIndex(recordIndex)
, mScale(trafo.scale)
, mRotationScale(trafo.rotation)
{
}
MatrixTransform::MatrixTransform(const MatrixTransform &copy, const osg::CopyOp &copyop)
: osg::MatrixTransform(copy, copyop)
, mIndex(copy.mIndex)
, mScale(copy.mScale)
, mRotationScale(copy.mRotationScale)
{
}
}

@ -0,0 +1,34 @@
#ifndef OPENMW_COMPONENTS_NIFOSG_MATRIXTRANSFORM_H
#define OPENMW_COMPONENTS_NIFOSG_MATRIXTRANSFORM_H
#include <components/nif/niftypes.hpp>
#include <osg/MatrixTransform>
namespace NifOsg
{
class MatrixTransform : public osg::MatrixTransform
{
public:
using osg::MatrixTransform::MatrixTransform;
MatrixTransform(int recordIndex, const Nif::Transformation &trafo);
MatrixTransform(const MatrixTransform &copy, const osg::CopyOp &copyop);
META_Node(NifOsg, MatrixTransform)
// NIF record index
int mIndex{0};
// Hack: account for Transform differences between OSG and NIFs.
// OSG uses a 4x4 matrix, NIF's use a 3x3 rotationScale, float scale, and vec3 position.
// Decomposing the original components from the 4x4 matrix isn't possible, which causes
// problems when a KeyframeController wants to change only one of these components. So
// we store the scale and rotation components separately here.
float mScale{0.f};
Nif::Matrix3 mRotationScale;
};
}
#endif

@ -3,7 +3,6 @@
#include <mutex>
#include <osg/Matrixf>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osg/Array>
#include <osg/LOD>
@ -43,8 +42,8 @@
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include "matrixtransform.hpp"
#include "particle.hpp"
#include "userdata.hpp"
namespace
{
@ -488,7 +487,7 @@ namespace NifOsg
break;
}
if (!node)
node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
node = new NifOsg::MatrixTransform(nifNode->recIndex, nifNode->trafo);
if (nifNode->recType == Nif::RC_NiCollisionSwitch && !(nifNode->flags & Nif::NiNode::Flag_ActiveCollision))
{
@ -523,15 +522,6 @@ namespace NifOsg
if (!rootNode)
rootNode = node;
// UserData used for a variety of features:
// - finding the correct emitter node for a particle system
// - establishing connections to the animated collision shapes, which are handled in a separate loader
// - finding a random child NiNode in NiBspArrayController
// - storing the previous 3x3 rotation and scale values for when a KeyframeController wants to
// change only certain elements of the 4x4 transform
node->getOrCreateUserDataContainer()->addUserObject(
new NodeUserData(nifNode->recIndex, nifNode->trafo.scale, nifNode->trafo.rotation));
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next)
{
if(e->recType == Nif::RC_NiTextKeyExtraData && textKeys)

@ -11,7 +11,7 @@
#include <components/nif/controlled.hpp>
#include <components/nif/data.hpp>
#include "userdata.hpp"
#include "matrixtransform.hpp"
namespace NifOsg
{
@ -381,16 +381,11 @@ void FindGroupByRecIndex::apply(osg::Geometry &node)
void FindGroupByRecIndex::applyNode(osg::Node &searchNode)
{
if (searchNode.getUserDataContainer() && searchNode.getUserDataContainer()->getNumUserObjects())
if (NifOsg::MatrixTransform* trans = dynamic_cast<NifOsg::MatrixTransform*>(&searchNode))
{
NodeUserData* holder = dynamic_cast<NodeUserData*>(searchNode.getUserDataContainer()->getUserObject(0));
if (holder && holder->mIndex == mRecIndex)
if (trans->mIndex == mRecIndex)
{
osg::Group* group = searchNode.asGroup();
if (!group)
group = searchNode.getParent(0);
mFound = group;
mFound = trans;
mFoundPath = getNodePath();
return;
}

@ -1,48 +0,0 @@
#ifndef OPENMW_COMPONENTS_NIFOSG_USERDATA_H
#define OPENMW_COMPONENTS_NIFOSG_USERDATA_H
#include <components/nif/niftypes.hpp>
#include <osg/Object>
namespace NifOsg
{
// Note if you are copying a scene graph with this user data you should use the DEEP_COPY_USERDATA copyop.
class NodeUserData : public osg::Object
{
public:
NodeUserData(int index, float scale, const Nif::Matrix3& rotationScale)
: mIndex(index), mScale(scale), mRotationScale(rotationScale)
{
}
NodeUserData()
: mIndex(0), mScale(0)
{
}
NodeUserData(const NodeUserData& copy, const osg::CopyOp& copyop)
: Object(copy, copyop)
, mIndex(copy.mIndex)
, mScale(copy.mScale)
, mRotationScale(copy.mRotationScale)
{
}
META_Object(NifOsg, NodeUserData)
// NIF record index
int mIndex;
// Hack: account for Transform differences between OSG and NIFs.
// OSG uses a 4x4 matrix, NIF's use a 3x3 rotationScale, float scale, and vec3 position.
// Decomposing the original components from the 4x4 matrix isn't possible, which causes
// problems when a KeyframeController wants to change only one of these components. So
// we store the scale and rotation components separately here.
// Note for a cleaner solution it would be possible to write a custom Transform node
float mScale;
Nif::Matrix3 mRotationScale;
};
}
#endif

@ -6,8 +6,6 @@
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/Emitter>
#include <components/nifosg/userdata.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
@ -22,15 +20,6 @@ namespace SceneUtil
| osg::CopyOp::DEEP_COPY_USERDATA);
}
osg::Object* CopyOp::operator ()(const osg::Object* node) const
{
// We should copy node transformations when we copy node
if (dynamic_cast<const NifOsg::NodeUserData*>(node))
return static_cast<NifOsg::NodeUserData*>(node->clone(*this));
return osg::CopyOp::operator()(node);
}
osg::Node* CopyOp::operator ()(const osg::Node* node) const
{
if (const osgParticle::ParticleProcessor* processor = dynamic_cast<const osgParticle::ParticleProcessor*>(node))

@ -30,8 +30,6 @@ namespace SceneUtil
virtual osg::Node* operator() (const osg::Node* node) const;
virtual osg::Drawable* operator() (const osg::Drawable* drawable) const;
virtual osg::Object* operator ()(const osg::Object* node) const;
private:
// maps new pointers to their old pointers
// a little messy, but I think this should be the most efficient way

@ -1,5 +1,6 @@
#include "serialize.hpp"
#include <osg/MatrixTransform>
#include <osgDB/ObjectWrapper>
#include <osgDB/Registry>
@ -74,6 +75,15 @@ public:
}
};
class MatrixTransformSerializer : public osgDB::ObjectWrapper
{
public:
MatrixTransformSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<osg::MatrixTransform>, "NifOsg::MatrixTransform", "osg::Object osg::Node osg::Transform osg::MatrixTransform NifOsg::MatrixTransform")
{
}
};
osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname)
{
return new osgDB::ObjectWrapper(createInstanceFunc<osg::DummyObject>, classname, "osg::Object");
@ -100,6 +110,7 @@ void registerSerializers()
mgr->addWrapper(new MorphGeometrySerializer);
mgr->addWrapper(new LightManagerSerializer);
mgr->addWrapper(new CameraRelativeTransformSerializer);
mgr->addWrapper(new MatrixTransformSerializer);
// Don't serialize Geometry data as we are more interested in the overall structure rather than tons of vertex data that would make the file large and hard to read.
mgr->removeWrapper(mgr->findWrapper("osg::Geometry"));
@ -118,7 +129,6 @@ void registerSerializers()
"SceneUtil::StateSetUpdater",
"SceneUtil::DisableLight",
"SceneUtil::MWShadowTechnique",
"NifOsg::NodeUserData",
"NifOsg::FlipController",
"NifOsg::KeyframeController",
"NifOsg::TextKeyMapHolder",

Loading…
Cancel
Save