Howto:Add contrails

From FlightGear wiki
Jump to navigation Jump to search
An Airbus A340 with contrails during cruise.

Contrails (short for "condensation trails") or vapour trails are visible trails of condensed water vapour made by the exhaust of aircraft engines. As the hot exhaust gases cool in the surrounding air they may precipitate a cloud of microscopic water droplets. If the air is cold enough, this trail will comprise tiny ice crystals. These are visible to the human eye in large trails in the correct termperatures. This depends also from the humidity of the sourrounding air. Less humidity prevents contrails or makes them faster dissapear. 80% of contrails only appear for less than few minutes.

There is a nice applet to simulate contrails: Contrail-Simulator

Physically accurate contrails in FGFS you can achieve with the Contrails-Script made by Zan aka Lauri Peltonen: Contrail-script by Lauri Peltonen

This howto will explain how to add the effect of contrails in a more simple, but less physically correct way to an aircraft.

Step 1: creating the contrail particles

First of all, we need to make the contrail particles.

  • In the $FG ROOT/Aircraft/example/Models folder, create a new folder called "effects".
  • In this folder, you need a smoke.png image file, this will be the particle which will be emitted. It should appear to be a rough texture with opacity around the edges (similar looking to a cloud).
  • In this folder, you will also need a .xml file for each engine named contrail1.xml. contrail2.xml etc. You have to make this .xml for each engine changing in each .xml the engine numer to the right one: /engine[0], /engine[1], /engine[2] etc. Place the following lines regarding the right engine number in each file:

Note: put the <PropertyList> tag before and </PropertyList> tag after the following document of course, as all our xml's carry this at the start and end!

  <particlesystem>
    <name>smoke</name>
    <texture>smoke.png</texture>
 
    <emissive type="bool">false</emissive>
    <lighting type="bool">false</lighting>
 
    <condition>
      <and>
        <greater-than>
          <property>/engines/engine[0]/n2</property>
          <value>50</value>
        </greater-than>
        <greater-than>
          <property>/position/altitude-ft</property>
          <value>19000</value>
        </greater-than>
        <less-than>
          <property>environment/temperature-degc</property>
          <value>-40</value>
        </less-than>
      </and>
    </condition>
 
    <attach>world</attach>
 
    <placer>
      <type>point</type> 
    </placer>
 
    <shooter>
      <theta-min-deg>-1.5</theta-min-deg>
      <theta-max-deg>1.5</theta-max-deg>
      <phi-min-deg>-1.5</phi-min-deg>
      <phi-max-deg>1.5</phi-max-deg>
      <speed-mps>
        <value>0</value>
        <spread>0</spread>
      </speed-mps>
      <rotation-speed>
        <x-min-deg-sec>0</x-min-deg-sec>
        <y-min-deg-sec>0</y-min-deg-sec>
        <z-min-deg-sec>0</z-min-deg-sec>
        <x-max-deg-sec>0</x-max-deg-sec>
        <y-max-deg-sec>0</y-max-deg-sec>
        <z-max-deg-sec>0</z-max-deg-sec>
      </rotation-speed>
    </shooter>
 
    <counter>
      <particles-per-sec>
        <value>35</value>
        <spread>0</spread>
      </particles-per-sec>
    </counter>
       
    <align>billboard</align>
 
    <particle>
      <start>
        <color>
          <red><value>   0.7 </value></red>
          <green><value> 0.7 </value></green>
          <blue><value>  0.7 </value></blue>
          <alpha><value> 0.3 </value></alpha>
        </color>
        <size>
          <value>2.45</value>
        </size>
      </start>
 
      <end>
        <color>
          <red><value>   1.0 </value></red>
          <green><value> 1.0 </value></green>
          <blue><value>  1.0 </value></blue>
          <alpha><value> 1.0 </value></alpha>
        </color>
        <size>
          <value>4</value>
        </size>
      </end>
 
      <life-sec>
        <value>10</value>
      </life-sec>
         
      <mass-kg>  0.5 </mass-kg>
      <radius-m> 0.5 </radius-m>
    </particle>
 
    <program>
      <fluid>               air  </fluid>
      <gravity type="bool"> true </gravity>
      <wind typ="bool">     true </wind>
    </program>
 
  </particlesystem>

After that xml is saved, you have completed step 1!

Step 2: adding the contrails to the aircraft

A340 with four trails,

