![]() |
|
|||||||
| Orbiter SDK Orbiter software developers post your questions and answers about the SDK, the API interface, LUA, meshing, etc. |
![]() |
|
|
Thread Tools |
|
|
#61 |
|
shoemaker without legs
![]() |
Quote:
|
|
|
|
|
|
#63 |
|
Aspiring rocket scientist
![]() ![]() ![]() |
I've run into more issues and rather than start a new thread I figure that I'll just continue this one.
My laptop is my test machine and while it maintains 30 fps in exterior or glass cockpit views this dropped into single digits in my VC. Because my FPS remained steady with the redraw events commented out (an the code was a complete mess) I've spent the last week tearing it down and rebuilding. Now I've traded low-FPS for new problem, CTDs. The culprit is our old friend, the LCD print function. ![]() The function worked previously and recieved only minor changes so I'm not sure where the issue lies. The changes were... ...In clbkloadvc Code:
// Register main panel numerical displays sh_LCDdisplay = oapiGetTextureHandle (mh_cockpit, GRP_Panel_LCDs); oapiVCRegisterArea (AID_LCD_simdate, _R(0,0,216,40), PANEL_REDRAW_ALWAYS, PANEL_MOUSE_IGNORE, PANEL_MAP_BACKGROUND, sh_LCDdisplay); ...in the function it's self Code:
void LEM::LCDPrint(SURFHANDLE surf, char* text, int row, int _length)
{
int cHeight = 40; // Character height [pixles]
int cWidth = 24; // Character width [pixels]
int cRow, cCol; // Character's position in bitmap [row / column]
int textwidth = cWidth * _length;
int fontxofs = 0;
int fontyofs = 15;
for (int i = 0; i < strlen(text); ++i)
{
cRow = (text[i] - 32) / 30;
cCol = (text[i] - 32) % 30;
int srcX = fontxofs + cCol * cWidth;
int srcY = fontyofs + cRow * cHeight;
int tgtX = i * cWidth;
int tgtY = row * cHeight;
oapiBlt( surf, sh_Inst, tgtX, tgtY, srcX, srcY, cWidth, cHeight); // blit
}
}
Finally: Are there any general rules of thumb for optimising VCs that anyone can share? I'm learning as I go here. ---------- Post added 08-05-12 at 01:35 AM ---------- Previous post was 08-04-12 at 09:47 PM ---------- Solved the CTDs! ![]() oapiGetTextureHandle takes the texture index as an argument not the meshgroup. ![]() The SDK's panel tutorials refer to a "mesh surface" which i thought refered to a specific face/group but it does not. Now that I know what I was doing wrong I can get back to work. The funny thing is that before I began consolidating/optimising I literally had "texture #1" assigned to "Group #1", "texture #2" to "Group #2", and so on. It worked after a fashion but boy do I feel silly now. ---------- Post added at 01:45 AM ---------- Previous post was at 01:35 AM ---------- Question! From a processing/memory standpoint is it better to do multiple simple redraw events(update each gauge individually) or do fewer but more complex redraw events such as redrawing a whole section of the panel? The VC is turning into a real frame rate killer and I'm looking for advice on how best to prevent this. |
|
|
|
|
|
#64 |
|
shoemaker without legs
![]() |
Quote:
But what you have to ask yourself the most is how often the whole panel actually needs to redraw, and wheather it needs to be all at once. Most elements are enough to update once per second, and you don't have to do them all at the same time. For those elements where it doesn't matter, compensate time acceleration and update them in real time. I really can't see how you could run into framerate troubles when you divide up the workload smartly (you can't possibly have much more of it than IMS.... )And if the thing is still too slow, you might take Urwumpe's advise about editing texture coordinates under advisement. |
|
|
|
| Thanked by: |
|
|
#65 |
|
Aspiring rocket scientist
![]() ![]() ![]() |
Could you explain "divide up the workload smartly" are there general rules of thumb for optimising VCs that I should be aware of?
Likewise you say "you don't have to do them all at the same time" but how does that work? You either update at every time step or you update when a condition changes. Either way the calculation for a given timestep are all going to be done together. If you look at the image above you'll see 20 tape gauges (10 sets of 2) as it stands I calulate/redraw each set seperately but in the actual sh_Inst texture they are contiguous so in theory I could render them all in a single (large) rectangle, should I? |
|
|
|
|
|
#66 |
|
shoemaker without legs
![]() |
Quote:
Quote:
However, you already have to blit the scales into the tapes, so blitting the background separately is a doubly bad idea. You could just make that background part of the scale and save yourself an entire operation per tape... |
|
|
|
| Thanked by: |
|
|
#67 |
|
Aspiring rocket scientist
![]() ![]() ![]() |
Quote:
Right now the clocks are all 'PANEL_REDRAW_ALWAYS' and display SimT and SimDT respectively. The MFD buttons are triggered by mouse event. Quote:
|
|
|
|
|
|
#68 |
|
shoemaker without legs
![]() |
Quote:
I use only REDRAW_USER for all my panel elements. In my mouse handling, each element evaluates the situation for itself and triggers only a redraw if the event actually changes something. For elements that redraw on timer, my panel element class has it's own timer function that gets updated every frame, but of course only triggers the redraw when it should happen. And, as I said, if you still have trouble, you can offset the timers a few centiseconds so they don't all redraw in the same frame. Quote:
Also, about those needles: If you really want high performance, make the needle a meshgroup and move it by animation instead of bliting (you'll also get "transparency" this way, so win all the way), and suddenly you end up with your 20 tapes not needing even a single bliting operation ever instead of what currently seems like three every frame... If the scales scroll, you could do the same and make the whole tape its own meshgroup, that rotates just like a real one to move the scale. |
|
|
|
| Thanked by: |
|
|
#69 |
|
Aspiring rocket scientist
![]() ![]() ![]() |
Quote:
Could you post an example? Quote:
I had already been considering doing the ADI ball as an actual mesh because I thought the code might be simpler, should I just go a head and do it? ---------- Post added at 07:29 PM ---------- Previous post was at 07:12 PM ---------- If I'm not going to have a scrolling scale should I do the gauges seperately? One benefit that comes to mind is being able to stagger the redraw events as you described above. Of course if I really wanted to go overboard I'd do the whole cockpit as mesh animations but I've been trying to keep the vert count to an absolutminimum because I was under the impression that animations/mesh rendering were a much bigger drain on system resources than textures. Last edited by Hlynkacg; 08-05-2012 at 07:24 PM. |
|
|
|
|
|
#70 |
|
shoemaker without legs
![]() |
Quote:
Here's what the registering of my "MFC" class looks like in clbkLoadPanel (well, one of the instances, anyways): Code:
RegisterPanelArea(hPanel, AID_MFC1, _R(8,8,258,238), PANEL_REDRAW_USER, PANEL_MOUSE_LBDOWN|PANEL_MOUSE_LBPRESSED|PANEL_MOUSE_LBUP|PANEL_MOUSE_ONREPLAY, panel2dtex, mfc[0]); The class has a function for triggering its own redraw: Code:
void IMS_MFC::TriggerRedraw()
{
if (vessel->GetActivePanel() == Panelid && oapiCameraInternal() && vessel == oapiGetFocusInterface())
oapiTriggerPanelRedrawArea(Panelid, MYid);
}
The first line checks if it is even located on the currently active panel of the vessel (as this function is also used for timed redraws, not just for input triggered redraws. Also, this isn't an API function, but it's irrelevant for VC anyways), if Orbiter is even in cockpitmode and wheather or not the current focus vessel is the vessel that contains this panel elements (otherwise, redrawing would not just be futile, but ctd-ishly dangerous, as I noticed). If all these conditions are fulfilled, the function triggers the redraw of its panel element. Otherwise there won't be a redraw (as none is necessary). In the event processing function of the class, it determines what exactly has been modified, and if the event warrants a re-write (that is, the apearance of the element changes by the event), it simply callsTriggerRedraw, like for example (mostly pseudocode): Code:
bool IMS_MFC::ProcessMouse2D(int event, int mx, int my)
{
if (ThisImportantButtonPressed)
{
Do;
Stuff;
This;
Button;
Should;
Do;
TriggerRedraw();
return true;
}
return false;
}
Then there's the timer function of the class, which is pretty straightforward too: Code:
bool IMS_MFC::CheckRedrawTimer(double simdt)
{
if (RedrawTimer == 0 || !active || mnu) return false; //if timer set to zero, not active or in menu mode, don't even bother
ElapsedTime += simdt / oapiGetTimeAcceleration(); //adjust for time acceleration. mor fps friendly.
if (ElapsedTime > RedrawTimer)
{
ElapsedTime = 0;
timerInterval = !timerInterval; //just a variable tat changes state every time. Usually used for blinkenlights
TriggerRedraw();
}
return true;
}
Quote:
Quote:
EDIT: Quote:
Quote:
Last edited by jedidia; 08-05-2012 at 08:13 PM. |
|
|
|
|
|
#71 |
|
Aspiring rocket scientist
![]() ![]() ![]() |
Quote:
All that remains (aside from creating the 3d model) is to rotate the mesh X, Y, and Z degrees along the given axes. Quote:
Last edited by Hlynkacg; 08-05-2012 at 10:06 PM. |
|
|
|
|
|
#72 |
|
shoemaker without legs
![]() |
Quote:
|
|
|
|
|
|
#73 |
|
Aspiring rocket scientist
![]() ![]() ![]() |
Quote:
---------- Post added at 11:48 PM ---------- Previous post was at 10:36 PM ---------- As an aside, I've adapted your timer routine to my LCDs and my fps has jumped from 12 to 25. Still not the 30-40 that I get in the default "glass cockpit" but a marked improvement none the less. |
|
|
|
|
|
#74 |
|
shoemaker without legs
![]() |
Quote:
![]() Quote:
|
|
|
|
![]() |
|
| Thread Tools | |
|
|
|||||
| Quick Links | Need Help? |