SDK Question Advice for Printing a Vessel's Name on Exterior?

Mr Martian

Orbinaut/Addon dev/Donator
Addon Developer
Donator
Joined
Jun 6, 2012
Messages
303
Reaction score
85
Points
28
Location
Sydney, Australia, Earth, Sol
Website
www.orbithangar.com
Hi All,

I was hoping for some advice for how to go about printing text on the exterior of a vessel's mesh. I want this text to be dynamic and based on text declared in the class's clbkSetClassCaps function. The default DeltaGlider does exactly this witht he craft's name printed on the verticle stabilizers. The function in the default DeltaGLider appears simple enough (below):
C++:
void DeltaGlider::PaintMarkings (SURFHANDLE tex)
{
    oapi::Font *font = oapiCreateFont (38, true, "Sans", FONT_BOLD);
    oapi::Sketchpad *skp = oapiGetSketchpad (tex);
    if (skp) {
        skp->SetFont (font);
        skp->SetTextColor (0xD0D0D0);
        skp->SetTextAlign (oapi::Sketchpad::CENTER);
        char cbuf[32];
        strncpy (cbuf, GetName(), 10);
        int len = min(strlen(GetName()), 10);
        skp->Text (196, 10, cbuf, len);
        skp->Text (196, 74, cbuf, len);
        skp->SetTextColor (0x808080);
        skp->SetTextAlign (oapi::Sketchpad::RIGHT);
        skp->Text (120, 158, cbuf, len);
        skp->SetTextAlign (oapi::Sketchpad::LEFT);
        skp->Text (133, 158, cbuf, len);
        oapiReleaseSketchpad (skp);
    }
    oapiReleaseFont (font);
}

I have used this exact code in my vessel class, called from clbkPostCreation, where the input is a SURFHANDLE defined in clbkSetClassCaps. I cannot get this to work at all though. When debugging, I can see that skp returns null pointer (debugger reads 0x00000000 {surf = ???}), and so noting in 'if (skp)' is called. When I debug in Orbiter_ng.exe and call this function I get an error on load (below).
Capture.PNG
If anyone could offer any advice on this I would really appreciate it. It seems like a very simple procedure, and I feel like there is probably just some library I am not linking with. Note that I have all settings and inclusions pretty much the same as the default ShuttlePB, so pretty barebones.

Thank you all,
MrMartian
 

Mr Martian

Orbinaut/Addon dev/Donator
Addon Developer
Donator
Joined
Jun 6, 2012
Messages
303
Reaction score
85
Points
28
Location
Sydney, Australia, Earth, Sol
Website
www.orbithangar.com
Did you specify the correct flags when creating the surface ?
Code:
    insignia_tex = oapiCreateSurfaceEx (256, 256, OAPISURFACE_RENDERTARGET | OAPISURFACE_TEXTURE | OAPISURFACE_MIPMAPS);
Thank you Gondos, no I missed that step! That being said, I still cannot get this working. This is the code I have:

C++:
void MyVessel::clbkSetClassCaps (FILEHANDLE cfg)
{
    AddMesh(mh_main);
    
    insignia_tex = oapiCreateSurfaceEx (512, 512, OAPISURFACE_RENDERTARGET | OAPISURFACE_TEXTURE | OAPISURFACE_MIPMAPS);
    SURFHANDLE hTex = oapiGetTextureHandle (mh_main, 1);
    if (hTex) oapiBlt (insignia_tex, hTex, 0, 0, 0, 0, 512, 512, SURF_NO_CK);
    if (insignia_tex) PaintLabel(insignia_tex);
}

void MyVessel::PaintLabel (SURFHANDLE tex)
{
    oapi::Font *font = oapiCreateFont (38, true, "Sans", FONT_BOLD);
    oapi::Sketchpad *skp = oapiGetSketchpad (tex);
    if (skp) {
        skp->SetFont (font);
        skp->SetTextColor (0xD0D0D0);
        skp->SetTextAlign (oapi::Sketchpad::CENTER);

        skp->SetBackgroundMode(oapi::Sketchpad::BkgMode::BK_OPAQUE);
        skp->Rectangle(0,0,512,512);

        oapiReleaseSketchpad (skp);
    }
    oapiReleaseFont (font);
}

