File: morphgeometry.hpp

package info (click to toggle)
openmw 0.49.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 33,992 kB
  • sloc: cpp: 372,479; xml: 2,149; sh: 1,403; python: 797; makefile: 26
file content (94 lines) | stat: -rw-r--r-- 3,438 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#ifndef OPENMW_COMPONENTS_MORPHGEOMETRY_H
#define OPENMW_COMPONENTS_MORPHGEOMETRY_H

#include <osg/Geometry>

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<osg::Geometry> sourceGeom);

        // 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 {}

        class MorphTarget
        {
        protected:
            osg::ref_ptr<osg::Vec3Array> 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<MorphTarget> 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<osg::Geometry> getSourceGeometry() const;

        void accept(osg::NodeVisitor& nv) override;
        bool supports(const osg::PrimitiveFunctor&) const override { return true; }
        void accept(osg::PrimitiveFunctor&) const override;

        osg::BoundingBox computeBoundingBox() const override;

    private:
        void cull(osg::NodeVisitor* nv);

        MorphTargetList mMorphTargets;

        osg::ref_ptr<osg::Geometry> mSourceGeometry;

        osg::ref_ptr<osg::Geometry> mGeometry[2];
        osg::Geometry* getGeometry(unsigned int frame) const;

        unsigned int mLastFrameNumber;
        bool mDirty; // Have any morph targets changed?

        mutable bool mMorphedBoundingBox;
    };

}

#endif