fcache specification

maxim capra

New member
hey,

does anybody know how i could find information on how the .fcache files are structured? i did have a look in the SDK, but i couldn't find the right information. currently i'm trying to reverse engineer it, looking at the hex values. but it's tedious. it's similar to all the other cache files like .mdd or .pfx, but a solid information about it would be useful. what i'm looking for is a cache format with particle rotation, because i would like to write an exporter for houdini and 3dsmax to get particles into lightwave - it seems pfx doesn't support that - position is not enough!

for your information: fcache ist the cache file of the new flocking system in lw11

thanks,
Philipp
 
I think I can remember that in the latest pfx version ( which is of course undocumented ) there is an extension chunk for rotation. Had the same project 1 year ago, but switched completely to houdini for particle fx, which made the import export obsolete ..
But thumbs up for your venture .. hope we will get some information on the caches .. me I would be very interested in the light-cache format .. a houdini Import export for those pointclouds would be marvelous ..
 
ok ... i think i figured it out by myself with a hex editor. i hope that's right:

everything in motorola big endian byte order, as usual

-- PSEUDO CODE
WriteLong numPoints

for i=1 to numPoints (

--BLOCK1 - the emitter
--i don't know yet what's in here, it's 9 float or long values.
--it changes, when i change the transform matrix of the emitter for example.
--but it doesn't matter, if you just want to import self made fcache files
--you could just fill it with zeros - it works! BLOCK2 is the important one....
WriteLong startFrame
WriteLong endFrame
for i=startFrame to endFrame (
for j=1 to 9 (WriteLong 0)
)

--BLOCK2 - the points (the position and rotation at every Frame):
WriteLong startFrame
WriteLong endFrame
for i=startFrame to endFrame (
WriteFloat PositionX
WriteFloat PositionY
WriteFloat PositionZ
)
WriteLong startFrame
WriteLong endFrame
for i=startFrame to endFrame (
WriteFloat RotationX
WriteFloat RotationY
WriteFloat RotationZ
)
)


maybe this does help someone..

still looking for .PFX files, especially the undocumented rotation chunk? someone?

Philipp
 
Last edited:
actually i still don't know how the rotation values work in fcache files. can someone point me in the right direction? getting lost here. it's 3 float values for every frame for every point, but it's not euler angles (not degrees, not radians), obviously no quaternions, no matrix. then i thought it might be something like normal directions, but this also doesn't make sense. i could send simplified cache files if someone is interested where i nailed it down just to the rotation part. the values don't make sense to me. :help:
 
here's the simplified fcache file. i zeroed everything out, BLOCK1 and the position part. if you put this on a new flock generator you should get 1 particle, timefame from 0 to 9, staying in position(0,0,0), just rotating around. look at the rotation values in the file. how do they correlate to this behaviour? i don't get it....
 

Attachments

  • flock.zip
    163 bytes · Views: 399
Last edited:
For anyone interested I have an old definition of the pfx format .. its strangely mangled by some automated translation, but still usable ..
 

Attachments

  • PFX-(ParticleFX)-Dateiformat---Disutomu-Inc-1.jpg
    PFX-(ParticleFX)-Dateiformat---Disutomu-Inc-1.jpg
    492.6 KB · Views: 451
Hey everyone, I've been directed to this thread and will post both the fcache and pfx format specs here later today for you all and make sure they get added to the SDK docs.
 
Hey everyone, I've been directed to this thread and will post both the fcache and pfx format specs here later today for you all and make sure they get added to the SDK docs.

thx man .. :thumbsup:

Maybe you could also add the GI Cache specs ??? Please !!!
 
Here goes: ---


PFX format:

PFX is a binary format with the following structure.

int32: 4 byte integer.
float: 4 byte floating point value.



