Particle Script: Difference between revisions

18,432 bytes added ,  29 February 2016
Replace woefully inaccurate guesses with properly researched discoveries
imported>Jackoalan
m (Jackoalan moved page Effect Script to Particle Script: "Particle" is the canonical encompassing term (CParticleGen being the relevant superclass))
imported>Jackoalan
(Replace woefully inaccurate guesses with properly researched discoveries)
Line 1: Line 1:
{{research|1|Details are subject to corrections}}
{{research|1|Elements beyond MP1 need to be discovered and documented}}
Retro games feature a uniform, fixed-function '''Effect Script''' system for describing various geometrical effects and weapon systems.  
Retro games feature a uniform, fixed-function '''Particle Script''' system for describing various geometrical effects and weapon systems.  
The PAK archives contain binary resources using [[wikipedia:FourCC|FourCCs]] to build a [[wikipedia:Associative_array|key-value dictionary]].  
The PAK archives contain binary resources using [[wikipedia:FourCC|FourCCs]] to build a [[wikipedia:Associative_array|key-value dictionary]].  
These codes correspond to application-specific parameters controlling the effect system in question.
These codes correspond to application-specific parameters controlling the system in question.


The binary script format uses a grammar that supports <code>bool</code>, <code>int</code>, <code>float</code>, <code>float3</code>, and <code>float4</code>  
The scripts use a [[wikipedia:Dataflow programming|dataflow paradigm]] built around value-generating ''element'' classes of the following types:
parameters to be evaluated and assigned to the dictionary. In addition, the various effect systems provide dynamic node classes that are evaluated as part of the effect runtime.  
 
