void TransitionToWorldPointStage::Update(float dt)
            {
                if(m_jumpIfFar && ShouldJumpTo(m_endTransitionInterestPointEcef))
                {
                    m_transitionTime = m_transitionDuration;

                    // Calling SetView here instead of just doing an early-out so that anything that depends on the camera's position will work
                    // (such as mapscene startup searches) [MPLY-8855]
                    Eegeo::v3 endHeadingVector = ComputeHeadingVector(m_endTransitionInterestPointEcef, m_endInterestHeading);
                    Eegeo::Space::EcefTangentBasis newInterestBasis(m_endTransitionInterestPointEcef, endHeadingVector);
                    m_gpsGlobeCameraController.SetView(newInterestBasis, m_endInterestDistance);
                    return;
                }
                
                m_transitionTime += dt;
                float transitionParam = Eegeo::Math::SmoothStep(0.f, 1.f, m_transitionTime / m_transitionDuration);
                
                float interpolatedDistance = Eegeo::Math::Lerp(m_startInterestDistance, m_endInterestDistance, transitionParam);
                Eegeo::dv3 interpolatedInterestPosition = Eegeo::dv3::Lerp(m_startTransitionInterestPointEcef, m_endTransitionInterestPointEcef, transitionParam);
                float currentAssumedAltitude = 0;
                
                m_terrainHeightProvider.TryGetHeight(interpolatedInterestPosition, 0, currentAssumedAltitude);
                
                if(interpolatedInterestPosition.Length() < Eegeo::Space::EarthConstants::Radius + currentAssumedAltitude)
                {
                    interpolatedInterestPosition = interpolatedInterestPosition.Norm() * (Eegeo::Space::EarthConstants::Radius + currentAssumedAltitude);
                }
                
                float interpolatedHeading = Eegeo::Math::Lerp<float>(m_startInterestHeading, m_endInterestHeading, transitionParam);
                Eegeo::v3 interpolatedHeadingVector = ComputeHeadingVector(interpolatedInterestPosition, interpolatedHeading);
                
                Eegeo::Space::EcefTangentBasis newInterestBasis(interpolatedInterestPosition, interpolatedHeadingVector);
                m_gpsGlobeCameraController.SetView(newInterestBasis, interpolatedDistance);
            }
 void TransitionToInteriorPointStage::Update(float dt)
 {
     if(m_failed)
     {
         return;
     }
     
     if(!m_initialisedNextInterior && m_interiorInteractionModel.HasInteriorModel())
     {
         m_interiorInteractionModel.SetSelectedFloorIndex(m_targetFloorIndex);
         m_endCameraInterestAltitude = m_cameraController.GetFloorOffsetHeight();
         m_cameraInterestAltitudeStartTime = m_transitionTime;
         m_initialisedNextInterior = true;
     }
     
     if(m_jumpIfFar && ShouldJumpTo(m_newInterestPoint))
     {
         m_transitionTime = 1.01f;
     }
     else
     {
         m_transitionTime += dt/m_transitionDuration;
         float t = Eegeo::Math::Clamp01(m_transitionTime);
         float smoothT = Eegeo::Math::SmoothStep(t);
         Eegeo::dv3 lerpInterestPoint = Eegeo::dv3::Lerp(m_startInterestPoint, m_newInterestPoint, smoothT);
         m_cameraController.SetInterestLocation(lerpInterestPoint);
         
         float lerpDistance = Eegeo::Math::Lerp(m_startDistanceToInterest, m_targetDistanceToInterest, smoothT);
         m_cameraController.SetDistanceToInterest(lerpDistance);
         
         if(m_initialisedNextInterior)
         {
             float t2 = m_cameraInterestAltitudeStartTime >= 1.0f ? 1.0f : Eegeo::Math::Clamp01((m_transitionTime - m_cameraInterestAltitudeStartTime)/(1.0f-m_cameraInterestAltitudeStartTime));
             float smoothT2 = Eegeo::Math::SmoothStep(t2);
             float lerpAltitude = Eegeo::Math::Lerp(m_startCameraInterestAltitude, m_endCameraInterestAltitude, smoothT2);
             m_cameraController.SetCameraInterestAltitude(lerpAltitude);
         }
     }
     
     // Check fail condition and clean up on fail
     if(!m_interiorSelectionModel.IsInteriorSelected())
     {
         m_failed = true;
         m_cameraController.SetApplyRestrictions(true);
         m_cameraController.SetApplyFloorOffset(true);
     }
     
 }
            void CameraTransitionController::StartTransitionTo(Eegeo::dv3 newInterestPoint, float distanceFromInterest, float newHeadingRadians, bool jumpIfFar)
            {
                if(IsTransitioning())
                {
                    StopCurrentTransition();
                }

                m_navigationService.SetGpsMode(Eegeo::Location::NavigationService::GpsModeOff);

                if(jumpIfFar && ShouldJumpTo(newInterestPoint))
                {
                    Eegeo::Space::EcefTangentBasis newInterestBasis;
                    Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(newInterestPoint,
                            Eegeo::Math::Rad2Deg(newHeadingRadians),
                            newInterestBasis);
                    m_cameraController.SetView(newInterestBasis, distanceFromInterest);
                    return;
                }

                const Eegeo::Space::EcefTangentBasis& currentInterestBasis = m_cameraController.GetInterestBasis();
                m_startTransitionInterestPointEcef = currentInterestBasis.GetPointEcef();
                m_startInterestDistance = m_cameraController.GetDistanceToInterest();
                m_startInterestHeading = Eegeo::Camera::CameraHelpers::GetAbsoluteBearingRadians(currentInterestBasis.GetPointEcef(),
                                         currentInterestBasis.GetForward());;

                m_endTransitionInterestPointEcef = newInterestPoint;
                m_endInterestDistance = distanceFromInterest;
                m_endInterestHeading = newHeadingRadians;

                m_transitionTime = 0.0f;

                const float CAMERA_TRANSITION_SPEED_IN_METERS_PER_SECOND = 1000.0f;
                const float MIN_TRANSITION_TIME = 0.5f;
                const float MAX_TRANSITION_TIME = 2.0f;
                float distance = (m_endTransitionInterestPointEcef - m_startTransitionInterestPointEcef).ToSingle().Length();

                m_transitionDuration = Eegeo::Clamp(distance/CAMERA_TRANSITION_SPEED_IN_METERS_PER_SECOND, MIN_TRANSITION_TIME, MAX_TRANSITION_TIME);

                m_isTransitioning = true;

                if(std::abs(m_endInterestHeading - m_startInterestHeading) > Eegeo::Math::kPI)
                {
                    if(m_endInterestHeading > m_startInterestHeading)
                        m_endInterestHeading -= 2.f * Eegeo::Math::kPI;
                    else
                        m_startInterestHeading -= 2.f * Eegeo::Math::kPI;
                }
            }
