Alamo Particle File Format

Introduction

Alamo Particle Files (extension: .ALO) in Petroglyph's games describe a set of particle emitters. Each emitter emits a certain type of particle with a certain interval. Alamo Particle Files are an instance of Chunked Files.

Format #1

Particle files with this format are used in the game "Star Wars: Empire at War" and its expansion pack "Star Wars: Empire at War: Forces of Corruption."

Alamo Particle File

00000900h: Particle System

This chunk is the container chunk for the particle system description

00000000h: Name

string name

This chunk holds the particle system's name as an ASCIIZ string. This name must match the filename without extension.

00000001h: ID

dword id

This chunk contains the particle system's ID. This is a value used internally in the editor and can be disregarded.

00000800h: Emitters

This chunk is the container chunk for the emitters in the particle system

00000700h: Emitter

This chunk is the container chunk for a single emitter in the particle system.

00000002h: Properties

04: dword    shader
05: uint     numAdditionalVertices
06: uint     unused1
07: byte     inBursts
08: byte     linkToSystem
09: float[3] inwardSpeed
10: float[3] acceleration
11: float    outwardAcceleration
12: float    gravity
15: float    lifetime
16: dword    numTextureElements
17: float    unused2
18: float    randomizedScale
19: float    randomizedLifetime
20: dword    index
21: byte     unused3
23: float    randomizedRotation
35: byte     rotationDirection
36: float    initialDelay
37: float    burstDelay
38: dword    numParticlesPerBurst
39: dword    numBursts
40: float    emitterSpeedMult
42: dword    numParticlesPerSecond
43: byte     unused4
44: float[4] randomizedColor
45: byte     randomizedIsGrayscale
46: byte     isNotBillboarded
47: dword    groundInteraction
48: float    bounciness
49: byte     affectedByWind
50: float    freezeTime
51: float    skipTime
52: dword    emitMode
53: byte     objectSpaceAcceleration
59: byte     isHeatParticle
60: float    emitOffset
61: byte     isWeatherParticle
62: float    unused5
63: float    weatherCubeSize
64: float    weatherFadeoutDistance
65: byte     hasTail
66: float    tailSize
67: byte     useEmitterSpeedMult
68: byte     windDisturbance
70: byte     noDepthTest
71: float    weatherCubeDistance
72: byte     randomizedRotationDirection

00000003h: Color texture name

string name

This chunk contains the name of the emitters's color texture as a single ASCIIZ string. This texture typically consists of multiple particle textures in one; the particular coordinates for this emitter's particles are determined by the index track and the number of elements in the texture.

00000016h: Name

string name

This chunk contains the emitters's name as a single ASCIIZ string. This value has no in-game use but is useful when editing the particle system.

00000029h: Property groups

This chunk contains three property groups that respectively describe each particle's initial speed, lifetime and position. The second group (lifetime) is special: the type is always set to "Box" (1) and the values are always set as follows: minX = maxX = 0;

minY = lifetime * (1 - randomizedLifetime);

maxY = lifetime;

minZ = maxZ = 0.0f;
The lifetime and randomizedLifetime are taken from the emitter properties (0002) chunk. As such this group contains redundant information and should be ignored when read.

00001100h: Property group

This chunk describes a single property group

00001101h: Data

dword type
float minX, minY, minZ
float maxX, maxY, maxZ
float sideLength
float sphereRadius
dword sphereEdge
float cylinderRadius
dword cylinderEdge
float cylinderHeight
float valX, valY, valZ

A property group describes a range of possible values a particle property can assume. When a particle is spawned, a value is chosen by random from the range and set as the particle's position or speed, depending on the group. The group contains several mutually exclusive fields that define the range of possible values depending on the type of range. The possible types (as stored in the 'type' field) are:

Exact

When the 'type' field is 0, (valX, valY, valZ) describes the exact value this property should be.

Example usage:

value = vector3(valX, valY, valZ);

Box

When the 'type' field is 1, the sideLength value describes the size of a cube centered at (0,0,0) within which the value for the property should be chosen

Example usage:

float half = sideLength / 2;

value = vector3(rnd(-half, half), rnd(-half, half), rnd(-half, half));

Cube

