Wrp File Format - OPRWv17 to 24
Introduction
Legend
- byte 8 bits, unsigned.
- ushort 2 bytes, unsigned.
- ulong 4 bytes, unsigned.
- float 4 bytes, signed.
File Format
structHeader Header;
//still unknown stuff here
//followed by
structPeaks Peaks;
structTextureGridMaterials MaterialIndices; //see discussion below. Not fully defined (yet)
ushort PackedRandom[texZ][texX]; //probably random values needed for calculating clutter models position
byte PackedBytes1[gridZ][gridX]; // seems to be related to clutters or sat mask distance as it is responsible for the clutterbug
float PackedElevation[gridZ][gridX];
structMaterials Materials;
structModels Models;
structClassedModels ClassedModels;
//something grid related[size unknown]
// followed by:
byte PackedBytes2[texZ][texX]; //seems to be connected to roads, runways and special grounds
byte PackedBytes3[gridZ][gridX]; //unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02
ulong maxObjectID; //not number of objects
ulong ObjectBlockOffset; //amount of bytes used for RoadNets
structRoadNet RoadNets[texZ,texX]; //probably organized in texture grid cells to realize terrain streaming
structObject Objects[unknown];
structMapInfo MapInfos[]; //have to be iterated until EndOfFile
Structures
structHeader
structHeader
{
char signature[4]; //"OPWR"
ulong version; //0x12 = 18
ulong texX,texZ; //textures cell dimensions. 256x256 eg
ulong gridX,gridZ; //elevations cell dimensions. 256x256 eg
float gridSize; //in meters (normally 50.0)
}
structPeaks
structPeaks
{
ulong nPeaks;
float XZY[nPeaks][3]; //Position of the Peak (Z is height)
}
structTextureGridMaterials
structTextureGridMaterials
{
//still need to be worked out
}
structMaterials
structMaterials
{
ulong nMaterials; //Number of Rvmat entries (at least one)
structMaterial Materials[nMaterials];
}
there is always a minimum of one rvmat entry. The first entry is *always* 0x00 0x00 (no file)
the *actual* number of files listed is therefore *always* one less than nRvmatEntries
structMaterial
structMaterial
{
asciiz rvmat_path;
byte 0x00;
}
structModels
structModels
{
ulong nModels; //number of models
asciiz model_path[nModels]; //e.g. ca\buildings\kostelik.p3d
}
The ModelIndex in the ObjectsBlock below is a direct reference to one of the above p3d files for that object entry. If there are 99 nModels then the Object entries will contain ModelIndexes between 0 and 98
structClassedModels
structClassedModels
{
ulong nClassedModels; //number of classed models
structClassedModel Models[nClassedModels];
}
structClassedModel
structClassedModel
{
asciiz class_name; //e.g. Land_Hangar
asciiz model_path; //e.g. ca\buildings\kostelik.p3d
float pos[3]; //XZY
ulong unknown;
}
structRoadNet
structRoadNet
{
ulong nRoadParts; // Zero or More...
structRoadPart RoadParts[nRoadParts];
}
Because of the variable length asciiz strings, the actual position of the following Objects block cannot be pre-calculated. Therefore,
the ObjectBlockOffset is also the size (in bytes) of the Roads Block
On a 256 x 256 cell island: Each cell *unconditionally* contains a roadnet entry. If there are no road(s) in that cell, there are no roadparts. There could, alternatively be multiple roads in that cell, and, multiple parts to each road.
For a 256 x 256 cell island with NO roads, the size of this block, the ObjectBlockOffset , would be 256 x 256 x 4 bytes.
structRoadPart
structRoadPart
{
ushort nRoadPositions;
float RoadPositions[nRoadPositions][3]; //XYZ
byte Flags[4];
asciiz Model;
float matrix[12];
}
structObject
structObject
{
ulong ObjectID;
ulong modelIndex;
float matrix[12];
ulong 0x02;
}
modelIndex is a direct reference to the Nth model entry in the Model Block above. If there are 99 p3d files listed in the Model Block, then any given Object entry will contain a modelIndex between 0 and 98. For any island, there are more than 100,000 (p3d) objects on the terrain. The ObjectID uniquely identifies *that* tree, at *that* position. The *same* tree, house, bush, will be used many times on the island at different locations. Thus many object entries contain the same modelIndex. Eg, the same, p3d tree.
structMapInfo
structMapInfo
{
ulong infoType;
if(infoType in [0,1,2,10,11,13,14,15,16,17,22,23,26,27,30]) structType1 type1;
if(infoType in [24,31,32]) structType2 type2;
if(infoType in [25,33]) structType3 type3;
if(infoType in [3,4,8,9,18,19,20,28,29]) structType4 type4;
if(infoType in [34]) structType5 type5;
}
structType1
structType1
{
ulong ObjectId
float x, z
}
structType2
structType2
{
ulong ObjectId
float[4][2] Bounds
}
structType3
structType3
{
long[2] unknown
float[2][2] line?
}
structType4
structType4
{
ulong ObjectId
float[4][2] Bounds
byte[4] Color //rgba
}
structType5
structType5
{
ulong ObjectId
float[2][2] line?
}
Packed Data
All variables starting with "Packed" are compressed with the common BIS algorithm that is also used in paa and OFP pbo files.