Tag: animation

What is the Difference between ANIM_hide and ATTR_draw_disable?

In order to understand the difference between hiding geometry and disabling drawing, you need to understand that an OBJ triangle can serve many purposes. Broadly, those purposes are:

  • Drawing (the most basic use).
  • Collision detection, of which we have three flavors: collision of the plane with the object (“hard surfaces”, or “physics”), collision of the mouse with the panel (manipulators, or clickable triangles) and collisions of the camera with the airplane (“solid camera”, which constrains the camera).

Any given triangle can be drawn and/or used to check for any of these collisions*; attributes change what the triangle is used for.

By default, all triangles are drawn; ATTR_draw_disable marks future triangles as not being drawn. This allows you to make a triangle that is used only for collisions. Examples might include a “hot spot” in front of a region on the panel (the hot spot might be easier to click than a small switch) and an invisible simple mesh to constrain the camera.

By comparison, ANIM_hide effectively removes some triangles from your model (temporarily) for all uses – drawing and collision detection of any kind. If a door is hidden, it’s not only not drawn, but it’s not going to stop the camera moving through it either.

Some key points to these distinctions:

  • Categorizing what a triangle is used for (drawing, various flavors of collisions) is static – that is, it is always the same for the object and never changes with datarefs or animation. This is intentional for performance reasons!
  • Animation to hide triangles affects the triangle in every way consistently – drawing and collisions.

Generally, you will get better performance improvements by removing categories from a triangle than by hiding it. (That is, it is better to not have manipulators on your cockpit, so it isn’t mouse-click collision-checked, than to hide it.) But the purpose of ATTR_draw_disable and ANIM_hide are different enough that which you use will be determined by the effect you are trying to create.

Finally, note that hiding an object completely (that is, the object does no drawing) does not provide the maximum performance benefit of not having an object at all. ANIM_hide was created to allow authors to create clever effects, not as a performance enhancer!

* This is not quite accurate: airplane-object collision checks are only available in scenery objects, and camera/airplane or mouse/panel collision checks are only available in the cockpit object.

Posted in Aircraft & Modeling, Cockpits, Development, File Formats, Modeling by | Comments Off on What is the Difference between ANIM_hide and ATTR_draw_disable?

Plugin-Based Prop Discs

I was discussing plugin-controlled prop discs with a third party developer. The developer wanted to know if custom prop disc control would end up inside Plane-Maker. It may end up doing so, but I don’t think this would be nearly as useful as it would seem. What follows is my explanation to him of why this is.

Let me draw an analogy: when it comes to systems modeling, using a plugin is to Plane-Maker as using Blender is to using Plane-Maker.

Users who cannot use Blender are frustrated because they cannot make something as nice as those who are building planes out of OBJs. Sometimes they ask for more features in Plane-Maker, like: more stations! This new editing mode! Make the UI better!

But…you tell me: will Plane-Maker’s UI ever be as flexible and powerful as Blender? And if it ever did get to be that good, would that have turned out to be a good use of LR’s time, when Blender is already available?

The motivation for OBJ-based airplane geometry via third party tools is that what users want to do cannot be easily generalized into a few simple cases. Every plane is different, so a truly flexible platform is needed.

The prop disc (and other systems modeling problems) are the same way. In developing the prop disc graphics, I spoke with a number of third party developers who had already tried to push prop discs as far as they could go, were using plugins, were drawing themselves, as well as 25 other crazy hacks. I also spoke to our internal art team. And what I found was: no one had any consensus on how the prop disc system should work. Everyone wanted to tune a very specific set of behaviors to their peculiar art assets.

That’s what drove me to put it into a plugin. When we need an equation or a strategy we reach the point where we need more flexibility than Plane-Maker can exhibit. A plugin can encapsulate a strategy or technique in a way that Plane-Maker radio buttons cannot.

