topic: Plugin SDK

Plugin Traffic Wake Turbulence

Starting with X-Plane 12, traffic injected into X-Plane using the TCAS datarefs casts wake turbulence that interacts with the user airplane. For your traffic to generate wake turbulence, your plugin must use the APIs introduced with X-Plane 11.50. If you haven’t already done so, read up on XPLMInstance on how to draw your traffic models in X-Plane in a Vulkan-compatible manner, and read about the TCAS API on how to tell X-Plane the state of your traffic targets.

New Datarefs to influence wake generation

By default, a traffic target will generate the wake appropriate for a small business jet, an aircraft weighing about 10 tons and having a wing span of about 12 meters. This will cause upset if the user flies into it with a C172 or other light plane, but will not cause a lot of disturbance if the user is flying an airliner. This is to minimize possible user frustration if dealing with a plugin that does not update X-Plane about the finer details of wake generation. If the plugin however supplies more information about the traffic it provides, X-Plane can fine tune the wake generation to be more appropriate for the exact type of traffic that is displayed. Keep in mind that wakes are strongest if the aircraft is slow, clean, and high AoA. X-Plane uses the lift force generated by the wing to determine the strength of the wake, and takes AoA into account that was used to generate that lift. With lower speed a higher AoA is needed to generate the same lift force, which causes a stronger wake. On the other hand, with flaps a lower AoA is needed to generate the same lift force, which causes a weaker wake.

sim/cockpit2/tcas/targets/wake/wing_span_m	float[64]	y	meter	wing span of the aircraft creating wake turbulence
sim/cockpit2/tcas/targets/wake/wing_area_m2	float[64]	y	meter	wing area (total area of both wings combined) of the aircraft creating wake turbulence
sim/cockpit2/tcas/targets/wake/wake_cat	int[64]	y	enum	wake category of the aircraft. This is for information purposes only and is not used to calculate the actual strength of the turbulence. 0 = Light, 1 = Medium, 2 = Heavy, 3 = Super
sim/cockpit2/tcas/targets/wake/mass_kg	float[64]	y	kg	actual mass of the aircraft creating the wake
sim/cockpit2/tcas/targets/wake/aoa	float[64]	y	degrees	angle of attack of the wing creating the wake
sim/cockpit2/tcas/targets/wake/lift_N	float[64]	y	Newton	instantaneous lift force of the whole wing generated right now, in Newtons

Wake reset

If a target moves by more than 200 meters in one frame (i.e. the 3d distance of the sim/cockpit2/tcas/targets/position/{x,y,z} triplet between two frames is greater than 200 meters) its wake is immediately cleared and reset. This is to avoid leaving a wake trail in space if a new aircraft is represented by the same TCAS slot and the target moves to a different point in space to represent a different aircraft.

Comments Off on Plugin Traffic Wake Turbulence

The X-Plane 12 Material Model

This document describes the X-Plane 12 material model – that is, how materials are authored and rendered for most solid 3-d elements in X-Plane. The material model is used for all OBJ 3-d models, aircraft, all scenery elements, and models inserted by plugins via the XPLM Instancing APIs.

X-Plane 12 Material Model Basics

X-Plane 12 uses an industry standard PBR “metalness” work-flow that matches the Disney/Unreal Engine 4 model, as well as a number of common tools including Substance Painter 2 and Blender’s “Principled BSDF” shading node. The goal is to provide close to WYSIWYG material authoring.

The main difference between X-Plane and other engines is in terms of what parameters can be controlled – some engines provide significantly more material parameters (at a higher rendering cost).

X-Plane lets you control:

  • Glossiness/roughness, either via a texture map or as a hard coded number in an art asset text file. We recommend using texture maps to control roughness/gloss.
  • Albedo/Base Color. The base color of the material is used as an albedo for dielectric materials, and as a reflection tint for metal colors – this is a fairly standard way to reuse a single color in metalness work-flows. In most X-Plane documentation this channel is simply called “albedo.”
  • Per pixel normal maps in tangent space using two channels.
  • An optional RGB/RGBA “emissive” overlay. This is calibrated to photometric units using a directive in the art asset text file. If an alpha channel is present, it will be added to the albedo alpha, which can be used for special effects but is generally not recommended.
  • Baked ambient occlusion for a small number of specialized art assets. (This feature is not currently available on OBJs, including plugins or aircraft, but may be added later.)

The model also lets you control in a texture map at most one of:

  • Base Reflectance (“F0”) – This is the amount of fresnel reflection a material exhibits when viewed with the camera perpendicular to the material (its least reflective position). Note that X-Plane uses F0 to control “metalness” as well but the two properties cannot be specified separately due to engine limitations – more details on this later.
  • Translucency – This parameter causes light on the back of a material to increase diffuse brightness, while limiting the diffuse brightness of the front of the material – it is meant for vegetation.  When not in use, translucency defaults to zero.
  • Separate normal alpha – Can be used to create normal-map decals that affect terrain without drawing full materials. When not in use, normal alpha defaults to albedo alpha.

Metalness, Fresnel and F0

In a metalness PBR work-flow, “metalness” describes two material models:

  • Dialectrics: light is reflected off the surface of the material based on an angle of incidence/reflection; this reflection is not tinted. Remaining light is absorbed and re-emitted with tinting based on the albedo color; the albedo describes both how much light is absorbed/re-emitted and its spectral quantity. F0 defines how much light is reflected under the lowest reflected conditions; as the camera angle to the material becomes a grazing angle, reflection increases based on Fresnel’s law.
  • Metals: light is either reflected with tinting or completely absorbed. This is an approximation of actual metal optics, which require a much more complex fresnel equation. The goal of a metal work-flow is essentially to get tinted mirrors with variable but high reflectivity to make chrome/mirror parts look acceptable.

The metalness parameter of your material blends these two models, ideally producing intermediate materials that represent what you would get if your material contained specs of both dielectric paint and underlying metal.

X-Plane’s design limitation is that it does not provide separate channels for both Metalness and F0, for performance reasons. To work-around this, X-Plane works as follows:

  • When F0 in the material is in the range of 0.00 to 0.08, F0 is used as metalness and F0. This produces a nearly dielectric material for most useful F0 ranges, including:
    • F0 = 0.0 – this is an unrealistic mostly non-specular material. We recommend this for textures that represent complex 3-d self-shadowing phenomenon, like a terrain texture of grass.
    • F0 = 0.02 – 0.04, e.g. plastic, concrete, vinyl.
    • F0 = 0.06, e.g. glass.
  • Once the material F0 gets above 0.08, we use F0 for metalness, but clamp F0 to 0.08. This limits the amount of dielectric reflection the material exhibits in a hybrid material.
  • Once F0 is very high (e.g. 0.9 or higher, e.g basically metal) the light contributed from the dielectric part of the equation is extremely low and rendering should match tools.

Values for Material F0 When Not Using a Texture

When X-Plane’s normal/material map is in “metalness” mode, the blue channel is used as the material F0, giving you access to the full range of behaviors, including 0.0 (no specularity), 0.04 (reasonable dielectrics), 1.0 (pure reflective metals), and intermediate values.

In any other mode, X-Plane will pick a material F0 automatically based on the following rules:

  • If the material uses BLEND_GLASS mode and is attached to an aircraft in a glass lighting mode (one of interior glass, exterior glass, exterior rain glass or interior reflective glass) then F0 will be set to 0.06 to provide reasonable glass reflections.
  • Otherwise if the material uses a “translucency” mode normal map, F0 will be set to 0.0.
  • Otherwise if the material uses any other normal map (full RGBA, gloss-map only, etc.) F0 will be set to 0.04.
  • Otherwise the material uses no normal map. If its gloss is set > 0.0, F0 will be set to 0.04. This handles the case where a material is marked shiny in an OBJ but has no normal map – the result will be a glossy plastic-like material.
  • Otherwise the material uses no normal map and has the default maximum roughness; F0 will be set to 0.0 to create the illusion of additional self-shadowing.

Changes from X-Plane 11 Materials

