root/OpenSceneGraph/trunk/include/osg/AnimationPath @ 8868

Revision 8868, 11.1 kB (checked in by robert, 6 years ago)

From Mathias Froehlich, "This is a generic optimization that does not depend on any cpu or instruction
set.

The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 43 Operations whereas multiplication with a
transform, or scale matrix is only 4
2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.

Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform? is about 20% slower
than the same codepath using the PositionAttitudeTransform? instead of the
MatrixTransform? with this patch applied.

If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.

An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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_ANIMATIONPATH
15#define OSG_ANIMATIONPATH 1
16
17#include <map>
18#include <istream>
19#include <float.h>
20
21#include <osg/Matrixf>
22#include <osg/Matrixd>
23#include <osg/Quat>
24#include <osg/NodeCallback>
25
26namespace osg {
27
28/** AnimationPath encapsulates a time varying transformation pathway. Can be
29  * used for updating camera position and model object position.
30  * AnimationPathCallback can be attached directly to Transform nodes to
31  * move subgraphs around the scene.
32*/
33class OSG_EXPORT AnimationPath : public virtual osg::Object
34{
35    public:
36   
37        AnimationPath():_loopMode(LOOP) {}
38
39        AnimationPath(const AnimationPath& ap, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
40            Object(ap,copyop),
41            _timeControlPointMap(ap._timeControlPointMap),
42            _loopMode(ap._loopMode) {}
43
44        META_Object(osg,AnimationPath);
45
46        class ControlPoint
47        {
48        public:
49            ControlPoint():
50                _scale(1.0,1.0,1.0) {}
51
52            ControlPoint(const osg::Vec3d& position):
53                _position(position),
54                _rotation(),
55                _scale(1.0,1.0,1.0) {}
56
57            ControlPoint(const osg::Vec3d& position, const osg::Quat& rotation):
58                _position(position),
59                _rotation(rotation),
60                _scale(1.0,1.0,1.0) {}
61
62            ControlPoint(const osg::Vec3d& position, const osg::Quat& rotation, const osg::Vec3d& scale):
63                _position(position),
64                _rotation(rotation),
65                _scale(scale) {}
66       
67            void setPosition(const osg::Vec3d& position) { _position = position; }
68            const osg::Vec3d& getPosition() const { return _position; }
69
70            void setRotation(const osg::Quat& rotation) { _rotation = rotation; }
71            const osg::Quat& getRotation() const { return _rotation; }
72
73            void setScale(const osg::Vec3d& scale) { _scale = scale; }
74            const osg::Vec3d& getScale() const { return _scale; }
75
76            inline void interpolate(float ratio,const ControlPoint& first, const ControlPoint& second)
77            {
78                float one_minus_ratio = 1.0f-ratio;
79                _position = first._position*one_minus_ratio + second._position*ratio;
80                _rotation.slerp(ratio,first._rotation,second._rotation);
81                _scale = first._scale*one_minus_ratio + second._scale*ratio;
82            }
83           
84            inline void interpolate(double ratio,const ControlPoint& first, const ControlPoint& second)
85            {
86                double one_minus_ratio = 1.0f-ratio;
87                _position = first._position*one_minus_ratio + second._position*ratio;
88                _rotation.slerp(ratio,first._rotation,second._rotation);
89                _scale = first._scale*one_minus_ratio + second._scale*ratio;
90            }
91
92            inline void getMatrix(Matrixf& matrix) const
93            {
94                matrix.makeRotate(_rotation);
95                matrix.preMultScale(_scale);
96                matrix.postMultTranslate(_position);
97            }
98
99            inline void getMatrix(Matrixd& matrix) const
100            {
101                matrix.makeRotate(_rotation);
102                matrix.preMultScale(_scale);
103                matrix.postMultTranslate(_position);
104            }
105
106            inline void getInverse(Matrixf& matrix) const
107            {
108                matrix.makeRotate(_rotation.inverse());
109                matrix.postMultScale(osg::Vec3d(1.0/_scale.x(),1.0/_scale.y(),1.0/_scale.z()));
110                matrix.preMultTranslate(-_position);
111            }
112
113            inline void getInverse(Matrixd& matrix) const
114            {
115                matrix.makeRotate(_rotation.inverse());
116                matrix.postMultScale(osg::Vec3d(1.0/_scale.x(),1.0/_scale.y(),1.0/_scale.z()));
117                matrix.preMultTranslate(-_position);
118            }
119
120        protected:
121
122            osg::Vec3d _position;
123            osg::Quat _rotation;
124            osg::Vec3d _scale;
125
126        };
127       
128
129        /** Given a specific time, return the transformation matrix for a point. */
130        bool getMatrix(double time,Matrixf& matrix) const
131        {
132            ControlPoint cp;
133            if (!getInterpolatedControlPoint(time,cp)) return false;
134            cp.getMatrix(matrix);
135            return true;
136        }
137
138        /** Given a specific time, return the transformation matrix for a point. */
139        bool getMatrix(double time,Matrixd& matrix) const
140        {
141            ControlPoint cp;
142            if (!getInterpolatedControlPoint(time,cp)) return false;
143            cp.getMatrix(matrix);
144            return true;
145        }
146
147        /** Given a specific time, return the inverse transformation matrix for a point. */
148        bool getInverse(double time,Matrixf& matrix) const
149        {
150            ControlPoint cp;
151            if (!getInterpolatedControlPoint(time,cp)) return false;
152            cp.getInverse(matrix);
153            return true;
154        }
155       
156        bool getInverse(double time,Matrixd& matrix) const
157        {
158            ControlPoint cp;
159            if (!getInterpolatedControlPoint(time,cp)) return false;
160            cp.getInverse(matrix);
161            return true;
162        }
163
164        /** Given a specific time, return the local ControlPoint frame for a point. */
165        virtual bool getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const;
166       
167        /** Insert a control point into the AnimationPath.*/
168        void insert(double time,const ControlPoint& controlPoint);
169       
170        double getFirstTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.begin()->first; else return 0.0;}
171        double getLastTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.rbegin()->first; else return 0.0;}
172        double getPeriod() const { return getLastTime()-getFirstTime();}
173       
174        enum LoopMode
175        {
176            SWING,
177            LOOP,
178            NO_LOOPING
179        };
180       
181        void setLoopMode(LoopMode lm) { _loopMode = lm; }
182       
183        LoopMode getLoopMode() const { return _loopMode; }
184
185
186        typedef std::map<double,ControlPoint> TimeControlPointMap;
187       
188        void setTimeControlPointMap(TimeControlPointMap& tcpm) { _timeControlPointMap=tcpm; }
189
190        TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; }
191       
192        const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; }
193       
194        bool empty() const { return _timeControlPointMap.empty(); }
195       
196        void clear() { _timeControlPointMap.clear(); }
197
198        /** Read the animation path from a flat ASCII file stream. */
199        void read(std::istream& in);
200
201        /** Write the animation path to a flat ASCII file stream. */
202        void write(std::ostream& out) const;
203
204        /** Write the control point to a flat ASCII file stream. */
205        void write(TimeControlPointMap::const_iterator itr, std::ostream& out) const;
206
207    protected:
208   
209        virtual ~AnimationPath() {}
210
211        TimeControlPointMap _timeControlPointMap;
212        LoopMode            _loopMode;
213
214};
215
216
217class OSG_EXPORT AnimationPathCallback : public NodeCallback
218{
219    public:
220
221        AnimationPathCallback():
222            _pivotPoint(0.0,0.0,0.0),
223            _useInverseMatrix(false),
224            _timeOffset(0.0),
225            _timeMultiplier(1.0),
226            _firstTime(DBL_MAX),
227            _latestTime(0.0),
228            _pause(false),
229            _pauseTime(0.0) {}
230
231        AnimationPathCallback(const AnimationPathCallback& apc,const CopyOp& copyop):
232            NodeCallback(apc,copyop),
233            _animationPath(apc._animationPath),
234            _pivotPoint(apc._pivotPoint),
235            _useInverseMatrix(apc._useInverseMatrix),
236            _timeOffset(apc._timeOffset),
237            _timeMultiplier(apc._timeMultiplier),
238            _firstTime(apc._firstTime),
239            _latestTime(apc._latestTime),
240            _pause(apc._pause),
241            _pauseTime(apc._pauseTime) {}
242
243       
244        META_Object(osg,AnimationPathCallback);
245
246        /** Construct an AnimationPathCallback with a specified animation path.*/
247        AnimationPathCallback(AnimationPath* ap,double timeOffset=0.0,double timeMultiplier=1.0):
248            _animationPath(ap),
249            _pivotPoint(0.0,0.0,0.0),
250            _useInverseMatrix(false),
251            _timeOffset(timeOffset),
252            _timeMultiplier(timeMultiplier),
253            _firstTime(DBL_MAX),
254            _latestTime(0.0),
255            _pause(false),
256            _pauseTime(0.0) {}
257
258        /** Construct an AnimationPathCallback and automatical create an animation path to produce a rotation about a point.*/
259        AnimationPathCallback(const osg::Vec3d& pivot,const osg::Vec3d& axis,float angularVelocity);
260 
261           
262        void setAnimationPath(AnimationPath* path) { _animationPath = path; }
263        AnimationPath* getAnimationPath() { return _animationPath.get(); }
264        const AnimationPath* getAnimationPath() const { return _animationPath.get(); }
265
266        inline void setPivotPoint(const Vec3d& pivot) { _pivotPoint = pivot; }
267        inline const Vec3d& getPivotPoint() const { return _pivotPoint; }
268
269        void setUseInverseMatrix(bool useInverseMatrix) { _useInverseMatrix = useInverseMatrix; }
270        bool getUseInverseMatrix() const { return _useInverseMatrix; }
271
272        void setTimeOffset(double offset) { _timeOffset = offset; }
273        double getTimeOffset() const { return _timeOffset; }
274       
275        void setTimeMultiplier(double multiplier) { _timeMultiplier = multiplier; }
276        double getTimeMultiplier() const { return _timeMultiplier; }
277
278
279        void reset();
280
281        void setPause(bool pause);
282        bool getPause() const { return _pause; }
283
284        /** Get the animation time that is used to specify the position along
285          * the AnimationPath. Animation time is computed from the formula:
286          *   ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier.*/
287        double getAnimationTime() const;
288
289        /** Implements the callback. */
290        virtual void operator()(Node* node, NodeVisitor* nv);
291       
292        void update(osg::Node& node);
293
294    public:
295
296        ref_ptr<AnimationPath>  _animationPath;
297        osg::Vec3d              _pivotPoint;
298        bool                    _useInverseMatrix;
299        double                  _timeOffset;
300        double                  _timeMultiplier;
301        double                  _firstTime;
302        double                  _latestTime;
303        bool                    _pause;
304        double                  _pauseTime;
305
306    protected:
307   
308        ~AnimationPathCallback(){}
309
310};
311
312}
313
314#endif
Note: See TracBrowser for help on using the browser.