1 #ifndef OPENMW_COMPONENTS_NIFOSG_RIGGEOMETRY_H 2 #define OPENMW_COMPONENTS_NIFOSG_RIGGEOMETRY_H 3 4 #include <osg/Geometry> 5 #include <osg/Matrixf> 6 7 namespace SceneUtil 8 { 9 class Skeleton; 10 class Bone; 11 12 /// @brief Mesh skinning implementation. 13 /// @note A RigGeometry may be attached directly to a Skeleton, or somewhere below a Skeleton. 14 /// Note though that the RigGeometry ignores any transforms below the Skeleton, so the attachment point is not that important. 15 /// @note The internal Geometry used for rendering is double buffered, this allows updates to be done in a thread safe way while 16 /// not compromising rendering performance. This is crucial when using osg's default threading model of DrawThreadPerContext. 17 class RigGeometry : public osg::Drawable 18 { 19 public: 20 RigGeometry(); 21 RigGeometry(const RigGeometry& copy, const osg::CopyOp& copyop); 22 META_Object(SceneUtil,RigGeometry)23 META_Object(SceneUtil, RigGeometry) 24 25 // 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. 26 void compileGLObjects(osg::RenderInfo& renderInfo) const override {} 27 28 struct BoneInfluence 29 { 30 osg::Matrixf mInvBindMatrix; 31 osg::BoundingSpheref mBoundSphere; 32 // <vertex index, weight> 33 std::vector<std::pair<unsigned short, float>> mWeights; 34 }; 35 36 struct InfluenceMap : public osg::Referenced 37 { 38 std::vector<std::pair<std::string, BoneInfluence>> mData; 39 }; 40 41 void setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap); 42 43 /// Initialize this geometry from the source geometry. 44 /// @note The source geometry will not be modified. 45 void setSourceGeometry(osg::ref_ptr<osg::Geometry> sourceGeom); 46 47 osg::ref_ptr<osg::Geometry> getSourceGeometry() const; 48 49 void accept(osg::NodeVisitor &nv) override; supports(const osg::PrimitiveFunctor &) const50 bool supports(const osg::PrimitiveFunctor&) const override{ return true; } 51 void accept(osg::PrimitiveFunctor&) const override; 52 53 struct CopyBoundingBoxCallback : osg::Drawable::ComputeBoundingBoxCallback 54 { 55 osg::BoundingBox boundingBox; 56 computeBoundSceneUtil::RigGeometry::CopyBoundingBoxCallback57 osg::BoundingBox computeBound(const osg::Drawable&) const override { return boundingBox; } 58 }; 59 60 struct CopyBoundingSphereCallback : osg::Node::ComputeBoundingSphereCallback 61 { 62 osg::BoundingSphere boundingSphere; 63 computeBoundSceneUtil::RigGeometry::CopyBoundingSphereCallback64 osg::BoundingSphere computeBound(const osg::Node&) const override { return boundingSphere; } 65 }; 66 67 private: 68 void cull(osg::NodeVisitor* nv); 69 void updateBounds(osg::NodeVisitor* nv); 70 71 osg::ref_ptr<osg::Geometry> mGeometry[2]; 72 osg::Geometry* getGeometry(unsigned int frame) const; 73 74 osg::ref_ptr<osg::Geometry> mSourceGeometry; 75 osg::ref_ptr<const osg::Vec4Array> mSourceTangents; 76 Skeleton* mSkeleton; 77 78 osg::ref_ptr<osg::RefMatrix> mGeomToSkelMatrix; 79 80 osg::ref_ptr<InfluenceMap> mInfluenceMap; 81 82 typedef std::pair<std::string, osg::Matrixf> BoneBindMatrixPair; 83 84 typedef std::pair<BoneBindMatrixPair, float> BoneWeight; 85 86 typedef std::vector<unsigned short> VertexList; 87 88 typedef std::map<std::vector<BoneWeight>, VertexList> Bone2VertexMap; 89 90 struct Bone2VertexVector : public osg::Referenced 91 { 92 std::vector<std::pair<std::vector<BoneWeight>, VertexList>> mData; 93 }; 94 osg::ref_ptr<Bone2VertexVector> mBone2VertexVector; 95 96 struct BoneSphereVector : public osg::Referenced 97 { 98 std::vector<std::pair<std::string, osg::BoundingSpheref>> mData; 99 }; 100 osg::ref_ptr<BoneSphereVector> mBoneSphereVector; 101 std::vector<Bone*> mBoneNodesVector; 102 103 unsigned int mLastFrameNumber; 104 bool mBoundsFirstFrame; 105 106 bool initFromParentSkeleton(osg::NodeVisitor* nv); 107 108 void updateGeomToSkelMatrix(const osg::NodePath& nodePath); 109 }; 110 111 } 112 113 #endif 114