Thursday, August 07, 2008

Custom Datarefs for OBJ Animation

I don't usually blog about plugin issues, but this one falls into limbo, somewhere between plugins, aircraft design and OBJ animation. This is written for plugin developers; if you don't write plugins, you can tune out.

Plugin Drawing

Plugin drawing is documented in a few tech notes - I strongly recommend reading them all.

The basic idea is this: to draw in a plugin, you register a callback. X-Plane tells you "it's time to draw" and you draw.

The first rule of drawing callbacks is: you only draw. You don't do anything else.
The second rule of drawing callbacks is: you only draw. You don't do anything else.

There are a number of good reasons for this.
  1. You don't know how many times, or in what order the callbacks will be called! You might be called four times per frame or none. So doing flight model calculations in a draw callback is a bad idea.
  2. Drawing has to be fast. In the drawing code we are trying to stuff the GPU to the gills with work to do. Drawing time is not a good time to go off and do other expensive calculations.When we look at the interaction of the CPU and GPU, we know that the flight model takes some pure CPU time, and we can improve efficiency by queuing an expensive OpenGL operation before we hit that CPU-only phase. If your plugin is doing its real calculations during draw time, our pipelining gets thrown off.
  3. We're continually increasing the parallelism of the sim via threads to take advantage of multiple cores. But plugins are single threaded by definition. This means that plugin interaction points will (in the future sim) halt parallel operation and slow overall performance. When we design parallel operation, we can try to optimize our design to avoid this "halt" case, but if you are doing something strange (like flight calculations in a draw loop) you're more likely to fall off the "fast path".
Surprise

Now here's the surprising thing: your dataref callback is actually a drawing callback, sort of!

Object datarefs are called back during object drawing. Therefore they have all of the above problems that drawing callbacks have. Here is my recommendation:
If you create a custom dataref that is used by an OBJ for animation, return a cached value from a variable in the dataref, and update that variable from the flight loop.
This avoids the risk of your "systems modeling" code being called more than once per frame, etc.

1 comment:

IainG said...

Hey that's great to know Ben, gotta but some of my calculations out of the draw callback now