Now we need to link the aircraft with the contrail you just made, which isn't too difficult:

  • Open up your $FG ROOT/Aircraft/example/Models folder, and open up the example.xml (the xml which allocates your aircraft's models and positions).

Somewhere in here (I prefer to keep it above the lights, but it doesn't really matter as long as they are in the main tags), place the code below, changing the coordinates to suit your aircraft's position (the x,y,z tags you can see). This shouldn't be too difficult, but you may have to keep reloading FlightGear and checking that you see them in the right places. As you can see, for the A340 as shown below, I referred to the contrail 4 times, once for each engine (I wanted it to be emitted four times) but using a different set of coordinates each time, for each particle starting point. Most aircraft will only need two, for two engine aircraft, so you can remove the two others, or add them to your discrepancy.

This tells where abouts your particles will be placed

  <!-- CONTRAIL -->
 
  <!-- Particules OSG -->
  <model>
    <path>Aircraft/A340-600/Models/effects/contrail1.xml</path>
    <offsets>
      <x-m> 10.290</x-m>
      <y-m>-18.550</y-m>
      <z-m>-2.928</z-m> 
      <roll-deg>    0 </roll-deg>
      <pitch-deg>   0 </pitch-deg>
      <heading-deg> 0 </heading-deg>
    </offsets>
  </model>
 
  <model>
    <path>Aircraft/A340-600/Models/effects/contrail2.xml</path>
    <offsets>
      <x-m> 10.290</x-m>
      <y-m> 18.550</y-m>
      <z-m>-2.928</z-m> 
      <roll-deg>    0 </roll-deg>
      <pitch-deg>   0 </pitch-deg>
      <heading-deg> 0 </heading-deg>
    </offsets>
  </model>
 
  <model>
    <path>Aircraft/A340-600/Models/effects/contrail3.xml</path>
    <offsets>
      <x-m> 10.290</x-m>
      <y-m>-8.550</y-m>
      <z-m>-2.928</z-m> 
      <roll-deg>    0 </roll-deg>
      <pitch-deg>   0 </pitch-deg>
      <heading-deg> 0 </heading-deg>
    </offsets>
  </model>
 
  <model>
    <path>Aircraft/A340-600/Models/effects/contrail4.xml</path>
    <offsets>
      <x-m> 10.290</x-m>
      <y-m> 8.550</y-m>
      <z-m>-2.928</z-m> 
      <roll-deg>    0 </roll-deg>
      <pitch-deg>   0 </pitch-deg>
      <heading-deg> 0 </heading-deg>
    </offsets>
  </model>

Where it says A340-600, you need to rename so that it understands the folder for YOUR aircraft (which has been referred to as "example" until now.

Wingtip condensation trails

If you've got the hang of adding contrails to your jet-engined beast then you could create wingtip condensation vapour trails for added effect. These are usually caused when flying low, in high humidity at high speed. Do the same as you did for the engines except, of course, locate the vapour trails at the wingtips.

Create a very small image in the same format as the smoke.png file and name it vapour.png.

Copy the listing below and name it vapour1.xml. The differences in <condition>, <counter> and <life-sec> are to switch the vapour trails on at low altitude and moderate speeds, make them as dense as possible and make them last only a short time. For military jets you can add a suitable <condition> for high-g accelerations.

 <PropertyList>
 
 <particlesystem>
   <name>smoke</name>
   <texture>vapour.png</texture>
 
   <emissive type="bool">false</emissive>
   <lighting type="bool">false</lighting>
 
   <condition>
     <and>
       <greater-than>
         <property>velocities/airspeed-kt</property>
         <value>120</value>
       </greater-than>
       <greater-than>
         <property>environment/relative-humidity</property>
         <value>50</value>
       </greater-than>
       <less-than>
         <property>/position/altitude-ft</property>
         <value>800</value>
       </less-than>
       <less-than>
         <property>environment/temperature-degc</property>
         <value>20</value>
       </less-than>
     </and>
   </condition>
 
   <attach>world</attach>
 
   <placer>
     <type>point</type> 
   </placer>
 
   <shooter>
     <theta-min-deg>-1.5</theta-min-deg>
     <theta-max-deg>1.5</theta-max-deg>
     <phi-min-deg>-1.5</phi-min-deg>
     <phi-max-deg>1.5</phi-max-deg>
     <speed-mps>
       <value>0</value>
       <spread>0</spread>
     </speed-mps>
     <rotation-speed>
       <x-min-deg-sec>0</x-min-deg-sec>
       <y-min-deg-sec>0</y-min-deg-sec>
       <z-min-deg-sec>0</z-min-deg-sec>
       <x-max-deg-sec>0</x-max-deg-sec>
       <y-max-deg-sec>0</y-max-deg-sec>
       <z-max-deg-sec>0</z-max-deg-sec>
     </rotation-speed>
   </shooter>
 
   <counter>
     <particles-per-sec>
       <value>25</value>
       <spread>5</spread>
     </particles-per-sec>
   </counter>
      
   <align>billboard</align>
 
   <particle>
     <start>
       <color>
         <red><value>   0.7 </value></red>
         <green><value> 0.7 </value></green>
         <blue><value>  0.7 </value></blue>
         <alpha><value> 0.3 </value></alpha>
       </color>
       <size>
         <value>2.45</value>
       </size>
     </start>
 
     <end>
       <color>
         <red><value>   1.0 </value></red>
         <green><value> 1.0 </value></green>
         <blue><value>  1.0 </value></blue>
         <alpha><value> 1.0 </value></alpha>
       </color>
       <size>
         <value>4</value>
       </size>
     </end>
 
     <life-sec>
       <value>1</value>
     </life-sec>
        
     <mass-kg>  0.5 </mass-kg>
     <radius-m> 0.5 </radius-m>
   </particle>
 
   <program>
     <fluid>               air  </fluid>
     <gravity type="bool"> true </gravity>
     <wind typ="bool">     true </wind>
   </program>
 
 </particlesystem>
 
 </PropertyList>

Don't forget to add two entries to your $FG ROOT/Aircraft/example/Models folder, as above, where you give the locations of the wingtips.

 <model>
  <path>Aircraft/your_plane_name_here/Models/Effects/vapour.xml</path>
  <offsets>
   <x-m>17.00</x-m>
   <y-m>-30.28</y-m>
   <z-m>1.55</z-m>
   <heading-deg>0</heading-deg>
   <roll-deg>    0 </roll-deg>
   <pitch-deg>   0 </pitch-deg>
  </offsets>
 </model>
 
 <model>
  <path>Aircraft/your_plane_name_here/Models/Effects/vapour.xml</path>
  <offsets>
   <x-m>17.00</x-m>
   <y-m>30.28</y-m>
   <z-m>1.55</z-m>
   <heading-deg>0</heading-deg>
   <roll-deg>    0 </roll-deg>
   <pitch-deg>   0 </pitch-deg>
  </offsets>
 </model>

Let's hope you're not too busy wrestling at the controls to appreciate the effects when landing!


Persistent Contrails

Persistent Contrail

Particles produce relatively realistic non-persistent contrails lasting several seconds, but under certain conditions contrails can last several minutes and possibly many minutes. The numbers of particles required to represent such persistent contrails can cause an unacceptable drop in frame rate, and cannot easily model the decay of old contrails. We can use submodels to represent some forms of persistent contrails.

The Persistent Contrail system comprises 3 elements:

  • A contrail calulator (Nasal/contrail.nas). This script calculates the temperature below which persistent contrails form at a given air pressure, based on an approximation of the Appleman Chart [1]. This approximation only calculates the temperature at which persistent contrails always occur, and does not address the temperatures at which contrails may occur. This might be a future extension.
  • A non-persistent contrail made up of particles as above.
  • A persistent contrail made up of at least 2 types of submodel:
    • Dummy Contrail. This submodel has no associated model. Its pupose is to start the persistent contrail where the non-persistent contrail ends.
    • Contrail. This is the submodel which displays. It comprises the model 'contrail20.ac' which comprises 20 particle-like elements and the shader 'contrail' which inherits from the shader 'clouds'. The shader controls the appearance and position of the elements. The width, length, depth, and transparency of the submodel are adjustable.

Any number of subsequent submodels can be attached to provide the decay tail of the persistent contrail.

Adding Persistent Contrails

You should refer to $FG ROOT/Aircraft/737-300 while reading this section.

  • Step 1: Add a non-persistent contrail:

Proceed as above. NOTE: it is not necessary to define a particle system for each engine unless you wish to differentiate them in some way.

  • Step 2: Add the submodel 'Contrail-Dummy'

Add this to your ~set.xml file within the <sim></sim> tags:

    <submodels>
      <servicable type="bool">true</servicable>
      <path type="string">Aircraft/737-300/b737-submodels.xml</path>
    </submodels>

Where the path is to wherever you put your submodel file.

Add the submodel file, or, if you have one already add this section:

  <submodel>
    <name>contrail-dummy</name>
    <model>Aircraft/737-300/Models/Effects/contrail_dummy.xml</model>
    <trigger>environment/contrail</trigger>
    <speed>-100</speed>
    <repeat>true</repeat>
    <delay>1.0</delay>
    <count>-1</count>
    <x-offset>-52.0</x-offset>
    <y-offset>0</y-offset>
    <z-offset>0</z-offset>
    <yaw-offset>0</yaw-offset>
    <pitch-offset>0</pitch-offset>
    <eda>10</eda>
    <wind>true</wind>
    <aero-stabilised>false</aero-stabilised>
    <buoyancy>32.1740485564</buoyancy>
    <random>false</random>
    <life>8.0</life>
    <submodel-path>Aircraft/737-300/b737-subsubmodels.xml</submodel-path>
    <expiry>true</expiry>
  </submodel>

Adjust the <delay> tag to control the rate of instantiation of the next submodel, the <life> tag to a little less than the life of the non-persistent contrail, and <x-offset> to where you start the non-persistent contrail. Some experimentation will be necessary.

Add the file which you have defined at <model>. In this example: Aircraft/737-300/Models/Effects/contrail_dummy.xml

  • Step 3 Add the subsubmodel 'Contrail:'

Add the file which you defined at <submodel-path> at Step 2 above. In this example: Aircraft/737-300/b737-subsubmodels.xml. This should contain something like:

  <submodel>
    <name>contrail-static</name>
    <model>Aircraft/737-300/Models/Effects/contrail_shader1.xml</model>
    <speed>0</speed>
    <repeat>false</repeat>
    <delay>0</delay>
    <count>-1</count>
    <x-offset>0</x-offset>
    <y-offset>0</y-offset>
    <z-offset>0</z-offset>
    <yaw-offset>0</yaw-offset>
    <pitch-offset>0</pitch-offset>
    <eda>10</eda>
    <wind>true</wind>
    <aero-stabilised>false</aero-stabilised>
    <buoyancy>32.0</buoyancy>
    <random>false</random>
    <life>36</life>
    <submodel-path>Aircraft/737-300/b737-subsubsubmodels.xml</submodel-path>
    <expiry>true</expiry>
  </submodel>

Add the file you have defined at <model>. Put the files contrail20.ac, contrail.png and contrail1.eff in the same place. Adjust the parameters in contrail1.eff until you get a contrail that you like. The parameters interact somewhat, so experimentation will be necessary.

  • Step 4 Add further contrail submodels:

Repeat Step 3 for subsubsubmodels etc. to obtain a nice decay tail. Refer to the example for the files you might need. The default isn't bad, but all contrails decay differently, so you might want to change some or all of the parameters to personalise the effect.


NOTES

1. It is not necessary to use Nasal/contrails.nas. You could use this instead Contrail-script by Lauri Peltonen

2. The example for the B373 uses the same property to control both the persistent and non-persistent contrails. It might be better to use different ones.

3. The example uses 4 levels of submodels - there is no reason why you shouldn't use more or less

KNOWN ISSUES

1. Submodel contrails are well-behaved with 2D and 3d clouds. Particles are not, and may have depth sorting problems. This is not a contrail issue but is generic for particles.

2. Contrails are not well-behaved with Thorsten's cloud system and will have depth sorting problems. The use of contrails with this cloud system will probably reduce the frame rate to below 10, and may stop FG altogether.

3. Framerate. If the number of submodels used by contails is kept below about 200, there should be a only a small drop in frame rate. Many more than this and there will be an unacceptable drop, YMMV, according to the system in use.

4. Multiplayer. Persistent contrails should, in principle, be visible over MP. However I have not yet come up with a solution at an acceptable cost to framerate.

TROUBLESHOOTING

If your persitent contrail isn't visible, ensure you have started fg with --enable-AI-models. Confirm that Persistent Contrails are checked in the menu View->Rendering Options.

Check that "init contrails" appears in the console in the start-up sequence. If not there might be a nasal error somewhere.

Open the Property Browser: if there are multiple Ballistic Objects in ai/models, then the system is probably functioning correctly.

If persistent contrails are still not visible check that 3d clouds work. If not, then it is likely that peristent contrails are also broken - they are derived from 3d clouds. This is probably the fault of your video driver. There is nothing more to be done.

If you have checked all these, and they still don't work - then report a bug.