/** * Message handler callback. * * @param data the message data */ void CadworkFlyMotionModel::OnMessage(MessageData* data) { Transformable *target = GetTarget(); if (target != NULL && IsEnabled() && (data->message == dtCore::System::MESSAGE_POST_EVENT_TRAVERSAL/*MESSAGE_PRE_FRAME*/) && // don't move if paused & using simtime for speed (since simtime will be 0 if paused) (!HasOption(OPTION_USE_SIMTIME_FOR_SPEED) || !System::GetInstance().GetPause())) { if(IsMouseGrabbed()) { // Get the time change (sim time or real time) double delta = GetTimeDelta(data); Transform transform; GetTarget()->GetTransform(transform); osg::Vec3 xyz, hpr; transform.Get(xyz, hpr); // rotation bool rotationChanged = false; if(!HasOption(OPTION_REQUIRE_MOUSE_DOWN)) { hpr = Rotate(hpr, delta, rotationChanged); if (rotationChanged) { transform.SetRotation(hpr); } } // translation bool translationChanged = false; xyz = Translate(xyz, delta, translationChanged); if (translationChanged) { transform.SetTranslation(xyz); } // homing if(mHomingButton->GetState()) { GoToHomePosition(); } // finalize changes if (rotationChanged || translationChanged) { GetTarget()->SetTransform(transform); } } // release cursor //if(mCursorReleaseButton->GetState()) //{ // ReleaseMouse(); //} ////grab cursor //if(mCursorGrabButton->GetState()) //{ // GrabMouse(); //} /** * Now some serious work. Below begins the 'animation' of the smooth camera * movement while zooming (by mouse wheel). First part is rotation when refocusing * and the second part is changing distance. Default animation duration is 0.4s. */ if(mAnimData.isAnimating()) { double f = (System::GetInstance().GetSimulationTime() - mAnimData._startTime) / mAnimData._motion->getDuration(); f = f<0 ? 0 : f > 1 ? 1 : f; //clamp f into a <0,1> range float t; mAnimData._motion->getValueInNormalizedRange(f,t); //gets normalized <0,1> linear value f and turns it into non-lineary interpolated value t also normalized (the function is defined in MathMotionTemplate constructor in AnimationData definition) /** handle amooth zooming */ if(mAnimData._isZooming) { float newdist; newdist = t * (mAnimData._toDist - mAnimData._fromDist) + mAnimData._fromDist; Transform trans; target->GetTransform(trans); if(mAnimData._isRotating) //rotating while zooming { osg::Vec3 xyz,hpr,oldhpr; trans.Get(xyz,oldhpr); trans.Set(xyz,mAnimData._toRotation); trans.Get(xyz,hpr); float deltaDist = mTmpPrevDistance - newdist; /*if (newdist < MIN_DISTANCE && (mAnimData._toDist < mAnimData._fromDist)) { deltaDist = MIN_DISTANCE - GetDistance(); }*/ osg::Vec3 translation (0.0f, deltaDist, 0.0f); osg::Matrix mat; dtUtil::MatrixUtil::HprToMatrix(mat, hpr); translation = osg::Matrix::transform3x3(translation, mat); xyz += translation; if(mDistanceShouldChange) mTmpPrevDistance = newdist;//(mNewCenter-xyz).length(); trans.Set(xyz,oldhpr); } else{ //zooming only osg::Vec3 xyz,hpr; trans.Get(xyz,hpr); float deltaDist = mTmpPrevDistance - newdist; osg::Vec3 translation (0.0f, deltaDist, 0.0f); osg::Matrix mat; dtUtil::MatrixUtil::HprToMatrix(mat, hpr); translation = osg::Matrix::transform3x3(translation, mat); xyz += translation; if(mDistanceShouldChange) mTmpPrevDistance = newdist; trans.Set(xyz,hpr); } target->SetTransform(trans); } if(mAnimData._isRotating) { osg::Quat newRotation; newRotation.slerp(f, mAnimData._fromRotation, mAnimData._toRotation); if(f>=1.) { newRotation = mAnimData._toRotation; } Transform trans; target->GetTransform(trans); osg::Vec3 xyz; trans.GetTranslation(xyz); trans.Set(xyz,newRotation); target->SetTransform(trans); /** cursor interpolation */ if(mAnimData._interpolateCursor){ float newx, newy; float x,y; mMouse->GetPosition(x,y); //get current position in case the user is moving the mouse float oldx, oldy; oldx = mAnimData._previousPhase * (mAnimData._toCursor.x() - mAnimData._fromCursor.x()); oldy = mAnimData._previousPhase * (mAnimData._toCursor.y() - mAnimData._fromCursor.y()); newx = f * (mAnimData._toCursor.x() - mAnimData._fromCursor.x());// + x/*mAnimData._fromCursor.x()*/; newy = f * (mAnimData._toCursor.y() - mAnimData._fromCursor.y());// + y/*mAnimData._fromCursor.y()*/; float truex, truey; truex = newx - oldx + x; truey = newy - oldy + y; mMouse->SetPosition(truex,truey); } } mAnimData._previousPhase = f; if(f>=1.) { /*Transform trans; target->GetTransform(trans); trans.Set(trans.GetTranslation(), mAnimData._toRotation); target->SetTransform(trans);*/ mAnimData.reset(); //clear all data, set all flags on false => not animating anymore } } } }