float AppCameraSplinePlaybackWrapper::GetHeadingDegrees() const
 {
     const Eegeo::m44 view = m_splinePlaybackController.GetCameraState().ViewMatrix();
     const Eegeo::v3 forward = Eegeo::v3(view.GetRow(0).z, view.GetRow(1).z, view.GetRow(2).z).Norm();
     const float headingRadians = Eegeo::Camera::CameraHelpers::GetAbsoluteBearingRadians(m_splinePlaybackController.GetRenderCamera().GetEcefLocation(), forward);
     return Eegeo::Math::Rad2Deg(headingRadians);
 }
            void AccuracyRingRenderable::RenderSpheres(Eegeo::Rendering::GLState &glState) const
            {
                glState.BindTexture2D(0);
                glState.ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

                glState.DepthMask(GL_FALSE);
                glState.DepthTest.Enable();
                glState.DepthFunc(GL_LESS);

                glState.CullFace.Disable();

                glState.StencilTest.Enable();
                glState.StencilFunc(GL_ALWAYS, 1, 0xFF);
                glState.StencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
                glState.StencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);

                Eegeo::m44 transform;
                Eegeo::m44 mvp;
                transform.Scale(m_outerRingRadius*2);
                transform.SetRow(3, Eegeo::v4(m_cameraRelativePosition, 1.0f));
                Eegeo::m44::Mul(mvp, m_viewProjection, transform);
                m_sphereRenderable.SetModelViewProjection(mvp);
                m_sphereRenderable.Render(glState);

                transform.Scale(m_innerRingRadius*2);
                transform.SetRow(3, Eegeo::v4(m_cameraRelativePosition, 1.0f));
                Eegeo::m44::Mul(mvp, m_viewProjection, transform);
                m_sphereRenderable.SetModelViewProjection(mvp);
                m_sphereRenderable.Render(glState);
            }
    Eegeo::m44 ExampleMeshRenderable::CalcModelViewProjection(const Eegeo::dv3& ecefCameraPosition, const Eegeo::m44& viewProjection, const float environmentFlatteningScale) const
    {
        const Eegeo::dv3& flattenedEcefPosition = m_environmentFlattenTranslate
            ? Eegeo::Rendering::EnvironmentFlatteningService::GetScaledPointEcef(GetEcefPosition(), environmentFlatteningScale)
            : GetEcefPosition();
        
        const Eegeo::v3& cameraRelativeModelOrigin = (flattenedEcefPosition - ecefCameraPosition).ToSingle();
        Eegeo::m44 translateRotate;
        translateRotate.SetFromBasis(m_orientationEcef.GetRow(0), m_orientationEcef.GetRow(1), m_orientationEcef.GetRow(2), cameraRelativeModelOrigin);

        Eegeo::m44 scale;
        if (m_environmentFlattenScale)
        {
            scale.Scale(Eegeo::v3(1.0f, environmentFlatteningScale, 1.0f));
        }
        else
        {
            scale.Identity();
        }
        
        Eegeo::m44 orientedCameraRelativeModel;
        Eegeo::m44::Mul(orientedCameraRelativeModel, translateRotate, scale);
        
        
        Eegeo::m44 modelViewProjection;
        Eegeo::m44::Mul(modelViewProjection, viewProjection, orientedCameraRelativeModel);
        return modelViewProjection;
    }
 void BoundsVisualiser::Draw(const Eegeo::v3& minExtents, const Eegeo::v3& maxExtents)
 {
     Build(minExtents, maxExtents);
     
     Eegeo_GL(glUseProgram(m_pShader->m_programHandle));
     
     Eegeo::m44 mvp;
     Eegeo::m44 w;
     w.Identity();
     Eegeo::m44::Mul(mvp, renderContext.GetViewProjectionMatrix(), w);
     
     Eegeo_GL(glUniformMatrix4fv(m_pShader->m_mvpUniform, 1, 0, (const GLfloat*)&mvp));
     
     Eegeo_GL(glEnableVertexAttribArray(m_pShader->m_positionSlot));
     
     Eegeo_GL(glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer));
     Eegeo_GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer));
     
     Eegeo_GL(glVertexAttribPointer(m_pShader->m_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0));
     
     for(u32 j = 0; j < NumIndices; j+=3)
     {
         Eegeo_GL(glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, (void*)(j * 2)));
     }
     
     Eegeo_GL(glBindBuffer (GL_ARRAY_BUFFER, 0));
     Eegeo_GL(glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
     
     DestroyGeometry();
 }
