1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2018 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSG_ANIMATIONMATERIAL
15#define OSG_ANIMATIONMATERIAL 1
16
17#include <osg/Material>
18#include <osg/Callback>
19
20#include <osgPresentation/Export>
21
22#include <iosfwd>
23#include <map>
24#include <float.h>
25
26namespace osgPresentation {
27
28/** AnimationMaterial for specify the time varying transformation pathway to use when update camera and model objects.
29  * Subclassed from Transform::ComputeTransformCallback allows AnimationMaterial to
30  * be attached directly to Transform nodes to move subgraphs around the scene.
31*/
32class OSGPRESENTATION_EXPORT AnimationMaterial : public virtual osg::Object
33{
34    public:
35
36        AnimationMaterial():_loopMode(LOOP) {}
37
38        AnimationMaterial(const AnimationMaterial& ap, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
39            Object(ap,copyop),
40            _timeControlPointMap(ap._timeControlPointMap),
41            _loopMode(ap._loopMode) {}
42
43        META_Object(osg,AnimationMaterial);
44
45
46        /** get the transformation matrix for a point in time.*/
47        bool getMaterial(double time,osg::Material& material) const;
48
49        void insert(double time,osg::Material* material);
50
51        double getFirstTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.begin()->first; else return 0.0;}
52        double getLastTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.rbegin()->first; else return 0.0;}
53        double getPeriod() const { return getLastTime()-getFirstTime();}
54
55        enum LoopMode
56        {
57            SWING,
58            LOOP,
59            NO_LOOPING
60        };
61
62        void setLoopMode(LoopMode lm) { _loopMode = lm; }
63
64        LoopMode getLoopMode() const { return _loopMode; }
65
66
67        typedef std::map<double, osg::ref_ptr<osg::Material> > TimeControlPointMap;
68
69        TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; }
70
71        const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; }
72
73        /** read the anumation path from a flat ascii file stream.*/
74        void read(std::istream& in);
75
76        /** write the anumation path to a flat ascii file stream.*/
77        void write(std::ostream& out) const;
78
79        bool requiresBlending() const;
80
81    protected:
82
83        virtual ~AnimationMaterial() {}
84
85        void interpolate(osg::Material& material, float r, const osg::Material& lhs,const osg::Material& rhs) const;
86
87        TimeControlPointMap _timeControlPointMap;
88        LoopMode            _loopMode;
89
90};
91
92
93class OSGPRESENTATION_EXPORT AnimationMaterialCallback : public osg::NodeCallback
94{
95    public:
96
97        AnimationMaterialCallback():
98            _useInverseMatrix(false),
99            _timeOffset(0.0),
100            _timeMultiplier(1.0),
101            _firstTime(DBL_MAX),
102            _latestTime(0.0),
103            _pause(false),
104            _pauseTime(0.0) {}
105
106
107        AnimationMaterialCallback(const AnimationMaterialCallback& apc,const osg::CopyOp& copyop):
108            osg::Object(apc, copyop),
109            osg::Callback(apc, copyop),
110            osg::NodeCallback(apc,copyop),
111            _animationMaterial(apc._animationMaterial),
112            _useInverseMatrix(apc._useInverseMatrix),
113            _timeOffset(apc._timeOffset),
114            _timeMultiplier(apc._timeMultiplier),
115            _firstTime(apc._firstTime),
116            _latestTime(apc._latestTime),
117            _pause(apc._pause),
118            _pauseTime(apc._pauseTime) {}
119
120
121        META_Object(osg,AnimationMaterialCallback);
122
123        AnimationMaterialCallback(AnimationMaterial* ap,double timeOffset=0.0f,double timeMultiplier=1.0f):
124            _animationMaterial(ap),
125            _useInverseMatrix(false),
126            _timeOffset(timeOffset),
127            _timeMultiplier(timeMultiplier),
128            _firstTime(DBL_MAX),
129            _latestTime(0.0),
130            _pause(false),
131            _pauseTime(0.0) {}
132
133        void setAnimationMaterial(AnimationMaterial* path) { _animationMaterial = path; }
134
135        AnimationMaterial* getAnimationMaterial() { return _animationMaterial.get(); }
136
137        const AnimationMaterial* getAnimationMaterial() const { return _animationMaterial.get(); }
138
139        void setTimeOffset(double offset) { _timeOffset = offset; }
140        double getTimeOffset() const { return _timeOffset; }
141
142        void setTimeMultiplier(double multiplier) { _timeMultiplier = multiplier; }
143        double getTimeMultiplier() const { return _timeMultiplier; }
144
145        void reset();
146
147        void setPause(bool pause);
148
149        /** get the animation time that is used to specify the position along the AnimationMaterial.
150          * Animation time is computed from the formula ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier.*/
151        double getAnimationTime() const;
152
153        /** implements the callback*/
154        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
155
156        void update(osg::Node& node);
157
158    public:
159
160        osg::ref_ptr<AnimationMaterial>     _animationMaterial;
161        bool                                _useInverseMatrix;
162        double                              _timeOffset;
163        double                              _timeMultiplier;
164        double                              _firstTime;
165        double                              _latestTime;
166        bool                                _pause;
167        double                              _pauseTime;
168
169    protected:
170
171        ~AnimationMaterialCallback(){}
172
173};
174
175}
176
177#endif
178