void PositionJavaPinButtonExample::Project (const Eegeo::Space::LatLongAltitude& location, Eegeo::v3& screenPosition)
{
	//project a 3D Ecef location to the screen
	Eegeo::m44 finalMatrix;

	Eegeo::Camera::RenderCamera renderCamera(GetGlobeCameraController().GetRenderCamera());

	Eegeo::m44::Mul (finalMatrix,
	                 renderCamera.GetProjectionMatrix(),
	                 renderCamera.GetViewMatrix());

	Eegeo::v3 local = (location.ToECEF() - renderCamera.GetEcefLocation()).ToSingle();
	Eegeo::v4 inVector(local, 1.0f);

	// get clip space coords
	Eegeo::v4 outVector = Eegeo::v4::Mul(inVector, finalMatrix);

	// divide through by w to get normalized device space coords -- range [-1, 1]
	screenPosition.SetX((outVector.GetX()/outVector.GetW()));
	screenPosition.SetY((outVector.GetY()/outVector.GetW()));
	screenPosition.SetZ((outVector.GetZ()/outVector.GetW()));

	// transform from [-1, 1] to [0, 1]
	screenPosition.SetX((screenPosition.GetX() + 1.0f) * 0.5f);
	screenPosition.SetY(1.0f - ((screenPosition.GetY() + 1.0f) * 0.5f));

	float viewport[] = {0, 0, renderCamera.GetViewportWidth(), renderCamera.GetViewportHeight()};

	// transform from [0, 1] to screen coords.
	screenPosition.SetX((screenPosition.GetX()*(viewport[2]-viewport[0])) + viewport[0]);
	screenPosition.SetY((screenPosition.GetY()*(viewport[3]-viewport[1])) + viewport[1]);
}
 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;
 }
void ExampleCameraJumpController::JumpTo(const Eegeo::Space::LatLongAltitude& interestPoint)
{
	Eegeo::Space::EcefTangentBasis interestBasis = m_cameraController.GetInterestBasis();
	interestBasis.SetPoint(interestPoint.ToECEF());
	m_cameraController.SetInterestBasis(interestBasis);
	m_cameraTouchController.Reset();
}
void Pick3DObjectExample::Start()
{
	m_movingObject = false;

	Eegeo::Space::LatLongAltitude objectStartLocation = m_interestLocation;
	objectStartLocation.SetAltitude(200.0f);
	m_objectLocationEcef = objectStartLocation.ToECEF();

	CreateSphereAtLocation(m_objectLocationEcef, UNPICKED_COLOUR);
}
void ExampleCameraJumpController::JumpTo(const Eegeo::Space::LatLongAltitude& interestPoint, float cameraHeadingDegrees, float cameraDistanceToInterest)
{
	// calculate a new interest coordinate basis
	Eegeo::Space::EcefTangentBasis interestBasis;
	Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(interestPoint.ToECEF(), cameraHeadingDegrees, interestBasis);

	// command the camera controller to set its view point
	m_cameraController.SetView(interestBasis, cameraDistanceToInterest);

	// reset the camera touch controller, so any camera movement due to touch input is cancelled
	m_cameraTouchController.Reset();
}
    void DynamicText3DExample::CreateDynamic3DText(const std::string& str,
                                                   float fontPointSize,
                                                   double latitudeDegrees,
                                                   double longitudeDegrees,
                                                   const Eegeo::v3& colour,
                                                   float alpha)
    {
        Eegeo::Space::LatLongAltitude location = Eegeo::Space::LatLongAltitude::FromDegrees(latitudeDegrees, longitudeDegrees, 0.f);
        Eegeo::dv3 posEcef = location.ToECEF();
        Eegeo::Space::CubeMap::CubeMapCellInfo cellInfo(Space::CubeMap::EcefToKey(posEcef, 15));

        std::vector<u32> textUtf32;
        Unicode::UnicodeConverter::Utf8ToUtf32(str.c_str(), textUtf32);

        Resources::PlaceNames::PlaceNameView* pPlaceNameView = m_placeNameViewBuilder.CreatePlaceNameView(textUtf32, "", fontPointSize, posEcef, "", cellInfo);

        if (pPlaceNameView != NULL)
        {
            pPlaceNameView->GetConfig().UpdateColorAndScale(colour, 1.f);
            pPlaceNameView->SetAlpha(alpha);
            m_views.push_back(pPlaceNameView);
        }
    }
