text: ////////////////////////////////////////////////////////////////////////////////////////////////////
  //                               This file is part of CosmoScout VR                               //
  //      and may be used under the terms of the MIT license. See the LICENSE file for details.     //
  //                        Copyright: (c) 2019 German Aerospace Center (DLR)                       //
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  #include "CelestialObserver.hpp"
  
  namespace cs::scene {
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  CelestialObserver::CelestialObserver(std::string const& sCenterName, std::string const& sFrameName)
      : CelestialAnchor(sCenterName, sFrameName) {
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  void CelestialObserver::updateMovementAnimation(double tTime) {
    if (mAnimationInProgress) {
      mPosition = mAnimatedPosition.get(tTime);
      mRotation = mAnimatedRotation.get(tTime);
  
      if (mAnimatedPosition.mEndTime < tTime)
        mAnimationInProgress = false;
    }
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  void CelestialObserver::setAnchorPosition(glm::dvec3 const& vPos) {
    if (!mAnimationInProgress) {
      CelestialAnchor::setAnchorPosition(vPos);
    }
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  void CelestialObserver::setAnchorRotation(glm::dquat const& qRot) {
    if (!mAnimationInProgress) {
      CelestialAnchor::setAnchorRotation(qRot);
    }
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  void CelestialObserver::changeOrigin(
      std::string const& sCenterName, std::string const& sFrameName, double dSimulationTime) {
    if (!mAnimationInProgress) {
      cs::scene::CelestialAnchor target(sCenterName, sFrameName);
  
      glm::dvec3 pos = target.getRelativePosition(dSimulationTime, *this);
      glm::dquat rot = target.getRelativeRotation(dSimulationTime, *this);
  
      setCenterName(sCenterName);
      setFrameName(sFrameName);
  
      setAnchorRotation(rot);
      setAnchorPosition(pos);
    }
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  void CelestialObserver::moveTo(std::string const& sCenterName, std::string const& sFrameName,
      glm::dvec3 const& position, glm::dquat const& rotation, double dSimulationTime,
      double dRealStartTime, double dRealEndTime) {
    mAnimationInProgress = false;
  
    cs::scene::CelestialAnchor target(sCenterName, sFrameName);
  
    glm::dvec3 startPos = target.getRelativePosition(dSimulationTime, *this);
    glm::dquat startRot = target.getRelativeRotation(dSimulationTime, *this);
  
    setCenterName(sCenterName);
    setFrameName(sFrameName);
  
    double cosTheta = glm::dot(startRot, rotation);
  
    // If cosTheta < 0, the interpolation will take the long way around the sphere.
    // To fix this, one quat must be negated.
    if (cosTheta < 0.0) {
      startRot = -startRot;
    }
  
    setAnchorRotation(startRot);
    setAnchorPosition(startPos);
  
    mAnimatedPosition = utils::AnimatedValue<glm::dvec3>(
        startPos, position, dRealStartTime, dRealEndTime, utils::AnimationDirection::eInOut);
  
    mAnimatedRotation = utils::AnimatedValue<glm::dquat>(
        startRot, rotation, dRealStartTime, dRealEndTime, utils::AnimationDirection::eInOut);
  
    mAnimationInProgress = true;
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  } // namespace cs::scene
  