Category: Development

Dealing With Repetition

I was going to post some pictures of the newly fixed “auto-vary” feature, but before I can do that in a way that makes any sense, I need to explain how X-Plane deals with texture repetition.

Texture repetition is the inevitable result of using “landuse-style” texturing (that is, a repeating single texture representing a type of land).  Typical X-Plane land use textures are 1024 x 1024 at max res and repeat about every 3-5 km.  Unfortunately, our brains are pattern-recognizing machines, and the result of this texturing scheme is that the “grid lines” of texture placement become apparent over wide views.  
We use a number of techniques to minimize this problem.
Lots of Land Uses
Our main tool to combat repetition is to not use a given land use for too large of an area.  This has the advantage of efficiently using the entire set of textures, and (because terrain textures change based on an irregular grid, based on elevation) the changes to textures are both irregular in shape and “plausible” in placement.
In this picture, you can see that the urban residential land use has been interrupted by various forest and grass textures.  This is intentional – Sergio tuned hte land use rules to make sure that we wouldn’t have large regions of one land use type.  Those blobs match the irregular grid, which gets its shape from the terrain’s elevation.
Variation
In the above picture, you can still see the repeating grid of the residential terrain; observe the right side – you’ll see the same repeating vertical pattern of road repeating over and over.  In order to further hide repetition, we use the same texture multiple times, but in offset locations.
Here you can see that the vertical line on the right side has been broken up a bit.
More VRAM
In some cases, a terrain covers such large areas despite the rule set (e.g. for really flat areas) that we use two separate textures and can vary between them.  Here you can see both input textures for our dry square crop land use, as well as the combined results.



In summary, we have three techniques:
  1. Add more rules to prevent large spans of a single land-use.
  2. Use a texture with multiple offsets (variation)
  3. Use two textures and vary between them.
Posted in Development, Scenery by | Comments Off on Dealing With Repetition

The “Airplane Modeling” Datarefs

I have blogged about this before, but I will try to create one simple explanation of what’s going on with sim/cockpit2 and sim/flightmodel2 datarefs.

Sandy and I (with the help of others who helped compile the list) created “new” datarefs (first released with X-Plane 9) , aimed at airplane modelers. These new sections are:

  1. sim/cockpit2/ which provides a new set of datarefs for cockpit modeling via OBJ animation and generic instruments.
  2. sim/flightmodel2/ which provides a new set of datarefs for airplane exterior modeling via OBJ animation.

These datarefs sometimes include new data that was not available in version 8, and sometimes they simply provide a second dataref with the same information. Why duplicate datarefs? The new datarefs have some special properties, so I wanted to have a complete set of datarefs for modelers with these new properties.

Skip to the end for the rules of thumb on how to use them.

Clean Naming

The new datarefs are designed to have longer, less confusing names; the old datarefs contained a lot of abbreviations – potentially acceptable for programmers (who are used to seeing things like fstat and chgrp on a regular basis) but not good for modelers who do not speek English as a first language. The new datarefs have long names and are more consistent in their conventions. They also contain complete documentation.

Array Sizes

You will see the array dimension of some of the new datarefs as symbolic constants, e.g. [engine] instead of [8]. This is because the dataref generation system we use knows that these new datarefs sometimes track the maximum number of parts in the aircraft structure. This tagging means that it is much simpler for Sandy and I to adjust the datarefs when Austin increases part maximums.

With the old datarefs, if Austin allows for 10 engines, Sandy and I must search for every [8] dataref and decide if it must be [10] – some will be per-engine and need to change, some will be per-battery and will not! With the new system, we simply redefine the “engine” constant to 10 and the datarefs adjust.

(Note that if your plugin really needs to run dynamically with any number of engines, the best thing to do is to read the array size using XPLMGetDatavX.)

Failure Support

There are two ways to view a dataref: before system failures (such that the dataref reflects simulated physical reality) and after system failures (such that the dataref reflects pilot indications). For example, when the pitot tube ices up, the pre-failure airspeed reflects how fast you are flying; the post-failure airspeed reflects how much crud is in your pitot tube.

