Orbiter-Forum  

Go Back   Orbiter-Forum > Orbiter Space Flight Simulator > Orbiter SDK
Register Blogs Orbinauts List Social Groups FAQ Projects Mark Forums Read

Orbiter SDK Orbiter software developers post your questions and answers about the SDK, the API interface, LUA, meshing, etc.

Reply
 
Thread Tools
Old 09-13-2017, 06:37 PM   #1
slaver0110
Orbinaut
 
slaver0110's Avatar
Default Need a bit of help with vessel cast

I have my orbital tug and class-specific MFD working well; without the help of everyone here it would have been impossible.

However, I'm having trouble with where the vessel-cast should take place.

A little background:
The MFD for the Tug is designed to be class-specific, so that a lot of flags in the vessel can be controlled and monitored from the MFD. This requires the including of the 'Tug1.h' file, and then a simple cast:
Code:
pVessel = static_cast<Tug1*>(v);
Of course, there has to be a checking routine to make sure that the current focus-vessel is of the Tug1 class, because my guess would be that if I changed to another vessel, the TugMFD would try to access the non-Tug vessel and crash Orbiter.
So, I use a simple check of the current focus vessel to make sure it's a Tug:
Code:
bool Tug1MFD::VesselCheck()
{
	hVessel = oapiGetFocusObject();
	v = oapiGetVesselInterface(hVessel);
	sprintf(TestClass, v->GetClassNameA());

	switch (strcmp(TestClass, "Tug1"))
	{
	case 0:
		pVessel = static_cast<Tug1*>(v);
		return true;
	case !0:
		return false;
	default:
		return false;
	}
}
This check works well, and does exactly what I need it to.
The problem is where I currently have the check originating from:
Code:
bool Tug1MFD::Update(oapi::Sketchpad *skp)
{
	Title(skp, "Tug1MFD");
	skp->SetFont(font);
	skp->SetTextColor(0x00FFFF);	

	switch (VesselCheck())
	{
	case true:
		iPodThrust = (float)pVessel->PodThrust * 100;
		len = sprintf_s(buff, TestClass);
		skp->Text(100, 100, buff, len);
		len = sprintf_s(buff, "PodFlag: %.0f", pVessel->PodFlag);
		skp->Text(100, 130, buff, len);
		len = sprintf_s(buff, "PodThrust: %2f", iPodThrust);
		skp->Text(100, 160, buff, len);
		if (CheckTugDock())
		{
			len = sprintf_s(buff, "DOCKED");
			skp->Text(100, 190, buff, len);
		}
		break;
	case false:
		len = sprintf_s(buff, "NOT A TUG");
		skp->Text(100, 100, buff, len);  break;
	}
	return true;
}
The more experienced coders here will immediately see what the problem is...yes, VesselCheck() is being called from the Update method.
While this works, it also means that while the Tug is the current focus, the cast is happening every frame!!!

And that's where I could use some help. I've been trying to think of a way to set this up so that once the Tug is the focus vessel, the cast happens once, and if the focus changes to a different vessel class it doesn't happen.

A little handholding in the right direction would be great here. As I said, the code works as-is, but the idea that it's re-casting every frame is one of those things that would cause me to lose sleep.

Cheers, and thanks in advance!!
slaver0110 is offline   Reply With Quote
Old 09-13-2017, 06:57 PM   #2
Face
Beta Tester
 
Face's Avatar

Default

Quote:
Originally Posted by slaver0110 View Post
 As I said, the code works as-is, but the idea that it's re-casting every frame is one of those things that would cause me to lose sleep.
Why? What do you think that casting is?
Face is offline   Reply With Quote
Old 09-13-2017, 06:58 PM   #3
Urwumpe
Certain Super User
 
Urwumpe's Avatar

Default

You do know that it is possible to make vessel-specific MFDs in Orbiter 2016?

Also, casting the vessel is not the big issue there - static_casts happen just inside the compiler. But checking the focus vessel every timestep is. If I remember correctly, a MFD instance is ALWAYS tied to a vessel, the focus vessel is passed to the constructor.
Urwumpe is offline   Reply With Quote
Old 09-13-2017, 07:18 PM   #4
slaver0110
Orbinaut
 
slaver0110's Avatar
Default

Quote:
Originally Posted by Urwumpe View Post
 But checking the focus vessel every timestep is. If I remember correctly, a MFD instance is ALWAYS tied to a vessel, the focus vessel is passed to the constructor.
Not sure if I'm reading you correctly here.
Are you saying that it's VesselCheck() that only needs to be executed once?

As for the class-specific MFD's in 2016, no I didn't know that.

Last edited by slaver0110; 09-13-2017 at 07:20 PM. Reason: Addendum
slaver0110 is offline   Reply With Quote
Old 09-13-2017, 07:33 PM   #5
Urwumpe
Certain Super User
 
Urwumpe's Avatar

Default

Quote:
Originally Posted by slaver0110 View Post
 Not sure if I'm reading you correctly here.
Are you saying that it's VesselCheck() that only needs to be executed once?
Yes - when the MFD instance is created.
Urwumpe is offline   Reply With Quote
Old 09-14-2017, 02:02 AM   #6
slaver0110
Orbinaut
 
slaver0110's Avatar
Default

Ah, I see it now.
Ok, reworked it into a method called by the MFD constructor, and it works perfectly.

