Eegeo::Camera::GlobeCamera::GlobeCameraController* DefaultCameraControllerFactory::Create()
 {
     Eegeo::Camera::GlobeCamera::GlobeCameraController* pController = new Eegeo::Camera::GlobeCamera::GlobeCameraController(
                                                                  m_terrainModelModule.GetTerrainHeightProvider(),
                                                                  m_mapModule.GetEnvironmentFlatteningService(),
                                                                  m_mapModule.GetResourceCeilingProvider(),
                                                                  m_touchController,
                                                                  m_config,
                                                                  m_screenPropertiesProvider.GetScreenProperties());
     
     // override default configuration to enable two-finger pan gesture to control additional camera pitch
     Eegeo::Camera::GlobeCamera::GlobeCameraTouchSettings touchSettings = pController->GetTouchSettings();
     touchSettings.TiltEnabled = m_tiltEnabled;
     pController->SetTouchSettings(touchSettings);
     
     Eegeo::Space::LatLongAltitude location = Eegeo::Space::LatLongAltitude::FromDegrees(m_interestPointLatitudeDegrees,
                                                                                         m_interestPointLongitudeDegrees,
                                                                                         m_interestPointAltitudeMeters);
     
     
     
     Eegeo::Space::EcefTangentBasis cameraInterestBasis;
     Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(location.ToECEF(), m_cameraControllerOrientationDegrees, cameraInterestBasis);
     
     pController->SetView(cameraInterestBasis, m_cameraControllerDistanceFromInterestPointMeters);
     
     return pController;
 }
                bool PoiRingTouchController::HandleTouchMove(const AppInterface::TouchData &data, const Eegeo::Camera::RenderCamera &renderCamera, Eegeo::Camera::GlobeCamera::GlobeCameraController& globeCameraController)
                {
                    if (m_myPinCreationModel.GetCreationStage() != Ring)
                    {
                        return false;
                    }

                    if (m_isDragging)
                    {
                        float screenPixelX = data.point.GetX();
                        float screenPixelY = data.point.GetY();

                        Eegeo::dv3 rayDirection;
                        Eegeo::Camera::CameraHelpers::GetScreenPickRay(renderCamera, screenPixelX, screenPixelY, rayDirection);

                        Eegeo::dv3 rayOrigin = globeCameraController.ComputeNonFlattenedCameraPosition();
                        Eegeo::dv3 rayIntersectionPoint;
                        double intersectionParam;
                        bool rayPick = PerformRayPick(rayOrigin, rayDirection, rayIntersectionPoint, intersectionParam);

                        if (rayPick)
                        {
                            m_myPinCreationModel.SetPosition(rayIntersectionPoint);
                        }

                        return true;
                    }

                    return false;
                }
RouteDrawingExample::RouteDrawingExample(RouteService& routeService,
        EegeoWorld& world,
        Eegeo::Camera::GlobeCamera::GlobeCameraController& cameraController)
	:m_routeService(routeService)
	,m_world(world)
	,m_createdRoutes(false)
	,m_globeCameraStateRestorer(cameraController)
{
	Eegeo::Space::EcefTangentBasis cameraInterestBasis;

	Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(
	    Eegeo::Space::LatLong::FromDegrees(37.793348, -122.399035).ToECEF(),
	    354.824249,
	    cameraInterestBasis);

	cameraController.SetView(cameraInterestBasis, 1374.298706);
}
                bool PoiRingTouchController::HandleTouchDown(const AppInterface::TouchData& data, const Eegeo::Camera::RenderCamera& renderCamera, Eegeo::Camera::GlobeCamera::GlobeCameraController& globeCameraController)
                {
                    if (m_myPinCreationModel.GetCreationStage() != Ring)
                    {
                        return false;
                    }

                    float screenPixelX = data.point.GetX();
                    float screenPixelY = data.point.GetY();

                    Eegeo::dv3 rayDirection;
                    Eegeo::Camera::CameraHelpers::GetScreenPickRay(renderCamera, screenPixelX, screenPixelY, rayDirection);

                    Eegeo::dv3 rayOrigin = globeCameraController.ComputeNonFlattenedCameraPosition();
                    Eegeo::dv3 rayIntersectionPoint;
                    double intersectionParam;

                    bool rayPick = PerformRayPick(rayOrigin, rayDirection, rayIntersectionPoint, intersectionParam);

                    if (rayPick)
                    {
                        Eegeo::dv3 iconPosition;
                        float iconSize;
                        m_poiRingController.GetIconPositionAndSize(iconPosition, iconSize);
                        
                        Eegeo::dv3 spherePosition;
                        float sphereRadius;
                        m_poiRingController.GetSpherePositionAndRadius(spherePosition, sphereRadius);

                        bool hitIcon = Eegeo::Geometry::IntersectionTests::TestRaySphere(rayOrigin, rayDirection, iconPosition, iconSize/2.0f);
                        if ((rayIntersectionPoint - spherePosition).Length() < sphereRadius || hitIcon)
                        {
                            m_isDragging = true;
                            return true;
                        }
                    }

                    return false;
                }