API Question Help redrawing virtual cockpit displays in D3D9

Mr Martian

Orbinaut/Addon dev/Donator
Addon Developer
Donator
Joined
Jun 6, 2012
Messages
311
Reaction score
114
Points
43
Location
Sydney, Australia, Earth, Sol
Website
www.orbithangar.com
Hi all,
I am working on a virtual cockpit which has a screen (simillar to the DeltaGlider's propellant status screen), and I am having some difficulties getting it to work properly with the D3D9 graphics client. It would appear on every redraw event, any objects are simply superimpossed over previously drawn objects (text, polygons, etc). Text for example will keep writing on top of itself until just rectangles are visible where characters once were, and I do not have this issue when running in Orbiter.exe (no D3D9 client).

This is the code I have, it's just a simple panel which for now just displays the outside pressure.

in clbkLoadVC:
C++:
bool MyVessel::clbkLoadVC (int id)
{
    switch (id) {
    case 0: // pilot
        SetCameraOffset (_V(0,1.2,12.5));
        SetCameraShiftRange (_V(0,0,0.1), _V(-0.2,0,0), _V(0.2,0,0));

        //pressure display panel
        SURFHANDLE tex1 = oapiGetTextureHandle (mh_cockpit,4); //defines tex1 for the texture handle that will display the callout
        oapiVCRegisterArea (AID_PRESS_DISPLAY,_R( 16, 104, 284, 213), PANEL_REDRAW_ALWAYS, PANEL_MOUSE_IGNORE, PANEL_MAP_BACKGROUND, tex1); // register the surface handle and spacing for the callout display/when visible/etc.
    }
    return true;
}

and in clbkVCRedrawEvent:
C++:
bool MyVessel::clbkVCRedrawEvent (int id, int event, SURFHANDLE surf)
{
    switch (id) {   
        case AID_PRESS_DISPLAY:
            RedrawPanel_CabinPress (surf, AID_PRESS_DISPLAY);
            return true;
    }
    return false;
}

and finally in the function 'RedrawPanel_CabinPress'. This just displays the outside pressure:
C++:
void ShuttlePB::RedrawPanel_CabinPress (SURFHANDLE surf, int disp)
{
    // register the text parameters
    char cbuf[20];
    HDC hDC = oapiGetDC (surf);
    SelectObject (hDC, g_Param.hFont[2]);
    SelectObject (hDC, g_Param.hBrush[1]);
    SetTextColor (hDC, RGB(0,255,0));   
    SetBkMode (hDC, TRANSPARENT);
    SetTextAlign (hDC, TA_RIGHT);

    switch (disp) {
    case AID_PRESS_DISPLAY:
        {
            // display outside pressure
            sprintf (cbuf, "%0.3f", GetAtmPressure());
            TextOut (hDC, 222, 42, cbuf, strlen(cbuf));

            oapiBltPanelAreaBackground (AID_PRESS_DISPLAY, surf);
        }
        break;
    }
    oapiReleaseDC (surf, hDC);
}

If anyone could offer any advice I would really appreciate it. Thank you all!

MrMartian
 

gattispilot

Addon Developer
Addon Developer
Joined
Oct 17, 2007
Messages
8,724
Reaction score
2,689
Points
203
Location
Dallas, TX
This is what we used in the eagle:

It draws the bars for thrust but also displays the text of trim, fuel,,,,
bool EAGLEUACS::RedrawPanel_Fuelstatus(SURFHANDLE surf) { char cbuf[256]; HDC hDC = oapiGetDC(surf); double level3 = GetThrusterGroupLevel(THGROUP_HOVER); double level4 = (level3 * (MAX_HOVER_THRUST * 4)); double level2 = GetPropellantMass(ph_main); double trim = (GetControlSurfaceLevel(AIRCTRL_ELEVATORTRIM) - .5); double trim1 = GetControlSurfaceLevel(AIRCTRL_ELEVATORTRIM); double trim2 = (trim - .5); th = GetThrusterGroupLevel(THGROUP_MAIN); //get thrust main level if (!th) th = -GetThrusterGroupLevel(THGROUP_RETRO); //get retro thrustes - 1 to 0 //sprintf(oapiDebugString(), "main %5f th %5f ", engmain, *es); //th = GetThrusterGroupLevel(THGROUP_MAIN); //get thrust main level // th = -1; // or get retro thrustes -1 to 0 //if (th != engmain) { engmain = th; if (th >= 0.0) { //draw thrust level //sprintf(oapiDebugString(), "main %5f th %5f ", engmain, th); SelectObject(hDC, g_Param.hBrush[1]);//green box Rectangle(hDC, 130, 144, (int)(130 + engmain * (330 - 130)), 187);//thrust //sprintf(oapiDebugString(), "main %5f th %5f ", engmain, th); } //sprintf(oapiDebugString(), "main %5f th %5f ", engmain, th); //retro else { //sprintf(oapiDebugString(), "main %5f th %5f ", engmain, th); SelectObject(hDC, g_Param.hBrush[2]);//yellow box Rectangle(hDC, 130, 144, (int)(130 - engmain * (200)), 187);//thrust } //} SelectObject(hDC, g_Param.hBrush[1]);//green box Rectangle(hDC, 130, 217, (int)(130 + level3 * (330 - 130)), 260);//hoverthrust Rectangle(hDC, 130, 70, (int)(130.0 + (level2 / 175)), 108); //fuel RANGE 175 th = (engmain >= 0.0 ? engmain * th : -engmain * th); th = (engmain >= 0.0 ? engmain * GetThrusterGroupLevel(THGROUP_MAIN)*4*MAX_MAIN_THRUST : -engmain * GetThrusterGroupLevel(THGROUP_RETRO) * 4 * MAX_RETRO_THRUST); Rectangle(hDC, 291, (int)(292 - (48.5 * trim2)), 315, (int)(298 - (48.5 * trim2))); //TRIM SelectObject(hDC, g_Param.font[3]); SetTextColor(hDC, RGB(0, 153, 0)); SetTextAlign(hDC, TA_LEFT); SetBkMode(hDC, TRANSPARENT); //trim sprintf(cbuf, "%0.1f", abs(trim1)); TextOut(hDC, 400, 325, cbuf, strlen(cbuf)); SelectObject(hDC, g_Param.font[2]); if (trim < -.5) { sprintf(cbuf, "DN", 2); TextOut(hDC, 360, 345, cbuf, strlen(cbuf)); } if (trim > -.5) { sprintf(cbuf, "UP", 2); TextOut(hDC, 360, 345, cbuf, strlen(cbuf)); } SelectObject(hDC, g_Param.font[3]); //sprintf(oapiDebugString(), "main %5f th %5f ", engmain, th); static char strbuf[16]; double absf1 = fabs(th);//thrust if (absf1 < 1e4) { if (absf1 < 1e2) sprintf(strbuf, "%5.2f", absf1); else if (absf1 < 1e3) sprintf(strbuf, "%5.1f", absf1); else sprintf(strbuf, "%4.2fk", absf1 * 1e-3); } else if (absf1 < 1e7) { if (absf1 < 1e5) sprintf(strbuf, "%4.1fk", absf1 * 1e-3); else if (absf1 < 1e6) sprintf(strbuf, "%4.0fk", absf1 * 1e-3); else sprintf(strbuf, "%4.2fm", absf1 * 1e-6); } else if (absf1 < 1e10) { if (absf1 < 1e8) sprintf(strbuf, "%4.1fm", absf1 * 1e-6); else if (absf1 < 1e9) sprintf(strbuf, "%4.0fm", absf1 * 1e-6); else sprintf(strbuf, "%4.2fG", absf1 * 1e-9); } else { if (absf1 < 1e11) sprintf(strbuf, "%4.1fG", absf1 * 1e-9); else if (absf1 < 1e12) sprintf(strbuf, "%4.0fG", absf1 * 1e-9); else sprintf(strbuf, "%5e", absf1); } TextOut(hDC, 345, 145, strbuf, strlen(strbuf)); //fuel double absf = fabs(level2);//fuel level if (absf < 1e4) { if (absf < 1e2) sprintf(strbuf, "%5.2f", level2); else if (absf < 1e3) sprintf(strbuf, "%5.1f", level2); else sprintf(strbuf, "%4.2fk", level2 * 1e-3); } else if (absf < 1e7) { if (absf < 1e5) sprintf(strbuf, "%4.1fk", level2 * 1e-3); else if (absf < 1e6) sprintf(strbuf, "%4.0fk", level2 * 1e-3); else sprintf(strbuf, "%4.2fm", level2 * 1e-6); } else if (absf < 1e10) { if (absf < 1e8) sprintf(strbuf, "%4.1fM", level2 * 1e-6); else if (absf < 1e9) sprintf(strbuf, "%4.0fm", level2 * 1e-6); else sprintf(strbuf, "%4.2fG", level2 * 1e-9); } else { if (absf < 1e11) sprintf(strbuf, "%4.1fG", level2 * 1e-9); else if (absf < 1e12) sprintf(strbuf, "%4.0fG", level2 * 1e-9); else sprintf(strbuf, "%5e", level2); } TextOut(hDC, 345, 70, strbuf, strlen(strbuf)); double absf2 = fabs(level4);//hover if (absf2 < 1e4) { if (absf2 < 1e2) sprintf(strbuf, "%5.2f", level4); else if (absf2 < 1e3) sprintf(strbuf, "%5.1f", level4); else sprintf(strbuf, "%4.2fk", level4 * 1e-3); } else if (absf2 < 1e7) { if (absf2 < 1e5) sprintf(strbuf, "%4.1fk", level4 * 1e-3); else if (absf2 < 1e6) sprintf(strbuf, "%4.0fk", level4 * 1e-3); else sprintf(strbuf, "%4.2fM", level4 * 1e-6); } else if (absf2 < 1e10) { if (absf2 < 1e8) sprintf(strbuf, "%4.1fM", level4 * 1e-6); else if (absf2 < 1e9) sprintf(strbuf, "%4.0fM", level4 * 1e-6); else sprintf(strbuf, "%4.2fG", level4 * 1e-9); } else { if (absf2 < 1e11) sprintf(strbuf, "%4.1fG", level4 * 1e-9); else if (absf2 < 1e12) sprintf(strbuf, "%4.0fG", level4 * 1e-9); else sprintf(strbuf, "%5e", level4); } TextOut(hDC, 340, 215, strbuf, strlen(strbuf)); oapiReleaseDC(surf, hDC); return true; }
 

Mr Martian

Orbinaut/Addon dev/Donator
Addon Developer
Donator
Joined
Jun 6, 2012
Messages
311
Reaction score
114
Points
43
Location
Sydney, Australia, Earth, Sol
Website
www.orbithangar.com
What you have looks pretty much the ssame as mine, I have tried changing the function to return a boolean, as your does:
C++:
bool MyVessel::RedrawPanel_TEST (SURFHANDLE surf, int disp)
{
    // register the text parameters
    char cbuf[20];
    HDC hDC = oapiGetDC (surf);
    SelectObject (hDC, g_Param.hFont[2]);
    SelectObject (hDC, g_Param.hBrush[1]);
    SetTextColor (hDC, RGB(0,255,0));
    
    SetBkMode (hDC, TRANSPARENT);
    SetTextAlign (hDC, TA_RIGHT);

    // outside pressure
    sprintf (cbuf, "%0.3f", GetAtmPressure() * 0.001);
    TextOut (hDC, 222, 42, cbuf, strlen(cbuf));
    oapiReleaseDC (surf, hDC);
    return true;
}

and call it like this:
C++:
    case AID_PRESS_DISPLAY:
            return RedrawPanel_TEST (surf, AID_PRESS_DISPLAY);

This didn't help though. May I ask how you call 'RedrawPanel_Fuelstatus' in the Eagle from clbkVCRedrawEvent? and what you have in clbkLoadVC? I feel like I am parsing the wrong bkmode or redraw event code...

Thank you!
 

Gondos

Well-known member
Joined
Apr 18, 2022
Messages
233
Reaction score
272
Points
78
Location
On my chair
Can you try with releasing the DC (oapiReleaseDC (surf, hDC); ) before blitting the texture ? (oapiBltPanelAreaBackground (AID_PRESS_DISPLAY, surf); )
 

gattispilot

Addon Developer
Addon Developer
Joined
Oct 17, 2007
Messages
8,724
Reaction score
2,689
Points
203
Location
Dallas, TX
bool EAGLEUACS::clbkVCRedrawEvent(int id, int event, SURFHANDLE surf) { bool return_value = false; if (id == ALL_MFD_BUTTONS) { PaintMFDButtons(surf); return_value = true; } switch (id) { case AID_ENGINEINDICATOR: RedrawPanel_Fuelstatus(surf); //return RedrawPanel_Fuelstatus(surf); return_value = true; } return return_value; // RedrawPanel_SPEEDstatus(surf, id); //return return_value; }

and in the VC
bool EAGLEUACS::clbkLoadVC(int id) { { SetCameraOffset(_V(-1.16, .461, 11.979)); SetCameraDefaultDirection(_V(0, 0, 1)); DefineMFDButtons(); VCMFDSPEC cdr1_mfd; VCMFDSPEC plt1_mfd; VCMFDSPEC cdr2_mfd; VCMFDSPEC plt2_mfd; VCMFDSPEC center1_mfd; VCMFDSPEC center2_mfd; cdr1_mfd = { 2,1 }; plt1_mfd = { 2,5 }; cdr2_mfd = { 2,2 }; plt2_mfd = { 2,0 }; center1_mfd = { 2,3 }; center2_mfd = { 2,4 }; oapiVCRegisterMFD(MFD_LEFT, &cdr1_mfd); oapiVCRegisterMFD(MFD_RIGHT, &plt1_mfd); oapiVCRegisterMFD(MFD_USER1, &cdr2_mfd); oapiVCRegisterMFD(MFD_USER2, &plt2_mfd); oapiVCRegisterMFD(MFD_USER3, &center1_mfd); oapiVCRegisterMFD(MFD_USER4, &center2_mfd); static VCHUDSPEC huds = { 2,12, { -1, .5, 160 }, 160 }; //sprintf(oapiDebugString(), "anim %d ", id); oapiVCRegisterHUD(&huds); switch (id) { case 0: // Left Seat huds.hudcnt = _V(-1, .5, 160); SetCameraOffset(_V(-1.16, .461, 11.979)); // Set camera position (x,y,z) SetCameraDefaultDirection(_V(0, 0, 1)); oapiVCSetNeighbours(-1, 1, -1, -1); // Set adjacent cameras (Left, Right, Top, Bottom) break; case 1: // center window // oapiVCTriggerRedrawArea(0, AID_FUELSTATUS); huds.hudcnt = _V(1.1, .2, 160); SetCameraOffset(_V(0.0, .69, 12)); // Set camera position (x,y,z) SetCameraDefaultDirection(_V(0, 0, 1)); oapiVCSetNeighbours(0, 2, -1, -1); // Set adjacent cameras (Left, Right, Top, Bottom) break; case 2: // right window // oapiVCTriggerRedrawArea(0, AID_FUELSTATUS); huds.hudcnt = _V(1, .2, 160); //huds.hudcnt = _V(1.1, .5, 160); SetCameraOffset(_V(1.16, .461, 11.979)); // Set camera position (x,y,z) SetCameraDefaultDirection(_V(0, 0, 1)); oapiVCSetNeighbours(1, 3, -1, -1); // Set adjacent cameras (Left, Right, Top, Bottom) break; case 3: // center back window huds.hudcnt = _V(-1, .2, 160); SetCameraOffset(_V(0.0, .692, 11.979)); // Set camera position (x,y,z) SetCameraDefaultDirection(_V(0, 0, -1)); oapiVCSetNeighbours(-1, 4, -1, -1); // Set adjacent cameras (Left, Right, Top, Bottom) break; case 4: // front pod SetCameraOffset(_V(0.0, .692, 8.2)); // Set camera position (x,y,z) SetCameraDefaultDirection(_V(0, 0, 1)); oapiVCSetNeighbours(-1, 0, -1, -1); vccamera = 1; // Set adjacent cameras (Left, Right, Top, Bottom) break; } // end "switch (id)" return true; } }
 

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,667
Reaction score
796
Points
128
Just to remind you that oapiGetDC() is very much obsolete, it's likely that there's no support for it after Orbiter 2024. So, HDC stuff shouldn't be used for a new add-ons.
 

gattispilot

Addon Developer
Addon Developer
Joined
Oct 17, 2007
Messages
8,724
Reaction score
2,689
Points
203
Location
Dallas, TX
Just to remind you that oapiGetDC() is very much obsolete, it's likely that there's no support for it after Orbiter 2024. So, HDC stuff shouldn't be used for a new add-ons.
Thanks. but the DG and Shuttle A for 2024 have that. And that's what some use for examples
 

Mr Martian

Orbinaut/Addon dev/Donator
Addon Developer
Donator
Joined
Jun 6, 2012
Messages
311
Reaction score
114
Points
43
Location
Sydney, Australia, Earth, Sol
Website
www.orbithangar.com
Can you try with releasing the DC (oapiReleaseDC (surf, hDC); ) before blitting the texture ? (oapiBltPanelAreaBackground (AID_PRESS_DISPLAY, surf); )
Thanks Gondos, I tried this and in D3D9 I get an 'Asserion failed' error:

assertion_error.PNG

It also appears to make no difference (both in D3D9 and in regular Orbiter.exe whether I call 'oapiBltPanelAreaBackground' or not. Works perfectly in Orbiter.exe without calling it.
 

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,667
Reaction score
796
Points
128
Thanks. but the DG and Shuttle A for 2024 have that. And that's what some use for examples
Yeah, I suppose so. The problem is that Orbiter is still officially using DirectX 7 and the sample programs must work with it. After Orbiter 2024 DX7 will be removed and the vessels updated. Also it's problematic because Orbiter 2016 doesn't have full D3D9 support. So, I guess any method that works is O.k. at this point.
 
Top