void LoadModelExample::Update(float dt)
{
	//let's put the vehicle in the air
	m_interestLocation.SetAltitude(100.0f);
    
	//set some big scale value so we can see the vehicle - vary between x20 and x70
    float scale = 20.0f + ((Eegeo::Math::Sin(m_elapsedTime)/ 2.0f + 0.5f) * 50.0f);
    Eegeo::m44 scaleMatrix;
    scaleMatrix.Scale(scale);
    
    Eegeo::Rendering::SceneModels::SceneModelTransformHelpers::PositionOnEarthSurface(*m_pModel, m_interestLocation, 0.f, scaleMatrix);

	// pulse the opacity of the disk material up and down over time.
    m_pDiscMaterialResource->GetMaterial()->SetAlpha(std::abs(Eegeo::Math::Sin(m_elapsedTime * 2)));

	m_elapsedTime += dt;
}
    void PinOverModelExample::MyModelRenderable::Render(Eegeo::Rendering::GLState& glState) const
    {
        Eegeo::m44 transform;
        Eegeo::dv3 location = Eegeo::Space::LatLong::FromDegrees(37.7858,-122.401).ToECEF();
        Eegeo::v3 up(location.Norm().ToSingle());
        Eegeo::v3 forward = (location  - Eegeo::v3(0.f, 1.f, 0.f)).Norm().ToSingle();
        Eegeo::v3 right(Eegeo::v3::Cross(up, forward).Norm());
        forward = Eegeo::v3::Cross(up, right);
        Eegeo::v3 cameraRelativePos = (location - m_renderContext.GetCameraOriginEcef()).ToSingle();
        Eegeo::m44 scaleMatrix;
        scaleMatrix.Scale(1.f);
        Eegeo::m44 cameraRelativeTransform;
        cameraRelativeTransform.SetFromBasis(right, up, forward, cameraRelativePos);
        Eegeo::m44::Mul(transform, cameraRelativeTransform, scaleMatrix);
        transform.SetRow(3, Eegeo::v4(cameraRelativePos, 1.f));

        glState.DepthTest.Enable();
        glState.DepthFunc(GL_LEQUAL);

        //loaded model faces are ccw
        glState.FrontFace(GL_CCW);

        m_model.GetRootNode()->SetVisible(true);
        m_model.GetRootNode()->SetLocalMatrix(transform);
        m_model.GetRootNode()->UpdateRecursive();
        m_model.GetRootNode()->UpdateSphereRecursive();
        m_model.GetRootNode()->DrawRecursive(m_renderContext, m_globalFogging, NULL, true, false);

        glState.FrontFace(GL_CW);

        Eegeo::EffectHandler::Reset();
    }
    void PODAnimationExample::Draw()
    {
        //create basis around a known location off coast of SF
        Eegeo::m44 transform;
        Eegeo::dv3 location = Eegeo::dv3(4256955.9749164,3907407.6184668,-2700108.75541722);
        Eegeo::v3 up(location.Norm().ToSingle());
        Eegeo::v3 forward = (location  - Eegeo::v3(0.f, 1.f, 0.f)).Norm().ToSingle();
        Eegeo::v3 right(Eegeo::v3::Cross(up, forward).Norm());
        forward = Eegeo::v3::Cross(up, right);
        Eegeo::v3 cameraRelativePos = (location - cameraModel.GetWorldPosition()).ToSingle();
        Eegeo::m44 scaleMatrix;
        scaleMatrix.Scale(1.f);
        Eegeo::m44 cameraRelativeTransform;
        cameraRelativeTransform.SetFromBasis(right, up, forward, cameraRelativePos);
        Eegeo::m44::Mul(transform, cameraRelativeTransform, scaleMatrix);
        transform.SetRow(3, Eegeo::v4(cameraRelativePos, 1.f));
        
        //loaded model faces are ccw
        renderContext.GetGLState().FrontFace(GL_CCW);
        
        pModel->GetRootNode()->SetVisible(true);
        pModel->GetRootNode()->SetLocalMatrix(transform);
        pModel->GetRootNode()->UpdateRecursive();
        pModel->GetRootNode()->UpdateSphereRecursive();
        pModel->GetRootNode()->DrawRecursive(renderContext, globalFogging, NULL, true, false);
       
        renderContext.GetGLState().FrontFace(GL_CW);

    }
 void LoadModelExample::Draw()
 {
     //form basis
     Eegeo::v3 up(mesh.up);
     Eegeo::v3 forward = -mesh.forward; //model is facing reverse (-ve z)
     Eegeo::v3 right(Eegeo::v3::Cross(up, forward).Norm());
     up = Eegeo::v3::Cross(forward, right);
     
    
     //compute a camera local position
     Eegeo::v3 cameraRelativePos = (mesh.positionEcef - renderContext.GetCameraOriginEcef()).ToSingle();
     
     //generate a transform from this basis and position...
     Eegeo::m44 cameraRelativeTransform;
     cameraRelativeTransform.SetFromBasis(right, up, forward, cameraRelativePos);
     
     Eegeo::m44 scaleMatrix;
     scaleMatrix.Scale(mesh.scale);
     
     //...and scale
     Eegeo::m44 transform;
     Eegeo::m44::Mul(transform, cameraRelativeTransform, scaleMatrix);
     transform.SetRow(3, Eegeo::v4(cameraRelativePos, 1.0f));
     
     //update the mesh instance with the transform
     mesh.node->SetLocalMatrix(transform);
     mesh.node->UpdateRecursive();
     mesh.node->UpdateSphereRecursive();
     mesh.node->UpdateBBRecursive();
     
     // Enable z buffering.
     Eegeo::Rendering::GLState& glState = renderContext.GetGLState();
     glState.DepthTest.Enable();
     glState.DepthFunc(GL_LEQUAL);
     glState.DepthMask(GL_TRUE);
     
     //draw the mesh
     mesh.node->DrawRecursive(renderContext, globalFogging, NULL, true, true);
     
     Eegeo::v3 min, max;
     mesh.node->GetMinExtent(min);
     mesh.node->GetMaxExtent(max);
     boundsVisualiser.Draw(min, max);
 }