APEX particle emitter actors output particles at the start of the particle pipeline. Presently there are three basic types of Emitter Authorable Objects. They are the Simple Shape Emitter, Air / Ground Emitter, and the Weapon Impact Emitter. The Air / Ground Emitters are special purpose emitters that emit particles relative to the ground. Finally the Weapon Impact Emitter outputs particles in response to a collision or an explosion.
The shape emitters can be one of these geometries, under the NvParameterized included reference, geometryType:
Within each of the shape geometry types is an emitterType which defines the frequency and position of the particles spawned in the emitter.:
The ApexEmitterActorParameters NvParameterized class contains the parameters necessary to create an Emitter Actor:
Please note that the particle emitter state does not reflect emitAssetParticles bool when an ApexEmitterActor is created. The application must still explicitely call ‘startEmit’ to get the emitter started.
Depending on the scene, overlap tests may become expensive. To prevent them from happening, leave both overlap mask strings empty on actor creation. The EmitterActorOverlapAABBSceneQuery profiler event is emitted during the overlap tests.
Particles are emitted after the application calls Scene::simulate() if the Emitter::startEmit() has been called. It is possible to emit particles just once by setting the persistent flag in startEmit() to false:
emitterActor->startEmit( false );
If the persistent flag is true, the emitter will emit particles every frame. Make note that the shaped emitter never takes into account particles that it emitted in previous frames for the density calculations.
The explicit geometry type makes the APEX emitter very flexible by allowing the user to create particles at specific positions and velocities. These particle positions and velocities may be stored in the asset where all actors have access to the lists. The actor can also hold its own particle positions and velocities. Note, particles stored in the asset can be emitted by any actor created by the asset, particles stored in the actor’s list may only be accessed by the actor. Example:
During runtime, to access an explicit emitter actor's asset particles:
emitterActor->getEmitterAsset()->getGeom()->isExplicitGeom()->getParticleList(...)
During runtime, to access an explicit emitter actor's particles:
emitterActor->isExplicitGeom()->getParticleList(...)
The emitAssetParticles member of the emitter actor’s NvParameterized parameters (ApexEmitterActorParameters) will switch whether or not the asset’s particle list is emitted by the actor. If this parameter is true, then only the particles added through the actor’s explicit geometry will be emitted.
When the geometry is explicit, the densityRange asset parameter actually becomes a particle spawn probability:
1.0 - all particles in the particle list will be spawned every frame
0.0 - no particles will be spawned
If particle velocites provided are zero, then a random value within the emitter asset’s velocityRange parameter is used.
Since the emitter actor will transform all particle positions to the emitter actor’s position, it is possible to set multiple poses for the emitter in one frame. Every time the EmitterActor::startEmit() method is called, the current pose is stored in an array and each individual pose is used to emit particles during the simulation.
The application can avoid position and velocity transformations on particles by leaving the pose at the non rotated origin and using absolute particle positions and velocities.
The impact emitter packages both particle emission events and explosion events into one actor. The application is expected to perform raycasts and determine the correct parameters to pass to the ImpactEmitterActor::registerImpact(...) method. The impact emitter asset and actor do not make any association between the physical material of the hit shape returned from the raycasts and the setID within the emitter.
It is expected that a game engine will already have physical material names, and these names can be stored as the event set name within the asset. All of the event set names (and their corresponding )may be retrieved using the ImpactEmitterAsset::getSetNames() method. To determine the a setID from a particular event set name, use the ImpactEmitterAsset::querySetID( const char * setName ) method.
The ground emitter is typically used to position ground debris around a player. As the player moves throughout the level, the emitter deposits particles on the ground. The pose of the ground emitter actor may be updated manually by calling GroundEmitterActor::setPose() or automatically with GroundEimtterActor::setAttachActor().
Ground emitters perform raycasts to determine where to place particles in a scene. If the application has not created its own MaterialLookupCallback class and registered it using GroundEmitterActor::setMaterialLookupCallback(), raycasts will be performed by the PhysX engine. These raycasts can be filtered using both an CollisionGroup bitmask and an GroupsMask.
The Named Resource Provider will callback in the NSCollisionGroupMask and NSCollisionGroup128 namespaces to retrieve both an CollisionGroup bitmask and an GroupsMask for the raycasts. If neither is provided, the raycast should collide with all objects. The application may set the NSCollisionGroup128 resource to NULL if GroupsMasks are not being used.
Every PhysX raycast will return an MaterialIndex (PxU16) for the physical material that was hit. This MaterialIndex needs to be mapped to one of the physical material strings listed in the emitter asset’s materialFactoryMapList. For each different physical material listed in the asset’s materialFactoryMapList, the Named Resource Provider will callback in the NSPhysicalMaterial namespace to fetch an MaterialIndex.
Here is a summary of the callbacks that the ground emitter may call:
Namespace | Reason |
---|---|
IOFX | A different IOFX could be used for each physical material listed in the materialFactoryMapList |
NSPhysicalMaterial | The physical material names must be mapped to MaterialIndex values by the application |
NSCollisionGroupMask | Raycasts may be filtered with a 32-bit bitmask of CollisionGroups (0xffffffff to hit everything) |
NSCollisionGroup128 | Raycasts may additionally be filtered with an GroupsMask, return 0 if GroupdsMasks are not used by the application |
Emitter asset previews are useful if a level editor wishes to place a representation of an emitter actor in a level.
The shaped emitter preview rendering will draw the geometry of the emitter.
Because impact emitter actors do not have a pose and simply receive impact locations from the application, they do not implement preview rendering
The ground emitter preview rendering will draw a cylinder that describes the refresh radius, upDirection, and spawnHeight.
To create an emitter preview class, get the default NvParameterized parameters from the asset using Asset::getDefaultAssetPreviewDesc(). Then set the pose and/or scale, then create the preview class using Asset::createApexAssetPreview():
//Initialized elsewhere depending on type of emitter asset being created
EmitterAsset *asset;
GroundEmitterAsset *asset;
//Common code which sets the asset preview descriptors
PxMat44 pose = PxMat44::identity();
pose.setPosition( physx::PxVec3( 0.0f, 10.0f, 0.0f ) );
NvParameterized::Interface* p = asset->getDefaultAssetPreviewDesc();
NvParameterized::setParamMat44(*p, "pose", pose);
NvParameterized::setParamF32(*p, "scale", 1.0f);
//Create emitter asset preview depending on type of emitter asset being created
mApexEmitterPreview = static_cast<EmitterPreview*>(asset.createApexAssetPreview( *p ));
mGroundEmitterPreview = static_cast<GroundEmitterPreview*>(asset.createApexAssetPreview( *p ));
The APEX Emitter Module provides different debug visualizations for the emitter actors (shaped, impact, and ground).
Click here for a list of the APEX Emitter debug visualization parameters
For general information on how to use debug visualization within APEX, please see Debug Visualization.
APEX Emitter outputs the following error and warning messages using the standard APEX error stream.
ERROR CODE | MESSAGE |
---|---|
APEX_INVALID_OPERATION | %s is not a valid descriptor class |
APEX_INTERNAL_ERROR | Could not create a new APEX Emitter parameter instance |
APEX_INTERNAL_ERROR | Cannot get NvParameterized handle for APEX Emitter geometry type. |
APEX_INTERNAL_ERROR | Could not initialize NvParameterized type: %s |
APEX_INTERNAL_ERROR | No matching NvParameterized type: %s |
APEX_INTERNAL_ERROR | IOFX, IOS, or IOS type not initialized |
APEX_INTERNAL_ERROR | No emitter geometry specified |
APEX_INTERNAL_ERROR | Invalid NvParameterized handle for name: eventSetList |
APEX_INTERNAL_ERROR | Cannot get NvParameterized handle for eventSet %d out of %d |
APEX_INTERNAL_ERROR | Could not access invalid NvParameterized eventSet |
APEX_INTERNAL_ERROR | Could not create a new Impact Emitter parameter instance |
APEX_INTERNAL_ERROR | Impact Emitter deserialization does not support versions before NvParameterized was added |
APEX_INTERNAL_ERROR | Invalid NvParameterized handle for name: eventSetList |
APEX_INTERNAL_ERROR | Cannot get NvParameterized handle for eventSet %d out of %d |
APEX_INTERNAL_ERROR | Could not initialize NvParameterized type: %s |
APEX_INTERNAL_ERROR | Invalid included NvParameterized type: %s |
APEX_DEBUG_INFO | IOS asset retrieval failure: %s |
APEX_DEBUG_INFO | IOS injector allocation failure |
APEX_DEBUG_WARNING | Not all objects have been emitted: |
APEX_DEBUG_WARNING | Unable to serialize an Emitter without a geometry |
APEX_DEBUG_WARNING | EmitterLodParamDesc version mismatch |
APEX_DEBUG_WARNING | Invalid eventSetName from Impact Emitter event sets |