Purpose:
Add a custom osgparticle instance to the scenario to simulate the dust generated when the tank model moves over the terrain.
-----------------------------
Overview:
Adding particle effects can effectively improve the appearance and authenticity of the simulation program. Particle engines are generally used to simulate smoke, flame, dust, and other similar effects. To add particle effects to an OSG scenario, you can use the following classes:
Particle System-maintain and manage the generation, update, rendering, and destruction of a series of particles. The particle system class inherits from the drawable class. The Rendering Control of particles is similar to that of other drawable objects: control the rendering attribute stateattribute. OSG provides a convenient function that allows you to control three commonly used rendering State attributes. The setdefaultattributes method can be used to specify the material (or specify NULL to disable the material), allow/prohibit additional image fusion, and allow/disable illumination.
Particle (osgparticle: particle)-basic unit of the particle system. Particle classes have both physical and image attributes. Its shape can be any point, quad, quad_tripstrip, hexagon, or line ). Each particle has its own lifecycle. The lifecycle is the number of seconds that each particle can survive. (Particles with a negative life cycle can survive for an infinite period of time) All particles have the size, Alpha value, and color attributes. Each group of particles can specify its maximum and minimum values. To facilitate particle lifecycle management, the particle system controls the rendering of a single particle by changing the maximum and minimum values of the lifecycle. (Linear interpolation between the minimum and maximum values based on the time consumed)
Programmers can also specify the least-to-maximum interpolation method. (See osgparticle: interpolator code)
Placement tool (osgparticle: placer)-sets the initial position of the particle. You can use a predefined placeholder or define your own placeholder. The defined splitters include pointplacer (where all particles are generated from the same point) and fan placement sectorplacer (where all particles are from a specified center point, the Radius Range and angle range of the fan surface are born), and The multipart placement multisegmentplacer (the User specifies a series of points where particles are generated along the line segments defined by these points ).
Transmitter (osgparticle: Shooter)-specifies the initial speed of the particle. The radialshooter class allows you to specify a speed range (meter/second) and the direction expressed by radians. The direction is specified by two angles: the angle between theta and Z axis, and the angle between PHI and XY plane.
Counter (osgparticle: Counter)-controls the number of particles produced by each frame. The randomratecounter class allows you to specify the maximum and minimum number of particles generated per frame.
Standard emission pole (osgparticle: modularemitter)-a standard emission pole includes a counter, a placeholder, and a transmitter. It provides a standard mechanism for users to control multiple elements in the particle system.
Particle System Updater-used to automatically update particles. When it is placed in a scenario, it calls the update method of all "surviving" particles in the pick traversal.
Standard Programmer (osgparticle: modularprogram)-In the lifecycle of a single particle, you can use the modularprogram instance to control the position of the particle. Modularprogram must be used together with the operator object.
Calculator (osgparticle: Operator)-provides a method to control the motion of particles in their lifecycles. You can change the parameters of an existing operator class instance or define your own operator class. Operator classes provided by OSG include: acceloperator (Application constant acceleration), angularacceloperator (Application constant angle acceleration), and fluidfrictionoperator (calculation based on specified density and viscous fluid motion ), and forceoperator ).
Code:
To use the above class to create a highly customized particle system, we can follow the steps below. (The steps in the brackets are optional. You can ignore them if the created particle system is relatively basic)
- Create a particle system instance and add it to the scenario.
- (Set the rendering state attribute of the particle system .)
- Create a particle object and associate it with the particle system.
- (Set the particle parameters .)
- Create a particle system Updater, associate it with a particle system instance, and add it to the scene.
- (Create a standard emitter pole to define: Counter-number of particles created per frame, placement-particle birth location, transmitter-initial speed .)
- (Associate the standard radiation pole with the particle system .)
- (Create a modularprogram standard programmer instance to control the movement of particles in the lifecycle: first create and define the operator calculator, and then add the calculator to the standard programmer .)
The following code completes the preceding steps. First, we need to establish basic tank and terrain models. (We will add the tank model to the scene later)
OSG: Group * rootnode = new OSG: group ();
OSG: node * terrainnode = new OSG: node ();
Osgviewer: viewer;
Terrainnode = osgdb: readnodefile ("// models // joedirt. Flt ");
If (! Terrainnode)
{
STD: cout <"couldn't load models, quitting." <STD: Endl;
Return-1;
}
Rootnode-> addchild (terrainnode );
OSG: node * tanknode = osgdb: readnodefile ("// models // T72-Tank // T72-tank_des.flt ");
If (! Tanknode)
{
STD: cout <"No tank" <STD: Endl;
Return-1;
}
The basic procedure for creating a particle system is to create a particle system object, an Updater object, and a particle object, and set the scenario at the same time.
// Create and initialize the particle system.
Osgparticle: Maid * dustparticle system = new osgparticle: Particle System;
// Set the material, whether to emit particles, and whether to use light.
Dustparticipant lesystem-> setdefaattriattributes (dust2.rgb ", false, false );
// Because the particle system class inherits from the drawable class, we can add it as a subnode of geode to the scenario.
OSG: geode * geode = new OSG: geode;
Rootnode-> addchild (geode );
Geode-> adddrawable (dustparticipant lesystem );
// Add an Updater to manage the particles of each frame.
Osgparticle: Maid * dustsystemupdater = new osgparticle: maid;
// Associate the Updater with a particle system object.
Dustsystemupdater-> addparticipant lesystem (dustparticipant lesystem );
// Add the Updater node to the scene.
Rootnode-> addchild (dustsystemupdater );
// Create a particle object and set its attributes for use by the particle system.
Osgparticle: particle smokeparticle;
Smokeparticle. setsizerange (osgparticle: rangef (0.01, 20.0); // unit: Meter
Smokeparticle. setlifetime (4); // unit: seconds
Smokeparticle. setmass (0.01); // unit: kg
// Set as the default particle object of the particle system.
Dustparticle system-> setdefaparticparticle template (smokeparticle );
The following code uses a standard radiation pole object to set some basic parameters of a particle: for example, the number of particles created per frame, the position where the new particles are generated, and the velocity of the new particles.
// Create a standard emitter object. (Including default counters, receivers, and transmitters)
Osgparticle: modularemitter * emitter = new osgparticle: modularemitter;
// Associate the emitter object with the particle system.
Emitter-> setparticipant lesystem (dustparticipant lesystem );
// Obtain the handle of the default counter in the emitter pole and adjust the number of new particles added to each frame.
Osgparticle: randomratecounter * dustrate =
Static_cast <osgparticle: randomratecounter *> (emitter-> getcounter ());
Dustrate-> setraterange (5, 10); // 5 to 10 new particles are generated every second.
// Customize a tolerance. Here we create and initialize a multipart tolerance.
Osgparticle: multisegmentplacer * linesegment = new osgparticle: multisegmentplacer ();
// Add a vertex to the placement device, that is, to define the position of the line segment when the particle is generated.
// (If the tanks and standard emitter poles are defined in the same position, we can implement
// Effect of dust particles on the extension line below the tank model .)
Linesegment-> addvertex (0, 0,-2 );
Linesegment-> addvertex (0,-2,-2 );
Linesegment-> addvertex (0,-16, 0 );
// Set the placement device for the standard emitter pole.
Emitter-> setplacer (linesegment );
// Customize a transmitter. Here we create and initialize a radialshooter radian transmitter.
Osgparticle: radialshooter * smokeshooter = new osgparticle: radialshooter ();
// Set the attributes of the transmitter.
Smokeshooter-> setthetarange (0.0, 3.14159/2); // radian value, with the Z axis angle.
Smokeshooter-> setinitialspeedrange (50,100); // unit: meter/second
// Set the transmitter for the standard emitter pole.
Emitter-> setshooter (smokeshooter );
Now we will add the emitter pole and tank model as the subnode of the transform node to the scene. The positions of the emitter pole and tank are determined by the conversion node. The placement device just defined will arrange the position of the particle Based on the transformed parameters.
OSG: matrixtransform * tanktransform = new OSG: matrixtransform ();
Tanktransform-> setupdatecallback (new orbit (); // callback function to make the node move cyclically.
// Add the radiation pole and tank model to the subnode of the transformed node.
Tanktransform-> addchild (emitter );
Tanktransform-> addchild (tanknode );
Rootnode-> addchild (tanktransform );
The following code creates a standard programmer modularprogram instance to control the update of particles in the lifecycle. The standard programmer object uses the operator calculator to control particles.
// Create a standard programmer object and associate it with the particle system.
Osgparticle: modularprogram * movedustinair = new osgparticle: modularprogram;
Movedustinair-> setparticipant lesystem (dustparticipant lesystem );
// Create a calculator object to simulate gravity, adjust its parameters, and add it to the programmer object.
Osgparticle: acceloperator * accelup = new osgparticle: acceloperator;
Accelup-> settogravity (-1); // you can specify a scaling factor for gravity acceleration.
Movedustinair-> addoperator (accelup );
// Add a calculator object to the programmer to calculate the air resistance.
Osgparticle: fluidfrictionoperator * airfriction = new osgparticle: fluidfrictionoperator;
Airfriction-> setfluidtoair ();
Movedustinair-> addoperator (airfriction );
// Finally, add the programmer to the scene.
Rootnode-> addchild (movedustinair );
The following code is the content of the simulation loop.
Viewer. setcameramanipulator (New osgga: trackballmanipulator ());
Viewer. setscenedata (rootnode );
Viewer. Realize ();
While (! Viewer. Done ())
{
Viewer. Frame ();
}
Return 0;