| 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 | #include <osg/Camera> |
|---|
| 17 | #include <osg/CameraView> |
|---|
| 18 | #include <osg/io_utils> |
|---|
| 19 | |
|---|
| 20 | using namespace osg; |
|---|
| 21 | |
|---|
| 22 | void AnimationPath::insert(double time,const ControlPoint& controlPoint) |
|---|
| 23 | { |
|---|
| 24 | _timeControlPointMap[time] = controlPoint; |
|---|
| 25 | } |
|---|
| 26 | |
|---|
| 27 | bool AnimationPath::getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const |
|---|
| 28 | { |
|---|
| 29 | if (_timeControlPointMap.empty()) return false; |
|---|
| 30 | |
|---|
| 31 | switch(_loopMode) |
|---|
| 32 | { |
|---|
| 33 | case(SWING): |
|---|
| 34 | { |
|---|
| 35 | double modulated_time = (time - getFirstTime())/(getPeriod()*2.0); |
|---|
| 36 | double fraction_part = modulated_time - floor(modulated_time); |
|---|
| 37 | if (fraction_part>0.5) fraction_part = 1.0-fraction_part; |
|---|
| 38 | |
|---|
| 39 | time = getFirstTime()+(fraction_part*2.0) * getPeriod(); |
|---|
| 40 | break; |
|---|
| 41 | } |
|---|
| 42 | case(LOOP): |
|---|
| 43 | { |
|---|
| 44 | double modulated_time = (time - getFirstTime())/getPeriod(); |
|---|
| 45 | double fraction_part = modulated_time - floor(modulated_time); |
|---|
| 46 | time = getFirstTime()+fraction_part * getPeriod(); |
|---|
| 47 | break; |
|---|
| 48 | } |
|---|
| 49 | case(NO_LOOPING): |
|---|
| 50 | |
|---|
| 51 | break; |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | |
|---|
| 56 | TimeControlPointMap::const_iterator second = _timeControlPointMap.lower_bound(time); |
|---|
| 57 | if (second==_timeControlPointMap.begin()) |
|---|
| 58 | { |
|---|
| 59 | controlPoint = second->second; |
|---|
| 60 | } |
|---|
| 61 | else if (second!=_timeControlPointMap.end()) |
|---|
| 62 | { |
|---|
| 63 | TimeControlPointMap::const_iterator first = second; |
|---|
| 64 | --first; |
|---|
| 65 | |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | double delta_time = second->first - first->first; |
|---|
| 70 | |
|---|
| 71 | if (delta_time==0.0) |
|---|
| 72 | controlPoint = first->second; |
|---|
| 73 | else |
|---|
| 74 | { |
|---|
| 75 | controlPoint.interpolate((time - first->first)/delta_time, |
|---|
| 76 | first->second, |
|---|
| 77 | second->second); |
|---|
| 78 | } |
|---|
| 79 | } |
|---|
| 80 | else |
|---|
| 81 | { |
|---|
| 82 | controlPoint = _timeControlPointMap.rbegin()->second; |
|---|
| 83 | } |
|---|
| 84 | return true; |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | void AnimationPath::read(std::istream& in) |
|---|
| 89 | { |
|---|
| 90 | while (!in.eof()) |
|---|
| 91 | { |
|---|
| 92 | double time; |
|---|
| 93 | osg::Vec3d position; |
|---|
| 94 | osg::Quat rotation; |
|---|
| 95 | in >> time >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w(); |
|---|
| 96 | if(!in.eof()) |
|---|
| 97 | insert(time,osg::AnimationPath::ControlPoint(position,rotation)); |
|---|
| 98 | } |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | void AnimationPath::write(TimeControlPointMap::const_iterator itr, std::ostream& fout) const |
|---|
| 102 | { |
|---|
| 103 | const ControlPoint& cp = itr->second; |
|---|
| 104 | fout<<itr->first<<" "<<cp.getPosition()<<" "<<cp.getRotation()<<std::endl; |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | void AnimationPath::write(std::ostream& fout) const |
|---|
| 108 | { |
|---|
| 109 | int prec = fout.precision(); |
|---|
| 110 | fout.precision(15); |
|---|
| 111 | |
|---|
| 112 | const TimeControlPointMap& tcpm = getTimeControlPointMap(); |
|---|
| 113 | for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin(); |
|---|
| 114 | tcpmitr!=tcpm.end(); |
|---|
| 115 | ++tcpmitr) |
|---|
| 116 | { |
|---|
| 117 | write(tcpmitr, fout); |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | fout.precision(prec); |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | AnimationPathCallback::AnimationPathCallback(const osg::Vec3d& pivot,const osg::Vec3d& axis,float angularVelocity): |
|---|
| 124 | _pivotPoint(pivot), |
|---|
| 125 | _useInverseMatrix(false), |
|---|
| 126 | _timeOffset(0.0), |
|---|
| 127 | _timeMultiplier(1.0), |
|---|
| 128 | _firstTime(DBL_MAX), |
|---|
| 129 | _latestTime(0.0), |
|---|
| 130 | _pause(false), |
|---|
| 131 | _pauseTime(0.0) |
|---|
| 132 | { |
|---|
| 133 | _animationPath = new AnimationPath; |
|---|
| 134 | _animationPath->setLoopMode(osg::AnimationPath::LOOP); |
|---|
| 135 | |
|---|
| 136 | double time0 = 0.0; |
|---|
| 137 | double time1 = osg::PI*0.5/angularVelocity; |
|---|
| 138 | double time2 = osg::PI*1.0/angularVelocity; |
|---|
| 139 | double time3 = osg::PI*1.5/angularVelocity; |
|---|
| 140 | double time4 = osg::PI*2.0/angularVelocity; |
|---|
| 141 | |
|---|
| 142 | osg::Quat rotation0(0.0, axis); |
|---|
| 143 | osg::Quat rotation1(osg::PI*0.5, axis); |
|---|
| 144 | osg::Quat rotation2(osg::PI*1.0, axis); |
|---|
| 145 | osg::Quat rotation3(osg::PI*1.5, axis); |
|---|
| 146 | |
|---|
| 147 | |
|---|
| 148 | _animationPath->insert(time0,osg::AnimationPath::ControlPoint(pivot,rotation0)); |
|---|
| 149 | _animationPath->insert(time1,osg::AnimationPath::ControlPoint(pivot,rotation1)); |
|---|
| 150 | _animationPath->insert(time2,osg::AnimationPath::ControlPoint(pivot,rotation2)); |
|---|
| 151 | _animationPath->insert(time3,osg::AnimationPath::ControlPoint(pivot,rotation3)); |
|---|
| 152 | _animationPath->insert(time4,osg::AnimationPath::ControlPoint(pivot,rotation0)); |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | class AnimationPathCallbackVisitor : public NodeVisitor |
|---|
| 156 | { |
|---|
| 157 | public: |
|---|
| 158 | |
|---|
| 159 | AnimationPathCallbackVisitor(const AnimationPath::ControlPoint& cp, const osg::Vec3d& pivotPoint, bool useInverseMatrix): |
|---|
| 160 | _cp(cp), |
|---|
| 161 | _pivotPoint(pivotPoint), |
|---|
| 162 | _useInverseMatrix(useInverseMatrix) {} |
|---|
| 163 | |
|---|
| 164 | virtual void apply(Camera& camera) |
|---|
| 165 | { |
|---|
| 166 | Matrix matrix; |
|---|
| 167 | if (_useInverseMatrix) |
|---|
| 168 | _cp.getInverse(matrix); |
|---|
| 169 | else |
|---|
| 170 | _cp.getMatrix(matrix); |
|---|
| 171 | |
|---|
| 172 | camera.setViewMatrix(osg::Matrix::translate(-_pivotPoint)*matrix); |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | |
|---|
| 176 | virtual void apply(CameraView& cv) |
|---|
| 177 | { |
|---|
| 178 | if (_useInverseMatrix) |
|---|
| 179 | { |
|---|
| 180 | Matrix matrix; |
|---|
| 181 | _cp.getInverse(matrix); |
|---|
| 182 | cv.setPosition(matrix.getTrans()); |
|---|
| 183 | cv.setAttitude(_cp.getRotation().inverse()); |
|---|
| 184 | cv.setFocalLength(1.0f/_cp.getScale().x()); |
|---|
| 185 | |
|---|
| 186 | } |
|---|
| 187 | else |
|---|
| 188 | { |
|---|
| 189 | cv.setPosition(_cp.getPosition()); |
|---|
| 190 | cv.setAttitude(_cp.getRotation()); |
|---|
| 191 | cv.setFocalLength(_cp.getScale().x()); |
|---|
| 192 | } |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | virtual void apply(MatrixTransform& mt) |
|---|
| 196 | { |
|---|
| 197 | Matrix matrix; |
|---|
| 198 | if (_useInverseMatrix) |
|---|
| 199 | _cp.getInverse(matrix); |
|---|
| 200 | else |
|---|
| 201 | _cp.getMatrix(matrix); |
|---|
| 202 | |
|---|
| 203 | mt.setMatrix(osg::Matrix::translate(-_pivotPoint)*matrix); |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | virtual void apply(PositionAttitudeTransform& pat) |
|---|
| 207 | { |
|---|
| 208 | if (_useInverseMatrix) |
|---|
| 209 | { |
|---|
| 210 | Matrix matrix; |
|---|
| 211 | _cp.getInverse(matrix); |
|---|
| 212 | pat.setPosition(matrix.getTrans()); |
|---|
| 213 | pat.setAttitude(_cp.getRotation().inverse()); |
|---|
| 214 | pat.setScale(osg::Vec3(1.0f/_cp.getScale().x(),1.0f/_cp.getScale().y(),1.0f/_cp.getScale().z())); |
|---|
| 215 | pat.setPivotPoint(_pivotPoint); |
|---|
| 216 | |
|---|
| 217 | } |
|---|
| 218 | else |
|---|
| 219 | { |
|---|
| 220 | pat.setPosition(_cp.getPosition()); |
|---|
| 221 | pat.setAttitude(_cp.getRotation()); |
|---|
| 222 | pat.setScale(_cp.getScale()); |
|---|
| 223 | pat.setPivotPoint(_pivotPoint); |
|---|
| 224 | } |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | AnimationPath::ControlPoint _cp; |
|---|
| 228 | osg::Vec3d _pivotPoint; |
|---|
| 229 | bool _useInverseMatrix; |
|---|
| 230 | }; |
|---|
| 231 | |
|---|
| 232 | void AnimationPathCallback::operator()(Node* node, NodeVisitor* nv) |
|---|
| 233 | { |
|---|
| 234 | if (_animationPath.valid() && |
|---|
| 235 | nv->getVisitorType()==NodeVisitor::UPDATE_VISITOR && |
|---|
| 236 | nv->getFrameStamp()) |
|---|
| 237 | { |
|---|
| 238 | double time = nv->getFrameStamp()->getSimulationTime(); |
|---|
| 239 | _latestTime = time; |
|---|
| 240 | |
|---|
| 241 | if (!_pause) |
|---|
| 242 | { |
|---|
| 243 | |
|---|
| 244 | if (_firstTime==DBL_MAX) _firstTime = time; |
|---|
| 245 | update(*node); |
|---|
| 246 | } |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | |
|---|
| 250 | NodeCallback::traverse(node,nv); |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | double AnimationPathCallback::getAnimationTime() const |
|---|
| 254 | { |
|---|
| 255 | return ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier; |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | void AnimationPathCallback::update(osg::Node& node) |
|---|
| 259 | { |
|---|
| 260 | AnimationPath::ControlPoint cp; |
|---|
| 261 | if (_animationPath->getInterpolatedControlPoint(getAnimationTime(),cp)) |
|---|
| 262 | { |
|---|
| 263 | AnimationPathCallbackVisitor apcv(cp,_pivotPoint,_useInverseMatrix); |
|---|
| 264 | node.accept(apcv); |
|---|
| 265 | } |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | |
|---|
| 269 | void AnimationPathCallback::reset() |
|---|
| 270 | { |
|---|
| 271 | #if 1 |
|---|
| 272 | _firstTime = DBL_MAX; |
|---|
| 273 | _pauseTime = DBL_MAX; |
|---|
| 274 | #else |
|---|
| 275 | _firstTime = _latestTime; |
|---|
| 276 | _pauseTime = _latestTime; |
|---|
| 277 | #endif |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | void AnimationPathCallback::setPause(bool pause) |
|---|
| 281 | { |
|---|
| 282 | if (_pause==pause) |
|---|
| 283 | { |
|---|
| 284 | return; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | _pause = pause; |
|---|
| 288 | |
|---|
| 289 | if (_firstTime==DBL_MAX) return; |
|---|
| 290 | |
|---|
| 291 | if (_pause) |
|---|
| 292 | { |
|---|
| 293 | _pauseTime = _latestTime; |
|---|
| 294 | } |
|---|
| 295 | else |
|---|
| 296 | { |
|---|
| 297 | _firstTime += (_latestTime-_pauseTime); |
|---|
| 298 | } |
|---|
| 299 | } |
|---|