Figure 1. Screen shots from the helicopter simulator |
You can download the helicopter simulator demo from here. (1.8 Mbyte ZIP file, runs under DOS.)
Military and civilian professional aircraft simulators are used to train aircraft personnel. This is usually cheaper and less dangerous than to train people in a real aircraft. Beyond that, the crew can train situations that they cannot or can rarely learn in real aircraft, because the conditions are extreme or dangerous. These simulation engines usually have a lot of expensive graphics hardware to produce awesome graphics.
The other kind of simulators are used by the computer games industry. Because of obvious business reasons, the game has to be widely available, therefore it has to run on cheap personal computers. Until a short time age, this usually lead to limited success mainly because of hardware limitations.
The newest hardware of today bring a lot of computing power with a reasonable price, which makes it possible to create professional quality simulators on personal computers. This computing capacity is less than those available in today's professional simulation engines or 3D graphic workstations, but the personal computers also have several advantages:
These simulators usually use a world of polygons and techniques such as Gouraud-shading and texture mapping at the rendering process. Some simulators also introduce new ideas. However, there are a lot of differences amongst the products in the emphasis of the different techniques, and the result is often a program, which performs good in one area, but poor in the other one.
Eagles is an experimental application for the techniques of a such system, that tries to use the best method in each part of the rendering process. We will have a look at the features of the software in this document. The first section introduces the choice of programming environment and the structure of the program. The following sections have a look at the different components.
Eagles consists of several modules:
Now let us have a look at the components!
The resource loading strategy is quite unusual. The traditional approach for these systems splits the available memory into parts for each kind of resource. This method is safe, because you will always have the memory for resources, but it is quite inefficient. The memory manager of Eagles works very much like a virtual memory manager of a modern operating system, except that the virtual memory area on the disk is read-only, so the manager does not need to write data back to the hard disk. The resources are stored in several files. Each time the program wants a resource, the resource manager checks whether it is in the memory or not, and loads it if necessary, thus the largest part of the memory memory serves as a "cache" for disk resources, resulting in a very efficient memory usage. The final programs runs fine on a DOS-based system with as low as 4 megabytes of main memory.
This new approach is more flexible, but it is not so safe with critical resources. We call a resource critical when the system is unable to continue the simulation without it. For example, if the system is unable to load the physical parameters of the helicopter into the memory, the simulation engine will be unable to calculate a lot of important data, thus the whole system will fail. In the case of Eagles, it is theoretically possible, that at some point the system will not have the required memory for loading a resource, thus the simulation has to stop.
To reduce this effect, there are two kind of access methods for the resources. At the first one, if the resource manager is unable to load a resource, it will stop the simulation. So if a procedure wants to load a resource with this method, it does not have to pay attention of checking the result, because this method will always return a correct value. This method is applied to critical data such as object geometry data or colour tables.
The other method may fail, and return NULL instead of a valid pointer. But this causes little difficulties since it is applied only to non-critical data such as object textures or sound data. The both methods ensure that the less valuable resources do not obstruct the loading of more valuable ones.
Because the resources are loaded into memory on demand, the manager is
efficient only if the storage medium provides quick access times and high
data transfer rate. Most modern hard disks satisfy these criteria, because
the average seek time is low, usually around 10ms
The resource manager acts like a DBMS, but it is much simpler as an actual DBMS, because the database is read-only, so it does not have to worry about transactions and structures that allow efficient update of the database.
To obtain the highest possible speed in the rendering process, we had to introduce some constraints. These constraints do not allow the viewer to view the world of any possible angle. To be more concrete, the pitch and the yaw of the viewing angle is limited, because that simplifies two rendering methods of the three significantly.
Figure 2. Pitch and yaw angles are limited |
The program works in indexed-colour video mode with 256 colours, because that mode allows nice pictures while providing fast image generation compared to hi-colour and true-colour video modes. The 256-colour palette is not totally fixed, it is divided up into three parts. Those parts may be changed if the components of the world change, i.e. we use another terrain or another sky texture. The first 128 colours belong to the terrain, the next 96 to the objects and the last 32 to the sky. Actually, the 96 colours maintained for the objects are fixed, but the other two parts are not.
The basic unit of the simulation is a mission. A mission file determines which terrain and which sky to use. The mission file stores the palette to be used with the specific mission. This allows the programmer, for example to use the same sky bitmap with different palettes in different missions. In one mission, the regular palette may be used, while in a night mission he/she may use a darkened version of the palette.
Two tables are also required to produce some effects. Because the program
uses an indexed colour mode, the calculation of the Gouraud-shading used
at the terrain rendering is not straightforward. The
shading table is used
to help shading calculations. The basic idea is the following: let us
suppose, that we have two colours, both represented by a one-byte indexes
to the palette entry. (Actually, the
index may be only in the range of 0..127, because we use only 128 colours
for the terrain). We would like to compute several colours, that fall
between our two selected ones, and are also in the palette. So, we
calculate the RGB representations of the two colours, and we linearly
interpolate the RGB values of the colours between them. Then, we choose
the nearest colour from the palette for each RGB value between the two
colours. But if we fix the number of intermediate colours, then the
results of a such calculation may be pre-computed for all the possible
cases. Eagles uses 8 intermediate colours, and so the size of the
table is
The second table is called effect table, and is used to produce atmospheric effects such as fog, smoke, and fade of the furthest parts of the terrain. This table is for all the 256 colours, not just for the terrain colours. The table consists of several sub-tables. One sub-table is responsible for one effect, e.g. darkening the colours by 50%. It is an array of 256 bytes, and it contains the nearest colours for the darkened original colours. With a sub-table, darkening a part of the screen can be performed quite quickly, this pseudo-code explains it:
for each pixel(x,y) to be darkened { byte oldvalue= screen_array [y] [x]; byte newvalue= sub_table [oldvalue]; screen_array [y] [x]= newvalue; }
4.2 Rendering the sky
The simulator uses the painter's algorithm at the rendering process.
First, the sky is rendered. This section introduces the rendering method
used for sky drawing and proves its efficiency.
Because the pitch and yaw values of the viewpoint are limited, the rendering engine can use a very simple model for the sky. Instead of dealing with a lot of geometrical objects, the sky is simply a texture map. The renderer copies the appropriate part of the texture onto the screen, which is described by a rectangle on the texture map. If the viewer turns to the left, the renderer will shift the viewing rectangle to the left on the texture map. If the viewer is increasing its pitch, the rectangle goes down. If the viewer is rotating to the left, the viewing rectangle will rotate to the right.
This process allows only constant sky, but it is not a bad approximation of the reality, if the viewer is moving only slowly within the world and is at low altitudes.
Figure 3. The screen space and the texture space |
The sky renderer renders the sky bitmap onto the screen in columns, from left to right, and uses some tricks to improve the speed. First, it takes one screen column, and for each screen pixel in the column calculates the corresponding texel on the texture bitmap. Then, it calculates the difference of the texture coordinates between screen pixels below each other. For the next columns, it will calculate only the texture coordinate of the top pixel, then the next coordinates will be approximated by adding the values of the first column. In fact, instead of texture coordinates, the algorithm may calculate directly with memory pointers, which will allow even quicker image generation. The above optimisations make it possible to draw 4 pixels of the sky with only 11 assembly instructions.
Because we add the difference values of the first column instead of calculating the correct ones, the resulting image will not be as accurate as it could be with regular texture mapping algorithms. However, the resulting image artifacts will not be significant, if we choose the texture map properly, and we avoid using sharp boundaries in the map, as it can be seen on Figure 4.
(a) A bitmap with sharp boundaries |
(b) The actual bitmap | |
Figure 4. The inaccuracy in sky rendering |
4.3.1 Structure of the terrain data
The terrain itself is stored as a height-field array. Imagine, that we cut a
rectangular area from a real terrain, then we divide it up into x*y small
rectangles parallel to the edges, so that we will get x*y pieces of
elementary terrain patches. Then we store the height and colour for each
patch in a 2-dimensional array. This is already much more efficient than
storing a lot of polygons, because we need to store only two numbers per
terrain patch instead of storing the polygon data: coordinates of
vertices, vertex indices, etc.
The process can easily result in a huge amount of data, that consumes a
lot of memory and processing time. For example, if we want to store a
To reduce memory usage, the surface data is divided up into 128*128 patch
sized areas, and each area is stored and loaded into memory independently.
These areas are called segments. The simulator stores the height of
the surface patch in one byte, and the colour in another byte (chosen from
the colour palette introduced by the Colour Management section). So the
total storage requirement of a segment will be
The terrain renderer also takes use of the fact that we do not need to
show the further parts of the terrain in such detail as the closest
ones. It uses the same idea as mipmapping. The terrain is stored in
different resolutions, and the renderer uses data from lower resolution
segments while it draws the further parts of the terrain to the screen.
In the current application, the base terrain consists of 1024*1024 terrain
patches at the highest resolution. The terrain resolution is approximately
10 meters per terrain patches, so the whole terrain covers a
Figure 5. The structure of the segments The segments on the left, middle and right show the same area in decreasing detail level. |
This approach leads us to several advantages. First, the rendering engine
needs to keep less data in the memory and reload the data less often
from hard disk. The other, and most important advantage is, that we have
to render much less surface patches while maintaining almost the same
visual quality. A quick calculation to prove this: in the helicopter
simulator the base terrain visibility is approximately
The new rendering mechanism also allows us to use different detail levels of the terrain and different visibility range depending on the viewpoint's altitude.
So, the number of polygons in the visibility range is in the magnitude of 15,000. That is still quite a lot to sort and draw with the conventional polygon rendering methods, especially if we would like to use some kind of shading or texture mapping, not just plain polygons. Because of that, the terrain renderer works in a special way.
In the previous section, we saw that the terrain data is stored in some detail levels. Now, we are going to have a look at the rendering process itself within one detail level.
Fortunately, the terrain data is arranged into a matrix, thus we do not have to worry about polygon depth sorting before using the painter's algorithm. So, we start the rendering with the furthest patches, and then closing in.
First, the algorithm calculates the locations on the screen (if it is on the screen at all) for the furthest visible terrain patches, round the viewer. The process in marked with dark blue arrows on Figure 6. Then, the algorithm calculates the parameters of the lines connecting the points on the screen. Then, it does it again for nearer surface patches. This is marked with light blue arrows on the figure. Then, the algorithm connects the resulting dark blue and light blue lines on the screen in every column of pixels (marked by the red arrows).
Figure 6. The process of terrain rendering |
The above process is faster than rendering a lot of polygons. However, it has several disadvantages. The main disadvantage is, that it produces acceptable image quality only when the viewer looks nearly horizontally (both pitch and yaw values are near zero). But this is not a serious disadvantage for some kind of applications, like the helicopter simulator.
In the real application, this rendering method is extended to all the detail levels of the terrain.
The object renderer does not come up with many new ideas. The main source for the polygon rendering and visibility calculations is [PCGPE].
The objects are stored in OBF files on the disk, and are translated to C++ classes during the loading process. The structures used in the file format and in the C++ classes map directly onto each other. For each object, vectors store the locations of all the vertices in the object, and several normal vectors also required for rendering. These vertices can be used to build polygons. Different types of polygons include:
Figure 7. The different polygons in the helicopter simulator |
These polygons can be used to build the objects. The objects also contain some information about the spatial location of different parts to make the visibility calculations faster. The method is very similar to BSP-trees, but instead of putting each polygon into the tree, the polygons are grouped into convex groups, and only the groups are stored in the leafs of the tree.
The visibility calculation between the objects themselves is performed with the painter's algorithm. Before rendering the whole scene, all the objects in the world are sorted according to their distance, and they are drawn from further to closer ones, synchronously with the terrain.
The objects are also allowed to contain other objects, and scale or rotate those objects. A such connection point can have an activation function, i.e. a function in the source, which will be called by the object renderer subsystem every time the child object within the parent object is drawn. This activation function may modify certain parameters of the connection, it may rotate or scale the child object, or determine what is going to be the child object. This allows us to create many dynamic simulation effects, e.g. rotating rotor, dynamic weapon pylons etc.
The object subsystem supports also detail levels. Each object can have several detail levels. The current detail level being used for the object depends on the viewing distance. The designer can determine for each part of the object, from what distance should it be visible. This can be useful to decrease the complexity of objects if they are at a great distance from the viewer.
Because these ones are commercial products, they are usually produced with a lot more effort than Eagles. Therefore, they seem to be more professional than the simulator presented in this paper. However, Eagles provides good graphics and simulation speed, and in some aspects it may be better than the commercial opponents.
The first simulator is AH-64D Longbow
([LONGBOW]) from Jane's Combat Simulations,
a part of Electronic Arts. The game was released in June,
1996, and comes on a single CD-ROM. According to the company's claims, it
is made with more than 20 man-years of effort and covers more than
The sky model is more sophisticated that the one in Eagles, and gives a more realistic view.
Unlike in Eagles, the terrain is modeled with texture mapped polygons. There seems to be a trick in the texture mapping to reduce the memory requirement of textures, because the whole texture map seems to be built up from patches of one colour. This could be achieved via the vector quantisation method described by [VQTEXTURE]. The terrain renderer gives an overall good impression, but the geometric complexity of the landscape is obviously less than in the simulator presented in this paper.
The 3D graphical model of the helicopters is very detailed, they appear almost photo-realistic on the screen. This is mainly because the aircrafts have more complex geometric models than in Eagles.
Figure 8a. Screen shots from AH-64D Longbow
( [LONGBOW] ) These screen shots are available at the official Longbow homepage. |
5.2 Hind
Hind was marketed in October 1996 by Interactive Magic on one
CD-ROM. Compared to the other products, the game features quite extensive
modeling of what is happening in the real world. Individual soldiers are
modeled with different weapons.
Surprisingly, the simulator tries to achieve good visional quality by increasing the geometric complexity of the world. It models the aircraft and the world with more polygons and less texture maps, as we can find in the usual approach. The helicopters and other objects within the world are quite impressive.
Hind uses the same technique for terrain modeling. The method was good for the objects in the world, but it is not very effective with the terrain. While Longbow used extensive texture-mapping to hide the simple geometric model of the landscape, this simulator uses almost plain polygons in many cases, which makes the terrain to look quite artificial.
Figure 8b. Screen shots from Hind
( [HIND] ) The first two images are available at the official Hind homepage. The third image is from the review of GamesDomain. |
Comanche 3 ( [COMANCHE3] )is the long-awaited sequel of Comanche by NovaLogic. The game is currently still under development, and the final version is to be released in March 1997. At the moment, there is no information available about the game itself.
The screen shots seem to be quite impressive. According to the information from the company, the simulation engine uses VoxelSpace 2 technology for terrain rendering. This is the advanced version of VoxelSpace, which is originated from Comanche, and is quite similar to the terrain renderer of Eagles.
The polygon engine produces is also very high quality. It seems, that it uses some anti-aliasing technique as well, so together with the terrain engine they produce incredibly realistic images.
Figure 8c. Official screen shots from Comanche 3
( [COMANCHE3] ) The screen shots are available at the official Comanche 3 page |
To provide a full comparison, this section contains the recommended requirements for the simulators presented in this section. The source of the data for Hind and Longbow is [GD], the source of Comanche 3 data is [COMANCHE3], and the Eagles data is based on the author's experiments.
Name | Target OS | CPU | Memory | HD Space | CD-ROM drive |
---|---|---|---|---|---|
AH-64D Longbow | DOS | Pentium-133 | 16 Mbyte | 97 Mbyte | 4x speed |
Hind | DOS or Win95 | Pentium-75 | 8 Mbyte | 15 Mbyte | 2x speed |
Comanche 3 | DOS or Win95 | * | * | * | * |
Eagles | DOS | Pentium-100 | 4 Mbyte | ** | ** |
Table 1. The recommended hardware for the simulators
* : Data not available
** : Data not available or not meaningful
7. Credits
The author would like to express his thanks to the following
people and organizations:
All brands and names appearing in this text are registered trademarks of the respective companies.
Last modified on 6-3-1997