void CameraTransitioner::StartTransitionTo(Eegeo::dv3 newInterestPoint, double distanceFromInterest, float newHeading, bool jumpIfFarAway)
{
	if(IsTransitioning())
	{
		StopCurrentTransition();
	}

	if(jumpIfFarAway && ShouldJumpTo(newInterestPoint))
	{
		Eegeo::Space::EcefTangentBasis newInterestBasis;
		Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(newInterestPoint, Eegeo::Math::Rad2Deg(newHeading), newInterestBasis);
		m_cameraController.SetView(newInterestBasis, distanceFromInterest);
		StopCurrentTransition();
		return;
	}

	const Eegeo::Space::EcefTangentBasis& currentInterestBasis = m_cameraController.GetInterestBasis();
	m_startTransitionInterestPoint = currentInterestBasis.GetPointEcef();
	m_startInterestDistance = m_cameraController.GetDistanceToInterest();

	float bearingRadians = Eegeo::Camera::CameraHelpers::GetAbsoluteBearingRadians(currentInterestBasis.GetPointEcef(), currentInterestBasis.GetForward());
	m_startTransitionHeading = bearingRadians;
	m_endTransitionHeading = newHeading;
	m_endTransitionInterestPoint = newInterestPoint;
	m_endInterestDistance = distanceFromInterest;
	m_transitionTime = 0.f;

	const float CAMERA_TRANSITION_SPEED_IN_METERS_PER_SECOND = 100.0f;
	const float MIN_TRANSITION_TIME = 2.0f;
	const float MAX_TRANSITION_TIME = 10.0f;
	float distance = (m_endTransitionInterestPoint - m_startTransitionInterestPoint).Length();

	m_transitionDuration = Eegeo::Clamp(distance/CAMERA_TRANSITION_SPEED_IN_METERS_PER_SECOND, MIN_TRANSITION_TIME, MAX_TRANSITION_TIME);

	m_isTransitioning = true;

	if(abs(m_endTransitionHeading - m_startTransitionHeading) > M_PI)
	{
		if(m_endTransitionHeading > m_startTransitionHeading)
			m_endTransitionHeading -= 2 * M_PI;
		else
			m_startTransitionHeading -= 2 * M_PI;
	}

}