X-Plane 11 introduced PBR materials; the X-Plane 12 model is an incremental update. The changes are:

  • X-Plane 12 renders “intermediate metals” (materials with F0/metalness between 0.25 and 0.75) in a manner compatible with SP2/Blender; X-Plane 11 would build these materials as if the dielectric part of the material had a super-high F0, resulting in a lot of extra specularity. The result would be that intermediate metals would be much brighter and more washed out than in standard authoring environments. If your model makes heavy use of intermediate metals you may need to change your albedo/re-bake your materials.
  • X-Plane 12 adds photometric calibration to emissive channels.
  • X-Plane 12 adds an optional translucent mode – translucency was effectively always off in X-Plane 11.
2 Comments

Testing in X-Plane

This document outlines how to test X-Plane via CLI commands and telnet.

Laminar Research develops tests via telnet, then passes them to X-Plane via script.

Using telnet

Launch X-Plane with the CLI flag

--testing

Then connect to the sim using the CLI command

telnet localhost 49000

List of Commands

acf <string>

Loads the aircraft at the specified path (be sure to use quotes). Ex: acf “Aircraft/Laminar Research/Cessna 172SP/Cessna_172SP_G1000.acf”

move lle <latitude> <longitude> <elevation in meters>

Reposition your plane at an exact lat/lon/elevation. Note: aircraft will be initialized with 0 airspeed, so this is best used on the ground if possible.

move <ICAO> <optional ramp start>

Reposition the aircraft at the specified airport. Defaults to runway 0, unless a ramp start is specified.

command <command> <optional time in seconds>

Execute the specified command for the specified duration, in seconds. See Commands.txt for the full list of commands. Note that the test runner is incredibly fast, so it’s recommended to add a

wait

(see below) after each command.

Datarefs

dref set <dataref> <value>

Set a dataref & value. See DataRefs.txt for the full list of datarefs.

expect <dataref> <conditional> <value>

Checks that the specified dataref meets an expected value. Ex. expect sim/flightmodel/engine/ENGN_running[0] == 1

wait <time in seconds, can be a decimal>

Waits the specified time before executing the next line. Important to use after commands to ensure it fully completes before moving on. Waiting longer times, such as multiple minutes, after a move or aircraft load can be useful to ensure all aspects of a flight stabilize.

camera dump

Outputs current camera location to telnet.

camera <additional params>

Sets specific camera location. (Recommended to get the exact command from camera dump.)

quit

Quit the sim. Also useful to reset parameters between tests.

Writing & Running tests

Test files must include the following header:

A
1000
CLI_SCRIPT

Save your test script as a .txt or .test file.

Use the command line argument

--script=[file name]

To launch X-Plane and run your test script. Note that X-Plane will use the existing preferences at launch. If there are syntax errors in your script, X-Plane will print the error in the terminal (Mac only) and log.txt for investigation. The results of the test run will be output in the same places as well. Finally, tests that fail any “expect <dataref>” lines will automatically save a screenshot at the fail point in the main X-Plane directory.

Example Script

Download a sample script here.

1 Comment

Helicopter governor and correlator configuration

X-Plane 12 revises the interaction of collective and throttle control in helicopters. Existing helicopters retain the default behavior of X-Plane 11 until modified in Plane Maker 12 to opt into one of the new governor systems. The joystick control assignments for collective and throttle don’t change, but there’s a new joystick curve available for Robinson-style throttle control.

Governor types

In Plane Maker 12, you can choose the type of throttle governor you can equip your helicopter with:

  1. No governor – this corresponds to leaving the governor checkbox unchecked in Plane Maker 11. The throttle will be fully manual. This is helpful if you want to code your own governor in a plugin.
  2. X-Plane 11 governor – this corresponds to checking the governor checkbox in Plane Maker 11 and preserves the behavior for legacy aircraft.
  3. Robinson-style piston correlator and governor – This adds a correlator to the throttle, and adds the “detent” to the throttle range surpassing the correlator. The governor will only engage at 80% or more rotor RPM
  4. Turbine governor – This changes the throttle to work like a condition lever in normal operation. It has a range below the idle release button where the engine is shut off. Above, you roll the throttle all the way on to enter governing range.

Correlator

The correlator is a linear collective to throttle linkage that automatically opens the throttle as collective input increases. In Plane Maker, you can set two control points to define the linear connection. The correlator is added after the throttle, and does not change the twist of the throttle grip. The correlator input is added to the throttle twist grip input whenever the throttle is out of detent, which by default is 5% throttle, but can be customized to your throttle hardware with a joystick control curve. By holding the throttle in detent (rolling it below 5% or the customized point on your hardware) it is possible to practice auto-rotations with the engine running, as the then the correlator will not kick in during the flare.

Piston Governor

The piston governor adds onto the throttle grip, so unlike the correlator the effect of the governor can be seen on the grip as the throttle will be twisted. When switched on, the governor will kick in once the throttle has been increased enough to go over 80% RPM. Because the governor adds to the correlator, the change in throttle grip caused by the governor will be relatively small, as big power changes are already absorbed by the correlator.

In case of governor failure, the governor fails in the current position, leaving the correlator intact, so it will require small adjustments by the pilot.

Turbine Governor

Unlike the piston governor, the turbine governor governs maximum RPM. The throttle twist grip works more like a condition lever, if the governor is operating normally. The throttle has an OFF range (fuel shut off), then ground idle and then flight range. The “shutoff” range is guarded by the Idle Release lock, preventing accidental engine shutdowns. By twisting the throttle towards flight mode, maximum fuel flow will be enabled, but the actual fuel flow will be adjusted by the governor. The governor works without actually twisting the handle itself, so the throttle handle will show no feedback that the governor is operating, unlike in the piston variant. By blipping the rotor RPM trim, the governed RPM can be adjusted slightly.

In case of governor failure, the fuel flow restriction is removed, so the throttle in flight mode will most likely cause the rotor to overspeed. The pilot will need to reduce the throttle to prevent that, and will then need to manually control the throttle to keep the rotor RPM in the desired range. If configured in Plane Maker, a correlator input will be added to the throttle in case of governor failure, to limit the need for large excursions with the throttle.

The Off-range of the throttle on the turbine helicopter corresponds to the “detent” on the piston helicopter. That is, if you set your hardware up with a response curve for detent, that detent will act as the shut-off position (beyond idle release) on the turbine throttle grip. The commands

sim/engines/collective_idle_release

(for collective twist throttle) and

sim/engines/collective_idle_release_1 to sim/engines/collective_idle_release_8

(for individual overhead levers)

need to be held while retarding the throttle into the off-range, in order to prevent accidental shut-downs.

If you don’t have a hardware throttle, the X-Plane default throttle commands prevent you from accidentally killing the engine by rolling off the throttle. To turn the engine off, you need to hold the command to fully roll off the throttle, release it, and then push it again to actually roll the throttle over the detent and shut the engine off.

Comments Off on Helicopter governor and correlator configuration

Joystick Datarefs

Below you’ll find a reference for the meaning of the joystick axis assignments values from the dataref sim/joystick/joystick_axis_assignments.

Assigned Value Meaning
0 None
1 Pitch
2 Roll
3 Yaw
4 Throttle
5 Collective
6 Left toe brake
7 Right toe brake
8 Prop
9 Mixture
10 Carb heat
11 Flaps
12 Thrust vector
13 Wing sweep
14 Speedbrakes
15 Displacement
16 Reverse
17 Elevator trim
18 Aileron trim
19 Rudder trim
20 Throttle 1
21 Throttle 2
22 Throttle 3
23 Throttle 4
24 Prop 1
25 Prop 2
26 Prop 3
27 Prop 4
28 Mixture 1
29 Mixture 2
30 Mixture 3
31 Mixture 4
32 Reverse 1
33 Reverse 2
34 Reverse 3
35 Reverse 4
36 Landing gear
37 Nosewheel tiller
38 Backup throttle
39 Cowl flaps
40 [Old, unused]
41 View left/right
42 View up/down
43 View zoom
44 Camera left/right
45 Camera up/down
46 Camera zoom
47 Gun/bomb left/right
48 Gun/bomb up/down
49 VR Touchpad X
50 VR Touchpad Y
51 VR Trigger
52 Custom command(s)
53 Throttle 5
54 Throttle 6
55 Throttle 7
56 Throttle 8
57 Cowl flaps 1
58 Cowl flaps 2
59 Cowl flaps 3
60 Cowl flaps 4
61 Cowl flaps 5
62 Cowl flaps 6
63 Cowl flaps 7
64 Cowl flaps 8
65 Throttle Vertical
66 Throttle Horizontal
Leave a comment

