Docking system creation (ASM tweak)

From FSDeveloper Wiki
Jump to: navigation, search

Introduction

This tutorial will explain how you can code your own Visual Guidance Docking System (VGDS). On big airports these system are very common to guide the pilot while parking his aircraft. The basic model of the docking system used in this tutorial has been made with GMax and the ASM code of the system will then be tweaked to get the interaction with the aircraft (like the distance indication, etc). This means that you should be familiar a little bit with source code tweaking before trying to make a VGDS as well. Let's get started!

Safegate

Before we are going to model our VGDS it is time to look at a real VGDS and see which features it has and which of them we want to implement in FS. In this tutorial I will use the SafeGate system as it is used on Schiphol Airport. Below you find an image of how the system looks.

Safegate photo.jpg

Basically there are three kinds of information that this system can provide to the pilot.

First there are two row of lights at the left and right of the system. These indicate the distance till the stop point. At the top of the system there is the message bar that can show information to the pilot. For example if the parking is OK or if he has overshoot his stop point. Just below this message bar there is the stop bar. This bar can only show the work STOP and it will be on when the stop point has been reached.

The SafeGate docking system has a mechanical system to indicate if the pilot should steer left or right. As the bar is placed about 50 cm in front of the board the pilot needs to make sure it aligns with the aircraft picture behind to make sure he is on the taxiline. In digital docking systems the direction is indicated with another display. The same techniques as descibed below can be used for this direction as well of course.

Basic model

Before we can actually start tweaking the source code of our docking system, we first need to make a basic model for it in GMax of course. The figures below show the front and side view of the final design.

Safegate side.jpg Safegate front.jpg

Basically it is just a case with the correct texture on it to represent to actual look. The most important part here is that I have added four polygons that represent the areas where changing information is displayed. By changing the texture on these polygons depending on certain condition we can get the docking system to respond to the aircraft. Below is a 3D view of the final GMax model.

Safegate gmax 3d.jpg

Switching textures

Before we start actually coding these dynamic polygons, it is time to think about a way to do that first. Basically we have two options.

The first is to load a different texture for the polygon, depending on the condition. The texture mapping of the polygon can then stay the same, as we just show a different texture.

An alternative is to use one big texture containing all variation, but change the mapping of the polygon depending on the conditions.

At first I tested the first option, but it has some drawbacks. The first is that you will get a lot of textures. The final docking system will be able to show the aircraft type as well and in that case you reach around 100 textures very easy. This is not really useful for distribution. Another disadvantage of switching the actual texture is that you will see a slight loading time when they need to be switched. For a short while the background color of the polygon will show, which is very disturbing for a docking system of course.

Therefore I have chosen in the end to use one big textures and let the mapping of the polygon change. This requires a bit more source code tweaking, but the final result is better in my opinion.

Distance indicator

We will start with coding the distance indicator. In reality this is a row of lights, but on the model all these lights are represented by a piece of texture. Below you see the total texture that has been used for these lights. As you can see there are 16 vertical bars on the texture. Each of them has one additional light enabled.

Safegate distance.jpg

Now it is time to start tweaking the source. The first step is to find out which vertices are used by the distance indicator. Below is the piece of code that draws these polygons. Using the texture name I was able to identify them. As you can see in the DRAW_TRI_BEGIN command the first vertex of the distance bar is 170.

MATERIAL 2,1 ; <255,255,255,255> SAFEGATE_DISTANCE.BMP;;;
BGL_ZBIAS 1
DRAW_TRI_BEGIN 170, 8
DRAW_TRI    4,   6,   7 ; poly=117 part=1
DRAW_TRI    0,   2,   3 ; poly=19 part=1
DRAW_TRI    3,   1,   0 ; poly=20 part=1
DRAW_TRI    7,   5,   4 ; poly=118 part=1
DRAW_TRI_END
BGL_ZBIAS 0

Looking in the vertex list it can then be seen that these 8 vertices define the distance bar. The first three parameters are the coordinates of the polygon, we don't want to change these of couse. The next three parameters are the vector of the polygon, these parameters should not be modified as well. The final two paramters are the ones we are going to tweak now, as they define the mapping of the texture.

