diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 86d657792e..4627ea2f09 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -59,7 +59,7 @@ add_component_dir (nif ) add_component_dir (nifosg - nifloader controller particle userdata + nifloader controller particle matrixtransform ) add_component_dir (nifbullet diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 3c95394a68..a4db2cba3e 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -4,14 +4,13 @@ #include #include #include -#include #include #include #include -#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(node); + NifOsg::MatrixTransform* trans = static_cast(node); osg::Matrix mat = trans->getMatrix(); float time = getInputValue(nv); - NodeUserData* userdata = static_cast(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); diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index c81f97a714..df1086f56f 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -9,11 +9,9 @@ #include #include -#include //UVController +#include -// FlipController #include -#include #include #include @@ -22,8 +20,6 @@ namespace osg { - class Node; - class StateSet; class Material; } diff --git a/components/nifosg/matrixtransform.cpp b/components/nifosg/matrixtransform.cpp new file mode 100644 index 0000000000..96450313de --- /dev/null +++ b/components/nifosg/matrixtransform.cpp @@ -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 ©, const osg::CopyOp ©op) + : osg::MatrixTransform(copy, copyop) + , mIndex(copy.mIndex) + , mScale(copy.mScale) + , mRotationScale(copy.mRotationScale) + { + } +} diff --git a/components/nifosg/matrixtransform.hpp b/components/nifosg/matrixtransform.hpp new file mode 100644 index 0000000000..61d2438dee --- /dev/null +++ b/components/nifosg/matrixtransform.hpp @@ -0,0 +1,34 @@ +#ifndef OPENMW_COMPONENTS_NIFOSG_MATRIXTRANSFORM_H +#define OPENMW_COMPONENTS_NIFOSG_MATRIXTRANSFORM_H + +#include + +#include + +namespace NifOsg +{ + + class MatrixTransform : public osg::MatrixTransform + { + public: + using osg::MatrixTransform::MatrixTransform; + MatrixTransform(int recordIndex, const Nif::Transformation &trafo); + MatrixTransform(const MatrixTransform ©, const osg::CopyOp ©op); + + 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 diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 04aa91a1fe..68e3f9a9ce 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -43,8 +42,8 @@ #include #include +#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) diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index f71dcdd967..7c72771186 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -11,7 +11,7 @@ #include #include -#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(&searchNode)) { - NodeUserData* holder = dynamic_cast(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; } diff --git a/components/nifosg/userdata.hpp b/components/nifosg/userdata.hpp deleted file mode 100644 index 42fcaff471..0000000000 --- a/components/nifosg/userdata.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef OPENMW_COMPONENTS_NIFOSG_USERDATA_H -#define OPENMW_COMPONENTS_NIFOSG_USERDATA_H - -#include - -#include - -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 diff --git a/components/sceneutil/clone.cpp b/components/sceneutil/clone.cpp index c3261515d6..1de7bfd91e 100644 --- a/components/sceneutil/clone.cpp +++ b/components/sceneutil/clone.cpp @@ -6,8 +6,6 @@ #include #include -#include - #include #include @@ -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(node)) - return static_cast(node->clone(*this)); - - return osg::CopyOp::operator()(node); - } - osg::Node* CopyOp::operator ()(const osg::Node* node) const { if (const osgParticle::ParticleProcessor* processor = dynamic_cast(node)) diff --git a/components/sceneutil/clone.hpp b/components/sceneutil/clone.hpp index cf6d79e683..8c5fbd3510 100644 --- a/components/sceneutil/clone.hpp +++ b/components/sceneutil/clone.hpp @@ -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 diff --git a/components/sceneutil/serialize.cpp b/components/sceneutil/serialize.cpp index f84a19876c..398d9cc0cc 100644 --- a/components/sceneutil/serialize.cpp +++ b/components/sceneutil/serialize.cpp @@ -1,5 +1,6 @@ #include "serialize.hpp" +#include #include #include @@ -74,6 +75,15 @@ public: } }; +class MatrixTransformSerializer : public osgDB::ObjectWrapper +{ +public: + MatrixTransformSerializer() + : osgDB::ObjectWrapper(createInstanceFunc, "NifOsg::MatrixTransform", "osg::Object osg::Node osg::Transform osg::MatrixTransform NifOsg::MatrixTransform") + { + } +}; + osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname) { return new osgDB::ObjectWrapper(createInstanceFunc, 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",