// todo: move this code to C# side.
// Renders world axis at the bottom-left corner.
static void RenderWorldAxis()
{
    RenderContext* rc = RenderContext::Inst();
    RenderSurface* surface = s_engineData->pRenderSurface;
    LineRenderer *lr = LineRenderer::Inst();
    Camera& cam = rc->Cam();    
    float margin = 36; // margin in pixels
    float xl = 28; // axis length in pixels.
    float vw = (float)surface->GetWidth();
    float vh = (float)surface->GetHeight();
    Matrix view = cam.View();    
    view.M41 = -vw/2 + margin;
    view.M42 = -vh/2 + margin;
    view.M43 = -xl;
    
    float3 look = cam.CamLook();    
    bool perspective = !cam.IsOrtho();

    // for orthographic hide one of the axis depending on view-type
    const float epsilon  = 0.001f; // use relatively large number for this test.
    bool renderX = perspective || abs(look.x) < epsilon;
    bool renderY = perspective || abs(look.y) < epsilon;
    bool renderZ = perspective || abs(look.z) < epsilon;
    
    Matrix proj = Matrix::CreateOrthographic(vw,vh,1,10000);
    cam.SetViewProj(view,proj);

    float3 centerV(0,0,0);
    // draw x,y,z
    if(renderX)
        lr->DrawLine(centerV,float3(xl,0,0),float4(1,0,0,1));    
    if(renderY)
        lr->DrawLine(centerV,float3(0,xl,0),float4(0,1,0,1));    
    if(renderZ)
        lr->DrawLine(centerV,float3(0,0,xl),float4(0,0,1,1));       

    lr->RenderAll(rc);

    Font* font = s_engineData->AxisFont;
    if(font)
    {   
        float fh = font->GetFontSize();
        float fhh = fh /2.0f;
        FontRenderer* fr = LvEdFonts::FontRenderer::Inst();
        Matrix vp = view * proj;
                
        // draw x,y,z
        if(renderX)
        {
            float3 xpos = surface->Project(float3(xl,fhh,0),vp);
            fr->DrawText(font,L"X",(int)xpos.x,(int)xpos.y,float4(1,0,0,1));
        }

        if(renderY)
        {
            float3 ypos = surface->Project(float3(0,xl+fhh,0),vp);
            fr->DrawText(font,L"Y",(int)ypos.x,(int)ypos.y,float4(0,1,0,1));
        }

        if(renderZ)
        {
            float3 zpos = surface->Project(float3(0,fhh,xl),vp);
            int ycoord =(int) ((zpos.y + fh) > vh ? vh - fh : zpos.y);
            fr->DrawText(font,L"Z",(int)zpos.x,ycoord,float4(0,0,1,1));
        }
        fr->FlushPrintRequests( rc );
    }    
    
}
LVEDRENDERINGENGINE_API void __stdcall LvEd_Begin(ObjectGUID renderSurface, float viewxform[], float projxform[])
{
    ErrorHandler::ClearError();
    
    s_engineData->pRenderSurface = reinterpret_cast<RenderSurface*>(renderSurface);

    RenderContext* rc = RenderContext::Inst();

    ExpFog fog;
    fog.enabled = 0;
    if(s_engineData->GameLevel)
    {
        fog = s_engineData->GameLevel->GetFog();
    }            
    rc->SetFog(fog);
    
    // set render target and depth buffer.
    rc->SetContext(gD3D11->GetImmediateContext());
    ID3D11DeviceContext* d3dcontext = rc->Context();

    ID3D11RenderTargetView* rt[1] = {s_engineData->pRenderSurface->GetRenderTargetView()};

    // set render target and depth buffer.
    d3dcontext->OMSetRenderTargets(1,rt,s_engineData->pRenderSurface->GetDepthStencilView());

    // Setup the viewport
    D3D11_VIEWPORT vp = s_engineData->pRenderSurface->GetViewPort();    
    d3dcontext->RSSetViewports( 1, &vp );
    float4 vf(vp.Width,vp.Height,vp.TopLeftX,vp.TopLeftY);
    rc->SetViewPort(vf);

    Matrix view(viewxform);    
    rc->Cam().SetViewProj(view, Matrix(projxform));
    
    d3dcontext->RSSetState(NULL);
    d3dcontext->OMSetDepthStencilState(NULL,0);
    d3dcontext->OMSetBlendState( NULL, NULL, 0xFFFFFFFF );

    // setup default lighting.
    DirLight& light = *LightingState::Inst()->DefaultDirLight();
    light.ambient = float3(0.05f,0.06f,0.07f);    
    light.diffuse = float3(250.0f/255.0f, 245.0f/255.0f, 240.0f/255.0f);       
    light.specular = light.diffuse; // float3(0.4f,0.4f,0.4f);
    light.dir = float3(0.258819073f, -0.965925932f, 0.0f);
    
    d3dcontext->ClearDepthStencilView( s_engineData->pRenderSurface->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0 );
    if(s_engineData->GameLevel->m_activeskyeDome && s_engineData->GameLevel->m_activeskyeDome->GetVisible())
    {
        s_engineData->GameLevel->m_activeskyeDome->Render(RenderContext::Inst());
    }
    else
    {
        float4 color = s_engineData->pRenderSurface->GetBkgColor();
        d3dcontext->ClearRenderTargetView( s_engineData->pRenderSurface->GetRenderTargetView(), &color.x );
    }

    //Level editor may perform some rendering before LvEd_RenderGame get called.
    s_engineData->basicRenderer->Begin(RenderContext::Inst()->Context(), 
        s_engineData->pRenderSurface,
        RenderContext::Inst()->Cam().View(),
        RenderContext::Inst()->Cam().Proj());
}