Consider what would happen if custom prop disc parameters were built into Plane-Maker. Everyone would have to wait until Austin implemented the prop disc algorithm they wanted. How would this be bad? Let me count the ways?

  1. How many algorithms do you think Austin has time to code? Not more than he has fingers on his right hand. Only the five lucky third party developers who get their algorithm coded will be happy with this.
  2. Austin code exactly what you want? Don’t get your hopes up.
  3. , what you asked for wasn’t what you wanted? We can’t change the behavior now, that would break compatibility!
  4. oh…your email got eaten by a spam filter? Too bad…no custom prop disc for you!
  5. Sorry, we don’t have a release vehicle lined up for the next 3 months. You’ll have to wait.

This problem is already happening across pretty much every aspect of systems modeling: airplane have unique, quirky systems which are usually useful for exactly one plane. It is not even remotely sustainable for X-Plane to code these things one at a time with a set of check-boxes. We might as well have a pop-up menu for every airplane ever invented, and simulate every single airplane inside the sim itself. Imagine the development costs…if a single high quality MSFS add-on sells for $30-$50…

Think of the prop disc via plugins situation (and the strobe lights are the same way) as an experiment in generic instruments for systems. By transitioning to a generic abstaction for instruments we’ve let a lot more users do exactly what they want with a small, high performance piece of code. The original instrument strategy (one of everything) reached a point where we simply couldn’t meet user needs in a cost-effective manner.

Posted in Aircraft, Aircraft & Modeling, Development, Modeling by | 7 Comments

I Feel Manipulated

Tom has a new video on youtube of his just finished Falco. The video shows what screen-shots cannot: that the mouse interactions on the plane are really well crafted.

If you’re just discovering X-Plane (or just discovering that X-Plane’s 3-d cockpits can be very interactive), here’s X-Plane’s “raw” capabilities for manipulation:

  • The simplest manipulations are based on mapping the mouse from the 3-d cockpit back to the 2-d panel. This can only be done when the 3-d cockpit is textured using a piece of 2-d panel. This is the oldest way to make a clickable cockpit in X-Plane, dating back to the original X-Plane 3-d cockpits. The advantage of this method is that it’s very easy to set up; the disadvantage is that the mouse click gestures tend to be “flat” in their operation.
  • As Tom’s plane demonstrates, you can manipulate just about any dataref or command via a drag along a specific axis. Axes are subject to animation, so there’s a lot of potential for “grabbing” things with this interface.
  • X-Plane also supports direct “click” manipulation – this can be handy for buttons where you don’t want to require the user to move the mouse around. There are several types of click manipulation.

Click and drag manipulations can be tied into the plugin system – your plugin sees a manipulation as a change to a plugin-created dataref. This makes it possible to create almost any imaginable mouse effect. If you don’t want to write a plugin, you can still write up the manipulators to any of X-Plane’s datarefs (there are thousands) or commands (we’re getting up toward the 1000 mark on these too).

To create manipulators on your cockpit, you can use the latest plugin for AC3D. A manipulator is a property on a mesh within your object – each mesh can have its own manipulation with its own properties.

X-Plane does not have an IK solver. Rather, movement of “stuff” in your cockpit is indirect.

  1. Your manipulator changes a dataref as the user drags along an axis.
  2. The dataref change shows as an animation on your mesh.

Fortunately, ac3d has a “Guess” button for the axis manipulators. If you set a mesh to be manipulated by dragging along an axis, the guess button will examine your animations and suggest an axis that will create the most “natural” looking animation for the manipulation. For example, if you have a throttle handle that rotates, the guess button will provide a drag axis perpendicular to the throttle (to push the levers); if you have a throttle lever that pushes, the guess button will make a drag axis that runs along the lever.

Posted in Aircraft & Modeling, Cockpits, Development, Modeling, Tools by | 5 Comments

ATTR_light_level vs. Generic Instruments

Propsman caught something:

…is modifying the value of a batch of ATTR_light_level tris comparable [performance-wise] with toggling the state of a backlit generic instrument? Instinct tells me that you must have the latter more streamlined than the former, but maybe not?

He is right: in the current implementation, ATTR_light_level is probably a bit more expensive than using generic instruments. This may not be true in the future though.
  • The generic instrument code is pretty tight.
  • Right now ATTR_light_level sometimes has to adjust shaders, which can be expensive.
  • In the future, ATTR_light_level has the potential to be very heavily optimized, while the generic instrument code will always be CPU based.

