1056 lines
39 KiB
HTML
1056 lines
39 KiB
HTML
|
|
<!-- Standard Header Begin -->
|
|
<html>
|
|
|
|
<head>
|
|
<title>FlightGear Flight Simulator</title>
|
|
<link rel="stylesheet" type="text/css" href="../default.css">
|
|
</head>
|
|
|
|
<body>
|
|
<div id="top">
|
|
<a href="../"><img id="titlebar" src="../images/fglogosm.jpg" alt=""></a>
|
|
</div>
|
|
|
|
<table id="global">
|
|
<tbody><tr>
|
|
<td id="menu">
|
|
<!-- Use a replacescript to update the menu -->
|
|
<h3>About</h3>
|
|
<a href="..">Home</a><br>
|
|
</td>
|
|
<td id="page">
|
|
<!-- Standard Header End -->
|
|
<h1>Mini-HOWTO: 3D Aircraft Models in FlightGear</h1>
|
|
|
|
<h2>11 March 2002</h2>
|
|
<h2>David Megginson</h2>
|
|
<br>
|
|
|
|
<div>
|
|
<h3>Introduction</h3>
|
|
|
|
<br>This mini-HOWTO explains how to add 3D aircraft models to
|
|
FlightGear, and how to animate and position those models. No C++
|
|
programming is required, but the user will need some knowledge of
|
|
FlightGear's property system and XML markup, and will need to
|
|
understand the coordinate system FlightGear uses for its models:<br>
|
|
|
|
<ul>
|
|
<li>distances are in meters</li>
|
|
<li>angles are in degrees</li>
|
|
<li>the x-axis runs lengthwise, towards the back</li>
|
|
<li>the y-axis runs sideways, towards the right</li>
|
|
<li>the z-axis runs upwards</li>
|
|
<li>heading is a rotation around the z-axis, where positive is
|
|
clockwise viewed from above</li>
|
|
<li>pitch is a rotation around the y-axis, where positive is clockwise
|
|
viewed from the left</li>
|
|
<li>roll is a rotation around the x-axis, where positive is clockwise
|
|
viewed from behind</li>
|
|
</ul>
|
|
|
|
<p>[[TODO: will someone volunteer to draw diagrams?]]</p>
|
|
|
|
<p>This mini-HOWTO contains three parts:</p>
|
|
|
|
<ol>
|
|
<li><a href="#loading">Loading the model</a></li>
|
|
<li><a href="#repositioning">Repositioning the model</a></li>
|
|
<li><a href="#animating">Animating the model</a></li>
|
|
</ol>
|
|
|
|
<!-- end of "Summary" -->
|
|
</div>
|
|
|
|
|
|
<div><a name="loading"></a>
|
|
<h3>1. Loading the model</h3>
|
|
|
|
<p>Through <a href="http://plib.sourceforge.net/">plib</a>, FlightGear
|
|
supports many different 3D file formats, including VRML1, AC3D, DXF,
|
|
MDL (from <cite>Microsoft Flight Simulator</cite>), and many others.
|
|
The property <var>/sim/model/path</var> in the main FlightGear
|
|
property tree controls what model will be loaded; it takes
|
|
a string value giving the relative path of the model from
|
|
<var>FG_ROOT</var> (the root of the base package, such as
|
|
<code>/usr/local/lib/FlightGear</code> or
|
|
<code>C:\FLIGHTGEAR\</code>).</p>
|
|
|
|
<p>The easiest way to load a new model is to set the property at
|
|
startup with the <var>--prop:</var> command-line option; for example,
|
|
to use a 3D aircraft model that you have installed in
|
|
<code>$FG_ROOT/Models/my-cessna.wrl</code>, you could invoke
|
|
FlightGear like this (under Unix-like systems):</p>
|
|
|
|
<blockquote><pre>fgfs --prop:/sim/model/path=Models/my-cessna.wrl
|
|
</pre></blockquote>
|
|
|
|
<p>(<strong>Note:</strong> Normaly any textures used by the model must appear
|
|
in the same directory. If <code>my-cessna.wrl</code> uses the
|
|
textures <code>cessna01.rgb</code> and <code>cessna02.rgb</code>, you
|
|
should install those textures in <code>$FG_ROOT/Models/</code>.
|
|
It is howerever possible to specify a path (relative to the model path)
|
|
to specify where the textures could be found.)</p>
|
|
|
|
<p>When you want to set a 3D model permanently as the default for an
|
|
aircraft rather than specifying it on the command line, you need to
|
|
edit an aircraft settings file. In the
|
|
<code>$FG_ROOT/Aircraft/</code> directory there is a series of files
|
|
ending in <code>-set.xml</code>, such as <code>c172-set.xml</code>,
|
|
<code>dc3-yasim-set.xml</code>, and <code>beech99-uiuc-set.xml</code>.
|
|
When you start FlightGear with the <var>--aircraft</var> option, it
|
|
reads the properties from one of these files; for example</p>
|
|
|
|
<blockquote><pre>fgfs --aircraft=dc3-yasim
|
|
</pre></blockquote>
|
|
|
|
<p>Loads the properties from
|
|
<code>$FG_ROOT/Aircraft/dc3-yasim-set.xml</code> into the main
|
|
FlightGear property tree. These files are in the same XML
|
|
property-list format as <code>$FG_ROOT/preferences.xml</code> and the
|
|
FlightGear save files. There may be many XML files with different
|
|
startup conditions, sounds, panels, 3D models, etc. for any single
|
|
aircraft type, so you are best off copying an existing one, renaming
|
|
it, then changing the value inside the <var>path</var> element inside
|
|
<var>model</var> inside <var>sim</var>:</p>
|
|
|
|
<blockquote><pre><PropertyList>
|
|
<sim>
|
|
<model>
|
|
<path>Models/my-cessna.wrl</path>
|
|
<texture-path>./Textures</texture-path>
|
|
</model>
|
|
</sim>
|
|
</PropertyList>
|
|
</pre></blockquote>
|
|
|
|
<p>So far, all of the examples have had the <var>/sim/model/path</var>
|
|
property point directly at the 3D model file
|
|
(<code>Models/my-cessna.wrl</code>); however, if you want to be able
|
|
to reposition or animate the model, you need to point to an
|
|
intermediate XML file instead, and then put the repositioning and
|
|
animation information into the XML file. Here's a simple example of a
|
|
3D-model wrapper file, with no repositioning or animation
|
|
information:</p>
|
|
|
|
<blockquote><pre><PropertyList>
|
|
<path>my-cessna.wrl</path>
|
|
<texture-path>./Textures</texture-path>
|
|
</PropertyList>
|
|
</pre></blockquote>
|
|
|
|
<p>Like the <var>-set.xml</var> files, this file is in XML property
|
|
list format, but the properties in it are not added to the main
|
|
FlightGear property tree; they're used only while loading the
|
|
model. The following sections will explain how to add repositioning
|
|
and animation information to the file; for now, the only property to
|
|
worry about is <var>path</var>: it provides the relative path to the
|
|
actual 3D file from the XML wrapper file (<strong>not</strong> from
|
|
<var>FG_ROOT</var>!). Usually, you should put the wrapper file in the
|
|
same directory as the 3D file, and then have
|
|
<var>/sim/model/path</var> point to the wrapper file, either on the
|
|
command line</p>
|
|
|
|
<blockquote><pre>fgfs --prop:/sim/model/path=Models/my-cessna.xml
|
|
</pre></blockquote>
|
|
|
|
<p>or in the <code>-set.xml</code> file:</p>
|
|
|
|
<blockquote><pre><PropertyList>
|
|
<sim>
|
|
<model>
|
|
<path>Models/my-cessna.xml</path>
|
|
</model>
|
|
</sim>
|
|
</PropertyList>
|
|
</pre></blockquote>
|
|
|
|
<!-- end of "Loading the model" -->
|
|
</div>
|
|
|
|
|
|
<div><a name="repositioning"></a>
|
|
<h3>2. Repositioning the Model</h3>
|
|
|
|
<p>Often, an aircraft model not designed specifically for FlightGear
|
|
will not be positioned or oriented correctly; for example, it might be
|
|
too far off the ground, and the nose might point to the side or even
|
|
straight up.</p>
|
|
|
|
<p>Inside the XML wrapper file (<em>not</em> the main FlightGear
|
|
property tree), there are six properties that allow you to tweak the
|
|
default position and orientation of the model:</p>
|
|
|
|
<dl compact="compact"><dt><strong>/offsets/x-m</strong></dt><dd>The distance to reposition the model along the x-axis.</dd><dt><strong>/offsets/y-m</strong></dt><dd>The distance to reposition the model along the y-axis.</dd><dt><strong>/offsets/z-m</strong></dt><dd>The distance to reposition the model along the z-axis.</dd><dt><strong>/offsets/heading-deg</strong></dt><dd>The angle by which to rotate the model around the z-axis.</dd><dt><strong>/offsets/roll-deg</strong></dt><dd>The angle by which to rotate the model around the x-axis.</dd><dt><strong>/offsets/pitch-deg</strong></dt><dd>The angle by which to rotate the model around the y-axis.</dd></dl>
|
|
|
|
<p>For example, if you wanted to use the 3D model
|
|
<code>my-cessna.wrl</code> but found that the nose was pointing to the
|
|
right instead of straight-ahead and the wheels were 1.5 meters off the
|
|
ground, you could reorient it in the XML wrapper file like this:</p>
|
|
|
|
<blockquote><pre><PropertyList>
|
|
<sim>
|
|
<model>
|
|
<path>Models/my-cessna.xml</path>
|
|
</model>
|
|
</sim>
|
|
<offsets>
|
|
<heading-offset-deg>270</heading-offset-deg>
|
|
<z-offset-m>-1.5</z-offset-m>
|
|
</offsets>
|
|
</PropertyList>
|
|
</pre></blockquote>
|
|
|
|
<p>It usually takes a bit of experimentation to get the model
|
|
positioned correctly.</p>
|
|
|
|
<!-- end of "Repositioning the Model" -->
|
|
</div>
|
|
|
|
|
|
<div><a name="animating"></a>
|
|
<h3>3. Animating the Model</h3>
|
|
|
|
<p>Now for the interesting part. FlightGear allows you to animate
|
|
models by having parts rotate or spin in response to property changes:
|
|
for example, the propellers can spin when the engine is on and the
|
|
elevators can move up and down with your controller. There is no
|
|
fixed limit on what parts can be animated: the only requirements are
|
|
that the part is named in the 3D model file, and that there is a
|
|
property in the main tree that you can use to get the positioning
|
|
information.</p>
|
|
|
|
<p>Currently, there are several types of animation recognized:</p>
|
|
|
|
<ol>
|
|
<li>none</li>
|
|
<li>billboard</li>
|
|
<li>rotate</li>
|
|
<li><a href="#scale">scale</a></li>
|
|
<li><a href="#blend">blend</a></li>
|
|
<li>select</li>
|
|
<li>spin</li>
|
|
<li>timed</li>
|
|
<li>translate</li>
|
|
<li><a href="#texrotate">texrotate</a></li>
|
|
<li><a href="#textranslate">textranslate</a></li>
|
|
<li><a href="#textmultiple">textmultiple</a></li>
|
|
<li><a href="#material">material</a></li>
|
|
<li><a href="#range">range</a></li>
|
|
<li><a href="#alphatest">alpha-test</a></li>
|
|
</ol>
|
|
|
|
<p>Typically you will use combinations of rotate, spin, and translate
|
|
to animate the main control surfaces for most standard-configuration
|
|
aircraft. <var>none</var> is a no-op; <var>spin</var> rotates the
|
|
object around an axis with a known rotational velocity (not worrying
|
|
about the exact position), and <var>rotate</var> rotates the object
|
|
around an axis to an exact position.</p>
|
|
|
|
<p>Every animation appears inside an <var>animation</var> element, and
|
|
contains a <var>type</var> property and at least one
|
|
<var>object-name</var> property:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>Rudder</object-name>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>The object name must match exactly the object name used in the 3D
|
|
file (including case). You may include more than one object name to
|
|
apply the same transformation to more than one object, assuming that
|
|
they rotate around exactly the same line:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>LeftElevator</object-name>
|
|
<object-name>RightElevator</object-name>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>Each animation must be associated with exactly one property from
|
|
the main FlightGear property tree (remember that the properties in the
|
|
wrapper file are not part of the main tree), using <var>property</var>
|
|
to provide the property name:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>Rudder</object-name>
|
|
<property>/controls/rudder</property>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>This example rotates the rudder according to the value of the
|
|
<var>/controls/rudder</var> property (or at least, it will when we
|
|
specify the center and axis of rotation below); however,
|
|
<var>/controls/rudder</var> is normalized from -1.0 to 1.0, and we
|
|
probably want to rotate the rudder more than that; as a result, we
|
|
need to use the <var>factor</var> property to do scaling. For
|
|
example, if the rudder on the actual aircraft rotates 18 degrees in
|
|
each direction, we would use a factor of 18 to scale the rudder
|
|
position from -18 degrees to 18 degrees:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>Rudder</object-name>
|
|
<property>/controls/rudder</property>
|
|
<factor>18</factor>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>If you wanted to reverse the direction of rudder movement, you
|
|
would use a factor of -18.</p>
|
|
|
|
<p>There is also an <var>offset</var> property that can be useful for
|
|
starting the rotation from a point other than center. For example,
|
|
let's say that you want the rudder to start 1% to the left rather than
|
|
dead center; you could specify that like this:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>Rudder</object-name>
|
|
<property>/controls/rudder</property>
|
|
<offset>-0.01</offset>
|
|
<factor>18</factor>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>The offset is applied <em>before</em> the factor.</p>
|
|
|
|
<p>Finally, there are <var>min</var> and <var>max</var> properties
|
|
that can constrain the amount of rotation in degrees, as in this (very
|
|
complicated) example for the Cessna 310 landing gear:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>NoseWheel</object-name>
|
|
<property>/gear/gear[0]/position-norm</property>
|
|
<factor>120</factor>
|
|
<offset>-1</offset>
|
|
<min>-90</min>
|
|
<max>0</max>
|
|
<center>
|
|
<x-m>-2.28</x-m>
|
|
<y-m>0.0</y-m>
|
|
<z-m>-0.65</z-m>
|
|
</center>
|
|
<axis>
|
|
<x>0</x>
|
|
<y>1</y>
|
|
<z>0</z>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>In this example, the gear position (from 0.0 for fully retracted to
|
|
1.0 for fully extended) is multiplied by a factor of 120 and an offset
|
|
of -1, then clamped to between -90 and 0. In the 3D model, the gear
|
|
is extended by default, so we end up with the following rotations
|
|
through the gear's range of movement:</p>
|
|
|
|
<table border="1">
|
|
|
|
<tbody><tr>
|
|
<th>position-norm</th>
|
|
<th>+ offset -1</th>
|
|
<th>* factor 120</th>
|
|
<th>clamped to min/max -90:0</th>
|
|
<th>comments</th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>0.0</td>
|
|
<td>-1.0</td>
|
|
<td>-120.0</td>
|
|
<td>-90.0</td>
|
|
<td>fully retracted</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>0.25</td>
|
|
<td>-0.75</td>
|
|
<td>-90.0</td>
|
|
<td>-90.0</td>
|
|
<td>still retracted</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>0.5</td>
|
|
<td>-0.5</td>
|
|
<td>-60.0</td>
|
|
<td>-50.0</td>
|
|
<td>1/3 extended</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>0.75</td>
|
|
<td>-0.25</td>
|
|
<td>-30.0</td>
|
|
<td>-30.0</td>
|
|
<td>2/3 extended</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>1.0</td>
|
|
<td>0.0</td>
|
|
<td>0.0</td>
|
|
<td>0.0</td>
|
|
<td>fully extended (default position)</td>
|
|
</tr>
|
|
|
|
</tbody></table>
|
|
|
|
<p>The gear does not move at all during the first 1/4 of the
|
|
position-norm value, giving the doors a chance to open and close in a
|
|
separate animation. Obviously, this would be easier to manage with an
|
|
interpolation table, and future versions of the model animation will
|
|
likely support interpolation.</p>
|
|
|
|
<p>Update: Interpolation tables our now supported. Each table entry
|
|
plots a dependency point and output values
|
|
are interpolated in a linear manner between two points. In the following
|
|
example an input property value of
|
|
25 will result in an application of a value 65 to the animation
|
|
(65 degrees rotation maybe):</p>
|
|
|
|
<blockquote><pre> <interpolation>
|
|
<entry>
|
|
<ind>0</ind>
|
|
<dep>0</dep>
|
|
</entry>
|
|
<entry>
|
|
<ind>16.67</ind>
|
|
<dep>60</dep>
|
|
</entry>
|
|
<entry>
|
|
<ind>25</ind>
|
|
<dep>65</dep>
|
|
</entry>
|
|
<entry>
|
|
<ind>33.3333</ind>
|
|
<dep>70</dep>
|
|
</entry>
|
|
<entry>
|
|
<ind>66.6667</ind>
|
|
<dep>71</dep>
|
|
</entry>
|
|
<entry>
|
|
<ind>100</ind>
|
|
<dep>75</dep>
|
|
</entry>
|
|
</interpolation>
|
|
</pre></blockquote>
|
|
|
|
<p>For a <var>spin</var> animation, the property provides a value in
|
|
revolutions per minute (RPM) rather than an absolute position in
|
|
degrees, and offset is not used. You can still use <var>factor</var>
|
|
to scale the property value if it is not in RPM.</p>
|
|
|
|
<p>Now, it is necessary to specify the axis of rotation for the
|
|
object, its virtual hinge. This is often the hardest part, requiring
|
|
a lot of trial-and-error when the axis of rotation is not lined up
|
|
with the x-, y-, or z- axis (think of ailerons on a swept wing with a
|
|
non-zero dihedral angle). You need to provide two groups of
|
|
information: a point through which the axis of rotation passes, and
|
|
the direction in which the axis is moving.</p>
|
|
|
|
<p>Update: there is now an alternate method for specifying axes
|
|
that avoids the trial-and-error approach. See below after the Cessna
|
|
172 animation examples.<p>
|
|
<p>For the point through which the axis passes, you use the
|
|
<var>/center/x-m</var>, <var>/center/y-m</var>, and
|
|
<var>/center/z-m</var> properties to specify a position in meters,
|
|
using the aircraft's coordinate system. Note that this is the system
|
|
before repositioning: if the original model was pointing sideways,
|
|
then your fuselage will run along the y-axis rather than the
|
|
x-axis. Here is an example for a rudder:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>Rudder</object-name>
|
|
<property>/controls/rudder</property>
|
|
<factor>18</factor>
|
|
<center>
|
|
<x-m>5.45</x-m>
|
|
<y-m>0.0</y-m>
|
|
<z-m>0.0</z-m>
|
|
</center>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>In this example, the point is right on the y and z axes, but 5.45
|
|
meters along the x axis (i.e. towards the back of the plane).</p>
|
|
|
|
<p>Finally, in addition to the center point, it's necessary to specify
|
|
the direction of the axis that passes through it, using the properties
|
|
<var>/axis/x</var>, <var>/axis/y</var>, and <var>axis/z</var>. These
|
|
are unitless values showing the rate of change in each direction; for
|
|
example, a straight up-and-down rotational axis could be specified
|
|
like this:</p>
|
|
|
|
<blockquote><pre><axis>
|
|
<x>0</x>
|
|
<y>0</y>
|
|
<z>1</z>
|
|
</axis>
|
|
</pre></blockquote>
|
|
|
|
<p>or like this:</p>
|
|
|
|
<blockquote><pre><axis>
|
|
<x>0</x>
|
|
<y>0</y>
|
|
<z>1000000</z>
|
|
</axis>
|
|
</pre></blockquote>
|
|
|
|
<p>Since there's 0 movement along the other two axes, it doesn't
|
|
matter. On the other hand, let's say that the rudder hinge sloped
|
|
back 5% because of a swept tail. In that case, the x-axis would have
|
|
to show some movement as well:</p>
|
|
|
|
<blockquote><pre><axis>
|
|
<x>0.05</x>
|
|
<y>0</y>
|
|
<z>1</z>
|
|
</axis>
|
|
</pre></blockquote>
|
|
|
|
<p>That could just as easily be written as</p>
|
|
|
|
<blockquote><pre><axis>
|
|
<x>1</x>
|
|
<y>0</y>
|
|
<z>20</z>
|
|
</axis>
|
|
</pre></blockquote>
|
|
|
|
<p>as long as the ratios are the same. For a complicated rotation
|
|
axis, like that for an aileron on a swept-back wing with a significant
|
|
dihedral angle, you'll have to specify movement along all three
|
|
axes:</p>
|
|
|
|
<blockquote><pre><axis>
|
|
<x>0.15</x>
|
|
<y>1.00</y>
|
|
<z>0.01</z>
|
|
</axis>
|
|
</pre></blockquote>
|
|
|
|
<p>Here's a complete example, showing the animation for the rudder on
|
|
the Cessna 172:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>Rudder</object-name>
|
|
<property>/controls/rudder</property>
|
|
<factor>18</factor>
|
|
<center>
|
|
<x-m>5.45</x-m>
|
|
<y-m>0.0</y-m>
|
|
<z-m>0.0</z-m>
|
|
</center>
|
|
<axis>
|
|
<x>0.72</x>
|
|
<y>0.0</y>
|
|
<z>1.0</z>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>And here's an example of a spin, using the Cessna 172
|
|
propeller:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>spin</type>
|
|
<object-name>Propeller</object-name>
|
|
<property>/engines/engine[0]/rpm</property>
|
|
<center>
|
|
<x-m>0</x-m>
|
|
<y-m>0</y-m>
|
|
<z-m>-.25</z-m>
|
|
</center>
|
|
<axis>
|
|
<x>1.0</x>
|
|
<y>0.0</y>
|
|
<z>0.0</z>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>There is an alternate method of specifying the axis that can often be find much easier.
|
|
This method is particularly
|
|
helpful for rotating on axes that are at odd angles, such as ailerons on dihedral swept
|
|
wings.</p>
|
|
|
|
<p>It is not necessary to specify a <center> tag for this method as it will be calculated
|
|
automatically. The <axis> tag requres two sets of coordinates (x1-m,y1-m,z1-m and
|
|
x2-m,y2-m,z2-m), one for each end of the axis.
|
|
With an aileron, for example, you would need to specify coordinates from both the right and left
|
|
corner of the aileron along the hinged edge. If your object rotates in the direction opposite
|
|
of what you intended you may correct it by simply swapping the two sets of coordinate values (swap x1
|
|
and x2, y1 and y2, z1 and z2).</p>
|
|
|
|
<p>Here is an example from the 747-400:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>rotate</type>
|
|
<object-name>AileronLeftOuter</object-name>
|
|
<property>/surface-positions/left-aileron-pos-norm</property>
|
|
<factor>-30</factor>
|
|
<axis>
|
|
<x1-m>18.28</x1-m>
|
|
<y1-m>-21.55</y1-m>
|
|
<z1-m>-0.37</z1-m>
|
|
<x2-m>22.51</x2-m>
|
|
<y2-m>-28.37</y2-m>
|
|
<z2-m>0.08</z2-m>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>You can get a lot of your initial measurements by viewing the model
|
|
in a 3D editor like <a href="http://prettypoly.sourceforge.net/">PPE</a>, and you can also
|
|
use PPE to name or rename objects so that you can animate them in
|
|
FlightGear. In the end, though, you'll almost have to do a little
|
|
tweaking by trial and error until everything looks right.</p>
|
|
|
|
<p>This document will likely be out of date by the time you read it.
|
|
Look at the actual XML wrapper files (currently in
|
|
<code>$FG_ROOT/Aircraft/<em>aircraft-type</em>/Models/</code>) to look
|
|
at how FlightGear is doing things now. In the future, we'll be adding
|
|
other animation types, including selecting among different versions of
|
|
the same object (such as a translucent propeller disk for high RPM),
|
|
non-rotational transformations, scaling, and conditionals (i.e. draw
|
|
engine exhaust only above a certain velocity).</p>
|
|
|
|
<h3><a name="scale">"scale" animation type</a></h3>
|
|
|
|
<p>Here is a contrived example of one way to use the "scale" animation
|
|
type. In this case a shadow map is placed below the aircraft and we
|
|
can control the size based on some property value (i.e. alitutude
|
|
above the ground.) In real life, the shadow size should stay pretty
|
|
much fixed, so this technique might ultimately be more useful for a
|
|
landing light.</p>
|
|
|
|
<blockquote><pre> <animation>
|
|
<type>scale</type>
|
|
<object-name>ShadowMap</object-name>
|
|
<property>/position/altitude-agl-ft</property>
|
|
<x-factor>0.05</x-factor>
|
|
<x-offset>1.0</x-offset>
|
|
<y-factor>0.05</y-factor>
|
|
<y-offset>1.0</y-offset>
|
|
<z-factor>0.0</z-factor>
|
|
<z-offset>1.0</z-offset>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>As with the other animations, you need to specify an object-name and
|
|
the property that will drive this animation. And, as with other types
|
|
of transform animations, the order they are applied is important. For
|
|
a given object, you will probably want to put the scaling animation
|
|
after any other translate or rotate animations.</p>
|
|
|
|
<p>You have some individual control over the X, Y, and Z axis scaling.
|
|
For each dimension you can provide factors (x-factor, y-factor, and
|
|
z-factor) and also offsets (x-offset, y-offset, and z-offset.) You
|
|
can also specify minimum values (x-min, y-min, z-min) and maximum
|
|
values (x-max, y-max, and z-max) for scaling results.</p>
|
|
|
|
<p>The amount of scaling for each dimension is computed by the
|
|
following formula (and then clamped if a min or max value is
|
|
specified.)</p>
|
|
|
|
<blockquote><pre> scale = offset + property * factor
|
|
</pre></blockquote>
|
|
|
|
<p>Specifying an offset of 1.0 and a factor of 0.0 is equivalent to no
|
|
scaling at all.</p>
|
|
|
|
<p>As you can see in the above example, at ground level (the property
|
|
value = 0.0) the scaling formula will evaluate to 1.0 (no scaling.)
|
|
As altitude above the ground increases, the scaling factor will
|
|
increase by 1.0 + agl * 0.05. Note that because a shadow has no depth
|
|
we use a z-factor of 0.0 and a z-offset of 1.0 so the formula always
|
|
evalutes to a scaling factor of 1.0 in the Z dimension.</p>
|
|
|
|
<p>There is still a plib issue to be aware of when using scale
|
|
animation. When rendering an object, the plib bounding sphere culling
|
|
system isn't aware of the scale transformation so it will do the cull
|
|
based on the object's original size. If you have made the object
|
|
bigger, it will disappear if the space occupied by the original size
|
|
of the object goes out of the view frustum. If you make the object
|
|
smaller then this won't be a problem because the larger original
|
|
object will always contain it's currently smaller version. So one
|
|
work around would be to build the object at it's maximum size and then
|
|
use the scaling transform to always make it smaller.</p>
|
|
|
|
<h3><a name="blend">"blend" animation type</a></h3>
|
|
|
|
<p>The blend animation type can be used to adjust the transparency of
|
|
an object. To controll it's behavior it is possible to define:</p><p>
|
|
|
|
<table>
|
|
<tbody><tr>
|
|
<td><b>property</b></td>
|
|
<td><i>use the value of this property in the calculation</i></td>
|
|
</tr>
|
|
<tr>
|
|
<td><b>offset</b></td>
|
|
<td><i>offset, ranges from 0.0 to 1.0</i></td>
|
|
</tr>
|
|
<tr>
|
|
<td><b>factor</b></td>
|
|
<td><i>multiplication factor for the property</i></td>
|
|
</tr>
|
|
</tbody></table>
|
|
|
|
</p><p>The formula used is:
|
|
</p><blockquote><pre>alpha = property * factor + offset
|
|
</pre></blockquote>
|
|
|
|
<p>The result should be between 0.0 and 1.0 where 0.0 equals to a fully visible model and 1.0 equals to a fully transparent model.</p>
|
|
|
|
<p>To gain greater controll over the result it is possible to limit
|
|
the result by defining a <min> and/or a <max> parameter.
|
|
</p>
|
|
|
|
<p><strong>Note:</strong> This effect will only work if there is already a transparent component in the object, either in the vertex color or in the texture.
|
|
<!-- end of "Animating the Model" -->
|
|
|
|
|
|
<h3><a name="texrotate">"texrotate" texture rotation animation type</a></h3>
|
|
|
|
<p>This animation will adjust the texture mapping on an object
|
|
so that the texture image appears to rotate about
|
|
the specified center on the object. Note that when talking
|
|
about texture mapping, meaningful values are from
|
|
0.0 ~ 1.0. Texture coordinates are commonly specified as (u,v).
|
|
A square object's lower left corner would generally be
|
|
specified as (u=0,v=0) and the upper right corner as (u=1,v=1). The
|
|
center will be (u=0.5, v=0.5). These values
|
|
will be vary (within the 0.0 ~ 1.0 range) if only a portion of a texture is
|
|
mapped (see compass rose example below).</p>
|
|
|
|
<p>For the purpose of specifying the <center> tag
|
|
you need only use the x and y coordinates.
|
|
The <axis> tag usually only requires a value for z. It is possible to
|
|
obtain some unusual texture mapping effects, like as giving the illusion of
|
|
perspective on a flat stationary surface by using the other axes. Here is
|
|
an example of a rotating compass rose on the 747-400 PDF
|
|
(primary flight display):<p>
|
|
|
|
<blockquote><pre> <animation>
|
|
<type>texrotate</type>
|
|
<object-name>rose</object-name>
|
|
<property>/orientation/heading-magnetic-deg</property>
|
|
<center>
|
|
<x>0.75</x>
|
|
<y>0.75</y>
|
|
<z>0.0</z>
|
|
</center>
|
|
<axis>
|
|
<x>0</x>
|
|
<y>0</y>
|
|
<z>-1</z>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>The center in this example is (0.75, 0.75) because the compass
|
|
rose only occupies the upper right corner of the total
|
|
texture image that it is contained in. The other three quardrants
|
|
have other textures for the same model. As mentioned
|
|
before, the coordinates are (0,0) lower left to (1,1) upper right,
|
|
the center of the upper right quadrant is thus (0.75, 0.75).
|
|
|
|
<h3><a name="textranslate">"textranslate" texture translation animation type</a></h3>
|
|
|
|
<p>This animation will adjust the texture mapping on an object so
|
|
that the texture image appears to slides around
|
|
on the object. An <axis> tag is required to specify the axis
|
|
along which the texture is moved (the direction of movement). The
|
|
following example displays the right most digit in the altitude indicator
|
|
on the primary flight display:</p>
|
|
|
|
<blockquote><pre> <animation>
|
|
<type>textranslate</type>
|
|
<object-name>alt1</object-name>
|
|
<property>/position/altitude-ft</property>
|
|
<factor>0.01</factor>
|
|
<axis>
|
|
<x>0</x>
|
|
<y>1</y>
|
|
<z>0</z>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<p>There are also some special properties available for use in the texture animations. These are:</p>
|
|
|
|
<ol>
|
|
<li>step</li>
|
|
<li>scroll</li>
|
|
</ol>
|
|
|
|
<p>The <step> property is useful if you want animations to
|
|
happen in steps rather than smoothly. It causes values that are
|
|
fractional (between) steps size to be ingnored. It can be used for
|
|
things like changing digits on nurmeric displays or a ticking second
|
|
hand on a clock. The <scroll> property works with the
|
|
<step> property. The scroll value specifies the distance the input
|
|
property value should be from a step when scrolling to the next
|
|
position begins. This type of scrolling is common on EFIS cockpit
|
|
displays. The following example gives an "odometer effect"
|
|
where the hundreds position digit doesn't move until the input value
|
|
is within is within 1 (e.g. > 99):</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>textranslate</type>
|
|
<object-name>asi3</object-name>
|
|
<property>/velocities/airspeed-kt</property>
|
|
<factor>0.001</factor>
|
|
<step>100</step>
|
|
<scroll>1</scroll>
|
|
<axis>
|
|
<x>0</x>
|
|
<y>1</y>
|
|
<z>0</z>
|
|
</axis>
|
|
</animation>
|
|
</pre></blockquote>
|
|
|
|
<h3><a name="textmultiple">"textmultiple" type, combining texture animation types</a></h3>
|
|
|
|
<p>The textmultiple animation type isn't a real animation type, but
|
|
instead it is a method of combining multiple texture
|
|
tansform operations on the same object. Unlike object vertex
|
|
operations, texture operations can not be stacked (a plib limitation),
|
|
which means that if you configure two or more texture animation tags
|
|
on the same object, only the first in the list will be used. By
|
|
listing operations using texmultiple they are combined together in
|
|
Simgear and then handled as a single operation.</p>
|
|
|
|
<p>If you need to combine together a translation and rotation
|
|
this is the only way to do it currently. Note that
|
|
transform operations are applied in the same order that they are
|
|
listed in the configuration file. The following
|
|
example for the horizon texture from the 747-400 primary flight
|
|
display explains the format clearly:</p>
|
|
|
|
<blockquote><pre><animation>
|
|
<type>texmultiple</type>
|
|
<object-name>horizon</object-name>
|
|
<transform>
|
|
<property>/orientation/pitch-deg</property>
|
|
<subtype>textranslate</subtype>
|
|
<factor>0.0045</factor>
|
|
<axis>
|
|
<x>0</x>
|
|
<y>1</y>
|
|
<z>0</z>
|
|
</axis>
|
|
</transform>
|
|
<transform>
|
|
<property>/orientation/roll-deg</property>
|
|
<subtype>texrotate</subtype>
|
|
<center>
|
|
<x>0.50</x>
|
|
<y>0.50</y>
|
|
</center>
|
|
<axis>
|
|
<x>0</x>
|
|
<y>0</y>
|
|
<z>-1</z>
|
|
</axis>
|
|
</transform>
|
|
</animation>
|
|
</pre></blockquote>
|
|
<h3><a name="range">"range" animation type</a></h3>
|
|
<p>The range type is used to select part of a model using its distance from the
|
|
viewer as the criterion. To be viewed, the model must be between a minimum
|
|
distance and a maximum one. Minimum distance can be specified either with the
|
|
<min-m> element or the <min-property> element that are exclusive.
|
|
The first one allow to specify a fixed distance in meters, the latter allow to
|
|
lookup the value from a property. Both can be multiplied by a fixed amount,
|
|
specified in the <min-factor> element. The same apply for the maximum
|
|
value with <max-m>, <max-property> and <max-factor> elements.
|
|
The example below shows how it can be used :</p>
|
|
<blockquote>
|
|
<pre><animation>
|
|
<type>range</type>
|
|
<object-name>Detailed</object-name>
|
|
<min-m>0</min-m>
|
|
<max-property>/sim/rendering/static-lod/detailed</max-property>
|
|
</animation>
|
|
</pre>
|
|
</blockquote>
|
|
<h3><a name="alphatest">"alpha-test" animation type</a></h3>
|
|
<p>This "animation" is a way to set an alpha test on a model branch. The effect
|
|
is to avoid depth buffer writing of pixel that are not seen because they are
|
|
transparent. This is particulary useful when modeling a metallic structure or a
|
|
tree with a billboard. The threshold of transparency is set with the
|
|
<alpha-factor> element like this :</p>
|
|
<blockquote>
|
|
<pre><animation>
|
|
<type>alpha-test</type>
|
|
<object-name>Detailed</object-name>
|
|
<alpha-factor>0.01</alpha-factor>
|
|
</animation>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<h3><a name="material">"material" animation type</a></h3>
|
|
<p>This "animation" can set any of the material properties on a model branch, including
|
|
the texture file path. The following minimalistic example animation allows to change the
|
|
"panel" object's emissive color from (0,0,0) to (1,.2,0) by setting the factor property
|
|
to values between 0.0 and 1.0.</p>
|
|
|
|
<blockquote>
|
|
<pre><animation>
|
|
<type>material</type>
|
|
<object-name>panel</object-name>
|
|
<emission>
|
|
<red>1.0</red>
|
|
<green>0.2</green>
|
|
<blue>0.0</blue>
|
|
<factor-prop>/controls/lighting/instruments-norm</factor-prop>
|
|
</emission>
|
|
</animation>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
<p>Changes made with this animation type are by default only effective for the objects listed in
|
|
<object-name> tags, whereby you can use more than one of those. The next example, however,
|
|
sets the optional <global> property, so that changes affect all objects that share
|
|
the same material. This is the preferred method and should be used whereever possible. It isn't
|
|
only faster, but also doesn't break other animations by forcing objects into the same branch.
|
|
Note that all material properties can be set to fixed values, for instance <red> or, by appending
|
|
"-prop", to the contents of another property node: <red-prop>. Because a "material" animation
|
|
can contain a lot of such property paths, which is a nuisance to write, hard to read, and a potential
|
|
source for typos, there's a <property-base> component. Its string value is prepended to
|
|
all material property names (but not to property paths in a <condition> statement!).
|
|
The following example shows all available elements:</p>
|
|
|
|
<blockquote>
|
|
<pre><animation>
|
|
<type>material</type>
|
|
<object-name>fuselage</object-name>
|
|
<condition>
|
|
<property>/sim/model/foo/animate-fuselage-material</property>
|
|
</condition>
|
|
<global type="bool">true</global>
|
|
<property-base>/sim/model/foo/material/fuselage</property-base>
|
|
<diffuse>
|
|
<red-prop>diffuse/red</red-prop>
|
|
<green-prop>diffuse/green</green-prop>
|
|
<blue-prop>diffuse/blue</blue-prop>
|
|
<factor-prop>diffuse/factor</factor-prop>
|
|
<offset-prop>diffuse/offset</offset-prop>
|
|
</diffuse>
|
|
<ambient>
|
|
<red-prop>ambient/red</red-prop>
|
|
<green-prop>ambient/green</green-prop>
|
|
<blue-prop>ambient/blue</blue-prop>
|
|
<factor-prop>ambient/factor</factor-prop>
|
|
<offset-prop>ambient/offset</offset-prop>
|
|
</ambient>
|
|
<emission>
|
|
<red-prop>emission/red</red-prop>
|
|
<green-prop>emission/green</green-prop>
|
|
<blue-prop>emission/blue</blue-prop>
|
|
<factor-prop>emission/factor</factor-prop>
|
|
<offset-prop>emission/offset</offset-prop>
|
|
</emission>
|
|
<specular>
|
|
<red-prop>specular/red</red-prop>
|
|
<green-prop>specular/green</green-prop>
|
|
<blue-prop>specular/blue</blue-prop>
|
|
<factor-prop>specular/factor</factor-prop>
|
|
<offset-prop>specular/offset</offset-prop>
|
|
</specular>
|
|
<shininess>
|
|
<transparency>
|
|
<alpha-prop>transparency/alpha</alpha-prop>
|
|
<factor-prop>transparency/factor</factor-prop>
|
|
<offset-prop>transparency/offset</offset-prop>
|
|
<min>0.0<min> <!-- no min-prop! -->
|
|
<max>1.0<max> <!-- no max-prop! -->
|
|
</transparency>
|
|
<texture>texture</texture>
|
|
<threshold>threshold</threshold>
|
|
</animation>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>A change to one of the components in each color group does always update
|
|
all three color components. Unset values default to zero. The <texture> path
|
|
is relative to the model's <texture-path> directory, or, if unset, to the model
|
|
directory. All numerical values are clamped to 0.0-1.0, except <shininess>, which is
|
|
clamped to 0.0-128.0. The <alpha> property (<transparency> group) makes an
|
|
object fully transparent (and thus invisible) with 0.0, and fully opaque with 1.0.
|
|
("alpha" could also be called "opaqueness".) The <threshold> property sets the
|
|
alpha/opaqueness threshold. It is only relevant for semitransparent textures. Only parts
|
|
of the texture that are more opaque than this are diplayed at all. If it is set
|
|
to 0.0, all parts of the texture will be shown. If it is 0.5, only parts with
|
|
opaqueness greater than 0.5 (or transparency less than 0.5) are shown.</p>
|
|
|
|
<p>Note that defining two or more of these animations for the same object,
|
|
or a mixture of "material" and "blend" animations, will probably not yield
|
|
the result that you expect. Try to put all state manipulations for one
|
|
object or material in one "material" animation, and use its "transparency"
|
|
property instead of an extra "blend" animation.</p>
|
|
|
|
<p>To make a texture replaceable at runtime, use a "material" animation
|
|
like this:</p>
|
|
|
|
<blockquote>
|
|
<pre><animation>
|
|
<type>material</type>
|
|
<object-name>tail-vert</object-name>
|
|
<texture-prop>/sim/model/foo/texture</texture-prop>
|
|
</animation>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>and put something like this into your aircraft's *-set.xml file:</p>
|
|
|
|
<blockquote>
|
|
<pre><sim>
|
|
<model>
|
|
<foo>
|
|
<texture>logos/tail-logo.rgb</texture>
|
|
</foo>
|
|
</model>
|
|
</sim>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
<p>You can explore the influence of material changes at runtime, if you use
|
|
a material animation like the above complete example, and call the material
|
|
dialog on it, like in the following Nasal example. Note, that the path is
|
|
the same that you would set in <property-base>.
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>material.showDialog("/sim/model/foo/material/fuselage");</pre>
|
|
</blockquote>
|
|
|
|
<hr>
|
|
<address>David Megginson, 11 March 2002</address>
|
|
|
|
<!-- Standard Footer Begin -->
|
|
</td></tr>
|
|
</tbody>
|
|
</table>
|
|
<br>
|
|
</body>
|
|
|
|
</html>
|
|
|
|
<!-- Standard Footer End -->
|