Note that 'insignia_tex ' is declared in the header. At this point I am just trying to draw an opague rectangle, so as to see if the the function has worked, but nothing. The mesh is only a cube, with only one texture defined, so I can rule out printing to the wrong texture. I have been trying to figure this out for a long time now so any advice is really appreciated.

Thanks again!
 

Gondos

Well-known member
Joined
Apr 18, 2022
Messages
230
Reaction score
266
Points
78
Location
On my chair
Thank you Gondos, no I missed that step! That being said, I still cannot get this working. This is the code I have:

C++:
void MyVessel::clbkSetClassCaps (FILEHANDLE cfg)
{
    AddMesh(mh_main);
   
    insignia_tex = oapiCreateSurfaceEx (512, 512, OAPISURFACE_RENDERTARGET | OAPISURFACE_TEXTURE | OAPISURFACE_MIPMAPS);
    SURFHANDLE hTex = oapiGetTextureHandle (mh_main, 1);
    if (hTex) oapiBlt (insignia_tex, hTex, 0, 0, 0, 0, 512, 512, SURF_NO_CK);
    if (insignia_tex) PaintLabel(insignia_tex);
}

void MyVessel::PaintLabel (SURFHANDLE tex)
{
    oapi::Font *font = oapiCreateFont (38, true, "Sans", FONT_BOLD);
    oapi::Sketchpad *skp = oapiGetSketchpad (tex);
    if (skp) {
        skp->SetFont (font);
        skp->SetTextColor (0xD0D0D0);
        skp->SetTextAlign (oapi::Sketchpad::CENTER);

        skp->SetBackgroundMode(oapi::Sketchpad::BkgMode::BK_OPAQUE);
        skp->Rectangle(0,0,512,512);

        oapiReleaseSketchpad (skp);
    }
    oapiReleaseFont (font);
}

Note that 'insignia_tex ' is declared in the header. At this point I am just trying to draw an opague rectangle, so as to see if the the function has worked, but nothing. The mesh is only a cube, with only one texture defined, so I can rule out printing to the wrong texture. I have been trying to figure this out for a long time now so any advice is really appreciated.

Thanks again!
No problem :)
So right now you are creating a render texture, copying the original texture to it, rendering a rectangle on it and ... that's it.
You also need to replace the texture so that it's used when rendering the mesh. I think you need something like this :
Code:
    oapiSetTexture (mh_main, 1, insignia_tex);
 

Mr Martian

Orbinaut/Addon dev/Donator
Addon Developer
Donator
Joined
Jun 6, 2012
Messages
303
Reaction score
85
Points
28
Location
Sydney, Australia, Earth, Sol
Website
www.orbithangar.com
No problem :)
So right now you are creating a render texture, copying the original texture to it, rendering a rectangle on it and ... that's it.
You also need to replace the texture so that it's used when rendering the mesh. I think you need something like this :
Code:
    oapiSetTexture (mh_main, 1, insignia_tex);
That makes so much more sense now! Thank you @Gondos, it's working perfectly now! When I write text (with skp->Text) however it is mirrored left/right. Not much of an issue as I can fix this by just flipping my mesh, but I don't suppose you know a way to do this at the code-level instead?
Thanks again so much, this has alluded me for a long time:)
 

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,666
Reaction score
795
Points
128
There are a few ways to do mirror image. I haven't tested this but should work in D3D9/OpenOrbiter. Could work in Orbiter2016 but requires a use of Sketchpad2.h and casting to Sketchpad3 via Sketchpad3 *pSkp3 = (Sketchpad3 *)pSkp;
C++:
FMATRIX4 mW = pSkp->GetWorldTransform();
mW.m11 = -1.0f; // mirror x-axis
mW.m22 = -1.0f; // mirror y-axis
pSkp->SetWorldTransform(&mW);


//disable mirror
pSkp->SetWorldTransform();
 
Top