Pre-failure datarefs are appropriate for animating the exterior of the airplane. For example, if the gear indicator light fails but the gear is working, you want to animate your landing gear based on the real (pre-failure) gear position, so that the gear really does look like it’s down from an outside view.

Post-failure datarefs are appropriate for animating the cockpit. For example, you want to use that post-failure indicated airspeed for your air speed indicator, so that pitot ice will affect your generic instruments and animations, as well as the built-in instruments.

The new datarefs are designed to clearly provide two different views:

  • sim/cockpit2/ are all post-failure whenever possible, and are thus appropriate for cockpit modeling.
  • sim/flightmodel2/ are all pre-failure, and thus are appropriate for external airplane modeling.

Be careful not to swap them! You should always be using sim/flightmodel2/ for your aircraft and sim/cockpit2/ for your cockpit. If the dataref you need is in one and not the other, email me and I will add it to the right place.

Correct Multiplayer Behavior

The older datarefs all return data about the user’s airplane. However if you build an object, attached to an ACF, and that ACF is loaded for a multiplayer plane, you will get incorrect results — the user will see his own plane’s actions visualized on the multiplayer plane.

The new sim/cockpit2/ and sim/flightmodel2/ datarefs handle this case correctly: they return data about whichever airplane is being drawn. Thus if your object is attached to airplane number 5 in a multiplayer session, that’s the airplane that will animate your control surfaces.

(Plugin developers – outside airplane drawing, these datarefs return information about the user’s flight.)

For this reason, you should always use sim/cockpit2/ and sim/flightmodel2/ – not the older sim/cockpit and sim/flightmodel/ datarefs. If the dataref you want is only in the old sections but not the new ones, email me!

What Dataref Do I Use?

Here’s the rule of thumb:

  • If you are targeting X-Plane 6/7/8, you must use sim/cockpit and sim/flightmodel, otherwise
  • If you are targeting X-Plane 9, use sim/cockpit2 for your generic instruments and 3-d cockpit. Use sim/flightmodel2 for your attached objects.

That’s all there is to it!

Posted in Aircraft, Aircraft & Modeling, Cockpits, Development, Modeling, Panels by | Comments Off on The “Airplane Modeling” Datarefs

Two Video Cards, Two Vendors

The short answer is: this is not a very good idea.

Now with OS X, this configuration is supported, and OS X will cleverly copy graphic output from one video card to another to make the system work well. You will get a fps hit when this happens.

With Vista, this configuration isn’t supported. (Snarky comment: it is lame that Microsoft completely rewrote their video driver infrastructure and went backward in terms of configuration support.)

With Linux, I have no idea if this configuration can run. I do know that trying to change my configuration hosed Ubuntu thoroughly and I decided not to break my Linux boxes any more, having spent plenty of time doing that already in the last few days.

For X-Plane, we can’t handle this case very well (at best you get the framerate hit) because we need to share textures between the IOS screen and main screen. So if you are trying to set up an IOS screen, you really do need a dual-headed graphics card. For what it’s worth, every card I’ve gotten in the last few years has had two video outputs.

Posted in Development by | 3 Comments

Fun With Menubars

My Mac Pro has just gotten weirder – I put a Radeon HD 3870 into the second PCIe x16 slot. (The machine comes with  a GeForce 8800.)  I now have one monitor in each.

So here’s where things get fun:
  • Start X-Plane.  60 fps.
  • Drag the window to the second monitor.  30 fps.
  • Quit, move the menu bar to the second monitor, restart.  (X-Plane is now on the right.)  160 fps.
  • Drag the window back to the primary monitor on the left.  100 fps.

What’s going on?  Two things:

  • On OS X, X-Plane’s graphics are rendered by one video card, and that video card (in 921) is the card that has the menu on one of its monitors.
  • When an OpenGL window is displayed on a monitor that is not attached to the video card that is doing the rendering, OS X will copy the image from one video card to another, at a cost of some framerate.