Overriding TCAS and providing traffic information

With X-Plane 11.50, plugins that display traffic in X-Plane, whether auto-generated or from an online multiplayer network, have to use the XPLMInstance API to draw these aircraft in X-Plane’s world. Drawing with XPLMInstance places the 3D object in the world, but does not actually tell X-Plane or other interested third parties, such as EFBs, about the existence of another aircraft in the airspace around the user. Various techniques have been used by authors, which are commonly known as “TCAS hack” that involve taking control of X-Plane AI aircraft, but not drawing them, by inhibiting drawing from a 3D callback. Some plugins also get around this by providing “invisible” aircraft to be moved by X-Plane. With Vulkan and Metal, the 3D callback that was previously used to change the AI plane count for the “TCAS hack” no longer works. It is therefore necessary to adopt the new TCAS override, which provides an official and compatible way to notify both X-Plane and third-party plugins of traffic.

override_TCAS: Existing datarefs made useful

The new supported and recommended variant of the “TCAS hack”, now called “TCAS override”, relies entirely on datarefs and existing XPLM functions, so it requires no SDK update. It uses the following, well known datarefs, simply expanded in array size:

sim/operation/override/override_TCAS int
sim/cockpit2/tcas/indicators/relative_bearing_degs float[64]
sim/cockpit2/tcas/indicators/relative_distance_mtrs float[64]
sim/cockpit2/tcas/indicators/relative_altitude_mtrs float[64]

Using the new TCAS override requires that the plugin does the following:

  1. Acquire the AI planes with XPLMAcquirePlanes – This should be done with a null pointer for the desired model paths, so it is fast. You should only call this when you are ready to supply planes right now. That is, an online network plugin should not acquire planes before it is actually connected to the network! Since acquiring planes with no model load is fast, this should be deferred until the user is actually connected to a server.
  2. Activate TCAS override by setting the sim/operation/override/override_TCAS dataref to 1. Only the plugin that has successfully acquired the AI planes can set this dataref!
  3. Tell X-Plane how many planes you want to fill in with TCAS override (up to 63) by calling XPLMSetActiveAircraftCount.
    Note that you will get to update all 19 multiplayer planes then, even if the user has a lower AI aircraft count setting. It is not necessary for the user to increase AI aircraft count or provide special models to be loaded as AI. In fact, TCAS override works even if the user has 0 AI planes configured.
  4. Assign each target a unique 24bit number between 1 and 16777215 and set it to sim/cockpit2/tcas/targets/modeS_id[N]. This will be the mode S ID of the target and is used to track your target even if you move it between slots.
  5. Tell X-Plane about the traffic targets by writing to the existing relative_bearing_degs, relative_distance_mtrs and relative_altitude_mtrs datarefs or to the new sim/cockpit2/tcas/targets/position/double/ datarefs. Only the plugin who has acquired the AI planes can write these datarefs!
  6. Optional: Fill in more information than just the position into the new sim/cockpit2/tcas/targets/position/ datarefs. This way, you can keep X-Plane and other plugins updated about the state of up to 63 other planes.
  7. Optional: Provide a map layer to the X-Plane map with icons for the planes you are providing. If you are doing that, set sim/operation/override/override_multiplayer_map_layer to 1 to stop X-Plane from drawing its own icons.
  8. If you have fewer targets than anticipated, you can simply stop writing the positional data to a target slot. X-Plane will forget the target (and forget its unique ID). There is no need to set a lower XPLMSetActiveAircraftCount because X-Plane will drop TCAS targets that haven’t been updated in 10 frames.
  9. When you are done providing traffic (the user has disconnected from the online network) set the override_TCAS dataref to 0 and call XPLMReleasePlanes. This will re-enable X-Plane traffic or allow other plugins, like a real world traffic provider, to then take over traffic from you. This will also re-enable the X-Plane default map behavior, so you will want to tear down your custom map layer as well!

This will allow X-Plane to display your traffic on X-Plane’s default navdisplays, the G1000, the map and IOS console and also disseminate the information via ADS-B output to external EFB apps like FlyQ and ForeFlight.

For full source code, check out the code example!

Plugins and cockpit displays using existing datarefs

Existing aircraft most likely require no changes to pick up 19 traffic targets injected by TCAS override, since they are synced to the multiplayer datarefs.

Many third party aircraft use the absolute position datarefs to find out about traffic around them and show it on their navdisplay. These datarefs

sim/multiplayer/position/planeN_x double N = 1..20
sim/multiplayer/position/planeN_y double N = 1..20
sim/multiplayer/position/planeN_z double N = 1..20

will be updated by X-Plane, when a traffic plugin is using TCAS override, along with the derived velocity vector for ADS-B out.
XPLMCountAircraft will return the number of TCAS targets actively updated in the last 10 frames by the plugin owning the override, regardless of the user setting for AI aircraft. Therefore, all instruments can display all aircraft that are being written to, without requiring the user to change any settings.

The same number is also available from the new dataref

sim/cockpit2/tcas/indicators/tcas_num_acf int

Third-party aircraft are also free to adopt the relative position datarefs to display traffic around them, since they now will be filled in with useful information by the traffic provider.

New datarefs

New plugins can use the new set of datarefs that is not limited to 19 planes, but instead supports 63 aircraft currently. It is advisable to query the array size of sim/cockpit2/tcas/targets/modeS_id to find out how many targets the current version of X-Plane supports. Note that index 0 is reserved for the user plane.

X-Plane does not infer any information from the mode-S ID, nor does it make any guarantees about the user plane’s mode-S ID, other than that it is unique in the session, and that it fits in 24bits. Traffic providers can set the MSB of the 32bit integer (i.e. the_modeS_id | 0x80000000) to indicate their 24bit ID is a “real” ID that corresponds to the actual airframe they are providing. You would do this if you are replaying real-life ADS-B data. By default, the MSB should not be set: in that case you must not use the mode-S ID to look up aircraft type, airline, livery or other such information. The user airplane is simply assigned a unique ID at random, so it might well be that the user is flying a 172 with a mode-S code that in the real world belongs to a 747. Only if your plugin has reliable information about the mode-S code of its traffic (replaying real world ADS-B data), you can assign real IDs rather than randomized ones and set the MSB. You must not assume other plugins or X-Plane assign IDs matching real world aircraft databases when they don’t set the MSB.

You can optionally also provide a 7-byte flight ID (tailnumber or flightnumber) for each target which is used to identify the target on the X-Plane map.

Which of the positional datarefs are writable depends on how you update your targets:

  • In relative mode (writing the relative bearing, distance and altitude) X-Plane will calculate the world position, derive the velocity, and estimate the body angles for you. This is useful if all you care for is a blip on the display with roughly accurate data. Do not write to the xyz positions in that case!
  • In absolute mode (writing the x/y/z coordinates) your plugin should also write the vx, vz, vy velocities and roll/pitch/yaw body angles, as X-Plane will not estimate them. X-Plane will then fill in the relative bearing and distance information for you, and derive hpath and vpath from your cartesian velocities. X-Plane will also fill in the lat/lon/elevation global coordinates. This is useful for applications that know a lot about the state of the other plane, such as when it comes from an online network. Do not write to the bearing/distance/relativealtitude datarefs in this case!

Relative vs absolute updating is a per-target property, so your plugin can update different targets in different modes if required. The last dataref you write wins.

Coordinate transformation

X-Plane will do the conversion from Cartesian coordinates to latitude, longitude and elevation for you.

To convert from Cartesian x/y/z to relative bearings, use a polar coordinate transformation, with

sim/flightmodel/position/local_x and local_z

as the origin and

sim/flightmodel/position/true_psi

as the polar axis, with the relative bearing counting clockwise as is usual in all cockpit indicators. Note that we use elevation (sim/flightmodel/position/elevation and sim/multiplayer/position/planeN_el) and not local_y to calculate the altitude difference! This is important for targets that are far away from the coordinate origin, as the earth curves away under the local tangent plane and elevation will be higher than y.

Map icons