VERTEX_DEF    -0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.000500,0.000500 ; 170 part=  1 prim=6
VERTEX_DEF    -0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.000502,0.999501 ; 171 part=  1 prim=6
VERTEX_DEF    -0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.999498,0.000500 ; 172 part=  1 prim=6
VERTEX_DEF    -0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.999501,0.999501 ; 173 part=  1 prim=6
VERTEX_DEF     0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.000500,0.000500 ; 174 part=  1 prim=6
VERTEX_DEF     0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.000502,0.999501 ; 175 part=  1 prim=6
VERTEX_DEF     0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.999498,0.000500 ; 176 part=  1 prim=6
VERTEX_DEF     0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.999501,0.999501 ; 177 part=  1 prim=6

When I placed the texture in GMax there entire texture was mapped on the polygon, but we want only one vertical slice of course. As the texture contains 16 slices, each has a width of 0.0625 of the texture. Below are the first 8 vertices again, this time with the texture mapping so that the first slice is shown.

; all off
VERTEX_DEF    -0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0000,0.00 ; 170
VERTEX_DEF    -0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0000,1.00 ; 171
VERTEX_DEF    -0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,0.00 ; 172
VERTEX_DEF    -0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,1.00 ; 173
VERTEX_DEF     0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0000,0.00 ; 174
VERTEX_DEF     0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0000,1.00 ; 175
VERTEX_DEF     0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,0.00 ; 176
VERTEX_DEF     0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,1.00 ; 177

The next step is to copy these 8 vertices and paste them again below the origional vertices. To make it easier for yourself it is best to increase the vertex count in the comment. The texture mapping for these next vertices are set to the second slice of the texture. This proces needs to be repeated for every slice. Below the code is shown for two additional slices.

; bottom green
VERTEX_DEF    -0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,0.00 ; 178
VERTEX_DEF    -0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,1.00 ; 179
VERTEX_DEF    -0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,0.00 ; 180
VERTEX_DEF    -0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,1.00 ; 181
VERTEX_DEF     0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,0.00 ; 182
VERTEX_DEF     0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.0625,1.00 ; 183
VERTEX_DEF     0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,0.00 ; 184
VERTEX_DEF     0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,1.00 ; 185
; distance 1 green
VERTEX_DEF    -0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,0.00 ; 186
VERTEX_DEF    -0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,1.00 ; 187
VERTEX_DEF    -0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1875,0.00 ; 188
VERTEX_DEF    -0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1875,1.00 ; 189
VERTEX_DEF     0.372000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,0.00 ; 190
VERTEX_DEF     0.372000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1250,1.00 ; 191
VERTEX_DEF     0.528000,    0.152000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1875,0.00 ; 192
VERTEX_DEF     0.528000,    1.748000,   -0.176000,   0.000000, 0.000000,-1.000000,   0.1875,1.00 ; 193

There is one more thing that you should be careful about. By placing these additional vertices in the list, the vertex number of vertices below will also change. So when these are used in other polygons you need to change them as well. In my case all polygons I needed to tweak were on the bottom of the list, so that was no trouble.

So, once you have added all the additional vertices for your texture slices, it is time to adjust the code where the texture is assigned. By default this code looks like this:

MATERIAL 2,1 ; <255,255,255,255> SAFEGATE_DISTANCE.BMP;;;
BGL_ZBIAS 1
DRAW_TRI_BEGIN 170, 8
DRAW_TRI    4,   6,   7 ; poly=117 part=1
DRAW_TRI    0,   2,   3 ; poly=19 part=1
DRAW_TRI    3,   1,   0 ; poly=20 part=1
DRAW_TRI    7,   5,   4 ; poly=118 part=1
DRAW_TRI_END
BGL_ZBIAS 0

Below the MATERIAL command we are going to add additional code that checks the distance to the docking system. The SEPARATION_PLANE command is used, as this command allows you to check the distance along a certain vector. In the example code below it is check if the distance till the stopping point is 40 meters or more. The first parameter specifies the label to which a jump will be made if the distance is less then 40 meters. The next three parameters specify the direction of the vector and the last parameter specifies its length.

