#ifndef OPENMW_COMPONENTS_MORPHGEOMETRY_H #define OPENMW_COMPONENTS_MORPHGEOMETRY_H #include namespace SceneUtil { /// @brief Vertex morphing implementation. /// @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 MorphGeometry : public osg::Drawable { public: MorphGeometry(); MorphGeometry(const MorphGeometry& copy, const osg::CopyOp& copyop); META_Object(SceneUtil, MorphGeometry) /// Initialize this geometry from the source geometry. /// @note The source geometry will not be modified. void setSourceGeometry(osg::ref_ptr sourceGeom); class MorphTarget { protected: osg::ref_ptr mOffsets; float mWeight; public: MorphTarget(osg::Vec3Array* offsets, float w = 1.0) : mOffsets(offsets), mWeight(w) {} void setWeight(float weight) { mWeight = weight; } float getWeight() const { return mWeight; } osg::Vec3Array* getOffsets() { return mOffsets.get(); } const osg::Vec3Array* getOffsets() const { return mOffsets.get(); } void setOffsets(osg::Vec3Array* offsets) { mOffsets = offsets; } }; typedef std::vector MorphTargetList; virtual void addMorphTarget( osg::Vec3Array* offsets, float weight = 1.0 ); /** Set the MorphGeometry dirty.*/ void dirty(); /** Get the list of MorphTargets.*/ const MorphTargetList& getMorphTargetList() const { return mMorphTargets; } /** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */ MorphTargetList& getMorphTargetList() { return mMorphTargets; } /** Return the \c MorphTarget at position \c i.*/ inline const MorphTarget& getMorphTarget( unsigned int i ) const { return mMorphTargets[i]; } /** Return the \c MorphTarget at position \c i.*/ inline MorphTarget& getMorphTarget( unsigned int i ) { return mMorphTargets[i]; } osg::ref_ptr getSourceGeometry() const; virtual void accept(osg::NodeVisitor &nv); virtual bool supports(const osg::PrimitiveFunctor&) const { return true; } virtual void accept(osg::PrimitiveFunctor&) const; virtual osg::BoundingBox computeBoundingBox() const; private: void cull(osg::NodeVisitor* nv); MorphTargetList mMorphTargets; osg::ref_ptr mSourceGeometry; osg::ref_ptr mGeometry[2]; osg::Geometry* getGeometry(unsigned int frame) const; unsigned int mLastFrameNumber; bool mDirty; // Have any morph targets changed? mutable bool mMorphedBoundingBox; }; } #endif