X-Plane will update the map showing other planes. However, it cannot know what the appropriate icon for the plane type you are supplying would be. If you want to make meaningful icons, you can supply your own map layer and tell X-Plane to stop drawing generic icons by setting sim/operation/override/override_multiplayer_map_layer to 1. This override is automatically cancelled when you give up TCAS_override, so don’t forget to remove your map layer when you’re done providing traffic!

Plugin coordination

Since only one plugin can be providing the other planes at a time, it is important that plugins play nice with each other when it comes to deciding who gets to control the aircraft in the world. This is facilitated by the new plugin message XPLM_MSG_RELEASE_PLANES that is sent to a plugin owning the planes when another plugin requests them.

Playing nice starts with choosing the right time to call XPLMAcquirePlanes:
Do not call XPLMAcquirePlanes because you might at some point in the future maybe connect to some network. Do call XPLMAcquirePlanes only when the user actually decided to connect to the network.

Do register a callback with XPLMAcquirePlanes so that X-Plane can call you when another plugin gives up control over the planes.

Playing nicely requires receiving the XPLM_MSG_RELEASE_PLANES message and acting accordingly:
Do give up the planes if you are providing synthetic traffic and an online network now wants the planes. Traffic flown by humans should always take precedence over generated traffic. Do call XPLMReleasePlanes when appropriate.
Do not give up the planes to a synthetic traffic provider if you are currently connected to online flying, obviously.

Finally, give up the planes as soon as you no longer have a source. That is, if the user disconnects from their online flying network, do call XPLMReleasePlanes to give synthetic traffic providers a chance to provide AI traffic again.

For a full example, refer to the example plugin.

List of datarefs

sim/cockpit2/tcas/indicators/relative_bearing_degs	float[64]	y	degrees	Relative bearing of each other plane in degrees for TCAS - relative to sim/flightmodel/position/true_psi not ground track or anything else
sim/cockpit2/tcas/indicators/relative_distance_mtrs	float[64]	y	meters	Distance to each other plane in meters for TCAS
sim/cockpit2/tcas/indicators/relative_altitude_mtrs	float[64]	y	meters	Relative altitude (positive means above us) for TCAS
sim/cockpit2/tcas/indicators/tcas_alert	int	y	boolean	True if a TCAS alert is currently issued.
sim/cockpit2/tcas/indicators/tcas_num_acf	int	n	integer	If TCAS is not overriden by plgugin, returns the number of planes in X-Plane, which might be under plugin control or X-Plane control. If TCAS is overriden, returns how many targets are actually being written to with the override. These are not necessarily consecutive entries in the TCAS arrays. 
sim/cockpit2/tcas/targets/modeS_id	int[64]	y	integer	24bit (0-16777215 or 0 - 0xFFFFFF) unique ID of the airframe. This is also known as the ADS-B "hexcode".
sim/cockpit2/tcas/targets/modeC_code	int[64]	y	integer	Mode C transponder code 0000 to 7777. This is not really an integer, this is an octal number.
sim/cockpit2/tcas/targets/flight_id	byte[512]	y	string	7 character Flight ID, terminated by 0 byte. ICAO flightplan item 7.
sim/cockpit2/tcas/targets/icao_type	byte[512]	y	string	7 character ICAO code, terminated by 0 byte. C172, B738, etc... see //www.icao.int/publications/DOC8643/Pages/Search.aspx
sim/cockpit2/tcas/targets/position/x	float[64]	y	meter	local X coordinate, meter. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/y	float[64]	y	meter	local Y coordinate, meter. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/z	float[64]	y	meter	local Z coordinate, meter. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/lat	float[64]	n	degrees	global coordinate, degrees.
sim/cockpit2/tcas/targets/position/lon	float[64]	n	degrees	global coordinate, degrees.
sim/cockpit2/tcas/targets/position/ele	float[64]	n	meter	global coordinate, meter.
sim/cockpit2/tcas/targets/position/vx	float[64]	y	meter/s	local X velocity. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/vy	float[64]	y	meter/s	local Y velocity. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/vz	float[64]	y	meter/s	local Z velocity. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/vertical_speed	float[64]	y	feet/min	absolute vertical speed feet per minute. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/hpath	float[64]	n	degrees	ground track in true degrees. Derived from velocity vector.
sim/cockpit2/tcas/targets/position/vpath	float[64]	n	degrees	flight path angle in degrees. Derived from velocity vector.
sim/cockpit2/tcas/targets/position/V_msc	float[64]	n	meter/s	total true speed, norm of local velocity vector. That means it includes vertical speed!
sim/cockpit2/tcas/targets/position/psi	float[64]	y	degrees	true heading orientation. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/the	float[64]	y	degrees	pitch angle. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/phi	float[64]	y	degrees	bank angle. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/weight_on_wheels	int[64]	y	boolean	ground/flight logic. Writeable only when override_TCAS is set.
sim/cockpit2/tcas/targets/position/gear_deploy	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_gear_deploy[0]
sim/cockpit2/tcas/targets/position/flap_ratio	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_flap_ratio
sim/cockpit2/tcas/targets/position/flap_ratio2	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_flap_ratio2
sim/cockpit2/tcas/targets/position/speedbrake_ratio	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_speedbrake_ratio
sim/cockpit2/tcas/targets/position/slat_ratio	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_slat_ratio
sim/cockpit2/tcas/targets/position/wing_sweep	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_wing_sweep
sim/cockpit2/tcas/targets/position/throttle	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_throttle[0]
sim/cockpit2/tcas/targets/position/yolk_pitch	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_yolk_pitch 
sim/cockpit2/tcas/targets/position/yolk_roll	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_yolk_roll
sim/cockpit2/tcas/targets/position/yolk_yaw	float[64]	y	ratio	mirror of sim/multiplayer/position/planeN_yolk_yaw
sim/cockpit2/tcas/targets/position/lights	int[64]	y	bitfield	beacon=1, land=2, nav=4, strobe=8, taxi=16
sim/cockpit2/tcas/targets/position/double/plane1_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane1_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane1_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane2_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane2_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane2_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane3_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane3_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane3_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane4_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane4_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane4_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane5_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane5_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane5_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane6_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane6_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane6_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane7_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane7_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane7_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane8_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane8_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane8_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane9_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane9_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane9_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane10_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane10_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane10_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane11_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane11_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane11_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane12_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane12_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane12_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane13_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane13_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane13_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane14_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane14_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane14_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane15_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane15_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane15_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane16_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane16_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane16_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane17_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane17_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane17_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane18_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane18_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane18_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane19_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane19_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane19_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane20_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane20_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane20_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane21_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane21_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane21_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane22_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane22_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane22_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane23_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane23_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane23_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane24_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane24_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane24_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane25_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane25_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane25_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane26_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane26_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane26_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane27_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane27_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane27_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane28_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane28_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane28_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane29_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane29_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane29_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane30_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane30_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane30_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane31_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane31_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane31_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane32_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane32_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane32_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane33_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane33_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane33_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane34_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane34_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane34_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane35_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane35_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane35_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane36_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane36_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane36_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane37_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane37_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane37_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane38_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane38_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane38_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane39_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane39_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane39_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane40_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane40_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane40_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane41_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane41_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane41_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane42_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane42_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane42_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane43_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane43_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane43_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane44_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane44_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane44_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane45_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane45_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane45_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane46_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane46_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane46_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane47_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane47_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane47_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane48_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane48_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane48_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane49_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane49_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane49_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane50_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane50_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane50_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane51_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane51_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane51_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane52_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane52_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane52_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane53_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane53_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane53_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane54_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane54_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane54_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane55_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane55_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane55_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane56_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane56_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane56_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane57_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane57_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane57_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane58_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane58_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane58_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane59_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane59_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane59_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane60_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane60_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane60_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane61_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane61_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane61_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane62_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane62_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane62_ele	double	n	meter	global coordinate, meter. 
sim/cockpit2/tcas/targets/position/double/plane63_lat	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane63_lon	double	n	degrees	global coordinate, degrees
sim/cockpit2/tcas/targets/position/double/plane63_ele	double	n	meter	global coordinate, meter. 
Comments Off on Overriding TCAS and providing traffic information