struct PFX{

int32 version;
//Version number for the file format, if the version is >=5 , the PFX file has stored rotations.

int32 number of particles;
//number of total particles stored, regardless of when they are alive or dead.

int32 number of frames;
//This is the sum of the lifetime of each particle plus 1. For example, if you have ten particles from frame 0 to 120, the number of frames becomes 10 * ( ( 120-0 ) +1 ) or 1210.

struct {
int32 start_f;
//The frame that this particle becomes alive.

int32 end_f;
//The frame that this particle dies.

int32 life;
//The lifetime of the particle in frames.

float mass;
//Mass of the particle

float resistance;
//Wind resistance of the particle

float size;
//Size of the particle.

} particle_data [ number of particles ];

//if the file version >= 5
struct {
float heading;
float pitch;
float bank;
//The heading, pitch and bank angles ( that match LightWave's rotations )

float dummy[3];
//Unused data.
} rotation_data [ number of particles ];
};



FCache info:
FCache is a binary format with the following structure.

int32: 4 byte integer.
float: 4 byte floating point value.
struct Vector3 { float x,y,z; };
struct Matrix3 { float data[9]; };
typedef double LWTime;

struct FCache {

int32 version;
int32 agent_count;

struct Agent {
struct Cache{
int32 version;
LWTime start, end; //start and end times that the agents have values stored for.
int32 frames; //number of frames stored
Matrix3 data[frames]; //the actual data
} orientation;

struct Cache{
int32 version;
LWTime start, end;
int32 frames;
Vector3 data[frames];
} position;

struct Cache{
int32 version;
LWTime start, end;
int32 frames;
Vector3 data[frames];
} velocity;
} agents [ agent_count ];
};
 
Hey James,

thanks again for your help. I've got a few questions:

1. I think you forgot the position part in PFX??
2. the rotation part in PFX: this is not a rotation per frame per particle? only one rotation for every particle throughout his life?
3. i know it's picky, but it would be useful to see, where the loops go (loop through frames or particles or agents). a pseudo code on how to read the files for example would be better for understanding....
4. i still don't get the rotation part in fcache. example: i bake one agent, flying and rotating around. if i zero out the orientation part (matrix), the movement of the agent stays exactly the same. it seems, the orientation part is not needed? can i use just the matrix for orientation of every agent and don't use the velocity? or is it best to use both?

would be great if you can shed some light on these issues,

thank you,
philipp
 
actually my researches led to this PFX file structure. your's seem to be wrong or insufficient? anyway. this format is not usable for importing particle data from other 3d packages. only position is per frame AND per particle. rotation and scale cannot change over time ... sigh :( ....

PFX file format (particles) version 5

Motorola Big Endian byte order!
WriteLong = 4 byte integer
WriteFloat = 4 byte float


WriteLong format_version (5) //Version number for the file format, if the version is >=5 , the PFX file stores rotations.
WriteLong total_particles //number of total particles stored, regardless of when they are alive or dead.
WriteLong total_frames //This is the sum of the lifetimes of all particles in the stored framerange.

for i=1 to numPoints (

WriteLong startFrame //The frame that this particle becomes alive.
WriteLong endFrame //The frame that this particle dies.
WriteLong lifeFrame //The lifetime of the particle in frames.
WriteLong mass //Mass of the particle
WriteLong resistance //Wind resistance of the particle
WriteLong size //Size of the particle.

for i=startFrame to endFrame (
WriteFloat PositionX
WriteFloat PositionY
WriteFloat PositionZ
)
)
if format_version >= 4 ( //this chunk defines the rotation/scale/spin values per particle
for i=1 to numPoints (
WriteLong 0 (unknown)
WriteFloat rotateX
WriteFloat rotateY
WriteFloat rotateZ
WriteFloat scaleX
WriteFloat scaleY
WriteFloat scaleZ
WriteFloat spinX
WriteFloat spinY
WriteFloat spinZ
WriteFloat unknownX
WriteFloat unknownY
WriteFloat unknownZ
)
)


