This is a tiny feature coming in X-Plane 10.50, but it will make a big difference for a few key plugin use cases: X-Plane will provide the current world model-view, projection, and aircraft model-view matrices to plugins via datarefs.
If you aren’t a plugin developer, or you don’t like matrices, or you don’t write your own OpenGL code, then the rest of this post is going to be boring, so go watch FrooglePete interviewing two funny looking guys. [Edit: link fixed – why that was pointing to airport flattening is totally beyond me!]
For the three of you still here: three matrices will be available:
- The OpenGL projection matrix – that’s the one that is currently set up when your 3-d draw callback is called.
- The OpenGL modelview matrix – we call it the “world” matrix, it maps the official X-Plane OpenGL coordinate system to eye coordinates, and it is also set up when your plugin is called.
- The Aircraft modelview matrix – this is a matrix that maps aircraft coordinates (0,0,0 = CG, +X = right wing, -Z = nose) to eye coordinates.
You already are using two of these, the third is new. So who would even care? There are two use cases for this.
Stop Calling glGetFloatv!
Calling glGetXXX is bad. Modern Windows GL drivers send GL commands to a worker thread for execution, freeing up the rendering thread to keep going, improving framerate. But every time you ask OpenGL a question, our thread has to wait for that driver thread to catch up, slowing everybody down. The rule is simple: don’t call glGetXXXX.*
But there’s one case where your plugin might really need glGet: to get the current matrices for culling 3-d drawing.
This is where the datarefs come in – by reading our datarefs instead of calling glGetFloat, you can get the transform matrices without stalling the driver.
(If you have other glGetXXX that you can’t get rid of, ping me and I’ll try to find a work-around.)
Drawing On the Aircraft Without Jitter
The third matrix (the aircraft model-view matrix) is the matrix you would get if you translated to the aircraft’s location and then rotated around its orientation.
Here’s the key difference: when we do that calculation, we do the calculation in double-precision. We do this because the OpenGL origin can be tens of thousands of meters away from the aircraft, which in turn can be very, very close to the camera. In that situation, precision loss from single-precision floating point when multiplying together two very large matrices (that result in a very small matrix) results in apparent jitter when drawing.
The problem is: even if you wanted to do this calculation yourself in double precision, you can’t – the world matrix isn’t available to plugins in double precision.
So starting in X-Plane 10.50, the aircraft matrix is simply provided.
I did an experiment where I attached a green cube to an aircraft and then drew a blue cube at the same location from a plugin. With glTranslate/glRotate there was a ton of Z artifacts and slop that changed per frame because the two cubes were in slightly different positions. With the aircraft matrix, the green cube was invisible (except when disabling the plugin) because the blue cube overdrew it pixel-perfectly.
- What about glGetError? Call this only in debug mode (to catch mistakes in your GL code); use #if to make sure you’re not calling glGetError in release mode.
publishing the datarefs now will be a great, so we can implement it already
Nice with the new datarefs.
But… isn’t it time Laminar provides better info for plugin developers? I have a hard time finding good information: wiki has dead links, out of date examples, or missing examples.
IMHO it is important to provide good info on writing plugins — advanced aircraft need plugins, so it seems to me in everyone’s interest to provide it.
Maybe – the plugin system was never (and is actually still not) a Laminar Research thing – LR has contributed some hosting resources over time. I do agree the docs could be improved – the real problem is that the website is base on MediaWiki, which is both a PITA to use and a PITA to replace.
OK, thanks, I thought it was a Laminar thing actually. Maybe it should be 🙂
I enjoy these posts and please keep showing us what is under the kimono. Explanations like this help me to understand that Laminar Research is continuing to find ways to improve the program and not necessarily only adding on new features without improving the underlying system.
I am looking forward to the 10.50 (TEN DECIMAL FIFTY) beta series.
Just a gentle reminder to EVERYONE that if anyone starts that ridiculous discussion about version numbers again, I _will_ go on a comemnt-deleting spree!
Sounds like I can make use of this for my sling load plugin. Currently, I have a hard time calculating the point where the hook will connect the load sitting on the ground as precise as I would like.
Keep it coming!
It may not be that useful for that – the datarefs are only valid during DRAWING. But the aircraft’s local_x/y/z datarefs -are- already available in double precision. (This matrix is only necessary because the world matrix isn’t available in double precision.)
Will we be able to write to the projection matrix or just read it?
Just read it. All three matrices are read-only. If you were to write to them, other internal data structures would not be changed and the engine would end up out of sync. Furthermore, the datarefs can only be sanely read during a 3-d drawing callback, because they provide data for -that- drawing pass.
(So for example, if you opt into reflections or shadows in your plugin, during a drawing callback for shadows or reflections you’ll have a totally different world matrix set that reflects that pre-pass.)