So what’s going on above?  Well, the 60 fps is my 8800.  When I drag the window, the OS starts copying the graphics, slowing fps.  When I move the menu bar, the 3870 does the rendering, and we get much higher fps.  Once again, put the window on the monitor that is not attached to the video card, and fps hit.

Final note: fps tests of the 8800 vs 3870 with X-Plane 921:
Fps test 2, 8800: 46,49,51
Fps test 2, 3870: 70,75,80
Fps test 3, 8800: 24,25,25
Fps test 3, 3870: 40,41,43
In other words, the 3870 is significantly faster.  I believe that this is due to the OS X drivers, not the cards themselves.  Note that the 3870 is in a PCIe 1.0 slot and the 8800 is in a PCIe 2.0 slot.
Posted in Development by | 9 Comments

Hardware Guidance: Four Cores and DX10

I think we’ve reached the point where, if you are putting together a new computer and have X-Plane in mind:

  • Get a quad-core machine if the pricing is favorable (and I think it should be now).
  • Get a “Direct X 10” compatible graphics card.  That would be an nVidia 8, or 9 series (or I guess that crazy new 280 card) or a Radeon HD 2000/3000/4000.  DX10-type cards can be had for $100 to $150.

Quad core is easy: X-Plane 921 will use as many cores as yo have for texture loading (especially in paged scenery), uses two cores all the time, and uses 3 during DSF load.  The infrastructure for this additional scalability (previous builds used two cores, more or less) will let us put 3-d generation on 4 cores or more.  More on this in another post, but basically X-Plane’s utilization of cores is good and getting better, so four cores is good, particularly if it’s not a lot more expensive.

Now for DX10, first I have to say two things:
  1. We don’t use DirectX.  We have no intention of switching to DirectX, dropping OpenGL support, or dropping OS X/Linux support.  I just say “DX10” to indicate a level of hardware functionality (specified by Microsoft).  The DX10 cards have to have certain hardware tricks, and those tricks can be accessed both in OpenGL and Direct3D.  We will access them by OpenGL.
  2. We are not going to drop support for non-DX10 cards!  (We’re not that crazy.)

X-Plane does not yet utilize those new DX10 features, but the DX10-compatible cards are better cards than the past generations, and are now affordable*.  By making sure you get one of these, you’ll be able to use new graphic features when they come out.

* The roll-out of DX10 cards has been similar to DX9.  With the first generation cards there was one expensive but fast card and one cheap but slow card.  With DX10, NVidia got there first, with DX9 ATI did.  Like a few years ago, now that we’re a few revs into the new spec, both vendors are making high quality cards that aren’t too expensive.
Posted in Development by | 4 Comments

Spam My Wiki, Please

User Rs2Play is now the first user to be banned from the X-Plane Wiki.  WikiMedia has some automatic features, like banning all associated IP addresses with a banned user, so if you find yourself kicked from the Wiki in error, email me and I will fix it.  (This would only happen if you were in the same shared IP pool as the user in question.)  Thanks to the users who immediately removed the spam while I was out of the office.

(If we have more spam, I can promote a few users to admin status to ban spammers faster, but so far we have had only one case.)
Unfortunately the situation with the X-Plane SDK Wiki is not as good.  The problem is that the SDK Wiki does not use MediaWiki – it uses phpwiki, so we do not have the rich set of user admin tools that MediaWiki comes with out of the box.  There is currently a user who is (for some reason) attacking the user database by registering fake email addresses over and over.  I do not know what the user hopes to accomplish, other than wasting my time.
The unfortunate side effect is to leave the SDK Wiki user database in a state of chaos.  When I have time, I will be adding some new features to the user signup code and trying to clean out the user base.
Why are we not using MediaWiki for the SDK?  Well, besides history (we used what we found at the time), the SDK Wiki’s code is customized to integrate the SDK development tools with the Wiki itself.  This is how you get the latest documentation and user generated content on one page when you look up an XPLM function.
There is no scenery system Wiki – something I have debated a bit.  At this point though I am more concerned with getting the scenery tools out than with updating the documentation; once we have a more complete tool set, then I can ask the question “can users figure out how to use these tools.”
Posted in Development, News by | 1 Comment

