FlightGear: Generating Textured Lights in Blender

There are only few real light sources available in OpenGL (typically 8). Much too few for the virtual FlightGear world. One way to get around this limitation is to use objects with emissive material. This works well for complicated objects, but doesn't look very realistic, because there's no aura and the light becomes quickly invisible if you move away. Another way is to use flat objects with "halo" texture that are always directed at the viewer. This is the technique behind the lights of the Bo105 helicopter, the Golden Gate and the Dumbarton bridge, as well as the obstruction warning lights on antennas etc. The bad news: Creating such lights is a lot of extra work. It requires writing FlightGear animations, calculating vectors etc. The good news: most of this tedious work can be automated with a little Python extension script.

Installing the Blender script

Download the file fgfs_animation.py and put it in Blender's script directory. On Unices this is typically $HOME/.blender/scripts/. You can also configure Blender's script path to use another directory. The setting is in the info window that you get, for example, by dragging the lower main menu border down.


Creating the animation file

To try out the light generator function, start Blender and add an object to the scene. We'll use a simple circle: Add/Mesh/Circle, with 32 vertices, and assign a name to it. The script will derive all names for generated objects, materials, etc. from this name, and you make your life easier if this name isn't just "Circle.001". What about a useful and descriptive name? Don't make it too long, though, because the script will add a few characters.

name object 'foo'

Now you should have something like this:

before; only the circle

In case you wonder what the window on the right is. This is a rather new mode of the outliner. In this picture it was activated by splitting the 3D area (i.e. right clicking on the lower border and selecting Split Area), switching to the Outliner in the right window, and finally choosing View/Show Outliner from its menu.

All 32 vertices are selected by default and you can leave it at that. Now let the script create a (faked) light for each of the selected vertices. Call the script from the main menu: File/Export/FlightGear animation (fgfs-export.xml). (The script is in the Export menu because it writes (exports) FlightGear animation code.) You'll get a pop-up menu, from which you select Generate textured lights. This is what you get:

after; circle plus light faces

You see in the 3D window that the script added a square at the origin, consisting of two triangles. Actually, it's 32 squares, one over the other. You can see in the outliner window that they are named with the circle's name plus an "X" and a number. I have opened objects "fooX03", "fooX04" and "fooX05" so that you can see that all the added objects share the same mesh. This means that you can activate any of them and resize it, and all other light objects for this series will follow. They are linked.

Finally, you assign a light halo texture to one of the light objects. Just to one, because of the links. The other objects will automatically adopt the same texture and UV coordinates. You don't need to choose a material. This was already done by the script.

3D window and UV editor

All the new linked objects with their texture are just one aspect. In the background the script saved an animation file ready for use in FlightGear: fgfs-export.xml. If there was another file with this name in the same directory ... well, bad luck. In real projects, you will probably not use the animation file as is, but will copy the interesting parts into your already existing animation file. The generated xml file contains everything that is necessary to (1) scale the textured light objects according to viewing distance, (2) move them to the location of the vertex that it was created for, (3) makes sure that the faces always direct to the viewer (billboard animation), and (4) blend it with other (semi)transparent objects (alpha-test). Furthermore, all light objects are unselected at daylight. Many of the parameters will, of course, have to be tweaked for the particular purpose. All animations that aren't really necessary (especially the alpha-test animation) should be removed or commented out!

Testing the animation file with FlightGear

Although direct use of the animation file in FlightGear was not originally a goal of the Python script, it can be used for tests. Just save the Blender file first under, let's say test.blend, then delete the circle object, because this doesn't look so nice, and export the contents to test.ac. You should either configure the ac3d-exporter to use the mirror color for the emission property (Mir2Emis), or hand edit the test.ac file and make sure that emis is set to 1 1 1, spec to 0 0 0, and shi to 0:

MATERIAL "fooXmat" rgb 1 1 1 amb 0 0 0 emis 1 1 1 spec 0 0 0 shi 0 trans 0

Now you only need to write a small FlightGear configuration file config.xml:

<?xml version="1.0"?>
      <longitude-deg type="double">-122.37389</longitude-deg>
      <latitude-deg type="double">37.61948</latitude-deg>
      <elevation-ft type="double">65</elevation-ft>
      <heading-deg type="double">0.0</heading-deg>

create a directory $FG_ROOT/Local/Test/, copy test.ac and the texture image there, and move fgfs-export.xml there and rename it to test.xml. Finally, call fgfs like so:

$ fgfs --config=config.xml --aircraft=ufo --timeofday=midnight

And if you fly the UFO in KSFO to the VOR in the middle of the four runways, you'll see something like this:


It doesn't need to be midnight, just dark enough that the lighting goes on. Here's some more detail:

light details

And that's what is going on behind the scenes: In this picture the light objects aren't textured and the original circle is still there. You can move the UFO around this object, and the faces will always follow. No way to see their backsides! :-)

untextured light objects

Real World Example

If you are placing lights with the presented Python script, you have two possibilities: (a) either you select vertices on existing objects that belong to the model, or (b) you create helper objects solely for the purpose of placing lights, and you remove them before you export the model, or remove them from the exported object. In the following example I created three such helper objects: (1) one tetragon (circle with 4 vertices), (2) one triangle (circle with 3 vertices), and (3) one object consisting of three hexagons. The three objects could actually have been merged into just one object. Keeping them separated is desirable if you have different sorts of lights, with different textures, colors, sizes, etc., but on this tower they are the same anyway.