The only problem is that this command does not rotate with the heading you give to your object in the XML code (and none of the other commands that can be used to check your position does). Therefore you need to make different versions of your docking system for different headings. By specifing a heading in the SEPARATION_PLANE that matches the heading you are giving to your object, the features of the docking system will still work correct. Because I want to be able to change this heading easily, I have defined the vector with two variables, HEADING_VECTOR_X and HEADING_VECTOR_Y. This way I only need to change them once in the source code and not in every SEPARATION_PLANE command, if I want to change the heading at which the docking system will be used. For this example I have defined the variables in an additional ASM file (safegate_variables.asm) that is included in the docking system project. Please read the comments in this file to see how you can change the heading. The distance between the docking system and the stopping point, STOP_DISTANCE, is also defined in this file.

So back to the example, if the distance is more then 40 meters, the first vertex of the polygon is set to 170 (this was the first vertex of the distance indicator in my case). After the triangle list a jump is made to the label diend, as we only want to draw this slice for the moment of course. After the jump we place the label that is used when we are closer than 40 meter.

BGL_ZBIAS 1
SEPARATION_PLANE di00, HEADING_VECTOR_X, 0, HEADING_VECTOR_Y, (STOP_DISTANCE+40)*NVL
; 40 meter off
DRAW_TRI_BEGIN 170, 8
DRAW_TRI    4,   6,   7
DRAW_TRI    0,   2,   3
DRAW_TRI    3,   1,   0
DRAW_TRI    7,   5,   4
DRAW_TRI_END
BGL_JUMP_32 diend
di00 label word

After that label you can perform another check to the next distance or when it fails you jump to the next label. This process continues till you have added all different conditions you want. Below you see the code for two additional distance checks. For each condition the starting vertex of the polygon is changed so the vertices with the correct texture mapping are used.

SEPARATION_PLANE di02, HEADING_VECTOR_X, 0, HEADING_VECTOR_Y, (STOP_DISTANCE+12)*NVL
; < 15 meter - static bottom
DRAW_TRI_BEGIN 178, 8
DRAW_TRI    4,   6,   7
DRAW_TRI    0,   2,   3
DRAW_TRI    3,   1,   0
DRAW_TRI    7,   5,   4
DRAW_TRI_END
BGL_JUMP_32 diend
di02 label word
SEPARATION_PLANE di03, HEADING_VECTOR_X, 0, HEADING_VECTOR_Y, (STOP_DISTANCE+11)*NVL
; 12 meter - 1 green
DRAW_TRI_BEGIN 186, 8
DRAW_TRI    4,   6,   7
DRAW_TRI    0,   2,   3
DRAW_TRI    3,   1,   0
DRAW_TRI    7,   5,   4
DRAW_TRI_END
BGL_JUMP_32 diend
di03 label word

Do not forget to place the end label you used after the last condition. I used a distance check here, but you can also use other variables of course.

Stop and message bar

The same technique can of course also be used for the stop and the message bar. As the code tweak is similar I will not repeat it again. I just show the textures I have used, so you get an idea.

Safegate stop.jpg Safegate message.jpg

For the message bar I used one special feature I would like to show as well. When the pilot misses his stop point the message TOO FAR is displayed. The words TOO and FAR are shown one after another. I checked the variable BGL_TICK18, which is a timer, to show one of these messages. Below you see the code I used. The way of switching the textures is the same as described above for the distance check.

IFMSK mean01, BGL_TICK18,0008h
DRAW_TRI_BEGIN 302, 4
DRAW_TRI    3,   1,   0
DRAW_TRI    0,   2,   3
DRAW_TRI_END
BGL_JUMP_32 meend
mean01 label word
DRAW_TRI_BEGIN 306, 4
DRAW_TRI    3,   1,   0
DRAW_TRI    0,   2,   3
DRAW_TRI_END
meend label word

Final result

I have attached the origional ASM files and my tweaked ASM files to this thread. So you can see the final result of my docking system.

I hope this tutorial was clear enough to describe how I did it, but if not, please don't hesitate to post your questions in the BGLC tweaking forum.

Related files

Download sources (ZIP)