(More) Triangle Optimizations

Yesterday I described how triangles and meshes can be optimized and hypothesized that building OBJs carefully could improve vertex throughput.  Having looked at some numbers today, I think the potential for framerate improvement isn’t that great…an improvement would come from cache utilization (post vertex shader), and our cache usage seems to be pretty good already.

Simulating a FIFO vertex cache with 16 vertices (an average number – very old hardware might have 8 or 12, and newer hardware has at least 24 slots) I found that we miss the cache preventably around 15% of the time (using a random set of OBJs from LOWI to test) – sometimes we really missed bad (20-25%) but a lot of the time the miss rate might be as low as 5%.  
What these numbers mean is that at the very best, index optimizations in OBJs to improve vertex throughput might only improve vertex processing by about 15% (with the FPS improvement being less, since vertex throughput isn’t the only thing that slows us down).
In other words, if I solve the cache problem perfectly (which may be impossible) we get at best 15%.
So this could be a nice optimization (every 5% win counts, and they matter if you can improve fps by 5% over and over) but cache utilization isn’t going to change the nature of what you can model with an OBJ, because our cache utilization is already pretty good.
Have a Happy Thanksgiving!
Posted in Development by | Comments Off on (More) Triangle Optimizations

Triangle Optimizations

I’ve been looking a bit at triangle optimization – first some terminology:

  • Indexed triangles means that the vertices in a mesh are referred to by index numbers.  This is the scheme OBJ8 uses.  The advantage of indexing is that if a single vertex is used by many triangles (that share a corner) you only have to include the vertex data once, and then use that data many times by index.  (The savings from indexing depend on how often vertices are shared.)
  • Triangle strips are strips of triangles sharing common edges.  Because triangles in strips share so many common vertices, they can be stored in a compact form, for a savings of almost 3x.
Back in the old days, triangle strips were critical for performance (hence the presence of strips in the OBJ2 and OBJ7 formats).  However with modern hardware, indexing is more efficient – the slight increase in data size (due to the index) isn’t as expensive as the cost of specifying “we’re done with one strip, start the next one”.  (Consider that if we use indexed triangles, we can submit all triangles in one batch – with strips, we need one batch per strip.)  Thus OBJ8 uses indexing and doesn’t provide any strip primitives.
There is one other concept to be aware of: cache utilization.  Graphics cards remember the last few vertices they processed, so if a mesh repeats a vertex shortly after using it, the graphics card can save work.  Triangle strips naturally use a cache somewhat well because vertices occur in close succession.
Strips and DSF
DSF allows for triangle strips (and triangle fans) as a space-saving measure.  Even with indexing, the indices can be compressed if strips and fans are used, and with DSF, file size was a very high priority.
When the DSF file is loaded, the data is rebuilt into indexed triangles (and reindexed – the DSF internal structures don’t provide as good indexing as the DSF loader can create) – in version 803 we first started using indexed triangles and found it to be a big win.
MeshTool will generate triangle fans (as a space saving measure) – if you build a DSF by hand (using DSF2Text), use strips/fans to compress file size.
Because DSF focuses on file size, the quality of mesh output is a function of the DSF loader, which has to run while flying.  So while I can imagine some improvements in future performance, I don’t expect to be able to get huge wins because the very best mesh optimizing algorithms are much too slow for real-time use.
The DSF loader already produces full indexing and preserves cache utilization from strips and fans – the next logical optimization would be to reorder non-strip, non-fan triangles for better cache use on load; the order in the DSF file may be optimized for file size and not cache utilization.
Optimizing OBJs
Where I believe there could be real improvement is in OBJ8 generation.  The OBJ loader currently loads the indexed OBJ triangles exactly as specified in the file – build a smarter file and we can get faster framerate.  There are two possible ways to win:
  • Cache utilization – by ordering vertices for cache use, we can get better throughput.
  • Hidden surface removal – by putting the exterior triangle earlier in the OBJ, we can draw them first, occluding the interior of an object, which cuts down fill rate.  (In an airplane, you would want the exterior fuselage first in the OBJ, before the seats inside, so that only the pixels visible through the window are drawn.)