ExampleApp::ExampleApp(Eegeo::EegeoWorld* pWorld,
                       Eegeo::Camera::GlobeCamera::GlobeCameraInterestPointProvider& globeCameraInterestPointProvider,
                       Examples::ExampleController& exampleController)
	: m_pGlobeCameraController(NULL)
	, m_pCameraTouchController(NULL)
	, m_globeCameraInterestPointProvider(globeCameraInterestPointProvider)
	, m_pWorld(pWorld)
	, m_exampleController(exampleController)
{
	Eegeo_ASSERT(&m_globeCameraInterestPointProvider != NULL);

	Eegeo::EegeoWorld& eegeoWorld = *pWorld;

	Eegeo::Camera::GlobeCamera::GlobeCameraTouchControllerConfiguration touchControllerConfig = Eegeo::Camera::GlobeCamera::GlobeCameraTouchControllerConfiguration::CreateDefault();

	// override default configuration to enable two-finger pan gesture to control additional camera pitch
	touchControllerConfig.tiltEnabled = true;

	m_pCameraTouchController = new Eegeo::Camera::GlobeCamera::GlobeCameraTouchController(touchControllerConfig);

	const bool useLowSpecSettings = false;
	Eegeo::Camera::GlobeCamera::GlobeCameraControllerConfiguration globeCameraControllerConfig = Eegeo::Camera::GlobeCamera::GlobeCameraControllerConfiguration::CreateDefault(useLowSpecSettings);

	m_pGlobeCameraController = new Eegeo::Camera::GlobeCamera::GlobeCameraController(eegeoWorld.GetTerrainHeightProvider(),
	        eegeoWorld.GetEnvironmentFlatteningService(),
	        eegeoWorld.GetResourceCeilingProvider(),
	        *m_pCameraTouchController,
	        globeCameraControllerConfig);

	Eegeo::Camera::RenderCamera* renderCamera = m_pGlobeCameraController->GetCamera();
	const Eegeo::Rendering::RenderContext& renderContext = eegeoWorld.GetRenderContext();
	renderCamera->SetViewport(0.f, 0.f, renderContext.GetScreenWidth(), renderContext.GetScreenHeight());
	eegeoWorld.SetCamera(renderCamera);

	m_globeCameraInterestPointProvider.SetGlobeCamera(m_pGlobeCameraController);

	float interestPointLatitudeDegrees = 37.7858f;
	float interestPointLongitudeDegrees = -122.401f;
	float interestPointAltitudeMeters = 2.7;

	Eegeo::Space::LatLongAltitude location = Eegeo::Space::LatLongAltitude::FromDegrees(interestPointLatitudeDegrees,
	        interestPointLongitudeDegrees,
	        interestPointAltitudeMeters);

	float cameraControllerOrientationDegrees = 0.0f;
	float cameraControllerDistanceFromInterestPointMeters = 1781.0f;

	Eegeo::Space::EcefTangentBasis cameraInterestBasis;
	Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(location.ToECEF(), cameraControllerOrientationDegrees, cameraInterestBasis);

	m_pGlobeCameraController->SetView(cameraInterestBasis, cameraControllerDistanceFromInterestPointMeters);

	//register all generic examples
    m_exampleController.RegisterCameraExample<Examples::CameraSplineExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::CameraTransitionExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::ControlCityThemeExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::DebugPrimitiveRenderingExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::DebugSphereExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::DynamicText3DExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::EnvironmentFlatteningExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::EnvironmentNotifierExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::FileIOExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::LoadModelExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::ModifiedRenderingExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::NavigationGraphExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::Pick3DObjectExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::PinsExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::PinOverModelExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::PODAnimationExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::RenderToTextureExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::ResourceSpatialQueryExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::RouteDrawingExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::RouteSimulationAnimationExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::RouteThicknessPolicyExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::ScreenPickExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::ScreenUnprojectExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::SingleCityExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::ToggleTrafficExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::TrafficCongestionExampleFactory>(*m_pGlobeCameraController);
	m_exampleController.RegisterCameraExample<Examples::WebRequestExampleFactory>(*m_pGlobeCameraController);
}
    MobileExampleApp::MobileExampleApp(
        const std::string& apiKey,
        Eegeo::Modules::IPlatformAbstractionModule& platformAbstractions,
        Eegeo::Rendering::ScreenProperties& screenProperties,
        Eegeo::Location::ILocationService& locationService,
        Eegeo::UI::NativeUIFactories& nativeUIFactories,
        Eegeo::Config::PlatformConfig platformConfig,
        Eegeo::Helpers::Jpeg::IJpegLoader& jpegLoader,
        ExampleApp::InitialExperience::SdkModel::IInitialExperienceModule& initialExperienceModule,
        ExampleApp::PersistentSettings::IPersistentSettingsModel& persistentSettings,
        ExampleAppMessaging::TMessageBus& messageBus,
        ExampleAppMessaging::TSdkModelDomainEventBus& sdkModelDomainEventBus,
        Net::SdkModel::INetworkCapabilities& networkCapabilities,
        ExampleApp::Search::SdkModel::ISearchServiceModule& searchServiceModule,
        ExampleApp::Metrics::IMetricsService& metricsService,
        const ExampleApp::ApplicationConfig::ApplicationConfiguration& applicationConfiguration,
        Eegeo::IEegeoErrorHandler& errorHandler)
        : m_pGlobeCameraController(NULL)
        , m_pCameraTouchController(NULL)
        , m_pCurrentTouchController(NULL)
        , m_pNavigationService(NULL)
        , m_pWorld(NULL)
        , m_platformAbstractions(platformAbstractions, networkCapabilities)
        , m_pLoadingScreen(NULL)
        , m_pinDiameter(48.f)
        , m_initialisedApplicationViewState(false)
        , m_pCameraTransitionController(NULL)
        , m_pSecondaryMenuModule(NULL)
        , m_pSearchResultMenuModule(NULL)
        , m_pModalityModule(NULL)
        , m_pCategorySearchModule(NULL)
        , m_pMapModeModule(NULL)
        , m_pFlattenButtonModule(NULL)
        , m_pSearchModule(NULL)
        , m_pPinIconsTexturePageLayout(NULL)
        , m_pPinsModule(NULL)
        , m_pWorldPinsModule(NULL)
        , m_pSearchResultOnMapModule(NULL)
        , m_pReactionModelModule(NULL)
        , m_pReactionControllerModule(NULL)
        , m_pSearchResultPoiModule(NULL)
        , m_pPlaceJumpsModule(NULL)
        , m_pWeatherMenuModule(NULL)
        , m_pCompassModule(NULL)
        , m_pGpsMarkerModule(NULL)
        , m_pWorldAreaLoaderModule(NULL)
        , m_pAboutPageModule(NULL)
        , m_initialExperienceModule(initialExperienceModule)
        , m_pBlitter(NULL)
        , m_messageBus(messageBus)
        , m_sdkDomainEventBus(sdkModelDomainEventBus)
        , m_persistentSettings(persistentSettings)
        , m_pMyPinCreationModule(NULL)
        , m_pPoiRingModule(NULL)
        , m_pMyPinCreationDetailsModule(NULL)
        , m_pMyPinsModule(NULL)
        , m_pMyPinDetailsModule(NULL)
        , m_pOptionsModule(NULL)
        , m_pWatermarkModule(NULL)
        , m_pInteriorsExplorerModule(NULL)
        , m_pInteriorsEntitiesPinsModule(NULL)
        , m_screenProperties(screenProperties)
        , m_networkCapabilities(networkCapabilities)
        , m_setMetricsLocation(false)
        , m_searchServiceModule(searchServiceModule)
        , m_metricsService(metricsService)
        , m_applicationConfiguration(applicationConfiguration)
        , m_interiorsEnabled(platformConfig.OptionsConfig.EnableInteriors)
    {
        m_metricsService.BeginSession(ExampleApp::FlurryApiKey, EEGEO_PLATFORM_VERSION_NUMBER);

        m_pBlitter = Eegeo_NEW(Eegeo::Blitter)(1024 * 128, 1024 * 64, 1024 * 32);
        m_pBlitter->Initialise();
        
        m_pWorld = Eegeo_NEW(Eegeo::EegeoWorld)(apiKey,
                                                m_platformAbstractions,
                                                jpegLoader,
                                                screenProperties,
                                                locationService,
                                                *m_pBlitter,
                                                nativeUIFactories,
                                                Eegeo::EnvironmentCharacterSet::Latin,
                                                platformConfig,
                                                NULL,
                                                "http://cdn1.eegeo.com/coverage-trees/vglobal/v742/manifest.txt.gz",
                                                "http://d2xvsc8j92rfya.cloudfront.net/mobile-themes-new/v366/manifest.txt.gz",
                                                &errorHandler
                                                );

        Eegeo::Modules::Map::Layers::TerrainModelModule& terrainModelModule = m_pWorld->GetTerrainModelModule();
        Eegeo::Modules::Map::MapModule& mapModule = m_pWorld->GetMapModule();

        m_pNavigationService = Eegeo_NEW(Eegeo::Location::NavigationService)(&m_pWorld->GetLocationService(),
                               &terrainModelModule.GetTerrainHeightProvider());

        Eegeo::Camera::GlobeCamera::GpsGlobeCameraControllerFactory cameraControllerFactory(terrainModelModule.GetTerrainHeightProvider(),
                mapModule.GetEnvironmentFlatteningService(),
                mapModule.GetResourceCeilingProvider(),
                *m_pNavigationService);

        m_pAppModeModel = Eegeo_NEW(AppModes::SdkModel::AppModeModel)(m_pWorld->GetMapModule().GetInteriorsPresentationModule().GetInteriorSelectionModel(), m_messageBus);

        const bool useLowSpecSettings = false;

        Eegeo::Camera::GlobeCamera::GpsGlobeCameraComponentConfiguration gpsGlobeCameraConfig = Eegeo::Camera::GlobeCamera::GpsGlobeCameraComponentConfiguration::CreateDefault();
        gpsGlobeCameraConfig.panToUnlockThreshold =  0.03f;
        Eegeo::Camera::GlobeCamera::GlobeCameraTouchControllerConfiguration touchControllerConfig = Eegeo::Camera::GlobeCamera::GlobeCameraTouchControllerConfiguration::CreateDefault();
        Eegeo::Camera::GlobeCamera::GlobeCameraControllerConfiguration globeCameraConfig = Eegeo::Camera::GlobeCamera::GlobeCameraControllerConfiguration::CreateDefault(useLowSpecSettings);

        m_pGlobeCameraController = cameraControllerFactory.Create(gpsGlobeCameraConfig, touchControllerConfig, globeCameraConfig, m_screenProperties);

        m_pCameraTouchController = &m_pGlobeCameraController->GetTouchController();

        Eegeo::Camera::GlobeCamera::GlobeCameraTouchSettings touchSettings = m_pGlobeCameraController->GetGlobeCameraController().GetTouchSettings();
        touchSettings.TiltEnabled = true;
        m_pGlobeCameraController->GetGlobeCameraController().SetTouchSettings(touchSettings);

        Eegeo::Space::LatLongAltitude location = m_applicationConfiguration.InterestLocation();
        float cameraControllerOrientationDegrees = m_applicationConfiguration.OrientationDegrees();
        float cameraControllerDistanceFromInterestPointMeters = m_applicationConfiguration.DistanceToInterestMetres();

        Eegeo::Space::EcefTangentBasis cameraInterestBasis;
        Eegeo::Camera::CameraHelpers::EcefTangentBasisFromPointAndHeading(location.ToECEF(), cameraControllerOrientationDegrees, cameraInterestBasis);

        m_pGlobeCameraController->SetView(cameraInterestBasis, cameraControllerDistanceFromInterestPointMeters);

        m_pCameraTransitionController = Eegeo_NEW(ExampleApp::CameraTransitions::SdkModel::CameraTransitionController)(*m_pGlobeCameraController, *m_pNavigationService, terrainModelModule.GetTerrainHeightProvider());

        m_pStreamingVolume = Eegeo_NEW(Eegeo::Streaming::CameraFrustumStreamingVolume)(mapModule.GetResourceCeilingProvider(),
                                                                                       Eegeo::Config::LodRefinementConfig::GetLodRefinementAltitudesForDeviceSpec(platformConfig.PerformanceConfig.DeviceSpecification),
                                                                                       Eegeo::Streaming::QuadTreeCube::MAX_DEPTH_TO_VISIT,
                                                                                       mapModule.GetEnvironmentFlatteningService());
        
        CreateApplicationModelModules();
        
        m_pLoadingScreen = CreateLoadingScreen(screenProperties, m_pWorld->GetRenderingModule(), m_pWorld->GetPlatformAbstractionModule());


        
        if(m_applicationConfiguration.TryStartAtGpsLocation())
        {
            m_pNavigationService->SetGpsMode(Eegeo::Location::NavigationService::GpsModeFollow);
        }
    }