But to put it in perspective, all instrument drawing is slow compared to scenery drawing – in the scenery world we draw 50,000 triangles of identical OpenGL state in a row, and modern cards do that very, very well.  In the panel, we have to put in a lot of CPU time to figure out how to draw each quad or tri-strip.  Fortunately you probably don’t have 50,000 individually programmed flashing lights in your panel.  Heck – there’s “only” 3608 datarefs published by the sim.

Perhaps other questions are important when picking ATTR_light_level vs. panel texture:
  • Which is more useful: to be able to have several variant images and variant images that are not “lights” (this is only possible by generics) or the ability to vary the light level gradually and not just have on or off (this is only possible with ATTR_light_level)?
  • Which is simpler to author given the rest of the panel?

In other words, it’s all pretty “slow”, but fortunately “slow” isn’t that slow.  If your light has to blink, you may want to pick what looks best and is straightforward to author.

Posted in Aircraft, Aircraft & Modeling, Cockpits, Development, Modeling by | 3 Comments

Datarefs Vs. Commands III: What Is My command Doing?

It turns out that understanding what a command is doing gets really complicated.
The key idea to untangling it all is this:
  • Commands have duration, and that duration is the amount of time you “hold down” the button or key that actuates the command.
  • Not all commands do things for the entire duration.
An example will clarify this:
  • When you press and hold down the ‘p’ key to pause the sim, the sim pauses (or unpauses) instantly the moment you press the p key.  Holding the p key down for a long time does not change this.  Pause is a “momentary” command.
  • You have to keep the starter button/key held down for a few seconds to start an engine. If you press it and release it, the starter motor will only run for a fraction of a second, which is not enough time to start an aircraft engine.  Engine start is a “duration” command.
Virtual Datarefs
A “virtual dataref” isn’t really a dataref at all – it’s a string you can enter into an OBJ or generic instrument that looks like a dataref, but actually is something else.  There is one “set” of virtual datarefs in X-Plane right now.
In X-Plane, you can enter

CMND=some/command/name

into a generic instrument or obj animation – this creates a “virtual dataref” around the command’s “activation status”.  The virtual dataref acts like a read-only integer-type dataref whose value is 0 if the command is not being pressed right now and 1 if it is.
For example, if you animate a push button using CMND=sim/starters/engage_starter_1 (key framing the animation to be “out” when the virtual dataref is 0 and 1 when it is in) then you will have a button that appears to be pressed whenever the starters are engaged.  This will happen no matter how the starter is engaged – your animation will happen whether the user presses a joystick button, holds down a key, clicks on a manipulator, or a plugin runs the command.
Basically, virtual datarefs that provide “activation status” of commands exist so that you can animate the buttons in your virtual cockpit to match what the user is doing with the mouse, keyboard, etc.  These datarefs are read-only; use trigger generic instruments and command manipulators to actually run the command.
For Programmers
In that last section I pointed out that a virtual dataref is not a real dataref at least 3 times. Why am I harping on this?  Well, programmers, you cannot use XPLMFindDataRef to access virtual datarefs yourself.  Sorry.
Virtual datarefs exist to give authors of OBJs and panels access to command activation status, something they would not normally have.
Plugin programmers don’t need this – if you are programming a plugin you simply use XPLMRegisterCommandHandler and you will be told when the command is being actuated and released.  Using a command handler is a lot more efficient than reading a dataref because you will receive a call only when the command is pressed, instead of having to check the dataref value every frame.  If you need to monitor a lot of commands, the callbacks are a lot more efficient.
Command Activation Is Not The Same As System Activation
Let’s go back to the case of the “pause” command and review.  Here’s what we know about the pause command.
  • The command sim/operation/pause_toggle will change the sim’s pause state.  The instant this command is pressed, the sim will pause (if it is runnning) or unpause (if it is paused).
  • Holding down the sim/operation/pause_toggle command has no effect beyond its initial press. Hold it down for an hour, it doesn’t matter.
  • The virtual dataref CMND=sim/operation/pause_toggle tells you if the pause command is being held down at any instant.
Here’s what we know about the pause dataref.
  • The dataref sim/time/paused is 1 if the sim is paused, 0 if it is not.
  • This dataref cannot be written!