Here goes: ---


PFX format:

PFX is a binary format with the following structure.

int32: 4 byte integer.
float: 4 byte floating point value.



struct PFX{

int32 version;
//Version number for the file format, if the version is >=5 , the PFX file has stored rotations.

int32 number of particles;
//number of total particles stored, regardless of when they are alive or dead.

int32 number of frames;
//This is the sum of the lifetime of each particle plus 1. For example, if you have ten particles from frame 0 to 120, the number of frames becomes 10 * ( ( 120-0 ) +1 ) or 1210.

struct {
int32 start_f;
//The frame that this particle becomes alive.

int32 end_f;
//The frame that this particle dies.

int32 life;
//The lifetime of the particle in frames.

float mass;
//Mass of the particle

float resistance;
//Wind resistance of the particle

float size;
//Size of the particle.

} particle_data [ number of particles ];

//if the file version >= 5
struct {
float heading;
float pitch;
float bank;
//The heading, pitch and bank angles ( that match LightWave's rotations )

float dummy[3];
//Unused data.
} rotation_data [ number of particles ];
};
};
 
Slightly amended format.

PFX format:

PFX is a binary format with the following structure.

int32: 4 byte integer.
float: 4 byte floating point value.



struct PFX{

int32 version;
//Version number for the file format, if the version is >=5 , the PFX file has stored rotations.

int32 number of particles;
//number of total particles stored, regardless of when they are alive or dead.

int32 number of frames;
//This is the sum of the lifetime of each particle plus 1. For example, if you have ten particles from frame 0 to 120, the number of frames becomes 10 * ( ( 120-0 ) +1 ) or 1210.

struct {
int32 start_f;
//The frame that this particle becomes alive.

int32 end_f;
//The frame that this particle dies.

int32 life;
//The lifetime of the particle in frames.

float mass;
//Mass of the particle

float resistance;
//Wind resistance of the particle

float size;
//Size of the particle.

struct{
float x , y , z;​
} positions [ end_f - start_f ];

} particle_data [ number of particles ];

//if the file version >= 4
int32 number_of_recorded_collisions;
if ( number_of_recorded_collisions ) >0
struct {
int32 particle_index;
int32 frame_collision_occurs;
int32 ID_of_collision_item;
float x,y,z; //location of collision
} collisions [ number_of_recorded_collisions ];
//if the file version >= 5
struct {
float heading;
float pitch;
float bank;
//The heading, pitch and bank angles ( that match LightWave's rotations )

float scalex;
float scaley;
float scalez;

float spinh;
float spinp;
float spinb;

float dummy[3];
//Unused data.
} rotation_data [ number of particles ];
};
 
Last edited:
Hey James,

thanks again for your help. I've got a few questions:

4. i still don't get the rotation part in fcache. example: i bake one agent, flying and rotating around. if i zero out the orientation part (matrix), the movement of the agent stays exactly the same. it seems, the orientation part is not needed? can i use just the matrix for orientation of every agent and don't use the velocity? or is it best to use both?

fcache stores a matrix per 'frame' ( it's not necessarily per frame but that's convenient for now ) so that the orientation of the agent can be independent of the velocity. For example, all the agent's could be made to target a scene item while they fly around.
 
Originally Posted by jameswillmott
write my essay task
fcache stores a matrix per 'frame' ( it's not necessarily per frame but that's convenient for now ) so that the orientation of the agent can be independent of the velocity. For example, all the agent's could be made to target a scene item while they fly around.


Hello James,

Any examples of the orientation independent of the velocity? I've been looking for the information and found this thread on the forums (in GI cache topics on Unity forums, I guess). Years ago I used to work with Vray.

Sorry for bumping.
 
Last edited:
Hi Terry, if I understand the question correctly, what I meant was simply the format can record an agent moving backwards, or strafing, for example, in both those cases the velocity doesn't align with the orientation.
 
Back
Top