This second form of optimization may be of limited utility in that an OBJ8 optimizer has to respect authoring decisions about translucency, attributes, etc.

I am investigating OBJ optimization now – my hope would be to put optimization into a new version of the ac3d exporter and ObjConverter.
Strips and the iphone
There is one place that triangle strips do matter: the iphone.  It turns out that the iphone will process triangles a lot faster if they are presented in a strip-like order.  So the iphone DSFs are the first to use triangle strips (instead of fans), and the OBJ exporter for the iphone optimizes the OBJ mesh into triangle strip order.
My tests indicate that strip order makes no difference on modern ATI and nVidia GPUs, so there is no point in releasing these optimizations in the main X-Plane tools.  In the long term, I expect our OBJ tools will have two optimization paths – a strip-based path for the iphone and a cache utilization-based path for the desktop.
Posted in Development by | 2 Comments

Why Animating Cars Doesn’t Always Work Right

I saw a post about this on X-Plane.org…authors sometimes try to make a vehicle (a car, truck, etc) modeled via an OBJ “drive around” using animation translate commands.  The problem is that sometimes the objects disappear.  Here’s what is going on:

X-Plane uses a bounding sphere to decide whether to draw an object.  The bounding sphere is the smallest sphere X-Plane can fit around the entire object; if the sphere is on screen, the object is drawn (even if the object itself isn’t on screen).  We do this because we can test whether the sphere is on screen very quickly.
But what if the object has animation?  X-Plane attempts to guess how animation might affect the sphere by looking at animation commands and making the sphere a bit bigger where animation might move the object outside the sphere.  This process works, well, rather poorly. In particular, X-Plane doesn’t know exactly how your datarefs will change.  This results in two error cases:
  • If X-Plane assumes the animation is more drastic than it really is, we make the sphere too big.  The object will then be drawn even when it is not on screen (because the sphere is on screen because it is too big).  This case hurts fps but does not cause objects to disappear.
  • If X-Plane assumes the animation is less drastic than it really is, we do not make the sphere big enough, and sometimes the object “disappears” because the object is on screen but the (too small) sphere is not.

Now let’s apply this to objects that are driving around.  Usually this is done via a translate animation command where datarefs feed the object’s position.

X-Plane estimates the effects of a translate animation using the largest and smallest key frame values.  But the animation engine will extrapolate beyond these key frames.  So consider these three cases:
  • As your dataref goes from -1 to 1, you translate by +/- 1 meter.  In this case, the bounding sphere will be increased in radius by one meter.
  • As your dataref goes from -25 to 25, you translate by +/- 25 meters.  In this case, the bounding sphere is increased in radius by twenty five meters.
  • As your dataref goes from -1000 to 1000, you translate +/- 1 kilometer.  In this case, the bounding sphere is increased in radius by 1000 meters.

Note that in all three of these cases, the animation works exactly the same!  But by using different dataref and value extremes, X-Plane’s estimate of the effects of the animation (and its change to the boundign sphere) can be quite different.

So…if you animate an object and it disappears, it is probably because the bounding sphere has not been increased, perhaps because a translation animation is being sent values outside its minimum and maximum values.
The problem is of course that to have an object “roam” over a large area, it must have a very large bounding sphere, which means it is being drawn a lot more than necessary.
Posted in Development, File Formats by | Comments Off on Why Animating Cars Doesn’t Always Work Right