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