Today is Rosh Hashanah, the Jewish New Year. In Jewish tradition it is also thought of as the birthday of the world. If you’re reading this blog, you probably have some interest in how X-Plane attempts to simulate the world on your computer. The attempt over the years to create a higher fidelity simulation has led me to a deeper appreciation of the subtlety, complexity, and beauty of the real thing.
(Nothing makes you realize how rich and intricate the world is than trying to model it with a few million triangles and ending up with something that looks completely crude.)
X-Plane’s digital world isn’t the only way that we interact with a proxy instead of the real thing. When we drive instead of walk, eat packaged food from a supermarket, talk on the telephone instead of talk in person, our technology becomes a proxy for our relationship with our direct natural environment – the planet, plants, animals, and other human beings.
Now I’m not saying that any of these things is bad. I’m not about to become a dairy farmer, and without the internet we couldn’t create X-Plane at all. But I think it’s important on this day, and hopefully every day to take time for activities that put us in direct contact with the world. Consider a few questions:
- How does what I eat affect the world?
- How does my travel affect the world?
- What impact does my home have on the world?
- Am I leaving the world in better condition for the next generation or worse?
Please … take a few moments to consider the world, the only home we’ve ever had.
When I was in the Dolomites a few years ago with Sergio we were looking at the dolomites from his friend’s balcony – mile after mile of beautiful mountains and rolling hills. I looked at him and said “God has more polygons than we do.” It was a joke at the time, but I think that the act of really observing the real world and realizing that the digital reality and technology we create can be a proxy and an addition but never a replacement is critical to understanding the responsibility for stewardship we have over the planet. Are we taking good care of our most precious gift?
Side note: please do not post tech support questions as blog comments – please use the x-plane-scenery yahoo list or the x-plane.org scenery forum. I would like to keep tech support discussions in easily search-able public places so future users can get answers quickly.
I saw a post on x-plane.org referring to the process of creating translucency in objects attached to airplanes as a dark art. There is definitely a lot of weirdness in how X-Plane draws airplane objects. I will try to shed some light on what’s really going on and how to deal with it. For this first post, I’ll explain the requirements of the hardware, which shape the ensuing chaos.
First, and most important, in order for X-Plane to render translucent geometry (objects or otherwise), the geometry must be drawn from farthest from the viewer to closest. This is in stark contrast to normal operation — for transparent or opaque geometry, we can draw the closest objects first, and the graphics card makes sure the far away objects don’t “paint over them”. But the technology that does this (z-buffering) doesn’t work when the closer geometry is translucent. (If the translucent geometry is drawn first, it acts opaque to what is behind it.) For more info on this phenomenon and what to do about it, look here.
So in order for our translucent cockpit objects to draw correctly they need to be drawn from “back to front”. But note that this term is relative to the camera — which object is closest will depend on where the camera is located!
The other cause of cockpit object weirdness is the near clipping plane. At any time when X-Plane is drawing, there are two limits on where we can draw:
- The near clipping plane defines an invisible wall – anything closer to the viewer than this distance will not be drawn.
- The far clipping plane defines the other invisible wall – anything farther from the viewer than this distance will not be drawn.
The far clipping plane is usually set far enough away that objects disappear into the fog before hitting it. The near clipping plane is usually set close enough that by the time an object hits it, your plane has crashed.
Now here’s the rub: the quality with which the graphics card can discriminate which polygon is closer (via z-buffering) goes down as the ratio of the far to near clipping plane gets larger!
Take a second to think about that. Basically if we want to increase the visibility in X-Plane without losing z-buffering fidelity ,we need to move the near clipping plane farther away from the user.
The real problem is this: X-Plane, with its sometimes long visibilities (when you get up into orbit, you can see a long way!!) really stretches the z-buffering fidelity of even modern cards. So we have to keep the near clip plane fairly far from the viewer in order to have the world look reasonable. But that distance might be a lot larger than the distance from the viewer to the interior of the cockpit!
We work around this by having two separate drawing passes. We first draw the “outside” world, with a near clipping plane that is fairly far away. (Every now and then a user tells me that this clip plane is causing scenery not to be drawn.) We then draw the cockpit interior and the user’s plane, with the near and far clip plane both reset to be a lot closer. This way we can use our “z-buffer precision” in different ways for different geometry.
(It should be noted that z-buffering does not correctly handle the relationship between near and far objects when we reset the near and far clip plane. This technique works because we assume that everything drawn in the “cockpit” view will draw over everything drawn in the “outside” view.)
In my next post I will explain what X-Plane actually draws. For now suffice it to say that X-Plane has the task of drawing from farthest to nearest, but also the task of drawing in two phases: a far-away outside view and a close inside view.
We are now seeing two sets of Mac OpenGL driver-related bug reports: problems with the new Mac Book Pros (with an nVideo GeForce 8600) and with the new iMacs (with an ATI Radeon HD2400 or HD2600).
This doesn’t surprise me for two reasons (both of which are speculation, btw…I am not privy to what goes on inside Apple):
- Both of these cards are “next-gen” in a major way: DX-10 compatible hardware. That means they have a lot of cool new features. My speculation is that this larger jump in functionality of the hardware means more changes (and more bugs) in the drivers.
- We’re getting closer and closer to the next major OS upgrade (10.5), but this new hardware has to run 10.4. So I wouldn’t be surprised if everyone at Apple is fighting two fires at once, limiting resources.
So while this is frustrating to Mac users who have these machines, I would encourage patience. I don’t think we’ve seen to date a Mac that has been “left broken” — several machines have had problems with the drivers in their initial intro, and Apple usually fixes them as soon as possible. In the long term I believe that these will both be really nice X-Plane machines.
Why don’t the cars drive backward when you pull the slider backward in replay mode? The short answer is “because we don’t care enough to fix it”, but a better answer might be “it would take a lot of programming time and suck up more resources from X-Plane to fix this…and we think our customers would rather that we focus our programming and your hardware resources on framerate.”
The cars are an interesting special case of a whole number of sim phenomena that we don’t attempt to track carefully in replay. Replay is designed to allow you to watch your flight – it would be cool if the scenery was doing the exact same thing during replay as during the flight, but I don’t think it’s essential for training purposes and it does come with a cost.
First remember: replay mode works by saving past values of the sim to RAM. So the more we save, the more RAM we chew up saving past history, and the less time we can save before we run out of virtual memory.
Now in some cases, the motion of dynamic sim objects is at least somewhat random. In this case we can’t easily “reverse” the algorithm that generated the motion.
But the cars are more problematic.
Not only is their motion somewhat random (each time a car makes a turn at a fork in the road it randomly decides which way to go), the cars are maintained in memory in a way that allows us to figure out who has to make the next turn very rapidly without using a lot of CPU. As much as the cars are a CPU hog, they would be much much worse without this memory structure.
The problem is, the memory structure is organized based on time flowing forward. That is, we can only tell you which car needs CPU attention next if the cars are driving forward. Put time into reverse and we now know which car needed our help last! Not useful!
So to make the cars drive backward we would have to transform this data structure every time the flow of time changed. I think it would be more annoying to have this massive CPU recomputation each time you rewound the replay than it would be nice to have the cars move backward. Why not have two data structures, one for forward, one for reverse? Well, now we’ve saved CPU but burned RAM. Either way, we’re talking about hardware resources that could be used for more scenery or more framerate.
The cars have yet another behavior that makes them hard to reverse: they are born and die! A car is born any time we realize that there aren’t enough cars on the road for the given rendering settings. A car dies any time it gets too far away from the user’s plane or reaches a point in the road where it can’t procede. (Typically these are 1-way streets that dead-end. This happens because the road data we use has very poor flow information, leading to some really strange streets.)
This cycle of cars being born and dying maintains a reasonably constant car population over time, and a car population that is near your plane as you fly. But to reverse traffic, we would have to reincarnate cars that had died previously. This would mean spending memory on remembering what cars had died. (Even if the algorithm to decide where a car is born, the algorithm to predict where a car will die is quite complex, because it requires looking at the entire set of steps the car would make during its life until it reaches the “point where it is killed”. So computing this information is out of the question.)
That’s probably more information than you wanted to know. Generally speaking, if someting unrelated to the flight model doesn’t replay in replay mode, it’s probably because it would be too “expensive” to remember its history. The cars are the most complex example, but definitely not the only example!
This goes into the bucket of “weird X-Plane behavior”: X-Plane will try both PNG and BMP file extensions when opening images, no matter what is in your file. How we got to this state is, at best, confusing.
Originally, most X-Plane image files did not contain a suffix. So an ENV file contains “grass” and X-Plane would change that to grass.bmp.
Then we added PNG support. X-Plane would try grass.png and then grass.bmp. In this case, not having the extensions turned out to be handy — authors could simply bulk-convert their images and go on with life.
With most new scenery system files, the extensions are a lot more rigid:
- The extension appears in the referencing file.
- The sim only tries that extension.
- If the format doesn’t match the extension, it’s an error.
So if you want a DSF file to reference a facade, it’s buildings.fac and if that .fac file is actually a forest file, it’s an error. The sim won’t try to decide which is more correct, the header of the file or the extension, it will just go “you’re nuts” and bail out.
But (for historical reasons) images are an exception. Keeping with the “any extension goes” theme for images, X-Plane will actually try PNG and then BMP versions of your file. The extension has to match the format…that is if you call your bmp foo.png X-Plane won’t load it at all.
We have PNG as our primary image format and BMP for backward compatibility. But it’s imaginable that we could have DDS and PNG both as primary formats — PNG for images that need lossless fidelity and DDS for images where compression is acceptable. In such an event, X-Plane’s tendency to try every extension means authors can bulk-convert from PNG to DDS (making their packages load faster) and go home happy.
In my previous post I described a bug where, when we have a split vertex in an apt.dat layout, X-Plane would draw taxiway lights all over the place. Fortunately, there is a workaround.
Remember that a split vertex is represented as two or three colocated vertices with one or two zero-length segments connecting them. The bug is that zero-length segments cause lights and lines to go haywire.
The fix is therefore simple:
- Programs that write apt.dat files can simply set the attributes on the zero-length segment to none.
- Future versions of X-Plane (with a real bug fix) can join taxiway lines even when there is a zero-length “break” in the attributes.
This picture shows the results – a split vertex with no attributes on the zero-length segment.
The next WED beta will automatically export split vertices this way – there will be no need to patch X-Plane or change your WED layouts.
In my previous blog post I defined a split vertex in an airport layout and described how they can be simulated in an apt.dat pile using multiple points.
Now that WED is in public beta and people can easily make split beziers, many have noticed the “split bezier” bug in X-Plane 860:
This is a vertex that is split…on the left you can see what it should look like – on the right you can see what it does look like. There are two problems going on:
- The taxiway lights have gone crazy at the split vertex. (This is what everyone sees.)
- The taxiway line is a bit jumbled at the split vertex too.
It should be noted that this bug will can also happen for any vertex (even unsplit) in rare occaisions due to interactions with the mesh. Same symptom, same buggy code, different cause.
The good news is:
- There is a workaround that will make the lights look correct and the lines acceptable in X-Plane 8.60.
- The workaround will be implemented inside WED – no need to change anything.
- When X-Plane is fixed, it will make the lines correct too.
In my next post I’ll describe the fix and what the results look like.
(This blog entry explains the background of split beziers – the next parts will explain the bugs that they cause and the workarounds.)
In apt.dat terminology, a split vertex is any vertex of a polygon where the control handles on either side of the vertex are not exact mirror images. (When there is only one control handle it is therefore by definition split!)
You need a split bezier any time you want to:
- Have a sharp corner between two curves and control the tangents of the curves or
- Have a sharp corner between a truly straight segment and control the curve of the next segment.
Split Beziers and apt.adt
Now here’s the rub: the apt.dat format does not allow for split beziers – each curved point has only one control handle – the other is calculated by x-plane by mirroring…thus no vertex can ever be split.
(This is due to a total lack of brains on my part when working on the apt.dat format, which is quite embarrassing considering how long I spent thinking about it.)
The Hack
There is a way to simulate a split bezier: if you use zero-length segments (that is, multiple points on top of each other), you can create a shape that works as if it is split.
In its simplest, a split bezier can be created by using 3 vertices.
- The first vertex uses the control handle of one side.
- The second vertex is not curved.
- The third vertex uses the control handle of the other side.
Why does this work? Well, a bezier curve between a curved point and a straight point has zero length if the two points are on top of each other. So what we’ve done is inserted two zero-length segments. The result of this mess is that the control handles on either “side” of this cluster of points can be different!
Is the second point really necessary! Yes! The reason is this: if we simply had the first and third point (two bezier points with different control handles), X-Plane would draw a loop from the first to the second. Remember: two colocated points with ONE control handle form a zero-length curve, but two colocated points with TWO control handles form a loop.
(To see this for yourself, just draw some examples in WED or photoshop. 🙂
Line Continuity
There is one more wrinkle we have to add to the puzzle in order to understand how this works, and what the pitfalls are: line continuity.
A bezier path (taxiway edge, linear segments, etc.) is made up of one or more bezier curves. Each curve has zero or more attributes.
When X-Plane draws the actual taxi lines and lights, it looks for continuous adjacent bezier curves with the same attribute and makes sure the linkage between those attributes is correct.
(This linkage is computed separately for each type of property. So if you have taxiway lines on two segments and lights on one, the taxiway lines will still link!)
The picture above shows a correct vs. an incorrect link. When dealing with unsplit beziers and non-curved points, linkage is pretty much automatic, it just works.
But there is a pitfall to our above hack for split vertices: we have three points on top of each other. They must all have the same attributes in order for linkage to work. A “break” in the continuity of the line for one of the zero-length segments still counts as a break in linkage. The picture on the right was produced by creating a split bezier and removing the double-yellow-line attribute from the second of three vertices.
In my next post I’ll explain the bugs that this causes in X-Plane 8.60.
An overlay DSF can define exclusion zones – rectangles where scenery from lower priority DSFs is not shown. Exclusion zones are organized by entity type – that is, you must make a separate exclusion zone for objects vs. forests.
The problem with exclusion zones in X-Plane 860 is that the implementation of exclusion zones isn’t quite right for lines and areas.
Essentially any element of a DSF is zero, one or two dimensional:
0d – Points (objects, very small facade objects).
1d – Lines (beaches, roads, large facades with no roofs, bezier lines and bezier object chains).
2d – Areas (large facades with roofs, bezier pavement, forests)
The problem is that X-Plane eliminates any entity if and only if one or more of its vertices intersects an exclusion zone.
This can be wrong in two ways:
– If an entity intersects the exclusion zone, it is deleted entirely, rather than having the exclusion zone subtracted.
– If an entity surrounds or goes through an exclusion zone without a vertex being in the zone, it is left alone.
Every now and then someone sends us this:
http://www.xtremesystems.org/forums/showthread.php?t=117500
The question is of course, why doesn’t X-Plane look like that yet?
Now there’s a lot of reasons why flight simulators don’t look like first person shooters…you can definitely optimize any game content for a specific viewpoint — X-Plane’s lack of constraints on the camera position (you can put the camera quite literally ANYWHERE on the Earth at any time of day, atmospheric condition, and orientation) means that there are going to be views that don’t look so hot. And the global scope of X-Plane means that we have to focus on quantity to a certain extent over quality. (If we made KSBD look totally awesome and didn’t ship any state but California in global scenery, where would we be.)
I’ve been working lately on pixel shaders and lighting…when you look at those shots, the total integration of a number of great lighting effects is responsible for a lot of the look. But…I think there’s a more fundamental issue that pixel shaders and carefully made content wouldn’t address.
Simply put, X-Plane’s LOD system isn’t scalable enough.
In order to get images that look that good you need to put a huge amount of detail up close near the camera, where the user can see it, but not put that detail in the background. (Imagine if every tree in those scenes was done in the detail of the foreground – the polygon count would be unmanageable.)
But X-Plane’s scenery SDK (the interface by which scenery content is specified to X-Plane, in other words, “the file formats”) lacks really strong LOD capabilities.
- The terrain mesh is fixed – you can use LOD to eliminate overlay details, but you can’t actually simplify terrain.
- The cost of LOD in objects is high enough to prohibit really gradual LOD. No morphing is provided.
- Textures are mipmapped but loading is not variable, so our VRAM budget doesn’t benefit from LOD and locality of textures in X-Plane space.
- Generated geometry (roads, trees, etc.) don’t have any LOD except “eliminate whole feature”.
- There is no far view of 3-d clouds.
- Airport layouts are tessolated at only one complexity.
I could go on and on…the bottom line is, X-Plane’s rendering model is very static.
Why did we do that? Well, it seemed like a good idea at the time. In particular, recalculating LOD is very expensive on the CPU and at the time we had only one core. Recalculating LOD would cost more in lost fps than it would benefit in offloading the GPU. So we went for static meshes that we could blast out to the card “real fast”.
What you might not know about those screenshots is what kind of hardware it’s running on:
http://www.gameklip.com/v/1606/
Yep…four cores, and overclocked by over a ghz. (I can only speculate that shortly after the clip ends the machine caught on fire. 🙂 In a multicore environment we can apply additional CPU resources to dynamically rebuild the environment to increase the “LOD range” (difference between the near and far view).
In fact, we already started to do that! In X-Plane 830 we modified the sim to build 3-d content (roads, forests, etc.) on a second core while flying, instantiating only the close ones. This saved RAM and improved the overall performance of the sim, and it increases our LOD range.
(Even if something isn’t drawn, it has a cost just to exist – by saying that things that are really far away don’t even exist we improve performance.)
As you can see from the above list, there’s still a lot to do on the LOD front. But the scenery system is continually growing – new features for the various primitives and improvements to the engine will let us continue to improve sim efficiency.