Thanks for the help.
And Cheers!!!
slaver0110 is offline   Reply With Quote
Old 09-14-2017, 07:10 AM   #7
jedidia
shoemaker without legs
 
jedidia's Avatar
Default

Quote:
While this works, it also means that while the Tug is the current focus, the cast is happening every frame!!!
The cast is not the problem. The string comparison.... eeeeewyeah, that's ugly.
You could use dynamic_cast instead of static_cast and check the returned pointer for null instead, that would be faster.

But I agree with the above suggestions. Keep your vessel pointer around for the lifetime of the MFD.
jedidia is offline   Reply With Quote
Thanked by:
Old 09-14-2017, 02:07 PM   #8
dbeachy1
O-F Administrator
 
dbeachy1's Avatar


Default

One thing to note regard casting if it hasn't been spelled out earlier in this thread: with the exception of dynamic_cast, typecasting do not incur any extra runtime overhead at all: it is simply telling the compiler how to "look at" a block of memory. More information is in this StackOverflow thread.

In other words, feel free to use static_cast, const_cast, or reinterpret_cast wherever you need it: they do not incur any extra runtime overhead at all.

P.S. I have never needed to use dynamic_cast anywhere in the XR projects, but I've needed to use each of the three other types (static_cast, const_cast, and reinterpret_cast). None of those add any runtime overhead at all, though.
dbeachy1 is offline   Reply With Quote
Thanked by:
Old 09-14-2017, 02:17 PM   #9
slaver0110
Orbinaut
 
slaver0110's Avatar
Default

Quote:
Originally Posted by jedidia View Post
 You could use dynamic_cast instead of static_cast and check the returned pointer for null instead, that would be faster.
Already done; switched to a dynamic cast and have everything exactly where I need it.

Code:
bool TestMFD::ValidVessel()
{
	hVessel = oapiGetFocusObject();
	VESSEL *v;
	v = oapiGetVesselInterface(hVessel);
	
	sprintf(TestClass, v->GetClassNameA());
	if (strcmp(TestClass, "Tug1") != 0)
	{
		CurrentView = V_NOCLASS;
		return false;
	}
	else
	{
		T1 = dynamic_cast<Tug1*>((VESSEL3*)v);
		CurrentView = V_ONLINE;
		return true;
	}
}
Just out of curiosity, what's wrong with the string comparison?
Cheers!!

---------- Post added at 02:17 PM ---------- Previous post was at 02:11 PM ----------

Quote:
Originally Posted by dbeachy1 View Post
 In other words, feel free to use static_cast, const_cast, or reinterpret_cast wherever you need it: they do not incur any extra runtime overhead at all.
This is exactly what I was originally concerned about. I imagined, due to inexperience, the cast happening every frame.

I'm learning, slowly but surely...
slaver0110 is offline   Reply With Quote
Old 09-14-2017, 02:51 PM   #10
Urwumpe
Certain Super User
 
Urwumpe's Avatar

Default

Quote:
Originally Posted by slaver0110 View Post
 This is exactly what I was originally concerned about. I imagined, due to inexperience, the cast happening every frame.
A cast usually only changes the data type of a pointer or variable. This means it happens either completely at compile time ( C cast, static_cast, reinterpret_cast, const_cast) or have only little overhead (dynamic_cast, out_cast).

It is simply needed for syntactic reasons. If a cast operator would not exist, we would implement one.
Urwumpe is offline   Reply With Quote
Old 09-14-2017, 10:45 PM   #11
jedidia
shoemaker without legs
 
jedidia's Avatar
Default

Quote:
Just out of curiosity, what's wrong with the string comparison?
Strings are arrays. Comparing and/or manipulating them is expensive, and should never be done on a frame by frame basis if it can be avoided.

I have lots of string comparisons in my loading code. But once the first frame ticks in, I avoid them like the plague.

Last edited by jedidia; 09-14-2017 at 10:48 PM.
jedidia is offline   Reply With Quote
Thanked by:
Old 09-14-2017, 11:54 PM   #12
jangofett287
Heat shield 'tester'
 
jangofett287's Avatar
Default

TBF, this use case is basically what dynamic_cast was made for. I'm not sure how expensive the type check is, but it's almost certainly less than a string comparison, even on short strings.
jangofett287 is offline   Reply With Quote
Thanked by:
Old 09-15-2017, 12:27 AM   #13
slaver0110
Orbinaut
 
slaver0110's Avatar
Default

Quote:
Originally Posted by jedidia View Post
 Strings are arrays. Comparing and/or manipulating them is expensive, and should never be done on a frame by frame basis if it can be avoided.
Thanks for that, and understood.
I've neatly grouped the string comparison with the ValidVessel method that is called off the MFD constructor, which I understand is only called once.

Again, thanks to everyone for all the help!!
And cheers!!
slaver0110 is offline   Reply With Quote
Thanked by:
Reply

  Orbiter-Forum > Orbiter Space Flight Simulator > Orbiter SDK


Thread Tools

Posting Rules
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
Forum Jump


All times are GMT. The time now is 08:30 AM.

Quick Links Need Help?


About Us | Rules & Guidelines | TOS Policy | Privacy Policy

Orbiter-Forum is hosted at Orbithangar.com
Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright 2007 - 2017, Orbiter-Forum.com. All rights reserved.