The phs format is a standard binary file.
An "Actor" represents one solid physical object in the scene, and can be a collection of primitives, models, and lights.
Actors can be connected with Joints
"Stray" primitives, models and lights are those not associated with an actor, and should be ignored.
The file data is listed in reading order:
float - file version number
int - number of actors in the scene
loop( number of actors )
//these 3 values are used for reading in primitives models and lights for this actor
numPrimitives, (int));
numModels, (int));
numLights, (int));
//actor data
//not used
function, (int));
//actors pos, is same as model[0] pos
pos, (NxVec3));
//not used
type, (int));
//collision group ID, not yet used
group, (int));
//true if the actor is static (ie level data)
staticEntity, (bool));
//density is mass relative to volume, will override mass setting unless density=0. Newton will just use it as mass setting, PhysX will use it as density
density, (float));
//
angularDamping, (float));
linearDamping, (float));
//8 custom float values, definable by the user
custom, (float)*8);
//mass of the actor, used if density = 0
mass, (float));
//
sleepVelocity, (float)*2);
//center of mass of the actor, in world co-ordinates (vector, 3*float)
centerOfMass, (NxVec3));
//not used (3*3*float)
centerOfMassOrientation, (NxMat33));
//if true, we use center of mass variable, if false, center of mass must be calculated based on mass distribution (check Scythe API for code) (v1.1)
manualCOM, (bool));
//indicates size of following string (v1.2)
filein.read((char*) &strSize, (int));
//char array representing name of actor (v1.2)
filein.read((char*) actors[i].name, (char )*strSize);
// (v1.2)
disableFluidCollision, (bool));
disableGravity, (bool));
//performance / stability setting used by ODE (v1.3)
maxIterations, (int));
//primitives
//this should be looped "numPrimitives" times
//3 axises making up a 3x3 matrix (each a vector 3*float)
filein->read((char*) &roo->axis[0], sizeof(NxVec3));
filein->read((char*) &roo->axis[1], sizeof(NxVec3));
filein->read((char*) &roo->axis[2], sizeof(NxVec3));
//position of the primitive in world coordinates(3*float)
filein->read((char*) &roo->pos, sizeof(NxVec3));
//type of primitive BOX=3, SPHERE=4, CAPSULE=5, CYLINDER=6, CONE=7, ELIPSE=8, MESH=9, NULL=10
filein->read((char*) &roo->type, sizeof(int));
//custom parameters
filein->read((char*) &roo->custom, sizeof(float)*8);
//collision group ID (not used)
fileout->read((char*) &p->group, sizeof(int));
//dimensions of the primitive (3*float) XYZ used as dimensions of box, for something like a capsule, Y=length and XZ are the same and represent the radius. not used for MESH types
fileout->read((char*) &p->size, sizeof(NxVec3));
//material ID (not yet used)
fileout->read((char*) &p->materialIndex, sizeof(int));
//density and mass not currently used at primitive level
fileout->read((char*) &p->density, sizeof(float));
fileout->read((char*) &p->mass, sizeof(float));
//skinwidth is a performance setting for ODE and PhysX
fileout->read((char*) &p->skinWidth, sizeof(float));
int strSize = 0;
fileout->read((char*) &strSize, sizeof(int));
fileout->read((char*) p->meshFile, sizeof(char )*strSize);
if(fileVersion >= 1.2f) {
strSize = 0;
fileout->read((char*) &strSize, sizeof(int));
fileout->read((char*)p->cookedFile, sizeof(char)*strSize);
}
fileout->read((char*) &p->useMeshFileOnly, sizeof(bool));
fileout->read((char*) &p->useMeshData, sizeof(bool));
if((fileVersion < 1.2f && p->useMeshData) || (fileVersion >= 1.2f && p->type == MESH))
{
p->meshData = new PhysicsMesh;
fileout->read((char*) &p->meshData->isConvex, sizeof(bool));
fileout->read((char*) &p->meshData->numVerts, sizeof(int));
fileout->read((char*) &p->meshData->numTris, sizeof(int));
p->meshData->verts = new float [p->meshData->numVerts*3];
p->meshData->normals = new float [p->meshData->numVerts*3];
p->meshData->tris = new unsigned short [p->meshData->numTris*3];
fileout->read((char*) p->meshData->verts, sizeof(float)*p->meshData->numVerts * 3);
fileout->read((char*) p->meshData->normals, sizeof(float)*p->meshData->numVerts * 3);
fileout->read((char*) p->meshData->tris, sizeof(unsigned short)*p->meshData->numTris * 3);
if(fileVersion >= 1.2f) {
fileout->read((char*) &p->meshData->doubleSided, sizeof(bool));
fileout->read((char*) &p->meshData->smooth, sizeof(bool));
}
}
if(fileVersion >= 1.2f)
{
fileout->read((char*) &p->fluidDrain, sizeof(bool));
fileout->read((char*) &p->triggerOnEnter, sizeof(bool));
fileout->read((char*) &p->triggerOnStay, sizeof(bool));
fileout->read((char*) &p->triggerOnLeave, sizeof(bool));
}
}
//models
actors[i].models = new PhysicsModel[actors[i].numModels];
for(int ii = 0 ; ii < actors[i].numModels ; ii++)
{
loadRootObject(&filein, &actors[i].models[ii]);
memset(actors[i].models[ii].modelName, '\0', 200);
int strSize;
filein.read((char*) &strSize, (int));
filein.read((char*) actors[i].models[ii].modelName, (char )*strSize);
// filein >> actors[i].models[ii].modelName;
// models[ii].pos, (NxVec3)); //not used, models pos is actors pos
models[ii].scale, (NxVec3));
}
//lights
actors[i].lights = new PhysicsLight[actors[i].numLights];
for(int ii = 0 ; ii < actors[i].numLights ; ii++)
{
lights[ii], (PhysicsLight));
}
}