1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 21:59:55 +00:00
openmw/components/sceneutil/riggeometry.hpp
scrawl 209e139aa8 Move double buffering implementation inside RigGeometry
The double buffering is an implementation detail so it should be handled as such, rather than mandating the scene graph to be structured in a certain way.

Override accept(NodeVisitor&) instead of using callbacks.
2017-09-01 21:42:34 +00:00

91 lines
2.9 KiB
C++

#ifndef OPENMW_COMPONENTS_NIFOSG_RIGGEOMETRY_H
#define OPENMW_COMPONENTS_NIFOSG_RIGGEOMETRY_H
#include <osg/Geometry>
#include <osg/Matrixf>
namespace SceneUtil
{
class Skeleton;
class Bone;
/// @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)
// At this point compileGLObjects() remains unimplemented, hard to avoid race conditions
// and there is limited value in compiling anyway since the data will change again for the next frame
struct BoneInfluence
{
osg::Matrixf mInvBindMatrix;
osg::BoundingSpheref mBoundSphere;
// <vertex index, weight>
std::map<unsigned short, float> mWeights;
};
struct InfluenceMap : public osg::Referenced
{
std::map<std::string, BoneInfluence> mMap;
};
void setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap);
/// Initialize this geometry from the source geometry.
/// @note The source geometry will not be modified.
void setSourceGeometry(osg::ref_ptr<osg::Geometry> sourceGeom);
osg::ref_ptr<osg::Geometry> getSourceGeometry();
virtual void accept(osg::NodeVisitor &nv);
private:
void cull(osg::NodeVisitor* nv);
void updateBounds(osg::NodeVisitor* nv);
osg::ref_ptr<osg::Geometry> mGeometry[2];
osg::Geometry* getGeometry(unsigned int frame) const;
osg::ref_ptr<osg::Geometry> mSourceGeometry;
osg::ref_ptr<osg::Vec4Array> mSourceTangents;
Skeleton* mSkeleton;
osg::ref_ptr<osg::RefMatrix> mGeomToSkelMatrix;
osg::ref_ptr<InfluenceMap> mInfluenceMap;
typedef std::pair<Bone*, osg::Matrixf> BoneBindMatrixPair;
typedef std::pair<BoneBindMatrixPair, float> BoneWeight;
typedef std::vector<unsigned short> VertexList;
typedef std::map<std::vector<BoneWeight>, VertexList> Bone2VertexMap;
Bone2VertexMap mBone2VertexMap;
typedef std::map<Bone*, osg::BoundingSpheref> BoneSphereMap;
BoneSphereMap mBoneSphereMap;
unsigned int mLastFrameNumber;
bool mBoundsFirstFrame;
bool initFromParentSkeleton(osg::NodeVisitor* nv);
void updateGeomToSkelMatrix(const osg::NodePath& nodePath);
};
}
#endif