| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | #include <osg/AnimationPath> |
|---|
| 14 | #include <osg/MatrixTransform> |
|---|
| 15 | #include <osg/PositionAttitudeTransform> |
|---|
| 16 | |
|---|
| 17 | using namespace osg; |
|---|
| 18 | |
|---|
| 19 | void AnimationPath::insert(double time,const ControlPoint& controlPoint) |
|---|
| 20 | { |
|---|
| 21 | _timeControlPointMap[time] = controlPoint; |
|---|
| 22 | } |
|---|
| 23 | |
|---|
| 24 | bool AnimationPath::getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const |
|---|
| 25 | { |
|---|
| 26 | if (_timeControlPointMap.empty()) return false; |
|---|
| 27 | |
|---|
| 28 | switch(_loopMode) |
|---|
| 29 | { |
|---|
| 30 | case(SWING): |
|---|
| 31 | { |
|---|
| 32 | double modulated_time = (time - getFirstTime())/(getPeriod()*2.0); |
|---|
| 33 | double fraction_part = modulated_time - floor(modulated_time); |
|---|
| 34 | if (fraction_part>0.5) fraction_part = 1.0-fraction_part; |
|---|
| 35 | |
|---|
| 36 | time = getFirstTime()+(fraction_part*2.0) * getPeriod(); |
|---|
| 37 | break; |
|---|
| 38 | } |
|---|
| 39 | case(LOOP): |
|---|
| 40 | { |
|---|
| 41 | double modulated_time = (time - getFirstTime())/getPeriod(); |
|---|
| 42 | double fraction_part = modulated_time - floor(modulated_time); |
|---|
| 43 | time = getFirstTime()+fraction_part * getPeriod(); |
|---|
| 44 | break; |
|---|
| 45 | } |
|---|
| 46 | case(NO_LOOPING): |
|---|
| 47 | |
|---|
| 48 | break; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | |
|---|
| 52 | |
|---|
| 53 | TimeControlPointMap::const_iterator second = _timeControlPointMap.lower_bound(time); |
|---|
| 54 | if (second==_timeControlPointMap.begin()) |
|---|
| 55 | { |
|---|
| 56 | controlPoint = second->second; |
|---|
| 57 | } |
|---|
| 58 | else if (second!=_timeControlPointMap.end()) |
|---|
| 59 | { |
|---|
| 60 | TimeControlPointMap::const_iterator first = second; |
|---|
| 61 | --first; |
|---|
| 62 | |
|---|
| 63 | |
|---|
| 64 | |
|---|
| 65 | |
|---|
| 66 | double delta_time = second->first - first->first; |
|---|
| 67 | |
|---|
| 68 | if (delta_time==0.0) |
|---|
| 69 | controlPoint = first->second; |
|---|
| 70 | else |
|---|
| 71 | { |
|---|
| 72 | controlPoint.interpolate((time - first->first)/delta_time, |
|---|
| 73 | first->second, |
|---|
| 74 | second->second); |
|---|
| 75 | } |
|---|
| 76 | } |
|---|
| 77 | else |
|---|
| 78 | { |
|---|
| 79 | controlPoint = _timeControlPointMap.rbegin()->second; |
|---|
| 80 | } |
|---|
| 81 | return true; |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | |
|---|
| 85 | void AnimationPath::read(std::istream& in) |
|---|
| 86 | { |
|---|
| 87 | while (!in.eof()) |
|---|
| 88 | { |
|---|
| 89 | double time; |
|---|
| 90 | osg::Vec3d position; |
|---|
| 91 | osg::Quat rotation; |
|---|
| 92 | in >> time >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w(); |
|---|
| 93 | if(!in.eof()) |
|---|
| 94 | insert(time,osg::AnimationPath::ControlPoint(position,rotation)); |
|---|
| 95 | } |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | void AnimationPath::write(std::ostream& fout) const |
|---|
| 99 | { |
|---|
| 100 | int prec = fout.precision(); |
|---|
| 101 | fout.precision(15); |
|---|
| 102 | |
|---|
| 103 | const TimeControlPointMap& tcpm = getTimeControlPointMap(); |
|---|
| 104 | for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin(); |
|---|
| 105 | tcpmitr!=tcpm.end(); |
|---|
| 106 | ++tcpmitr) |
|---|
| 107 | { |
|---|
| 108 | const ControlPoint& cp = tcpmitr->second; |
|---|
| 109 | fout<<tcpmitr->first<<" "<<cp._position<<" "<<cp._rotation<<std::endl; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | fout.precision(prec); |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | class AnimationPathCallbackVisitor : public NodeVisitor |
|---|
| 116 | { |
|---|
| 117 | public: |
|---|
| 118 | |
|---|
| 119 | AnimationPathCallbackVisitor(const AnimationPath::ControlPoint& cp, const osg::Vec3d& pivotPoint, bool useInverseMatrix): |
|---|
| 120 | _cp(cp), |
|---|
| 121 | _pivotPoint(pivotPoint), |
|---|
| 122 | _useInverseMatrix(useInverseMatrix) {} |
|---|
| 123 | |
|---|
| 124 | virtual void apply(MatrixTransform& mt) |
|---|
| 125 | { |
|---|
| 126 | Matrix matrix; |
|---|
| 127 | if (_useInverseMatrix) |
|---|
| 128 | _cp.getInverse(matrix); |
|---|
| 129 | else |
|---|
| 130 | _cp.getMatrix(matrix); |
|---|
| 131 | |
|---|
| 132 | mt.setMatrix(osg::Matrix::translate(-_pivotPoint)*matrix); |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | virtual void apply(PositionAttitudeTransform& pat) |
|---|
| 136 | { |
|---|
| 137 | if (_useInverseMatrix) |
|---|
| 138 | { |
|---|
| 139 | Matrix matrix; |
|---|
| 140 | _cp.getInverse(matrix); |
|---|
| 141 | pat.setPosition(matrix.getTrans()); |
|---|
| 142 | pat.setAttitude(_cp._rotation.inverse()); |
|---|
| 143 | pat.setScale(osg::Vec3(1.0f/_cp._scale.x(),1.0f/_cp._scale.y(),1.0f/_cp._scale.z())); |
|---|
| 144 | pat.setPivotPoint(_pivotPoint); |
|---|
| 145 | |
|---|
| 146 | } |
|---|
| 147 | else |
|---|
| 148 | { |
|---|
| 149 | pat.setPosition(_cp._position); |
|---|
| 150 | pat.setAttitude(_cp._rotation); |
|---|
| 151 | pat.setScale(_cp._scale); |
|---|
| 152 | pat.setPivotPoint(_pivotPoint); |
|---|
| 153 | } |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | AnimationPath::ControlPoint _cp; |
|---|
| 157 | osg::Vec3d _pivotPoint; |
|---|
| 158 | bool _useInverseMatrix; |
|---|
| 159 | }; |
|---|
| 160 | |
|---|
| 161 | void AnimationPathCallback::operator()(Node* node, NodeVisitor* nv) |
|---|
| 162 | { |
|---|
| 163 | if (_animationPath.valid() && |
|---|
| 164 | nv->getVisitorType()==NodeVisitor::UPDATE_VISITOR && |
|---|
| 165 | nv->getFrameStamp()) |
|---|
| 166 | { |
|---|
| 167 | double time = nv->getFrameStamp()->getReferenceTime(); |
|---|
| 168 | _latestTime = time; |
|---|
| 169 | |
|---|
| 170 | if (!_pause) |
|---|
| 171 | { |
|---|
| 172 | |
|---|
| 173 | if (_firstTime==DBL_MAX) _firstTime = time; |
|---|
| 174 | update(*node); |
|---|
| 175 | } |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | |
|---|
| 179 | NodeCallback::traverse(node,nv); |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | double AnimationPathCallback::getAnimationTime() const |
|---|
| 183 | { |
|---|
| 184 | return ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier; |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | void AnimationPathCallback::update(osg::Node& node) |
|---|
| 188 | { |
|---|
| 189 | AnimationPath::ControlPoint cp; |
|---|
| 190 | if (_animationPath->getInterpolatedControlPoint(getAnimationTime(),cp)) |
|---|
| 191 | { |
|---|
| 192 | AnimationPathCallbackVisitor apcv(cp,_pivotPoint,_useInverseMatrix); |
|---|
| 193 | node.accept(apcv); |
|---|
| 194 | } |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | void AnimationPathCallback::reset() |
|---|
| 199 | { |
|---|
| 200 | _firstTime = _latestTime; |
|---|
| 201 | _pauseTime = _latestTime; |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | void AnimationPathCallback::setPause(bool pause) |
|---|
| 205 | { |
|---|
| 206 | if (_pause==pause) |
|---|
| 207 | { |
|---|
| 208 | return; |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | _pause = pause; |
|---|
| 212 | if (_pause) |
|---|
| 213 | { |
|---|
| 214 | _pauseTime = _latestTime; |
|---|
| 215 | } |
|---|
| 216 | else |
|---|
| 217 | { |
|---|
| 218 | _firstTime += (_latestTime-_pauseTime); |
|---|
| 219 | } |
|---|
| 220 | } |
|---|