Plugin Guidance for OpenGL Drawing

This document provides guidelines for using OpenGL to draw from X-Plane plugins running inside X-Plane’s process.

While X-Plane can use OpenGL, Vulkan, or Metal drivers to render to a graphics card, plugin-drawing is supported only via OpenGL. OpenGL is not the fastest or most modern API, but it does provide a robust way to draw in 3-d without exposing complicated and error prone implementation details like memory management, resource barriers, or concurrency, making it an appropriate choice for custom user interface and custom aircraft glass displays.

General principles

In our work with third party add-ons, we see three kinds of add-on behavior that cause almost all of the compatibility problems, bugs, performance loss, and crashes. Here are three guiding principles for interacting with X-Plane.

Do Not Lie to X-Plane

If your add-on uses plugin APIs for purposes other than their intended uses, you may have performance or compatibility problems later. Avoid things like using drawing callbacks for non-drawing purposes, using 3-d drawing callbacks for 2-d drawing, or non-window callbacks for UI.

If your add-on lies to X-Plane about your intentions, X-Plane no longer has optimal situational awareness and can no longer run plugins in an optimal way. Achieving the best possible performance is only possible if everyone plays fair and by the rules.

Minimize XPLM and OpenGL Use

X-Plane users care deeply about performance; minimize your use of OpenGL and the XPLM to minimize your add-on’s negative impact on framerate. Only perform operations that are necessary, and cache values retrieved through XPLM API, except for OpenGL resources, to be reused later if possible. When drawing, avoid repeated OpenGL state changes and adopt modern OpenGL techniques where feasible. Using shaders and vertex buffer objects for static geometry is much faster than using pre OpenGL 2.0 immediate mode rendering.

Do Not Use Undocumented Behavior

Do not use the SDK in ways that are not covered by the documentation; undocumented use of the SDK can appear to work but destabilize the sim or interfere with other add-ons, or can break in a future X-Plane update. If you are not sure from the documentation whether something is legal, ask us!

Drawing Callbacks

Plugins receive an opportunity to draw inside X-Plane via drawing callbacks; the following section provides guidelines for when and how to use drawing callbacks correctly.

Register only the drawing callbacks that you need at the time you need them to do actual drawing! Dispatching any drawing callback requires a not-insignificant CPU time overhead and requires heavy synchronization in the case of Vulkan and Metal, both of which are completely wasted if no drawing actually happens.

Use Drawing Callbacks Only for Drawing

Use drawing callbacks only for drawing, not for updating simulation state, bookkeeping, network IO, etc. Drawing callbacks can be called multiple or zero times per frame based on the user’s monitor configuration, so add-ons that use drawing callbacks for other purposes both hurt performance and may not work correctly in some situations.

Use Real Windows for UI

Using real windows and the XPLM 3.x window API (XPLMCreateWindowEx, etc.) is highly recommended over using legacy draw callbacks. This provides the sim with the most situational awareness to improve dispatching and compositing of plugin windows. The real window API also provides correct UI interaction for floating windows and focus.

Use Drawing Callbacks for Panels

The panel and gauge drawing callbacks let you draw under or on top of the 2-d and 3-d panel. Be sure to check the draw-type datarefs for the callbacks – see Datarefs for Panel Drawing below. Your panel draw callback can be called for both the albedo layer and the emissive layer of the panel separately; make sure your code draws the appropriate content for each.

Use a Flight Loop Callback for Off-Screen FBOs

Use a flight loop callback to draw into your offscreen framebuffer. When you do this, X-Plane will not have set an FBO up for you to draw into, so you will bypass the overhead of synchronizing with our drawing on the GPU.

Use XPLMInstance and Particles for 3-d Drawing Where Possible

Avoid using the 3D drawing callbacks unless absolutely necessary. Dispatching 3D drawing callbacks comes with potentially negative performance impacts and isn’t necessary most of the time.

The best interface for drawing “stuff” in the 3-d world is the XPLM instancing API to draw objects into the world or tie particle effects to your custom datarefs in order to create custom effects. The instancing API is straightforward to use, available since X-Plane 11.0, and replaces XPLMDrawObject and XPLMDrawAircraft.

See also the Plugin Compatibility Guide for X-Plane 11.50.

Use a 2-d Callback for “Coach Marks”

When drawing overlays or other kinds of scene annotations, a 2D drawing callback is much better suited than a 3D drawing callback. You can use the projection matrices provided by X-Plane to efficiently transform 3D coordinates to 2D screen coordinates.

A sample of this can be found here: //developer.x-plane.com/code-sample/coachmarks/

See also the Plugin Compatibility Guide for X-Plane 11.50.

Use a Panel Texture to Draw “on” the Aircraft

If you need to draw onto the aircraft, e.g. to simulate damage to the fuselage, rain on a wind-screen, or a livery change, you can map a panel texture to that section of the aircraft and then use a panel drawing callback for drawing. This can be used for dynamic decals or other effects, for example, that would otherwise require complicated use of the 3D drawing callbacks.

Panel texturing is available for all parts of the aircraft, not just the cockpit object, but is more expensive than using disk-based textures – use it only where the dynamic effect is absolutely necessary.

If your add-on needs more panel texture space, you can use panel regions to get access to four separate dynamic textures.

Use the New 3-d Callback on Windows Only When Necessary

Using the new 3D drawing callback under Vulkan is not recommended unless absolutely necessary! It comes with a lot of gotchas and caveats and is intended only for add ons that truly need to do custom scenery drawing in 3D, like weather add ons. Before using the 3D drawing callback, evaluate all alternatives to see if there isn’t a better solution for what you are trying to achieve.

The new 3-d drawing callback works with OpenGL and Vulkan but not Metal; when running under Vulkan, a number of aspects of the drawing environment will be different:

  • The depth buffer will be in reverse-float-Z, not standard integer format; the clip control will be DirectX style and the depth compare function will be inverted.
  • The origin of the frame buffer may be inverted.

See the appendix for datarefs that let a plugin dynamically detect these conditions.

See also: Plugin Compatibility Guide for X-Plane 11.50.

OpenGL State Management

Your plugin shares an OpenGL context with other plugins and sometimes with X-Plane itself; this section provides guidance on how to change OpenGL state correctly.

Don’t Call glGetXXXX

Do not use glGet to retrieve OpenGL state. This usually results in some kind of stall for the driver and has detrimental effects on performance. For custom state management it is usually much better to potentially set OpenGL state again and then cache that known value for future state changes.

X-Plane provides access to the transform stack (upon entrance to your call stack) and viewports via datarefs, as well as the currently bound FBO (although ideally this should not be changed).

If you need a state that isn’t covered here, please contact us – there may be a different way to approach your rendering code.

Call glGetError in Debug Builds Only

Please call glGetError in debug builds and don’t ship code that breaks the OpenGL state machine. Your plugin should never execute code that leaves an OpenGL error in place.

When shipping your plugin, do notcall glGetError as it can hurt performance. A simple macro that wraps glGetError() calls and makes it easy to toggle usually works best and makes it easy to ship the version of code you want.

If your add-on creates framebuffers, please do check for framebuffer completeness once when you create the FBO; your add-on should not create and destroy FBOs on a regular basis.

Use the XPLM APIs to Manage State Where Possible

The XPLM APIs provide a number of calls to manage state; where these functions exist, please use them; they will avoid setting state multiple times.

  • XPLMSetGraphicsState controls blend enable, fixed function alpha test enable, depth mask and depth test enable, fixed function fog and lighting, and fixed function texture enabling.
  • XPLMBindTexture2d controls the 2-d texture binding point.
  • XPLMGenerateTextureIDs wraps texture object generation.

Restore all Other State Except Attributes When Done

Any OpenGL state other than vertex attributes that is not covered by the APIs above must be restored to its initial state when your callback completes. This includes:

  • Unbinding any bound shaders, VAOs, VBOs and non-2d textures to 0.
  • Restoring the drawing array state (only the fixed function vertex array should be enabled).

