void StelMovementMgr::panView(const double deltaAz, const double deltaAlt) { // The function is called in update loops, so make a quick check for exit. if ((deltaAz==0.) && (deltaAlt==0.)) return; double azVision, altVision; StelUtils::rectToSphe(&azVision,&altVision,j2000ToMountFrame(viewDirectionJ2000)); // Az is counted from South, eastward. // qDebug() << "Azimuth:" << azVision * 180./M_PI << "Altitude:" << altVision * 180./M_PI << "Up.X=" << upVectorMountFrame.v[0] << "Up.Y=" << upVectorMountFrame.v[1] << "Up.Z=" << upVectorMountFrame.v[2]; // if we are just looking into the pole, azimuth can hopefully be recovered from the customized up vector! // When programmatically centering on a pole, we should have set a better up vector for |alt|>0.9*M_PI/2. if (fabs(altVision)> 0.95* M_PI/2.) { if (upVectorMountFrame.v[2] < 0.9) { // qDebug() << "Recovering azimuth..."; azVision=atan2(-upVectorMountFrame.v[1], -upVectorMountFrame.v[0]); if (altVision < 0.) azVision+=M_PI; } // else // { // // qDebug() << "UpVector:" << upVectorMountFrame.v[0] << "/" << upVectorMountFrame.v[1] << "/" << upVectorMountFrame.v[2] << "Cannot recover azimuth. Hope it's OK"; // } } // if we are moving in the Azimuthal angle (left/right) if (deltaAz) azVision-=deltaAz; if (deltaAlt) { if (altVision+deltaAlt <= M_PI_2 && altVision+deltaAlt >= -M_PI_2) altVision+=deltaAlt; if (altVision+deltaAlt > M_PI_2) altVision = M_PI_2 - 0.000001; // Prevent bug if (altVision+deltaAlt < -M_PI_2) altVision = -M_PI_2 + 0.000001; // Prevent bug } // recalc all the position variables if (deltaAz || deltaAlt) { setFlagTracking(false); Vec3d tmp; StelUtils::spheToRect(azVision, altVision, tmp); setViewDirectionJ2000(mountFrameToJ2000(tmp)); setViewUpVector(Vec3d(0., 0., 1.)); // We ensured above that view vector is never parallel to this simple up vector. } }
void StelMovementMgr::moveToObject(const StelObjectP& target, float moveDuration, ZoomingMode zooming) { moveDuration /= movementsSpeedFactor; zoomingMode = zooming; move.aim=Vec3d(0); move.aimUp=mountFrameToJ2000(Vec3d(0., 0., 1.)); // the new up vector. We try simply vertical axis here. (Should be same as pre-0.15) move.aimUp.normalize(); move.start=viewDirectionJ2000; move.start.normalize(); move.startUp=getViewUpVectorJ2000(); move.startUp.normalize(); move.speed=1.f/(moveDuration*1000); move.coef=0.; move.targetObject = target; flagAutoMove = true; }
void StelMovementMgr::updateVisionVector(double deltaTime) { // Specialized setups cannot use this functionality! if (flagInhibitAllAutomoves) return; if (flagAutoMove) { if (!move.targetObject.isNull()) { // if zooming in, object may be moving so be sure to zoom to latest position // In case we have offset center, we want object still visible in center. // Note that if we do not center on an object, we set view direction of the potentially offset screen center! // This is by design, to allow accurate setting of display coordinates. Vec3d v; switch (mountMode) { case MountAltAzimuthal: v = move.targetObject->getAltAzPosAuto(core); break; case MountEquinoxEquatorial: v = move.targetObject->getEquinoxEquatorialPos(core); break; case MountGalactic: v = move.targetObject->getGalacticPos(core); break; default: qWarning() << "StelMovementMgr: unexpected mountMode" << mountMode; Q_ASSERT(0); v = move.targetObject->getAltAzPosAuto(core); // still do something useful } double lat, lon; StelUtils::rectToSphe(&lon, &lat, v); float altOffset=core->getCurrentStelProjectorParams().viewportCenterOffset[1]*currentFov*M_PI/180.0f; lat+=altOffset; StelUtils::spheToRect(lon, lat, v); move.aim=mountFrameToJ2000(v); move.aim.normalize(); move.aim*=2.; // For aiming at objects, we can assume simple up vector. move.startUp=getViewUpVectorJ2000(); move.aimUp=mountFrameToJ2000(Vec3d(0., 0., 1.)); } move.coef+=move.speed*deltaTime*1000; if (move.coef>=1.) { setViewUpVectorJ2000(move.aimUp); //qDebug() << "AutoMove finished. Setting Up vector (in mount frame) to " << upVectorMountFrame.v[0] << "/" << upVectorMountFrame.v[1] << "/" << upVectorMountFrame.v[2]; flagAutoMove=false; move.coef=1.; } else setViewUpVectorJ2000(move.startUp*(1.-move.coef) + move.aimUp*move.coef); // Use a smooth function float smooth = 4.f; double c; if (zoomingMode==ZoomIn) { if (move.coef>.9) { c = 1.; } else { c = 1. - pow(1.-1.11*move.coef,3.); } } else if (zoomingMode==ZoomOut) { if (move.coef<0.1) { // keep in view at first as zoom out c = 0; } else { c = pow(1.11*(move.coef-.1),3.); } } else c = std::atan(smooth * 2.*move.coef-smooth)/std::atan(smooth)/2+0.5; Vec3d tmpStart(j2000ToMountFrame(move.start)); Vec3d tmpAim(j2000ToMountFrame(move.aim)); double ra_aim, de_aim, ra_start, de_start; StelUtils::rectToSphe(&ra_start, &de_start, tmpStart); StelUtils::rectToSphe(&ra_aim, &de_aim, tmpAim); // Make sure the position of the object to be aimed at is defined... Q_ASSERT(move.aim[0]==move.aim[0] && move.aim[1]==move.aim[1] && move.aim[2]==move.aim[2]); // Trick to choose the good moving direction and never travel on a distance > PI if (ra_aim-ra_start > M_PI) { ra_aim -= 2.*M_PI; } else if (ra_aim-ra_start < -M_PI) { ra_aim += 2.*M_PI; } const double de_now = de_aim*c + de_start*(1.-c); const double ra_now = ra_aim*c + ra_start*(1.-c); Vec3d tmp; StelUtils::spheToRect(ra_now, de_now, tmp); setViewDirectionJ2000(mountFrameToJ2000(tmp)); // qDebug() << "setting view direction to " << tmp.v[0] << "/" << tmp.v[1] << "/" << tmp.v[2]; } else { if (flagTracking && objectMgr->getWasSelected()) // Equatorial vision vector locked on selected object { Vec3d v; switch (mountMode) { case MountAltAzimuthal: v = objectMgr->getSelectedObject()[0]->getAltAzPosAuto(core); break; case MountEquinoxEquatorial: v = objectMgr->getSelectedObject()[0]->getEquinoxEquatorialPos(core); break; case MountGalactic: v = objectMgr->getSelectedObject()[0]->getGalacticPos(core); break; default: qWarning() << "StelMovementMgr: unexpected mountMode" << mountMode; Q_ASSERT(0); v = move.targetObject->getAltAzPosAuto(core); // still do something useful in release build } double lat, lon; // general: longitudinal, latitudinal StelUtils::rectToSphe(&lon, &lat, v); float latOffset=core->getCurrentStelProjectorParams().viewportCenterOffset[1]*currentFov*M_PI/180.0f; lat+=latOffset; StelUtils::spheToRect(lon, lat, v); setViewDirectionJ2000(mountFrameToJ2000(v)); setViewUpVectorJ2000(mountFrameToJ2000(Vec3d(0., 0., 1.))); // Does not disturb to reassure this former default. } else { if (flagLockEquPos) // Equatorial vision vector locked { // Recalc local vision vector setViewDirectionJ2000(viewDirectionJ2000); } else { // Vision vector locked to its position in the mountFrame setViewDirectionJ2000(mountFrameToJ2000(viewDirectionMountFrame)); } } } }
Vec3d StelMovementMgr::getViewUpVectorJ2000() const { return mountFrameToJ2000(upVectorMountFrame); }
// Update autoZoom if activated void StelMovementMgr::updateAutoZoom(double deltaTime) { if (flagAutoZoom) { // Use a smooth function double c; if( zoomMove.startFov > zoomMove.aimFov ) { // slow down as we approach final view c = 1 - (1-zoomMove.coef)*(1-zoomMove.coef)*(1-zoomMove.coef); } else { // speed up as we leave zoom target c = (zoomMove.coef)*(zoomMove.coef)*(zoomMove.coef); } double newFov=zoomMove.startFov + (zoomMove.aimFov - zoomMove.startFov) * c; zoomMove.coef+=zoomMove.speed*deltaTime*1000; if (zoomMove.coef>=1.) { flagAutoZoom = 0; newFov=zoomMove.aimFov; } setFov(newFov); // updates currentFov->don't use newFov later! // In case we have offset center, we want object still visible in center. if (flagTracking && objectMgr->getWasSelected()) // vision vector locked on selected object { Vec3d v, vUp; switch (mountMode) { case MountAltAzimuthal: v = objectMgr->getSelectedObject()[0]->getAltAzPosAuto(core); break; case MountEquinoxEquatorial: v = objectMgr->getSelectedObject()[0]->getEquinoxEquatorialPos(core); break; case MountGalactic: v = objectMgr->getSelectedObject()[0]->getGalacticPos(core); break; default: qWarning() << "StelMovementMgr: unexpected mountMode" << mountMode; Q_ASSERT(0); } double lat, lon; // general: longitudinal, latitudinal StelUtils::rectToSphe(&lon, &lat, v); // guaranteed to be normalized. // vUp could usually be (0/0/1) in most cases, unless |lat|==pi/2. We MUST build an adequate Up vector! if (fabs(lat)>0.9*M_PI/2.0) { vUp = Vec3d(-cos(lon), -sin(lon), 0.) * (lat>0. ? 1. : -1. ); } else vUp.set(0.,0.,1.); float latOffset=core->getCurrentStelProjectorParams().viewportCenterOffset[1]*currentFov*M_PI/180.0f; lat+=latOffset; StelUtils::spheToRect(lon, lat, v); if (flagAutoMove) { move.aim=mountFrameToJ2000(v); move.aim.normalize(); move.aim*=2.; move.aimUp=mountFrameToJ2000(vUp); move.aimUp.normalize(); } else { setViewDirectionJ2000(mountFrameToJ2000(v)); setViewUpVectorJ2000(mountFrameToJ2000(vUp)); } } } }
// Unzoom and go to the init position void StelMovementMgr::autoZoomOut(float moveDuration, bool full) { moveDuration /= movementsSpeedFactor; if (objectMgr->getWasSelected() && !full) { // If the selected object has satellites, unzoom to satellites view // unless specified otherwise float satfov = objectMgr->getSelectedObject()[0]->getSatellitesFov(core); if (satfov>0.0 && currentFov<=satfov*0.9) { zoomTo(satfov, moveDuration); return; } // If the selected object is part of a Planet subsystem (other than sun), // unzoom to subsystem view satfov = objectMgr->getSelectedObject()[0]->getParentSatellitesFov((core)); if (satfov>0.0 && currentFov<=satfov*0.9) { zoomTo(satfov, moveDuration); return; } } zoomTo(initFov, moveDuration); if (flagAutoZoomOutResetsDirection) { moveToJ2000(core->altAzToJ2000(getInitViewingDirection(), StelCore::RefractionOff), mountFrameToJ2000(Vec3d(0., 0., 1.)), moveDuration, ZoomOut); setFlagTracking(false); setFlagLockEquPos(false); } }