So here’s what I mean when I say: command activation is not the same as system activation.
  • CMND=sim/operation/pause_toggle tells you if the pause button is being held down.
  • sim/time/paused tells you if the sim is actually paused or not.
  • They are simply not the same!
This becomes important when you start to model the buttons in airplanes.  Take for example an autopilot button for altitude hold.  In many planes, the button can be pushed in, and the moment you do, the altitude hold “arm” light will turn on.  Keep the button held in and it doesn’t have any more effect.  Altitude hold arm is a momentary command, but it has a system status indicator light.
I receive a number of questions about how to model this – and the answer is: take advantage of the fact that command activation (is the button pushed in) and system activation (is the light on) are not the same.
  • You would use a read-only dataref for the autopilot state to turn on the indicator light.  (There are two ways to do this: use ATTR_light_level to turn a _LIT texture on and off, or use panel texture and map a generic instrument like a rotary or an annunciator.)
  • You would use a command to make the button work.  Probably you’d use a command manipulator on the button mesh.
  • You would key frame the button’s animation based on the virtual dataref wrapped around the command you are using with the manipulator.
The result will be a button that lights up when the AP is armed but pushes in while it is being pressed (whether via the mouse in the 3-d cockpit or a joystick button press or a keyboard button press).
In my final post, I’ll comment on how much overlap there is between datarefs and commands.
Posted in Aircraft & Modeling, Development, Modeling by | Comments Off on Datarefs Vs. Commands III: What Is My command Doing?

DataRefs Vs. Commands I: What’s The Difference

What is the difference between a dataref and a command? They serve different purposes in X-Plane, but it’s easy to get them confused, especially because the names can look so similar. If you only take one thing away from this comparison, it should be:

  • Datarefs are information.
  • Commands are actions.

Datarefs

A dataref is a single bit of published information. For example, the user’s indicated airspeed, as seen by the pilot, is a dataref, stored in:

sim/cockpit2/gauges/indicators/airspeed_kts_pilot

Datarefs have names that do not change. Datarefs made available by X-Plane start with sim/ while datarefs made available by plugins start with another prefix. Datarefs have been in X-Plane since the release of the plugin system in version 6.70.

You can always read a dataref, but sometimes you can change it. Trying to change a dataref usually has one of three actions:

  • If the dataref is not writable at all, nothing happens.
  • If the dataref is writable, it will change.
  • Sometimes a dataref may be writable, but only after changing some other sim configuration. For example, you can only “write” to the control surface deflection datarefs after setting the control surface override dataref to 1. (If you don’t set this override, X-Plane will constantly write its own ideas of the control surface positions to the control surface datarefs and your changes will be lost.)

You can read and write datarefs:

Commands

A command is an action that the sim can take on your behalf. For example, the command

sim/autopilot/altitude_arm

arms the autopilot for altitude hold.

Like datarefs, commands have permanent names, starting with sim/ for X-Plane or other prefixes for plugins. Commands have been available in X-Plane since version 9.0.

You can always actuate a command, but there is no guarantee that it will do anything. For example, the engine starter command won’t start the engine if the plane has electrical starters and the battery is dead.

You can use commands by:

Plugins

Plugins can add both new datarefs and new commands to the sim. Plugins can also change the behavior of all built-in sim commands, and can change the information in some datarefs.

Where Do I Find Datarefs And Commands

X-Plane’s default commands and datarefs are listed in the text files Commands.txt and Datarefs.txt in the Resources/plugins folder. (Note: providing the command list is new to X-Plane 930.) The dataref list is also available on the X-Plane SDK Wiki.

Up next: when should I use a command and when should I use a dataref?
Posted in Aircraft & Modeling, Development, File Formats, Modeling, Panels, Scenery by | Comments Off on DataRefs Vs. Commands I: What’s The Difference

The “Airplane Modeling” Datarefs

I have blogged about this before, but I will try to create one simple explanation of what’s going on with sim/cockpit2 and sim/flightmodel2 datarefs.