You do not need to reset the client array pointerstate, nor should you assume upon entrance to a callback that it contains anything sane.

Restore the Current FBO By Dataref

If you must render to an offscreen FBO in a draw callback for some reason, you must restore the currently active FBO before returning from it. Don’t call glGet() to retrieve it, instead use the sim/graphics/view/current_gl_fbo dataref to figure out what FBO to restore.

XPLMDrawString and Friends May Change State

XPLMDrawString and the other API drawing calls can change all of the states mentioned above; while you do not need to clean up after them, do not assume your own state setup is correct after they have been called.

Illegal OpenGL Usage

The following techniques are not allowed from plugins running inside X-Plane.

Do Not Draw from Non-Drawing Callbacks

Non-drawing callbacks aren’t necessarily dispatched in a way that supports drawing. Drawing in a non drawing callback will lead to undefined behavior with regards to your own rendering and the effects on the rest of the sim.

Do Not Mutate X-Plane’s OpenGL Resources

Resources obtained through the XPLM API should be seen as immutable, with the exception of the contentsof the active FBO during draw callbacks. Attempting to change any internal X-Plane resources can lead to heavily decreased performance or have other unexpected side effects, like crashing.

Do Not Locate and Use Private X-Plane OpenGL Resources

Resources not exposed through the XPLM API are not fair game for use. These resources aren’t guaranteed to remain stable between or even within X-Plane runs or future versions. X-Plane is assumed to be the only consumer of these resources and will not attempt synchronizing with plugins when modifying them.

Do Not Hold on to X-Plane OpenGL Resources

While it might be tempting to hold on to OpenGL resources obtained in previous draw callbacks and then reuse them in other callbacks, doing so can have disastrous consequences. This is especially true under Vulkan and Metal, where resources require special synchronization. If missing, this can lead to driver or system crashes and desktop freezes.

Do Not Change State to Affect X-Plane

Attempting to change OpenGL state to trick X-Plane into rendering differently is heavily discouraged. This can lead to X-Plane doing improper bookkeeping of its own state, which can lead to heavily impacted performance. This is also not guaranteed to work between versions or even between runs and can break at any time.

Performance

This section contains performance guidelines for OpenGL plugins.

Pre-Initialize Your Add-on

Perform heavy initialization at aircraft load or flight start time. At runtime, a plugin should be able to just work without lazily initializing any state or computing expensive look up tables. The goal should be to never add unpredictable latency to the frame time.

Do Less

Avoid unnecessary work; preload resources and precompute expensive results.

Follow standard OpenGL performance practices:

  • Move computing work from fragment to vertex shaders.
  • Reduce API calls that change state.
  • Reduce the number of draw calls by merging them where possible.

Do More but Consistently

Attempting to improve framerate by adopting a flip-flop mechanism where one frame doesn’t do heavy work and the other does is highly discouraged. Schemes like this help nothing with the perceived performance of the sim, on the contrary, the very uneven frame times will have a noticeable impact on the user experience. It is much better to instead do the work every frame and provide a slightly lower but much more consistent framerate. Consistently drawing frames on the screen makes the sim appear much smoother to the user.

Consider Using Multicore

If your add-on needs to compute values per frame that are expensive (e.g. take several milliseconds to compute) and you cannot optimize the computation, consider doing the work on a separate thread.

Moving work to a separate thread in a plugin is quite complex because:

  • The SDK provides no built-in facilities to help with this.
  • No SDK APIs may be called from worker threads you create.
  • You do not have access to the SDK-provided OpenGL context from a worker thread.
  • You cannot block waiting for data completion from an SDK callback.

Typically to make this work you will need to launch a worker thread once and have it block on a semaphore to pick up tasks that can be computed independently without XPLM calls and then returned to the main thread via some kind of thread-safe queue.

Appendix A – DataRefs

This section covers datarefs that can be used to get more information about the rendering environment or interact with X-Plane during drawing callbacks. All callbacks should be resolved via XPLMFindDataref at plugin startup but should be read from inside the drawing callback to get information contextual to a particular draw callback. Read results may be undefined outside of or in the wrong draw callback.

Datarefs for Panel Drawing

These drawing callbacks are appropriate from panel drawing callbacks (before/after panel and gauges).

sim/graphics/view/panel_render_type (int, read-only)

This dataref indicates the type of panel rendering being done:

  • 0 render the entire panel (day time and lit elements with full lighting for 2-d panels)
  • 1 albedo only (render solid elements without lighting)
  • 2 emissive only (render lit elements only)

sim/graphics/view/panel_render_new_blending (int, read-only)

This dataref indicates whether the blending mode for the 3-d panel for the current aircraft is the deprecated, legacy “max” alpha blending mode or the modern preferred alpha blending with correct alpha treatment.

  • 0 blending mode is legacy max mode
  • 1 blending mode is modern

The blending equation for legacy max mode is:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);

The blending equation for modern blending mode is:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,

GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

glBlendEquation(GL_FUNC_ADD);

Modern blending mode will correctly composite multiple translucent elements over a translucent or clear panel; legacy max mode gives incorrect but often acceptable results.

Warning: legacy max mode is deprecated and will be dropped from X-Plane in the future. At that point all aircraft will render using blend mode regardless of the content of their art assets.

Datarefs for Panel Clicking

When the mouse is being used over a 3-d panel (via a region mapped with ATTR_cockpit), the following datarefs provide information about the click location.

sim/graphics/view/click_3d_x (float, read-only)

sim/graphics/view/click_3d_y (float, read-only)

This is the location of the mouse in the UV map coordinates of the underlying object.