When the 'type' field is 2, (minX, minY, minZ) and (maxX, maxY, maxZ) describe the bounds of a box within which the value for the property should be chosen

Example usage:

value = vector3(rnd(minX, maxX), rnd(minY, maxY), rnd(minZ, maxZ));

Sphere

When the 'type' field is 3, the sphereRadius indicates the radius of a sphere. If sphereEdge is zero, the value can be any value contained within the sphere. If sphereEdge is non-zero, the value can only be a value on the edge of the sphere (i.e. length(value) = sphereRadius)

Example usage:

float t = rnd(-PI , PI );

float p = rnd(-PI/2, PI/2);

float r = sphereEdge ? sphereRadius : rnd(0, sphereRadius);

value = vector3(r*cos(p)*cos(t), r*cos(p)*sin(t), r*sin(p));

Cylinder

When the 'type' field is 4, the cylinderRadius and cylinderHeight values define a cylinder. If cylinderEdge is zero, the value can be any value contained within the cylinder. If cylinderEdge is non-zero, the value can only be a value on the (curved) edge of the cylinder (i.e., sqrt(x*x + y*y) = cylinderRadius)

Example usage:

float t = rnd(-PI, PI);

float r = cylinderEdge ? cylinderRadius : rnd(0, cylinderRadius);

value = vector3(r*cos(t), r*sin(t), rnd(0, cylinderHeight));

00000001h: Tracks

This chunks contains the seven tracks that define the following respective aspects of a particle during its lifetime:

Red channel, Green channel, Blue channel, Alpha channel, Scale, Texture index, Rotation speed

The red, green, blue and alpha channels speak for themselves. The scale track determines the size of the particle by scaling it with the specified amount. The texture index indicates the coordinates within the texture. Rotation speed indicates the speed of the current rotation. Note that this is the current speed, and not the actual current rotation.

00000000h: Track Properties

02: float/byte firstKey
03: float/byte lastKey
04: dword      interpolation

This chunk contains the basic track information; the track value for t = 0, the track value for t = 1 and the interpolation method:

                Linear (0):	y = (x2 - x1) / (y2 - y1) * x;
                Smooth (1):	y = hermite(x1, x2, y1, y2, x);
                Step (2): 	y = (x >= x2) ? y2 : y1;
              
Note: the 02 and 03 chunks contain an 8-bit unsigned integer (0 - 255) for the Red, Green, Blue and Alpha tracks and a float for the other 3 tracks.

00000001h: Track Data

05: float name
02: dword  value

This chunk contains a shader parameter, of type INT. The parameter data is a single 32-bit signed integer.

The name and data of the parameter are stored in mini chunks. The mini-chunk type of the name and parameter data is 01h and 02h, respectively.

00000036h: Connections

37: dword death
39: dword birth

This chunk contains two emitter indices. The "death" emitter should be spawned whenever a particle from this emitter dies. The "birth" emitter should be spawned (and attached!) to each particle when it is created.

00000045h: Bump/Depth texture name

string name

This chunk contains the name of the emitters's bump or depth texture as a single ASCIIZ string. This texture typically consists of multiple particle textures in one; the particular coordinates for this emitter's particles are determined by the index track and the number of elements in the texture.

Depending on the particles' shader mode, this texture is unused, a bump texture or a depth texture.

00000002h: Persistance

byte persist

If this chunks contains a non-zero value, the particles continue to exist to finish simulating after the particle system has been removed. Otherwise, the particle are immediately removed along with the particle system.

Format #2

Particle files with this format are used in the game "Universe at War: Earth Assault".

Alamo Particle File

00001500h: Particle System

This chunk is the container chunk for the particle system description

00000000h: Name

string name

This chunk holds the particle system's name as an ASCIIZ string. This name must match the filename without extension.

00000001h: Unknown

byte unknown

00000002h: Persistance

byte persist

If this chunks contains a non-zero value, the particles continue to exist to finish simulating after the particle system has been removed. Otherwise, the particle are immediately removed along with the particle system.

00001520h: Emitters

This chunk is the container chunk for a emitters in the particle system

00001540h: Emitter

This chunk is the container chunk for a single emitter in the particle system.

00000000h: Emitter name

string name

This chunk contains the emitters's name as a single ASCIIZ string. This value has no in-game use but is useful when editing the particle system.