Particle system

From FlightGear wiki
Jump to navigation Jump to search
Caution  The feature documented below, in its current form, is currently being scheduled/expected (or discussed) to be significantly updated, or phased out, in future FlightGear versions + (rough estimate). This should be taken into account if you're interested in working on the feature or developing it further. If in doubt, please get in touch via the devel list first.

(According to a number of discussions on the developers mailing list, the Particle system must be considered fragile for the time being, so it is likely that it will need to be fixed, or completely redesigned. People interested in working on the underlying C++ code should get in touch via the developers mailing list first.)

This is a short specification/tutorial to define particle systems in FlightGear using XML.

As of early 2016, it's also become a summary of known restrictions and issues, as well as collection of pointer to related discussions about deprecating/re-implementing the particle system, possibly on top of effects and shaders.

Status

Cquote1.png As a look into our Wiki demonstrates, there's more than one issue with the particle system http://wiki.flightgear.org/Particle_system and I believe there's been talk about phasing it out before.
— Thorsten Renk (Feb 15th, 2016). [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png The particle system is buggy, not so well integrated, and very computationally expensive - it requires a lot of CPU work
— Edward d'Auvergne  (2016-02-16 17:55:30). Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png It doesn't play nice with-ordering (clouds can't obscure particles), it doesn't play nice with lighting and fogging (you can see particles forever through dense fog), it has computational issues at high speeds even where it should not because you attach it locally (which, sadly, airplanes frequently reach), it has odd properties when taking a screenshot, it has clipping problems with planes which use clipping for instruments,... And we can't fix any of that. It's a dead end. Frankly, I'd throw it out today if I had a suitable replacement ready for half of these reasons.
— Thorsten Renk (Feb 16th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png What's the benefit of particles if you can get something that has-ordering, can do proper light and fog, works independent of airplane speed, plays nice with screenshots and looks the same? (this is a genuine question...)
— Thorsten Renk (Feb 16th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png

Phasing out Particles

Cquote1.png I'd like to get rid of particles in the mid-term because they don't play nice with shaders, but I'd like to offer replacement techniques for aircraft developers before that. I think for thrusters, vapour trails, exhaust plumes in the short region which show only limited bending,... the thruster flame shader can deliver better than the particle system. For long contrails and things which need to bend with the flightpath (say the Shuttle SRB smoke or smoke for aerobatics - see the FG promotional video for nice examples...), we can probably do something using the cloud system and just stitch it together from segments. This could be driven by Nasal for prototyping purposes, but I suspect it should ultimately be xml-configurable when it's clear how this works. For wakes of ships, I think the wake shader can be extended to also cover what the particle system does now. For short smoke trails (say smoke stacks, burning wreckage,...) probably a variant of the thruster flame can again be used as they'd fit into a bounding box. Finally, I suspect precipitation could just be rendered procedurally onto an otherwise transparent quad projected into the current camera view a few meters away moving with the camera. If there's going to be a consensus that we'll get rid of the particle system in the mid term, I can priorie work on the above, but I suspect I may need some help with setting up the details. But I do feel there should be a plan, we shouldn't just discontinue particles like this.
— Thorsten Renk (Feb 15th, 2016). [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png After a little research, there's also the persistent contrail technique http://wiki.flightgear.org/Howto:Add_contrails#Persistent_Contrails using submodels that could be expanded - anyone has any experience with that? Submodels are not quirk-free either, but from a rendering POV they're a lot less problematic than particles.
— Thorsten Renk (Feb 15th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png

Reimplementing the Particle System

Cquote1.png Particles come with their own shaders OSG side and we can't access them at all - which means we can't merge them correctly into our scene organiation. Their lighting is never really correct, and you have to use lots of trickery to make it even plausible.
— Thorsten Renk (Feb 17th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png it's a dead end which we can't ever merge into our scene properly. So my view is we need to get out of the corner and move to something we have control over rendering-side.
— Thorsten Renk (Feb 17th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png no reason to kill of what is currently up and running in FlightGear. Maybe what we need is a pure GPU-based particle system? Though I haven't heard of too many of such implementations. However the Valve software particle system is CPU-based, like OSG, and it seems quite reasonable [1]. It is CPU rather than GPU bound [2], but their system is quite respected. Maybe a solution could be found for the benefit of both FlightGear and OSG? Anyway, I'm no rendering expert, so this is a little over my head.
— Edward d'Auvergne (Feb 17th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png It is probably worth noting that it is the current particle system _back-end_ that may be a dead end or its integration in FG. In general, it should not be impossible to insert whatever lighting computation into a particle system shader (apart from hitting resource constraints, such as #varying components) and putting each particle system instance in an appropriate render bin may well solve most of the translucent - translucent depth problems (but that might be a tricky problem to solve).
— Anders Gidenstam (Feb 17th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Last time I checked, the particle system shaders where hard-coded inside the OSG source code, so it's not quite clear to me how to insert anything into the shader FG-side. But I may be wrong - if there's a good way of opening this box up, I'm all game.
— Thorsten Renk (Feb 17th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png The object oriented hierarchal design of OSG seems to be quite powerful, so we could simply rewrite the box. We can take the particle system, the particles, the particle system updater, etc. as a base and subclass them all, extending as needed. The first thing I would add would be an adjustable maximum particle count for each particle system - to prevent modellers or bugs from accidentally grinding FlightGear to a halt or triggering OOM kills like the missing particles scene graph branch did. I wonder if any of the particle system techniques used by the major game engines have been published in sufficient detail for us to cleanly reimplement via OSG subclassing? Note that our current C++ interface to the OSG particle system in simgear should probably first be simplified and standardised to match our other scene graph branches (terrain, models, aircraft, interior).
— Edward d'Auvergne (Feb 17th, 2016). Re: [Flightgear-devel] Particle system future.
(powered by Instant-Cquotes)
Cquote2.png

Known Issues

Cquote1.png Another goal is to add more node bits (and a GUI dialog to control them) so various categories of objects can be disabled during the update pass. This will mean the direct hit of, say, AI models vs particles vs random trees can be measured. Of course it won't account for resources (memory, textures) burned by such things, but would still help different people identify slowness on their setups.
— James Turner (Jul 19th, 2012). Re: [Flightgear-devel] Rendering passes question.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png IIRC each particle system is attached to the scene graph in (at least) two places: at the emitter's location in the graph and in a global vector of particle system updaters. IIRC they are never removed from the global list of updaters (a bug - but a hard one to fix due to concurrency issues). Tim knows more about this.
— Anders Gidenstam (Apr 16th, 2011). Re: [Flightgear-devel] OSG caching.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png The particle system sucks in more than one way in FG... It's an OSG black box exposed to FG, but it has its own hard-coded shaders - it doesn't mesh with lighting right, it doesn't-order right, it doesn't cope with motion of objects gracefully... You can chalk up my recent work on thruster flames to an attempt to provide a technology to get rid of it in one area - as Erik has demonstrated, one can also use it to get rid of it for vapour trails. I wonder whether we can simply use a series of 3d clouds for the smoke - has to be managed aircraft-internally of course, but certainly has much better properties in the scene.
— Thorsten (May 31st, 2015). Re: Space Shuttle.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Back when we were running into issues related to effects, particles and random buildings - those were also only understood once we were able to fully disable those features to exclude those from the pool of potential culprits. So it is much easier to draw correct conclusions if we can remove "black box behavior" or at least keep it optionally disabled when troubleshooting certain issues.
— Hooray (Jan 7th, 2015). Re: Level of detail.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png particle velocity is affected by view position - form an outside view, just play with the view direction and you’ll see this. This suggest we’re using the wrong origin position to calculate the velocity, so when it moves rapidly the particle velocity gets confused. Probably we should be using the view’s look-at point if one exists, which will fix the model / chase / helicopter views.
— James Turner (Oct 15th, 2014). Re: [Flightgear-devel] Precipitation system update.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Our integration of the particle systems need to be rethought as this contains geometry with culling disabled which makes a pagedlod just never expire. Switching the particle systems off works pretty good so far.
— Mathias Fröhlich (Jul 21st, 2012). Re: [Flightgear-devel] Rendering passes question.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png There are two features incompatible with this paging system - particles; due to some long standing design defects in that code
— James Turner (Feb 24th, 2014). Re: [Flightgear-devel] Terrain Simplifier.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png the current particles code in Simgear has major performance problems - and some outright mistakes in its implementation. Notably the animation of the particles is done in the wrong phase of OSG’s frame loop, which can prevents particle animations being unloaded - i.e can cause tiles to never be unloaded. For this reason many people have been disabling particle effects to ensure stable frame-rates. However, the complication is the Simgear particle system is effectively a fork+edit of the osgParticle system, which I think is what we use for precipitation. Ideally we’d use the osgParticle system everywhere (since it has correct interactions with the rest of OSG) but it also has the issues about customising the rendering you mentioned. (I don’t think the Simgear particles are any better in that regard, but I may be wrong)
— James Turner (Oct 13th, 2014). Re: [Flightgear-devel] Precipitation issues.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png I have been unable to run FG with particles enabled since a long time due to random crashes in the particle code. Call stack frequently included functions your description mentions, so I hope this patch will fix that issue.
— Csaba Halász (Aug 1st, 2011). Re: [Flightgear-devel] startup crash in SimGear (with patch?).
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png The issue only shows when particles are enabled and an aircraft is actually using them - which already reduces the number of users ;-). I actually had it disabled for a long time. After enabling it recently, I also started having memory issues - on shutdown though. So that patch comes handy. The particular code has been there since the beginning of the module. Another, similar issue was fixed a while ago (http://www.gitorious.org/fg/simgear/commit/29aad066f0e57a04649b92083c4be7c6d490de31) but the property reference issue was overlooked. My guess is that there's usually no problem since the referenced property would still be part of the main property tree (?) - and have a reference there. Only when the property is dropped from the tree, should an issue occur (which would well explain my shutdown issues - but not necessarily the startup issues...).
Cquote2.png

Example

Note  Start & end size appear to be given in feet; some other measurements are in meters. There may be some internal confusion between the two measurement systems.
  <particlesystem>
    <name>fuel</name>
      <!-- <texture>particle.rgb</texture> -->
    <emissive>false</emissive>
    <lighting>true</lighting>
  
    <offsets>
      <x-m>35</x-m>
      <y-m>-0.3</y-m>
      <z-m>0</z-m>
      <!-- <pitch-deg>90</pitch-deg> -->
    </offsets>
    <!-- <condition>
      <and>
        <equals>
          <property>engines/engine/smoking</property>
          <value>true</value>
        </equals>
        <less-than>
          <property>position/altitude-agl-ft</property>
          <value>12000</value>
        </less-than>
      </and>
    </condition> -->
    <attach>world</attach>
  
    <placer>
      <type>point</type>
    </placer>
  
    <shooter>
      <theta-min-deg>84</theta-min-deg>
      <theta-max-deg>86</theta-max-deg>
      <phi-min-deg>-1.5</phi-min-deg>
      <phi-max-deg>1.5</phi-max-deg>
      <speed-mps>
        <value>10</value>
        <spread>2.5</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>1</value>
        <spread>0</spread>
      </particles-per-sec>
    </counter>
    <align>billboard</align>
       
    <particle>
      <start>
        <color>
          <red>
            <value>0.9</value>
          </red>
          <green>
            <value>0.09</value>
          </green>
          <blue>
            <value>0.09</value>
          </blue>
          <alpha>
            <value>1.0</value>
          </alpha>
        </color>
        <size>
          <value>0.25</value>
        </size>
      </start>
  
      <end>
        <color>
          <red>
            <value>1</value>
          </red>
          <green>
            <value>0.1</value>
          </green>
          <blue>
            <value>0.1</value>
          </blue>
          <alpha>
            <value>0.0</value>
          </alpha>
        </color>
        <size>
          <value>4</value>
        </size>
      </end>
  
      <life-sec>
        <value>10</value>
      </life-sec>
  
      <mass-kg>0.25</mass-kg>
      <radius-m>0.1</radius-m>
    </particle>
  
    <program>
      <fluid>air</fluid>
      <gravity type="bool">true</gravity>
      <wind type="bool">true</wind>
    </program>
 </particlesystem>

Stick this inside any model XML like it was an animation and it should work (notice the condition requires wheel on the ground)

Specification

Note<VALUEORPROP/> means you can either specify a property with factor and offset (result = (prop*factor)+offset ) in the usual way.
 <particlesystem>                       <!-- The base tag -->
  <type>string</type>                   <!-- Can be "normal" or "trail", normal is the usual quad
                                         particles, trail is  a string of connected line shapes
                                         by default. -->
  <offsets>                             <!-- this places the source of the particles (the emitter)
                                         in relation to the perhaps already offset model (see
                                         model-howto.html for details) -->
    <x-m>float</x-m>
    <y-m>float</y-m>
    <z-m>float</z-m>
    <pitch-deg>float</pitch-deg>
    <roll-deg>float</roll-deg>
    <heading-deg>float</heading-deg>
  </offsets>
  <condition>                           <!-- A typical condition that if not true stops particles
                                         from being emitted (PPS=0) -->
    <!-- ... -->
  </condition>
  <name>string</name>                   <!-- The name of the particle system (so it can be
                                         referenced by normal animations) -->
  <attach>string</attach>               <!-- An be "world" or "local". "world means the particles
                                         aren't "physically linked" to the model (necessary for
                                         use outside moving models), "local" means the opposite
                                         (can be used for static objects or inside moving
                                         objects) -->


  <texture>string</texture>             <!-- The texture path relative to the XML file location -->
  <emissive>bool</emissive>             <!-- Self-explanatory -->
  <lighting>bool</lighting>             <!-- Yet to be tested, but seems obvious -->
  <align>string</align>                 <!-- Can be "billboard" or "fixed" -->
  <placer>                              <!-- where particles are born -->
    <type>string</type>                 <!-- Can be "sector" (inside a circle), "segments"
                                         (user-defined segments) and "point" (default) -->
    *<radius-min-m>float</radius-min-m> <!-- Only for sector, inner radius at which particles appear -->
    *<radius-max-m>float</radius-max-m> <!-- Only for sector, outer radius at which particles appear -->
    *<phi-min-deg>float</phi-min-deg>   <!-- Only for sector, starting angle of the slide at which
                                         particles appear -->
    *<phi-max-deg>float</phi-max-deg>   <!-- Only for sector, ending angle of
                                        the slide at which particles appear -->
    <segments>                          <!-- Only for segments, encloses sequential points that
                                         form segments -->
      <vertex>                          <!-- Specifies one point, put as many as you want -->
        <x-m>float</x-m>
        <y-m>float</y-m>
        <z-m>float</z-m>
      </vertex>
      <!-- ... -->
      <vertex>
        <!-- ... -->
      </vertex>
    </segments>
  </placer>
  <shooter>                             <!-- The shooter defines the initial velocity vector for
                                         your particles -->
    *<theta-min-deg>float</theta-min-deg>  <!-- Horizontal angle limits of the particle cone -->
    *<theta-max-deg>float</theta-max-deg>
    *<phi-min-deg>float</phi-min-deg>   <!-- Vertical angle limits of the particle cone -->
    *<phi-max-deg>float</phi-max-deg>   <!-- For an illustration of theta/phi see 
                                         http://www.cs.clemson.edu/~malloy/courses/3dgames-2007/
                                         tutor/web/particles/particles.html -->
    <speed-mps>                         <!-- The scalar velocity (meter per second) -->
     <VALUEORPROP/>                     <!-- See note -->
     *<spread>                          <!-- The "tolerance" in each direction so values are in the
                                         range  [value-spread, value+spread] -->
    </speed-mps>
    <rotation-speed>                    <!-- The range of initial rotational speed of the particles -->
      *<x-min-deg-sec>float</x-min-deg-sec>
      *<y-min-deg-sec>float</y-min-deg-sec>
      *<z-min-deg-sec>float</z-min-deg-sec>
      *<x-max-deg-sec>float</x-max-deg-sec>
      *<y-max-deg-sec>float</y-max-deg-sec>
      *<z-max-deg-sec>float</z-max-deg-sec>
    </rotation-speed>
  </shooter>
  <counter>
    <particles-per-sec>
      <VALUEORPROP/>                    <!-- See note -->
      *<spread>                         <!-- The "tolerance" in each direction so values are in the
                                         range [value-spread, value+spread] -->
    </particles-per-sec>
  </counter>
  <particle>                            <!-- Defines the particle properties -->
    <start>
      <color>                           <!-- Initial color (at time of emission) -->
        <red><VALUEORPROP/></red>       <!-- Color component in normalized value [0,1] -->
        <green><VALUEORPROP/></green>
        <blue><VALUEORPROP/></blue>
        <alpha><VALUEORPROP/></alpha>
      </color>
      <size>                            <!-- As above, but for size (given in feet) -->
        <VALUEORPROP/>
      </size>
    </start>
    <end>
      <color>                           <!-- Final color (at the end of the particle life) -->
        <red><VALUEORPROP/></red>
        <green><VALUEORPROP/></green>
        <blue><VALUEORPROP/></blue>
        <alpha><VALUEORPROP/></alpha>
      </color>
      <size>
        <VALUEORPROP/>                  <!-- (In feet) -->
      </size>
    </end>
    *<life-sec>                         <!-- The time the particles will be alive, in seconds -->
      <VALUEORPROP/>
    *</life-sec>
    *<radius-m>float</radius-m>         <!-- Each particles is physically treated as a sphere with
                                         this radius -->
    *<mass-kg>float</mass-kg>           <!-- Mass in Kg -->
  </particle>
  <program>                             <!-- Defines external forces acting upon a particle -->
    <fluid>string<fluid>                <!-- Can be "air" or "water" -->
    <gravity>bool</gravity>             <!-- Can be "true" or "false". uses standard gravity -->
    <wind>bool</wind>                   <!-- Can be "true" or "false". uses user position wind (not
                                         the model position, but shouldn't be noticeable, you want
                                         to disabled it when using local attach) -->
  </program>
 </particlesystem>
Note  The <attach> tag isn't quite as innocent, as it for instance affects the direction gravity acts. In a locally attached particle system, gravity is assumed to act in model coordinates, i.e. usually aircraft-down rather than world-down - that can rapidly get confusing.

Remarks

  • Don't forget you can use existing animations with particles, so if you want to direct or translate the emitter, just use translate, rotate, spin and so on (other animations might have interesting effects too I guess).
However, avoid using the select animation for triggering the particle emission, use the condition directly in the particle system. Otherwise there is an issue with old particles reappearing when triggered again. It is fine to use it for longer-term hiding (like smoke emitting device being or not being installed), but not for conditions that might change often (like the command to start/stop emitting smoke).
  • Particle XML should be compatible with plib, as the tags will be ignored (you might get some warning if you attach them to animations though)
  • Try not to use a lot of particles in a way that fills the screen, that will demand lots of fill rate and hurt FPS
  • If you don't use any properties nor conditions, your particle system doesn't need to use a callback a so it's slightly better on the CPU (mostly useful for static models)
  • If your particle lifetime is too big you might run out of particles temporarily (still being investigated)
  • Use mass and size (radius) to adjust the reaction to gravity and wind (mass/size = density)
  • Although at the moment severe graphical bugs can be seen in the trails, they are usable.
  • Consider your options correctly! You should consider giving them no initial velocity and most important, no spread, otherwise particles will race and the trail will fold. Start simple (no velocities and forces) and work your way up.

Related content

Wiki articles

Mailing list threads

Readme file

Source code