sim/graphics/view/click_3d_x_pixels (float, read-only

sim/graphics/view/click_3d_y_pixels (float, read-only)

This is the location of the mouse in panel pixel coordinates, or -1 if the mouse is not over the panel.

For all of these datarefs, they are only valid during draw callbacks for the monitor that the mouse is over. Therefore if your plugin is multi-monitor aware, you need to read these from the draw callback for the window that you are using to capture clicks.

(We do not recommend using these datarefs to implement mouse interactions; to capture clicks on a 2-d screen, use a generic instrument on the panel, or consider a real 3-d manipulator on the object itself.)

Datarefs for Panel Location and Scrolling

The location of the panel is provided via two sets of rectangles during panel and gauge drawing callbacks:

sim/graphics/view/panel_total_pnl_l (float, read-only)

sim/graphics/view/panel_total_pnl_b (float, read-only)

sim/graphics/view/panel_total_pnl_r (float, read-only)

sim/graphics/view/panel_total_pnl_t (float, read-only)

These four datarefs form the total bounds of the panel in the modelview coordinate system of the panel drawing callback. You can use these datarefs from inside a panel drawing callback to “calibrate” the location of your drawing. Due to scrolling of panels, the origin of the panel bitmap is not guaranteed to be in any one location on the panel.

sim/graphics/view/panel_visible_pnl_l (float, read-only)

sim/graphics/view/panel_visible_pnl_b (float, read-only)

sim/graphics/view/panel_visible_pnl_r (float, read-only)

sim/graphics/view/panel_visible_pnl_t (float, read-only)

These four datarefs provide the rectangle within the panel that is visible within the current OpenGL viewport. If the panel does not completely fill the viewport, some values could be outside the total bounds of the panel.

These datarefs can be used to identify which panel region is being rendered, for aircraft that use cockpit panel regions. They can also be used to cull gauge drawing that is not going to be visible.

Note that these datarefs are not the same as the current viewport – they are specified in modelview coordinates – that is, the current transform in effect for OpenGL drawing.

sim/graphics/view/panel_total_win_l (float, read-only)

sim/graphics/view/panel_total_win_b (float, read-only)

sim/graphics/view/panel_total_win_r (float, read-only)

sim/graphics/view/panel_total_win_t (float, read-only)

For 2-d panels that are visible on-screen, these datarefs provide the location of the total panel in modelview coordinates during UI drawing callbacks (e.g. post-window draw callbacks and XPLMDisplay window draw callbacks). These datarefs can be used to calibrate the panel location to user interface elements.

sim/graphics/view/panel_visible_win_l (float, read-only)

sim/graphics/view/panel_visible_win_b (float, read-only)

sim/graphics/view/panel_visible_win_r (float, read-only)

sim/graphics/view/panel_visible_win_t (float, read-only)

These datarefs provide the visible extent of the panel in current modelview coordinates during UI callbacks; they can be used for culling gauges that are drawn in UI layers but must match the panel’s location.

Datarefs for 3-d Drawing Callbacks

These datarefs can be read during 3-d drawing callbacks to find details about 3-d drawing.

sim/graphics/view/world_render_type (int, read-only)

This dataref indicates the type of rendering that X-Plane is trying to accomplish with its 3-d callback. The following render passes are visible to plugins:

  • 0 Regular 3-d rendering pass
  • 1 Prep source imagery for water reflections
  • 3 Render depth for shadow maps
  • 6 Prep source imagery for environment cube maps

3-d draw callbacks may be called more than once, so opting out of drawing based on this enumeration can have performance benefits.

Note: by default only regular 3-d render passes are dispatched to plugins; you must enable the capability “XPLM_WANTS_REFLECTIONS“ to receive other types of 3-d drawing callbacks.

Note: the modern 3-d callback does not dispatch shadows; use XPLM object instances for shadow-casting solid geometry.

sim/graphics/view/plane_render_type (int, read-only)

Before X-Plane 11.40, the aircraft drawing phases were the only ones that correctly separated solid and blended drawing; during an aircraft-phase drawing callback this dataref contains:

  • 1 Solid geometry is being drawn for the aircraft. If HDR is enabled and the drawing pass is normal, drawing is going into the G-Buffer.
  • 2 Blended geometry is being drawn for the aircraft. If HDR is enabled, this will be after the G-Buffer is resolved.

For plugins using the modern 3-d drawing callback, the one callback that a plugin receives is equivalent to a post-aircraft drawing callback for blending. Solid drawing is not available – use instancing to add models to the X-Plane world.

sim/graphics/view/draw_call_type (int, read-only)

For 3-d drawing callbacks, this dataref indicates the type of drawing being done for VR multi-eye rendering:

  • 1 Mono (regular) drawing is in progress
  • 3 Stereo drawing is in effect and this call is to render the left eye
  • 4 Stereo drawing is in effect and this call is to render the right eye.

When the left and right eye are dispatched, the transform stack will have been modified to take into account per-eye offsets.

sim/graphics/settings/HDR_on (int, read-only)

This boolean dataref tells whether the HDR deferred renderer is enabled.

  • 0 HDR is not enabled
  • 1 HDR is enabled

sim/graphics/settings/scattering_on (int, read-only)

This boolean dataref tells whether atmospheric scattering is enabled; since atmospheric scattering is always on in X-Plane 11, it will always have a value of 1.

Datarefs for OpenGL State and Modes

All drawing callbacks provide datarefs that provide access to the transform stack at the time your drawing callback is called.

sim/graphics/view/projection_matrix (float[16], read-only)

sim/graphics/view/modelview_matrix (float[16], read-only)

sim/graphics/view/viewport (int[4], read-only)

These three datarefs provide complete access to the modelview, projection and viewport transformations, allowing you to map between modelview and OS window coordinates.

sim/graphics/view/world_matrix (float[16], read-only)

sim/graphics/view/acf_matrix (float[16], read-only)

sim/graphics/view/projection_matrix_3d (float[16], read-only)

These three datarefs can be read during a 2-d drawing callback or window drawing callback to gain access to the transform stack that was used to render the 3-d world, if there was a 3-d render. The world matrix provides the model-view matrix for standard OpenGL world coordinates (e.g. for XPLMWorldToLocal).

The acf matrix provides a modelveiw matrix whose origin is the aircraft’s nominal CG and whose axes are aligned with the aircraft. This is equivalent to starting with the world matrix, translating to the aircraft location and rotating by the aircraft Eulers, but may provide better precision.

sim/graphics/view/is_reverse_float_z (int, read-only)

This dataref indicates whether the depth buffer for the current drawing callback is using regular linear depth encoding or reverse-float-Z conventions.

ValueDepth FormatDepth FunctionDepth Range

0GL_DEPTH_COMPONENT_24GL_LEQUAL-1..1

1GL_DEPTH_COMPONENT_32FGL_GEQUAL0..1

The depth buffer will have an attached 8 bit stencil buffer.

sim/graphics/view/is_reverse_y (int, read-only)

This dataref indicates whether the current rendering pass uses OpenGL conventions for the framebuffer (origin in lower left, Y axis points up) or DirectX/Metal Conventions (origin in upper right, Y axis points down). Even when X-Plane is running in reverse Y mode, the transform stack will be set up such that the model view matrix has the same input coordinate system, e.g. Y is up in 3-d, and Z is south.

Legacy Datarefs for Object Animation

When datarefs are read from a plugin to compute an object’s animation pose or to calculate the setup of its lights, the following datarefs are available to read to learn which object is being rendered.

sim/graphics/animation/draw_object_x (float, read-only)

sim/graphics/animation/draw_object_y (float, read-only)

sim/graphics/animation/draw_object_z (float, read-only)

sim/graphics/animation/draw_object_psi (float, read-only)

This technique for determining which object is being animated is deprecated and is made obsolete by XPLMInstancing.

1 Comment

Plugin compatibility guide for X-Plane 11.50

Starting with X-Plane 11.50, users have the ability to change the graphics API that is used by X-Plane. They now have the option to choose between OpenGL (all platforms), Vulkan (Windows and Linux) and Metal (macOS). This has potential implications for third party code that interacts with X-Plane’s rendering. The main goal with Vulkan and Metal is to deliver a more consistent and higher framerate, while also maintaining compatibility with the existing add on ecosystem as much as possible.

Compatibility with existing plugins

As a general note, existing plugins running under the OpenGL renderer in X-Plane 11.50 should behave exactly the same as in X-Plane 11.41. Assuming the plugins behaved nicely and played by the rules of the SDK, compatibility between 11.50 OpenGL and 11.41 is provided.

Whether a user selects OpenGL, Vulkan or Metal, the following kinds of operations don’t require any changes to existing add-ons:

  • Scenery add ons. All renderers support the existing scenery features and texture formats and will look the same on all platforms.
  • Plugins that don’t interact with the rendering system and instead provide additional functionality without the need to draw in the world.
  • Window drawing using the XPLM 3 SDK windows. This includes UI elements drawn using the XPWidgets library as well as custom OpenGL drawing.
  • 2D drawing callbacks. This includes UI elements drawn using the XPWidgets library as well as custom OpenGL drawing.
  • Panel drawing callbacks. This includes 2D panels as well as 3D panels drawn inside the aircraft.
  • 3D drawing using the XPLM instancing API.

Breaking changes have been made to the 3D drawing callbacks. All 3D drawing phases have been deprecated as of X-Plane 11.50 and will no longer be called under either the Vulkan or Metal renderer. Additionally, the XPLMDrawObjects() and XPLMDrawAircraft() APIs have been deprecated and also no longer works with either Vulkan or Metal. 3D drawing callbacks, XPLMDrawObjects(), and XPLMDrawAircraft() will continue to work under OpenGL in 11.50 like they did in 11.41.

X-Plane has offered an alternative to the XPLMDrawObjects() and XPLMDrawAircraft() APIs since X-Plane 11.10 in the form of the instancing API, which we highly encourage developers to adopt. While not a direct, drop in replacement, it offers much more flexibility for plugin authors and X-Plane than the previous system did. You can read the documentation for the instancing API here and check out our example code here.

OpenGL compatibility notes

When a user runs X-Plane with either Vulkan or Metal, X-Plane itself will exclusively run with the selected backend and no rendering is done using OpenGL. To provide compatibility with plugins X-Plane will create a OpenGL context that is exclusively for use by plugins. X-Plane will create minimal resources in this OpenGL context to enable support for APIs like XPLMGetTexture() and to facilitate sharing of framebuffers across Vulkan/Metal and OpenGL. Plugins should not assume the existence of any resources in an OpenGL context and should instead use public APIs to retrieve resources. No guarantee is made with regards to availability of resources in the OpenGL context across versions or even runs of X-Plane. Plugins that try to sniff resources from the OpenGL context, whether running under Vulkan, Metal or OpenGL, are considered misbehaved and no compatibility guarantees are made.

Plugins that use Vulkan/Metal compatible drawing operations don’t need to do any special processing or precautions. X-Plane provides all synchronization and resource sharing across the rendering APIs as part of its internal plugin bridge system. We expect this OpenGL plugin bridge to exist for the foreseeable future as something that plugins can be authored against. OpenGL provides an easy to use API for plugin needs without any of the complications that come with Vulkan or Metal.

Alternatives to 3D drawing

As mentioned above, the X-Plane 11.41 3D drawing phases have been deprecated in X-Plane 11.50 and are no longer called on Vulkan and Metal. This should not be a problem for most plugins, although a few might require changing to the XPLM instancing API. However, we have found that a lot of third party plugins rely on the 3D drawing phases to read datarefs or do internal bookkeeping, without actually doing any real drawing. This will no longer work under either Vulkan or Metal with 11.50 due to these drawing phases no longer being dispatched, although it is still possible under OpenGL.

We strongly recommend authors avoid doing this in general, even on OpenGL. 3D drawing phases are meant exclusively for 3D drawing, and dispatching them isn’t free in terms of CPU overhead on X-Plane’s end. Plugins that don’t require 3D drawing capability should instead use the flight loop callbacks to do all of their bookkeeping.

We also discovered that a lot of 3D drawing is actually in the form of overlays or other kinds of markers or labels on 3D objects. These can be done from a 2D drawing callback instead of a 3D drawing callback by transforming the 3D world coordinates onto the 2D screen and then using those coordinates to draw. This will work regardless of whether a user runs OpenGL, Vulkan or Metal. Example code that deals with the 3D world to 2D screen coordinate transform can be found here. Note though that this will always draw over world objects since there is no depth information available.

We expect most plugins to be able to entirely phase out their usage of the 3D drawing phases with minimal code changes necessary, either by adopting the instancing API, moving bookkeeping to the flight loop, or using a 2D drawing callback to draw overlays. We highly recommend exploring these alternatives to the previous 3D drawing approaches as they allow X-Plane to run much more efficiently.

3D drawing using the modern drawing phase

Plugins that require completely custom drawing in the X-Plane world with the ability to be occluded by other objects won’t work with the above work arounds. We don’t expect very many plugins to be in this category, with custom weather rendering plugins being the notable exception. For plugins like this, X-Plane 11.50 offers a new 3D drawing phase as part of the XPLM 302 SDK: xplm_Phase_Modern3D. For technical reasons this drawing phase is not available on Metal and only runs on Vulkan and OpenGL!

This new drawing phase has many caveats and gotchas and comes with the big fat warning that it isn’t very cheap in terms of CPU overhead. We highly discourage the use of it unless it’s absolutely necessary to perform real, custom 3D drawing! As mentioned before, the biggest caveat is that this drawing phase will not be called under Metal. Additionally there is only a single drawing phase now which conceptually sits right where the old before xplm_Phase_Airplanes draw phase used to be. The before and after phase of the modern 3D drawing phase are called directly in succession and no X-Plane rendering happens in between.

There are two additional things to watch out for when doing 3D rendering in general:

First, X-Plane can run with reverse-z semantincs. Meaning that the depth range is [0, 1] as opposed to the traditional [-1, 1] and the depth comparison is GEQUAL instead of LEQUAL. As a side effect, this means that the depth buffer is cleared to 0 instead of 1. When in reverse-z mode, the depth buffer will be in floating point format (DEPTH_32F) instead of the traditional 24bit integer format. X-Plane will set up the OpenGL state and projection matrices for you to reflect these changes when dispatching plugins, but it’s something you might want to be aware of if you do any depth buffer readbacks, set the depth state yourself, or calculate your own projection matrices. Whether X-Plan is in reverse-z mode can be observed through the sim/graphics/view/is_reverse_float_z dataref. When running under Vulkan, X-Plane will always run in reverse-z mode, when running under OpenGL it’ll only be in reverse-z mode for VR rendering.

Second, X-Plane can run with reverse-y semantics. In reverse-y mode, the colour and depth buffer are flipped along the y-axis (the origin is top left and grows downward). When running in reverse-y mode, it’s the responsibility of the plugin author to flip the front face winding to avoid polygons from getting incorrectly backface culled. The projection matrix provided by X-Plane takes care of the changed projection parameters, but if you do your own projection matrix set-up you’ll have to do this change yourself. Whether X-Plane is in reverse-y mode can be observed through the sim/graphics/view/is_reverse_y dataref. When running under Vulkan, only 3D drawing with the HDR renderer is in reverse-y mode. 2D rendering phases and OpenGL rendering are never in reverse-y mode.

6 Comments

Sim/operation/windows/system_window

This is a handle to the OS’s native window that X-Plane is running in. This dataref is only safe for 32-bit builds of X-Plane; use sim/operation/windows/system_window_64 to get a 64-bit native window handle.

You should almost never need to use this dataref!

Contents X-Plane 6.70 -> 10.10

Macintosh: this dataref is a Carbon WindowRef.

Windows: This is a Window HWND.

Linux: This is an X11 XID for a Window object. (TODO: unclear when this first became available, as Linux was not a supported OS for 6.70)

Contents X-Plane 10.20 and Newer, 32-bit builds

Macintosh: this returns NULL; the underlying Cocoa window is not available.

Windows: This is a Window HWND.

Linux: This is an X11 XID for a Window object.

Contents X-Plane 10.20 and Newer, 64-bit builds

Macintosh: this returns NULL; the underlying Cocoa window is not available.

Windows: This is the low 32 bits of a Window HWND.

Linux: This is the low 32 bits of an X11 XID for a Window object.

Leave a comment

Datarefs for the CDU screen

X-Plane 11.35b5 adds datarefs to read the contents of the X-Plane default FMS Control and Display Unit (CDU) screen.

The CDU is limited to 16 lines of text with 24 characters per line. Note that not all CDUs use all 16 lines – Some use a combined scratchpad/message line, others have an additional line under the scratchpad for messages. Some CDUs have four line selectable rows of data, others have 6. So while you can read data from CDUs of all sizes up to 16 lines, not all CDUs will fill 16 lines with content.

Text

The datarefs

sim/cockpit2/radios/indicators/fms_cdu1_text_line0

to

sim/cockpit2/radios/indicators/fms_cdu1_text_line15

and

sim/cockpit2/radios/indicators/fms_cdu2_text_line0

to

sim/cockpit2/radios/indicators/fms_cdu2_text_line15

contain the contents of each line as an UTF-8 string. Note that one character might need more than one byte of the dataref to display. You are expected to be able to read at least the following UTF-8 characters:

  • U+00B0 (degree sign): (0xC2 0xB0)
  • U+2610 (ballot box): (0xE2 0x98 0x90)
  • U+2190 (left arrow): (0xE2 0x86 0x90) to U+2193 (downwards arrow): (0xE2 0x86 0x93)
  • U+0394 (greek capital letter delta): (0xCE 0x94)
  • U+2B21 (white hexagon): (0xE2 0xAC 0xA1)
  • U+25C0 (left-point triangle): (0xE2 0x97 0x80)
  • U+25B6 (right-pointing triangle): (0xE2 0x96 0xb6)

More special characters might be added in future versions.

Formatting info

The datarefs

sim/cockpit2/radios/indicators/fms_cdu1_style_line0

to

sim/cockpit2/radios/indicators/fms_cdu1_style_line15

and

sim/cockpit2/radios/indicators/fms_cdu2_style_line0

to

sim/cockpit2/radios/indicators/fms_cdu2_style_line15

contain the formatting information for each character in the line as one byte (unsigned char) with the following special meaning:

  • The highest bit is set for a text displayed in large font. So use mask (1<<7) for the bit that tells you large vs small font.
  • The second highest bit is set for a text displayed in reverse video (colored background, black text). So use mask (1<<6) for the bit that tells you to invert the colors.
  • The third highest bit is set for a text displayed flashing (text being turned an and off periodically). So use mask (1<<5) for the bit that tells you to flash.
  • The fourth highest bit is set for a text with an underscore. So use mask (1<<4) for the bit that tells you to display an underscore under the character.
  • The remaining four bits encode the color of the text (or the background for reverse video): BLACK(0),CYAN(1),RED(2),YELLOW(3),GREEN(4),MAGENTA(5),AMBER(6),WHITE(7).
12 Comments