Ultimately, the systems use a recursive, node-based approach of generating animated scalar and vector values to control the effect.
* [[#Int Elements|Int]]
* [[#Real Elements|Real]] (float)
* [[#Vector Elements|Vector]] (3-component float)
* [[#Mod Vector Elements|Mod Vector]] (3-component float)
** Local velocity vector in/out
** Local position vector in/out
* [[#Color Elements|Color]] (4-component float, internally converted to RGBA8)
* [[#UV Elements|UV]] ([[TXTR_(File_Format)|TXTR]] reference and [[wikipedia:UV_mapping|UV coordinate]] source)
* [[#Emitter Elements|Emitter]]
** Initial local position vector (3-component float)
** Initial local velocity vector (3-component float)
 
The system features several subclasses that output generated values through <code>GetValue</code> as a function of the current frame index.
These implementations may recursively accept input from other elements, permitting effect designs of scalable complexity.


== File Layout ==
== File Layout ==


All effect script file formats use a context-sensitive, free-form layout to build the key-value dictionary.
All effect script file formats are read linearly to populate a ''description'' tree of element nodes, serving as a template to build an arbitrary number of ''generator'' instances:


* Script Magic FourCC (see [[#Script Types|table below]])
* Script Magic FourCC (see [[#Script Types|table below]])
* Entries
* Parameters
** Key FourCC (see [[#Script Types|script-format articles]])
** Key FourCC
** Value Parameter(s) (one of:)
** Value Parameter(s) (one of:)
*** <code>CNST</code>: Bool/Scalar/Vector literal
*** <code>NONE</code>: null value (equivalent to not specifying the key at all)
**** bool/int/float/float3/float4 value
*** Element FourCC ([[#Elements|see below]])
*** <code>NONE</code>: Dummy value (equivalent to not specifying the key at all)
**** Child Elements (count/types according to parent)
*** Node Key ([[#Script Nodes|see below]])
**** Node Parameters
* <code>_END</code>
* <code>_END</code>


Line 32: Line 43:
|[[PART (File Format)|PART]]
|[[PART (File Format)|PART]]
|<code>GPSM</code>
|<code>GPSM</code>
|Particle effect
|Particle element generator
|-
|-
|[[SWHC (File Format)|SWHC]]
|[[SWHC (File Format)|SWHC]]
|<code>SWSH</code>
|<code>SWSH</code>
|Swoosh effect
|Swoosh generator
|-
|-
|[[ELSC (File Format)|ELSC]]
|[[ELSC (File Format)|ELSC]]
|<code>ELSM</code>
|<code>ELSM</code>
|Electric effect
|Electric generator
|-
|-
|[[DPSC (File Format)|DPSC]]
|[[DPSC (File Format)|DPSC]]
|<code>DPSM</code>
|<code>DPSM</code>
|Decal effect
|Decal generator
|-
|-
|[[WPSC (File Format)|WPSC]]
|[[WPSC (File Format)|WPSC]]
Line 55: Line 66:
|}
|}


== Script Nodes ==
== Elements ==
 
Many of the animated qualities in particle scripts are achieved with dynamic ''elements''.
These elements provide I/O interfaces and internally process numeric data that passes through.
They may also gather data from other sources within the particle system's state.
 
=== Int Elements ===
 
{| class="wikitable"
! FourCC
! Parameters
! Description
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|ADD_|IntElement&nbsp;a, IntElement&nbsp;b|Add|Returns ''a'' + ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CHAN|IntElement&nbsp;a, IntElement&nbsp;b, IntElement&nbsp;thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CLMP|IntElement&nbsp;min, IntElement&nbsp;max, IntElement&nbsp;val|Clamp|Returns ''val'' clamped between ''min'' and ''max''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CNST|s32&nbsp;value|Constant|Returns ''value'' on every call|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|DETH|IntElement&nbsp;passthrough, IntElement&nbsp;thresholdFrame|Death|Always returns ''passthrough'', and signals out-of-band to cease updating the system when the current frame index exceeds ''thresholdFrame''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GAPC||{{unknown|'''Unknown'''}}||{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GEMT||{{unknown|'''Unknown'''}}||{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GTCP||{{unknown|'''Unknown'''}}||{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|ILPT|IntElement&nbsp;percent|Lifetime Percent|Queries the frame index at ''percent''/100.0 into the lifetime of the particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|IMPL|IntElement&nbsp;val|Impulse|Returns ''val'' ONLY at frame index 0, then returns 0 for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|IRND|IntElement&nbsp;a, IntElement&nbsp;b|Initial Random|Rolls a random value between ''a'' and ''b'' on frame index 0; returns that value for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYE|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of synchronized animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYP|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of percentage-tweened animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|MODU|IntElement&nbsp;a, IntElement&nbsp;b|Modulo|Returns ''a'' % ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|MULT|IntElement&nbsp;a, IntElement&nbsp;b|Multiply|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PULS|IntElement&nbsp;aDuration, IntElement&nbsp;bDuration, IntElement&nbsp;a, IntElement&nbsp;b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|RAND|IntElement&nbsp;a, IntElement&nbsp;b|Random|Rolls a random value between ''a'' and ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SPAH|IntElement&nbsp;val, IntElement&nbsp;waitMin, IntElement&nbsp;waitMax|Sample And Hold|Stores ''val'' for a random count of frames between ''waitMin'' and ''waitMax'' and repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SUB_|IntElement&nbsp;a, IntElement&nbsp;b|Subtract|Returns ''a'' - ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|TSCL|RealElement&nbsp;dv|Time Scale|Returns ''dv'' times the current frame index (rounding down to nearest integer)|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}
 
=== Real Elements ===
 
{| class="wikitable"
! FourCC
! Parameters
! Description
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|ADD_|RealElement&nbsp;a, RealElement&nbsp;b|Add|Returns ''a'' + ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CEQL|RealElement&nbsp;ca, RealElement&nbsp;cb, RealElement&nbsp;pass, RealElement&nbsp;fail|Compare Equals|Returns ''pass'' if ''ca'' and ''cb'' are within 0.00001 difference, otherwise ''fail''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CEXT|IntElement&nbsp;a|{{unknown|'''Unknown'''}}|Involves a lookup table|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CHAN|RealElement&nbsp;a, RealElement&nbsp;b, IntElement&nbsp;thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CLMP|RealElement&nbsp;min, RealElement&nbsp;max, RealElement&nbsp;val|Clamp|Returns ''val'' clamped between ''min'' and ''max''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CLTN|RealElement&nbsp;ca, RealElement&nbsp;cb, RealElement&nbsp;pass, RealElement&nbsp;fail|Compare Less-Than|Returns ''pass'' if ''ca'' is less-than ''cb'', otherwise ''fail''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CNST|float&nbsp;value|Constant|Returns ''value'' on every call|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CRNG|RealElement&nbsp;val, RealElement&nbsp;min, RealElement&nbsp;max, RealElement&nbsp;inRange, RealElement&nbsp;outOfRange|Constant Range|Returns ''inRange'' if ''val'' is between ''min'' and ''max'', otherwise ''outOfRange''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|DOTP|VectorElement&nbsp;a, VectorElement&nbsp;b|[[wikipedia:Dot product|Dot Product]]|Returns ''a'' · ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GTCR|ColorElement color|Get Component Red|Extracts red component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GTCG|ColorElement color|Get Component Green|Extracts green component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GTCB|ColorElement color|Get Component Blue|Extracts blue component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GTCA|ColorElement color|Get Component Alpha|Extracts alpha component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|IRND|RealElement&nbsp;a, RealElement&nbsp;b|Initial Random|Rolls a random value between ''a'' and ''b'' on frame index 0; returns that value for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|ISWT|RealElement&nbsp;a, RealElement&nbsp;b|Initial Switch|Returns ''a'' ONLY at frame index 0, then returns ''b'' for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|ITRL|IntElement&nbsp;a, RealElement&nbsp;b|Int Times Real|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYE|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of synchronized animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYP|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of percentage-tweened animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|LFTW|RealElement&nbsp;a, RealElement&nbsp;b|Lifetime Tween|Linearly-interpolates ''a'' to ''b'' over the lifetime of the particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|MULT|RealElement&nbsp;a, RealElement&nbsp;b|Multiply|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PAPn||Particle System Advance Parameter|Accesses the value stored into ADV[1-8] for each system update|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PRLW||Particle Rotation or Line Width|Returns the rotation (in degrees) or line width for the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PSLL||Particle Size or Line Length|Returns the size or line length for the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PULS|IntElement&nbsp;aDuration, IntElement&nbsp;bDuration, RealElement&nbsp;a, RealElement&nbsp;b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|RAND|RealElement&nbsp;a, RealElement&nbsp;b|Random|Rolls a random value between ''a'' and ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|RLPT|RealElement&nbsp;percent|Lifetime Percent|Queries the frame index at ''percent''/100.0 into the lifetime of the particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SCAL|RealElement&nbsp;dv|Time Scale|Returns ''dv'' times the current frame index|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SINE|RealElement&nbsp;magnitude, RealElement&nbsp;linearAngle, RealElement&nbsp;constantAngle|Sine Wave|Returns sin((curFrame * ''linearAngle'' + ''constantAngle'') * π / 180.0) * ''magnitude''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SUB_|RealElement&nbsp;a, RealElement&nbsp;b|Subtract|Returns ''a'' - ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|VMAG|VectorElement&nbsp;vec|Vector Magnitude|Computes magnitude (length) of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|VXTR|VectorElement&nbsp;vec|Vector X To Real|Extracts X component of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|VYTR|VectorElement&nbsp;vec|Vector Y To Real|Extracts Y component of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|VZTR|VectorElement&nbsp;vec|Vector Z To Real|Extracts Z component of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}
 
=== Vector Elements ===
 
{| class="wikitable"
! FourCC
! Parameters
! Description
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|ADD_|VectorElement&nbsp;a, VectorElement&nbsp;b|Add|Returns ''a'' + ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|ANGC|RealElement&nbsp;angleXBias, RealElement&nbsp;angleYBias, RealElement&nbsp;angleXRange, RealElement&nbsp;angleYRange, RealElement&nbsp;magnitude|Angle Cone|Generates a random vector based on (0,0,1) rotated about the X/Y axis. The angles of rotation (in degrees) are set by random ranges ''angleXRange'' and ''angleYRange'', centered around non-random ''angleXBias'' and ''angleYBias''. The resulting vector's length is set as ''magnitude''.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CCLU|VectorElement&nbsp;circleOffset, VectorElement&nbsp;circleNormal, IntElement&nbsp;cycleFrames, RealElement&nbsp;randomFactor|Circle Cluster|Generates a vector along an angular sweep of a unit-circle offset by ''circleOffset'', oriented according to ''circleNormal''. The sweep makes a full rotation within the circle over ''cycleFrames''. The resulting vector has a randomized 3D jitter added; scaled by ''randomFactor'' times the intermediate magnitude.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CHAN|VectorElement&nbsp;a, VectorElement&nbsp;b, IntElement&nbsp;thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CIRC|VectorElement&nbsp;circleOffset, VectorElement&nbsp;circleNormal, RealElement&nbsp;angleConstant, RealElement&nbsp;angleLinear, RealElement&nbsp;circleRadius|Circle|Generates a vector along an angular sweep of a circle of ''circleRadius'' offset by ''circleOffset'' oriented according to ''circleNormal''. The sweep angle (in degrees) is calculated as (''angleLinear'' * curFrame + ''angleConstant'').|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CNST|RealElement&nbsp;x, RealElement&nbsp;y, RealElement&nbsp;z|Constant|Composes a vector from 3 float components. If all 3 components are ''Constant'', then the internal representation is an optimized <code>CVector3f</code> data-structure.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CONE|VectorElement&nbsp;direction, RealElement&nbsp;baseRadius|Cone|Generates a vector within a cone directed towards ''direction''; with the cone's base limited by min(1.0, ''baseRadius'')|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CTVC|ColorElement color|Color To Vector|Converts RGB components of ''color'' to a 3-component vector|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYE|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of synchronized animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYP|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of percentage-tweened animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|MULT|VectorElement&nbsp;a, VectorElement&nbsp;b|Multiply|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PLCO||Previous Particle Location|Accesses the location (world space) of the current particle instance on the previous frame (or current frame if at frame 0)|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PLOC||Particle Location|Accesses the location (world space) of the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PSOF||Particle System Forward|Accesses the local forward-pointing vector of the current particle system, oriented in world space|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PSOU||Particle System Up|Accesses the local up-pointing vector of the current particle system, oriented in world space|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PSOR||Particle System Right|Accesses the local right-pointing vector of the current particle system, oriented in world space|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PSTR||Particle System Translation|Accesses the translation vector (world space) of the current particle system|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PULS|IntElement&nbsp;aDuration, IntElement&nbsp;bDuration, VectorElement&nbsp;a, VectorElement&nbsp;b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PVEL||Particle System Velocity|Accesses the velocity vector (world space) of the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|RTOV|RealElement&nbsp;val|Real To Vector|Assigns ''val'' to all 3 components of the returned vector|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SUB_|VectorElement&nbsp;a, VectorElement&nbsp;b|Subtract|Returns ''a'' - ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}


Many of the animated qualities in effect scripts are achieved with dynamic ''script nodes''.
=== Mod Vector Elements ===
These nodes provide parameter I/O interfaces and internally process numeric data that passes through.
They may also gather data from other sources within the effect system.


'''Scope''' is one of (''Constant'', ''System'', ''Particle'', ''Auto'')
{| class="wikitable"
! FourCC
! Parameters
! Description
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|BNCE|VectorElement&nbsp;planePoint, VectorElement&nbsp;planeNormal, RealElement&nbsp;friction, RealElement&nbsp;restitution, bool&nbsp;dieOnPenetrate|Bounce|Maintains the state of an unbounded plane in local space, defined by ''planePoint'' and ''planeNormal''. If the particle's position penetrates this plane, it will either be destroyed if ''dieOnPenetrate'' is set, or a [[wikipedia:Deflection_(physics)|deflection]] will occur. This deflection accounts for [[wikipedia:Friction#Coefficient_of_friction|''friction'']] along the plane and [[wikipedia:Coefficient_of_restitution|''restitution'']] of the objects represented by the particles.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CHAN|ModVectorElement&nbsp;a, ModVectorElement&nbsp;b, IntElement&nbsp;thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CNST|RealElement&nbsp;x, RealElement&nbsp;y, RealElement&nbsp;z|Constant|Composes a mod vector from 3 float components. If all 3 components are ''Constant'', then the internal representation is an optimized <code>CVector3f</code> data-structure. This vector overrides the particle's velocity in units/frame.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|EMPL|VectorElement&nbsp;implodePoint, RealElement&nbsp;velocityScale, RealElement&nbsp;maxRadius, RealElement&nbsp;minRadius, bool&nbsp;enableMinRadius|Exponential Implosion|Integrates a cumulative implosion force over time by influencing the velocity of particles within ''maxRadius'' of ''implodePoint'' (and outside ''minRadius'' if ''enableMinRadius'' set). The velocity of these particles is set as (particleVelocity + ''velocityScale'' * (''implodePoint'' - particlePosition)) units/frame.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|EXPL|RealElement&nbsp;impulseMagnitude, RealElement&nbsp;falloffFactor|Explode|Rolls a random, normalized vector scaled by ''impulseMagnitude'' on frame 0 and sets this as the particle's velocity in units/frame. Subsequent frames multiply the velocity by ''falloffFactor''.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|GRAV|VectorElement&nbsp;acceleration|Gravity|Integrates a simple cumulative ''acceleration'' in units/frame<sup>2</sup>|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|IMPL|VectorElement&nbsp;implodePoint, RealElement&nbsp;velocityScale, RealElement&nbsp;maxRadius, RealElement&nbsp;minRadius, bool&nbsp;enableMinRadius|Implosion|Integrates a cumulative implosion force-differential over time by influencing the velocity of particles within ''maxRadius'' of ''implodePoint'' (and outside ''minRadius'' if ''enableMinRadius'' set). The velocity of these particles is set as (particleVelocity + (''velocityScale'' / magnitude(''implodePoint'' - particlePosition)) * (''implodePoint'' - particlePosition)) units/frame.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|LMPL|VectorElement&nbsp;implodePoint, RealElement&nbsp;velocityScale, RealElement&nbsp;maxRadius, RealElement&nbsp;minRadius, bool&nbsp;enableMinRadius|Linear Implosion|Integrates a non-cumulative implosion force-differential over time by influencing the velocity of particles within ''maxRadius'' of ''implodePoint'' (and outside ''minRadius'' if ''enableMinRadius'' set). The velocity of these particles is set as ((''velocityScale'' / magnitude(''implodePoint'' - particlePosition)) * (''implodePoint'' - particlePosition)) units/frame.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PULS|IntElement&nbsp;aDuration, IntElement&nbsp;bDuration, ModVectorElement&nbsp;a, ModVectorElement&nbsp;b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SPOS|VectorElement&nbsp;pos|Set Position|Overrides the particle's position as ''pos''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SWRL|VectorElement&nbsp;helixPoint, VectorElement&nbsp;curveBinormal, RealElement&nbsp;targetRadius, RealElement&nbsp;tangentialVelocity|SWRL|Maintains a curve differential along a [[wikipedia:Helix|helix]] using a system derived from the [[wikipedia:Frenet–Serret_formulas|Frenet–Serret formulas]]. The helical axis crosses through ''helixPoint'' in local space, oriented along ''curveBinormal''. The particle's velocity is continuously updated to maintain ''targetRadius'' from the helical axis, while traveling along the curve tangent at ''tangentialVelocity'' units/frame.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|WIND|VectorElement&nbsp;windVelocity, RealElement&nbsp;factor|Wind|Integrates a cumulative force outside the particle's local reference; computed as ((''windVelocity'' - particleVelocity) * ''factor'') units/frame<sup>2</sup>|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}


* ''Constant'' parameters are evaluated once initially and retained within the system.
=== Color Elements ===
* ''System'' parameters are evaluated per-system, per-frame.
* ''Particle'' parameters are evaluated per-system, per-frame, per-particle-instance.
* ''Auto'' parameters select their scope based on the node's parent context.


{| class="wikitable"
{| class="wikitable"
!Signature
! FourCC
!Scope
! Parameters
!Description
! Description
!Notes
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|CFDE|ColorElement&nbsp;a, ColorElement&nbsp;b, RealElement&nbsp;startFrame, RealElement&nbsp;endFrame|Fade End|Returns ''a'' before ''startFrame'' and ''b'' after ''endFrame'', otherwise a linear-interpolation from ''a'' to ''b'' in-between.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CHAN|ColorElement&nbsp;a, ColorElement&nbsp;b, IntElement&nbsp;thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|CNST|RealElement&nbsp;r, RealElement&nbsp;g, RealElement&nbsp;b, RealElement&nbsp;a|Constant|Composes a color from 4 float components. If all 4 components are ''Constant'', then the internal representation is an optimized <code>CColor</code> data-structure.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|FADE|ColorElement&nbsp;a, ColorElement&nbsp;b, RealElement&nbsp;endFrame|Fade|Returns ''b'' after ''endFrame'', otherwise a linear-interpolation from ''a'' to ''b'' between frame 0 and ''endFrame''.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYE|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of synchronized animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|KEYP|[[#Keyframe Emitter Template|KeyframeEmitterData]]&nbsp;data|Keyframe Emitter|List of percentage-tweened animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PCOL||Particle Color|Accesses the color of the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|PULS|IntElement&nbsp;aDuration, IntElement&nbsp;bDuration, ColorElement&nbsp;a, ColorElement&nbsp;b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}
 
=== UV Elements ===
 
<div class="thumb tright">
<div class="thumbinner" style="width:130px;">
[[File:ATEX_example.png]]
[[File:ATEX_example_crunchy.gif]]
<!--
<style type="text/css">
.atex
{
  width: 32px;
  height: 32px;
  background: url('/retromodding/images/9/99/ATEX_example_css.png') left center;
  zoom: reset;
  animation: play .8s steps(16) infinite;
}
@keyframes play
{
  100% { background-position: -512px; }
}
</style>
<div class="atex"></div>
-->
<div class="thumbcaption">Example of an ATEX map used in the closing cinematic (spoilers)</div>
</div>
</div>
 
{| class="wikitable"
! FourCC
! Parameters
! Description
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|CNST|[[TXTR_(File_Format)|TXTR]]&nbsp;tex|Constant|References ''tex'' for sampling using constant UV rectangle points (0,0) (1,1)|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|ATEX|[[TXTR_(File_Format)|TXTR]]&nbsp;tex, IntElement&nbsp;tileW, IntElement&nbsp;tileH, IntElement&nbsp;strideW, IntElement&nbsp;strideH, IntElement&nbsp;cycleFrames, bool&nbsp;loop|Animated Texture|References ''tex'' for sampling using UV tiles scanned left-to-right, top-to-bottom as individual frames of animation. The UV coordinates are scaled and offset using the ''tile'' and ''stride'' parameters in texels. All tiles of the image are played over the course of ''cycleFrames''. If ''loop'' is set, the tiles repeat, otherwise lingers on the final tile.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}
 
=== Emitter Elements ===
 
{| class="wikitable"
! FourCC
! Parameters
! Description
! Notes
! MP1
! MP2
! MP3
! DKCR
! DKCTF
{{ParticleElementRow|SETR/SEMR|VectorElement&nbsp;position, VectorElement&nbsp;velocity|Simple Emitter|Directly initializes new particle instances with ''position'' and ''velocity'' arguments. The only difference with <code>SETR</code> is the ''position'' argument is tagged with <code>ILOC</code> and ''velocity'' is tagged with <code>IVEC</code>, theoretically making the parameters optional or re-orderable.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|SPHE|VectorElement&nbsp;sphereOrigin, RealElement&nbsp;sphereRadius, RealElement&nbsp;velocity|Sphere|Randomly initializes new particle positions along the surface of a sphere defined by ''sphereOrigin'' and ''sphereRadius''. The resulting velocity vector is computed from the ''sphereOrigin'' to this random point, with the magnitude set as ''velocity''.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
{{ParticleElementRow|ASPH|VectorElement&nbsp;sphereOrigin, RealElement&nbsp;sphereRadius, RealElement&nbsp;velocity, RealElement&nbsp;angleXBias, RealElement&nbsp;angleYBias, RealElement&nbsp;angleXRange, RealElement&nbsp;angleYRange|Angle Sphere|Randomly initializes new particle positions along the surface of an angular sphere-section defined by ''sphereOrigin'' and ''sphereRadius''. The angular section is based on position (0,0,1) rotated about the X/Y axis, randomized within ''angleXRange'' and ''angleYRange'' centered around ''angleXBias'' and ''angleYBias''. The resulting velocity vector is computed from the ''sphereOrigin'' to this random point, with the magnitude set as ''velocity''.|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
|}
 
=== Keyframe Emitter Template ===
 
<code>KEYE</code> and <code>KEYP</code> elements statically encode a list of key values for all element types (except Mod Vector, UV and Emitter elements).
''T'' represents the type being encoded.
 
{| class="wikitable"
! Data Type
! Description
! Notes
|-
|-
|<code>'''SETR'''(ILOC=float3 location_vector, IVEC=float3 velocity_vector)</code>
| u32
|System
| Percentage-Tweening Flag
|Point emitter
| If non-zero, this is a <code>KEYP</code> and there are exactly 101 keys in the list; all of these keys are linearly-interpolated over the lifetime of the particle instance (however long that may be)
|Used with <code>EMTR</code> attachment to produce particle instances
|-
|-
|<code>'''SEMR'''(float3 location_vector, float3 velocity_vector)</code>
| u32
|System
| {{unknown|'''Unknown'''}}
|Point emitter
| Not used by <code>GetValue</code>
|Seems to be similar to <code>SETR</code>
|-
|-
|<code>'''SPHE'''(float3 local_sphere_origin, float radius, float radial_velocity)</code>
| u8
|System
| Loop Flag
|Sphere emitter
| If non-zero, the key values are looped between ''loopStart'' and ''loopEnd'' indices (does not apply to <code>KEYP</code>)
|Emits particles from a sphere-surface
|-
|-
|<code>'''ASPH'''(float3 local_sphere_origin, float x_ang_bias, float y_ang_bias, float x_ang_range, float y_ang_range, float radius, float radial_velocity)</code>
| u8
|System
| {{unknown|'''Unknown'''}}
|Partial sphere emitter
| Not used by <code>GetValue</code>
|Emits particles from a sphere-surface section
|-
|-
|<code>float '''SCAL'''(float value)</code>
| u32
|Particle
| Loop End
|Linear-lifetime interpolator
| Final key index in the loop
|Interpolates from 0.0 to <code>value</code> over particle's lifetime
|-
|-
|<code>int/float/float3/float4 '''ADD'''(int/float/float3/float4 a, int/float/float3/float4 b)</code>
| u32
|Auto
| Loop Start
|Value adder
| First key index in the loop
|Dynamically adds two parameters
|-
|-
|<code>int/float/float3/float4 '''SUB'''(int/float/float3/float4 a, int/float/float3/float4 b)</code>
| u32
|Auto
| Key Count
|Value subtractor
| Count of keys encoded in the list
|Dynamically subtracts two parameters
|-
|-
|<code>int/float/float3/float4 '''MULT'''(int/float/float3/float4 a, int/float/float3/float4 b)</code>
| T[keyCount]
|Auto
| Keys
|Value multiplier
| The actual key values themselves
|Dynamically multiplies two parameters
|-
|<code>float '''CLMP'''(float low, float high, float val)</code>
|Auto
|Value clamp
|Dynamically clamps <code>val</code> between <code>low</code> and <code>high</code>
|-
|<code>int '''RLPT'''(float lifetime_percent)</code>
|Particle
|Resolve frame-index from lifetime percentage
|Computes the frame on which the particle will reach a specified lifetime-percent (0-100)
|-
|<code>float '''ISWT'''(float c, float v)</code>
|Auto
|Linear equation evaluator
|Evaluates <code>v * frame_index + c</code>
|-
|<code>int/float '''RAND'''(int/float low, int/float high)</code>
|System
|Pseudo-random number generator
|Generates a random number between <code>low</code> and <code>high</code>
|-
|<code>int/float '''IRND'''(int/float low, int/float high)</code>
|Particle
|Instance-cached pseudo-random number generator
|Generates a random number between <code>low</code> and <code>high</code> and retains the value for each particle instance
|-
|<code>float '''LFTW'''(float a, float b)</code>
|Particle
|Triangle-wave generator
|Generates a triangle-wave cycle over the particle instance's lifetime. Evaluates <code>a</code> at 0% lifetime, <code>b</code> at 50% lifetime, then back to <code>a</code> at 100% lifetime
|-
|<code>int/float/float3/float4 '''CHAN'''(int/float/float3/float4 a, int/float/float3/float4 b, int f)</code>
|Particle
|Time-based parameter switch
|Evaluates <code>a</code> before particle instance reaches frame index <code>f</code>; evaluates <code>b</code> afterwards
|-
|<code>float3 '''RTOV'''(float val)</code>
|Auto
|Scalar to vector (vector splat)
|Constructs a 3-component vector using <code>val</code> for each component
|-
|<code>int/float/float3/float4 '''PULS'''(int pulse_start_frame, int pulse_frame_count, int/float/float3/float4 a, int/float/float3/float4 b)</code>
|Particle
|Pulsing duty-cycle switch (periodic <code>CHAN</code>)
|Evaluates <code>a</code> until <code>pulse_start_frame</code> is reached, then evaluates <code>b</code> for <code>pulse_frame_count</code> frames. This cycle repeats indefinitely
|-
|<code>float '''SINE'''(float magnitude, float v, float c)</code>
|Auto
|Animated sine function
|<code>v</code> and <code>c</code> are in degrees. Evaluates <code>sin(v * frame_index + c) * magnitude</code>
|-
|<code>int/float/float3/float4 '''KEYE'''(&lt;key-array&gt;)</code>
|System
|Emitter-based key array
|Stores an array of values; one for each frame of the emitter's lifetime; with clamped-extrapolation
|-
|<code>int/float/float3/float4 '''KEYP'''(&lt;key-array&gt;)</code>
|Particle
|Particle-based key array
|Stores an array of 100 values; one for each percentage point of the particle instance's lifetime
|-
|<code>float '''PAPn'''()</code>
|Auto
|<code>ADVn</code> access token (1-8)
|Access the value evaluated for one of the <code>ADVn</code> keys in the particle system
|-
|<code>float '''PSLL'''()</code>
|–
|–
|–
|-
|<code>float '''PRLW'''()</code>
|–
|–
|–
|-
|<code>float '''PSOF'''()</code>
|–
|–
|–
|-
|<code>float '''VMAG'''(float3 v)</code>
|Auto
|Vector magnitude calculator
|Evaluates <code>sqrt(v.x^2 + v.y^2, v.z^2)</code>
|-
|<code>float '''CLTN'''(float ca, float cb, float a, float b)</code>
|Auto
|Less-than evaluator switch
|If <code>ca &lt; cb</code> then evaluates <code>a</code>, else <code>b</code>
|-
|<code>float '''CEQL'''(float ca, float cb, float a, float b)</code>
|Auto
|Equal evaluator switch
|If <code>ca == cb</code> then evaluates <code>a</code>, else <code>b</code>
|-
|<code>float '''VXTR'''(float3 vec)</code>
|Auto
|X component of vector
|Extracts X component of vector
|-
|<code>float '''VYTR'''(float3 vec)</code>
|Auto
|Y component of vector
|Extracts Y component of vector
|-
|<code>float '''VZTR'''(float3 vec)</code>
|Auto
|Z component of vector
|Extracts Z component of vector
|-
|<code>float '''CEXT'''(int val)</code>
|–
|–
|–
|-
|<code>float '''ITRL'''(int a, float b)</code>
|–
|–
|–
|-
|<code>int '''GTCP'''()</code>
|–
|–
|–
|-
|<code>float '''MODU'''(float numerator, float denominator)</code>
|Auto
|Floating-point modulo
|Dynamically evaluates remainder-division as <code>numerator % denominator</code>
|-
|<code>int '''ILPT'''(int val)</code>
|Particle
|Clamp to particle frame-count
|Clamps <code>val</code> to count of frames in particle instance
|-
|<code>float4 '''FADE'''(float4 a, float4 b, float t)</code>
|Particle
|Time-based (0-end) linear interpolator
|Interpolates from <code>a</code> to <code>b</code> over particle instance's first <code>t</code> frames
|-
|<code>float4 '''CFDE'''(float4 a, float4 b, float s, float e)</code>
|Particle
|Time-based (start-end) linear interpolator
|Interpolates from <code>a</code> to <code>b</code> between particle instance's <code>s</code> and <code>e</code> frames
|-
|<code>float3 '''ANGC'''(float x_bias, float z_bias, float x_ang, float z_ang, float magnitude)</code>
|Auto
|Spherical-section random vector generator
|Generates a vector of <code>magnitude</code> adhering to the XZ-angular constraints provided
|-
|<code>float3 '''CIRC'''(float3 circle_offset, float3 circle_normal, float angle_bias, float angle_range, float magnitude)</code>
|Auto
|Circular-section random vector generator
|Generates a vector of <code>magnitude</code> adhering to the circular constraints provided
|-
|<code>float3 '''CONE'''(float3 cone_vector, float base_radius)</code>
|Auto
|Cone random vector generator
|Generates a random vector from the cone's tip to somewhere within its base
|-
|<code>'''WIND'''(float3 wind_vector, float drift_magnitude)</code>
|Particle
|Wind velocity source
|Integrates a non-accelerated force simulating directional wind with a randomized drift
|-
|<code>'''GRAV'''(float3 grav_vector)</code>
|Particle
|Gravity velocity source
|Integrates a continuously-accelerated force simulating gravitational pull
|-
|<code>'''SWRL'''(float3 helix_start, float3 helix_end, float angular_vel, float linear_vel)</code>
|Particle
|Swirl velocity source
|Integrates a helically-shaped force simulating a 'swirling' motion
|-
|<code>'''BNCE'''(float3 plane_point, float3 plane_normal, float ?, float ?, bool ?)</code>
|Particle
|Bounce velocity source
|Establishes a local plane in the system for particles to bounce off
|-
|<code>'''EXPL'''(float initial_velocity, float velocity_damping)</code>
|Particle
|Explosion velocity source
|Moves particle away from emitted position at <code>initial_velocity</code> while continuously applying <code>velocity_damping</code>
|-
|<code>'''IMPL'''(float3 implosion_point, float force, float ?, float ?, bool ?)</code>
|Particle
|Implosion velocity source?
|–
|-
|<code>'''EMPL'''(float3 point, float force, float ?, float ?, bool ?)</code>
|Particle
|–
|–
|-
|<code>'''LMPL'''(float3 point, float force, float ?, float ?, bool ?)</code>
|Particle
|–
|–
|-
|<code>float3 '''SPOS'''(float3 vec)</code>
|Particle
|Position delta
|Subtract from current particle instance position
|-
|<code>float3 '''PLCO'''()</code>
|Particle
|World Position
|Evaluate particle world position
|-
|<code>float3 '''PLOC'''()</code>
|Particle
|Local Position
|Evaluate particle local (emitter-space) position
|-
|<code>'''ATEX'''(int seg_w, int seg_h, int ?, int ?, int frame_rate, bool loop)</code>
|Particle
|Animated texture attachment
|Used in particle script's <code>TEXR</code> key to apply a UV-scanned animated texture
|}
|}


[[Category:File Formats]]
[[Category:File Formats]]
Anonymous user