We’ve created documentation for the PRT file format. Here’s the page, if you have any comments about it, like maybe it needs clarifying in some parts, let us know.
-Mark
The Particle file (.PRT) format is the standard file format used in Krakatoa, which best supports all the options and capabilities that Krakatoa has to offer. The file format allows for the use of an arbitrary number of channels, each with a customizable type and name.
The file format is designed so the header is uncompressed while the particle data is compressed. This provides the ability to efficiently write a PRT file without knowing ahead of time how many particles will be written, by seeking back into the header and updating it with the correct particle count once all the particles have been written. When doing this, it is recommended that the value -1 be written to the particle count initially, so that Krakatoa and other programs can detect it as an error condition when loading the file.
Channel names are restricted, and should start with a letter or '_' character, and contain only letters, numbers and '_'. This restriction is imposed to provide for the possibility of implementing scripting support in Krakatoa and other systems where the channel names are directly used in the language to access those channels. Consider, for example, what a Krakatoa shading language would be like. Channel names are case sensitive.
For Krakatoa to work with a PRT file, the file must at minimum contain a Position channel which contains 3 values of a floating point type.
Format Specification
The PRT file format consists of:
- A header for general file information.
- A channel definitions section, detailing the channel-wise data included in each particle.
- A block of binary data for the particles. This is compressed using zlib's deflate method.
All data is in little-endian byte order.
PRT File Header
(56 bytes)
(8 bytes) Magic number that indicates the PRT file format. The number is defined by the following sequence of ASCII characters: {192, 'P', 'R', 'T', '\r', '\n', 26, '\n'} (4 bytes) A 32 bit int indicating the length of the header (Has value 56). (32 bytes) A human readable signature null-terminated string describing the file, currently "Extensible Particle Format" (4 bytes) A 32 bit int indicating version (Has value 1). (8 bytes) A 64 bit int indicating particle count
Reserved Bytes
(4 bytes)
(4 bytes) A 32 bit int, should be set to the value 4.
Channels Definition Section
(Variable Length)
Header (8 bytes)
(4 bytes) A 32 bit int indicating the number of channels. (4 bytes) A 32 bit int indicating the length of one channel definition structure (Has value 44).
Channel definitions (44 bytes each)
(32 bytes) A null-terminated string indicating the channel name. Must match the regex "[a-zA-Z_][0-9a-zA-Z_]*". (4 bytes) A 32 bit int indicating channel arity (number of data values that each particle has for this channel). (4 bytes) A 32 bit int indicating channel type. Supported channel types are indicated in the table below. (4 bytes) A 32 bit int indicating channel offset, relative to the start of the particle.
Data Type | Integer Value |
int16 | 0 |
int32 | 1 |
int64 | 2 |
float16 | 3 |
float32 | 4 |
float64 | 5 |
uint16 | 6 |
uint32 | 7 |
uint64 | 8 |
int8 | 9 |
uint8 | 10 |
Particle Data
(Variable Size)
The particle data is compressed using a zlib z_streamp object, with the basic zlib deflate API. In Krakatoa, this is implemented with the deflateInit, deflate, and deflateEnd functions for compression, and the inflateInit, inflate, and inflateEnd functions for decompression.
The particles are byte-packed one after another, in the layout specified by the channels definition section.
The float16 data type is the same as the half data type in OpenEXR. The most convenient way to work with them is using the half library component from OpenEXR.
Example
Let's say you want to write 10 particles to a PRT file, and that each particle will have position and velocity information associated with it.
The following values will need to be written for the header information.
{192, 'P', 'R', 'T', '\r', '\n', 26, '\n'} // magic number 56 // header length Extensible Particle Format // identification string 1 // version 1 10 // particle count 4 // reserved byte value 2 // number of channels 44 // channel definition length Position // channel name 4 // data type - float32 3 // triplet of values for 3D position 0 // first data channel in the particle, no offset Velocity // channel name 4 // data type - float32 3 // triplet of values for 3D velocity vector) 12 // offset 4*3=12 bytes to get past the position triplet
Following the header information, the channel-wise information will be compressed via zlib and written to the file. The pre-packed information will consist of 24 bytes per particle, 12 for the position triplet and 12 for the velocity triplet:
[float32][float32][float32][float32][float32][float32][float32][float32][float32][float32][float32][float32]... |_________________________||_________________________||_________________________||_________________________| position velocity position velocity |____________________________________________________||____________________________________________________| particle 1 particle 2
As mentioned above, it is recommended that the value -1 be written to the particle count initially, so that Krakatoa and other programs can detect it as an error condition when loading the file. Once the per particle information has been packed into the file, the particle count in the header can then be updated to the true value.