Sandy and I (with the help of others who helped compile the list) created “new” datarefs (first released with X-Plane 9) , aimed at airplane modelers. These new sections are:

  1. sim/cockpit2/ which provides a new set of datarefs for cockpit modeling via OBJ animation and generic instruments.
  2. sim/flightmodel2/ which provides a new set of datarefs for airplane exterior modeling via OBJ animation.

These datarefs sometimes include new data that was not available in version 8, and sometimes they simply provide a second dataref with the same information. Why duplicate datarefs? The new datarefs have some special properties, so I wanted to have a complete set of datarefs for modelers with these new properties.

Skip to the end for the rules of thumb on how to use them.

Clean Naming

The new datarefs are designed to have longer, less confusing names; the old datarefs contained a lot of abbreviations – potentially acceptable for programmers (who are used to seeing things like fstat and chgrp on a regular basis) but not good for modelers who do not speek English as a first language. The new datarefs have long names and are more consistent in their conventions. They also contain complete documentation.

Array Sizes

You will see the array dimension of some of the new datarefs as symbolic constants, e.g. [engine] instead of [8]. This is because the dataref generation system we use knows that these new datarefs sometimes track the maximum number of parts in the aircraft structure. This tagging means that it is much simpler for Sandy and I to adjust the datarefs when Austin increases part maximums.

With the old datarefs, if Austin allows for 10 engines, Sandy and I must search for every [8] dataref and decide if it must be [10] – some will be per-engine and need to change, some will be per-battery and will not! With the new system, we simply redefine the “engine” constant to 10 and the datarefs adjust.

(Note that if your plugin really needs to run dynamically with any number of engines, the best thing to do is to read the array size using XPLMGetDatavX.)

Failure Support

There are two ways to view a dataref: before system failures (such that the dataref reflects simulated physical reality) and after system failures (such that the dataref reflects pilot indications). For example, when the pitot tube ices up, the pre-failure airspeed reflects how fast you are flying; the post-failure airspeed reflects how much crud is in your pitot tube.

Pre-failure datarefs are appropriate for animating the exterior of the airplane. For example, if the gear indicator light fails but the gear is working, you want to animate your landing gear based on the real (pre-failure) gear position, so that the gear really does look like it’s down from an outside view.

Post-failure datarefs are appropriate for animating the cockpit. For example, you want to use that post-failure indicated airspeed for your air speed indicator, so that pitot ice will affect your generic instruments and animations, as well as the built-in instruments.

The new datarefs are designed to clearly provide two different views:

  • sim/cockpit2/ are all post-failure whenever possible, and are thus appropriate for cockpit modeling.
  • sim/flightmodel2/ are all pre-failure, and thus are appropriate for external airplane modeling.

Be careful not to swap them! You should always be using sim/flightmodel2/ for your aircraft and sim/cockpit2/ for your cockpit. If the dataref you need is in one and not the other, email me and I will add it to the right place.

Correct Multiplayer Behavior

The older datarefs all return data about the user’s airplane. However if you build an object, attached to an ACF, and that ACF is loaded for a multiplayer plane, you will get incorrect results — the user will see his own plane’s actions visualized on the multiplayer plane.

The new sim/cockpit2/ and sim/flightmodel2/ datarefs handle this case correctly: they return data about whichever airplane is being drawn. Thus if your object is attached to airplane number 5 in a multiplayer session, that’s the airplane that will animate your control surfaces.

(Plugin developers – outside airplane drawing, these datarefs return information about the user’s flight.)

For this reason, you should always use sim/cockpit2/ and sim/flightmodel2/ – not the older sim/cockpit and sim/flightmodel/ datarefs. If the dataref you want is only in the old sections but not the new ones, email me!

What Dataref Do I Use?

Here’s the rule of thumb:

  • If you are targeting X-Plane 6/7/8, you must use sim/cockpit and sim/flightmodel, otherwise
  • If you are targeting X-Plane 9, use sim/cockpit2 for your generic instruments and 3-d cockpit. Use sim/flightmodel2 for your attached objects.

That’s all there is to it!

Posted in Aircraft, Aircraft & Modeling, Cockpits, Development, Modeling, Panels by | Comments Off on The “Airplane Modeling” Datarefs

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.

Posted in Aircraft & Modeling, Development by | 1 Comment