#ifndef OPENMW_COMPONENTS_NIFOSG_RIGGEOMETRY_H #define OPENMW_COMPONENTS_NIFOSG_RIGGEOMETRY_H #include #include namespace SceneUtil { class Skeleton; class Bone; // TODO: This class has a lot of issues. // - We require too many workarounds to ensure safety. // - mSourceGeometry should be const, but can not be const because of a use case in shadervisitor.cpp. // - We create useless mGeometry clones in template RigGeometries. // - We do not support compileGLObjects. // - We duplicate some code in MorphGeometry. /// @brief Mesh skinning implementation. /// @note A RigGeometry may be attached directly to a Skeleton, or somewhere below a Skeleton. /// Note though that the RigGeometry ignores any transforms below the Skeleton, so the attachment point is not that /// important. /// @note The internal Geometry used for rendering is double buffered, this allows updates to be done in a thread /// safe way while not compromising rendering performance. This is crucial when using osg's default threading model /// of DrawThreadPerContext. class RigGeometry : public osg::Drawable { public: RigGeometry(); RigGeometry(const RigGeometry& copy, const osg::CopyOp& copyop); META_Object(SceneUtil, RigGeometry) // Currently empty as this is difficult to implement. Technically we would need to compile both internal // geometries in separate frames but this method is only called once. Alternatively we could compile just the // static parts of the model. void compileGLObjects(osg::RenderInfo& renderInfo) const override {} struct BoneInfluence { osg::Matrixf mInvBindMatrix; osg::BoundingSpheref mBoundSphere; // std::vector> mWeights; }; struct InfluenceMap : public osg::Referenced { std::vector> mData; }; void setInfluenceMap(osg::ref_ptr influenceMap); /// Initialize this geometry from the source geometry. /// @note The source geometry will not be modified. void setSourceGeometry(osg::ref_ptr sourceGeom); osg::ref_ptr getSourceGeometry() const; void accept(osg::NodeVisitor& nv) override; bool supports(const osg::PrimitiveFunctor&) const override { return true; } void accept(osg::PrimitiveFunctor&) const override; struct CopyBoundingBoxCallback : osg::Drawable::ComputeBoundingBoxCallback { osg::BoundingBox boundingBox; osg::BoundingBox computeBound(const osg::Drawable&) const override { return boundingBox; } }; struct CopyBoundingSphereCallback : osg::Node::ComputeBoundingSphereCallback { osg::BoundingSphere boundingSphere; osg::BoundingSphere computeBound(const osg::Node&) const override { return boundingSphere; } }; private: void cull(osg::NodeVisitor* nv); void updateBounds(osg::NodeVisitor* nv); osg::ref_ptr mGeometry[2]; osg::Geometry* getGeometry(unsigned int frame) const; osg::ref_ptr mSourceGeometry; osg::ref_ptr mSourceTangents; Skeleton* mSkeleton; osg::ref_ptr mGeomToSkelMatrix; osg::ref_ptr mInfluenceMap; typedef std::pair BoneBindMatrixPair; typedef std::pair BoneWeight; typedef std::vector VertexList; typedef std::map, VertexList> Bone2VertexMap; struct Bone2VertexVector : public osg::Referenced { std::vector, VertexList>> mData; }; osg::ref_ptr mBone2VertexVector; struct BoneSphereVector : public osg::Referenced { std::vector> mData; }; osg::ref_ptr mBoneSphereVector; std::vector mBoneNodesVector; unsigned int mLastFrameNumber; bool mBoundsFirstFrame; bool initFromParentSkeleton(osg::NodeVisitor* nv); void updateGeomToSkelMatrix(const osg::NodePath& nodePath); }; } #endif