Wrp File Format - OPRWv17 to 24

From Bohemia Interactive Community
Jump to navigation Jump to search

Template:unsupported-doc

Introduction

For a general description of wrp files see 8WVR

Legend

Little endian byte order, lsb first for numeric values, text is stored in Big endian byte order.

  • byte 8 bits, unsigned.
  • ushort 2 bytes, unsigned.
  • ulong 4 bytes, unsigned.
  • float 4 bytes, signed.
  • asciiz variable length zero terminated string
  • char: ascii character(s)

XYPair

XYPair
{
 ulong x,y;
}

XYZTriplet

XYZTriplet
{
 float    x,y,z;
}
Normally, this structure is normally associated with positional information.

File Format

Texture and Terrain Grid Sizes are derived from the header.

So far, this is the SAME format for OPRW20 (sara.pbo)

OPRWv20 : OPRWv18
{
 WrpHeader     Header;

 GridBlock     UnknownGrid1; 
 GridBlock     UnknownGrid2; 

 ulong         nPeaks;
 XYZTriplet    PeakPositions[nPeaks];

 GridBlock     TextureIndex; 

 ushort        PackedRandom[TextureGridSizeXY];   //probably random values needed for calculating clutter models position
 byte          PackedBytes1[TerrainGridSizeXY];   //seems to be related to clutters or sat mask distance as it is responsible for the clutterbug

 float         PackedElevation[TerrainGridSizeXY];

 ulong         nTextures;
 Texture       Textures[nTextures];        //"PrefixRoot\data\layers\some.rvmat\0\0"

 ulong         nModels;	
 asciiz        modelPaths[nModels];	    //"ca\buildings\kostelik.p3d\0"

 ulong         nClassedModels;
 ClassedModel  Models[nClassedModels];     //"Land_Hangar\0" : "ca\buildings\Hangar.p3d\0"

 GridBlock     UnknownGrid3; 

 ulong         SizeOfObjects;              //in bytes

 GridBlock     UnknownGrid4; 

 ulong         SizeOfMapInfo;              //in bytes

 byte          PackedBytes2[TextureGridSizeXY];   //seems to be connected to roads, runways and special grounds
 byte          PackedBytes3[TerrainGridSizeXY];   //unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02
 ulong         maxObjectID;

 ulong         SizeOfRoadNets;             //in bytes
 RoadNet       RoadNets[SizeOfRoadNets]; 

 Object        Objects[SizeOfObjects/SizeOfObject]; // SizeOfObject ==60

 MapInfo       MapInfos[...];
}
  • Because of the variable length of the asciiz strings in RoadParts, the actual position of the following #Objects block cannot be pre-calculated. Therefore the SizeOfRoadNets can be used, as it is the size (in bytes) of this RoadNet block.
  • Similarly, SizeOfObjects can be used to skip to the MapInfo

WrpHeader

WrpHeader     
{
 char    Filetype;        // "OPWR"
 ulong   version;         // 0x12 = 18
 XYPair  TextureGridSize; // 256 x 256 eg
 XYPair  TerrainGridSize; // ditto
 float   CellSize;        // generally 50.0 meters
}

This is a traditional wrp header endemic to most wrp formats. The CellSize was introduced during Elite


GridBlock

This is a compressed grid of cells

  • when present, the leading flag = 0x01
  • when a null GridBlock exists
{
  byte  flag;     // =0
  ulong NullBits; // = 0
}

GridBlock is currently in the 'discussion tab'.


TextureIndex

GridBlock TextureIndex
{
 ushort Array[TextureCellSizeXY];
}

the result of decompressing the GridBlock is to produce an array the size of the Header's cell size.

This array contains ushort index values into the Textures list that follows.

Like all similar indexes in all other wrp formats, each cell must contain a reference to a 'texture', hence no index value of zero can exist. (The first texture of the list is always a dummy entry)

Texture

Texture
{
 Concatenated Asciiz rvmat_paths; //"PrefixRoot\data\layers\some.rvmat\0\0"
}
  • This, and it's TextureIndex are more properly seen as a Materials list. However, the texturing intent is retained from previous versions of wrp files.
  • see PrefixRoot\ description. Essentially, it is a reference to a pbo.

Each cell in the grid references a (series of) texture(s) for it's surface. The TextureIndex is an index into these material names.

Thus, each entry of this materials list consists of concatenated asciiz strings in the form

"AnRvmatFile\0AnotherOne\0EvenMore\0\0"

Ie, the end of this entry = \0\0

It so happens that only one, single 'texture', a single rvmat file, is used per cell, but, the construct is there to have any amount.

therefore, this list is of the form

"AnRvmatFile\0\0"

There is always, at least one materials entry. The 1st entry. The first entry (effectively index 0) is a dummy, with an empty path, because it will never be accessed. Indexes start at 1.

Similar to it's 8WVR cousin (from which it is derived)the rvmat filenames *should* be unique (redundant, duplicate entries, defeat the purpose of the index). However, there is quite often some duplication.

ClassedModel

ClassedModel { asciiz class_name; //"Land_Hangar\0" asciiz model_path; //"ca\buildings\Hangar.p3d" XYZTriplet Position; ulong unknown; }

This is a fairly repetitious list of often identically named class and model, used as an index from an as yet unknown grid table.

RoadNet

RoadNet { ulong nRoadParts; // Zero or More... RoadPart RoadParts[nRoadParts]; } TextureGridSizeXY];

Every cell on the map has a RoadNet entry. If there are no road(s) for that cell, there are no RoadParts (nRoadParts=0)

RoadParts, while, ultimately being no more (or less) than just another P3D model, are contained separately to models generally, to better realize terrain streaming and for AI driving ability.

RoadPart

RoadPart { ushort nRoadPositions; XYZTriplet RoadPositions[nRoadPositions]; byte Flags[4]; asciiz Model; float matrix[12]; }

Object Optional

Object { ulong ObjectID; ulong modelIndex; // into the [[#Models|models path name list]] (1 based) float TransformMatrix[3][4]; // standard directX transform matrix ulong 0x02; }

  • maxObjectID is somewhat irrelevant. It is indeed the id of the highest value ObjectID, but, these 'ID's, while unique are highly arbitrary in nature and alter on any change to the 'world' when editing in oxygen/visitor. This ID can occur anywhere in the object list, and the id values before it are non-sequential. maxObjectID cannot be used as a nObject ID's eg.
  • If SizeOfObjects above == 0 then there are no objects.

Note that unlike it's 4/8WVR cousin, where each Object entry contains (an often) repetitious list of p3d files. The same construct is (now) used as per Textures and Indexes. Namely, a common list of models is indexed into, by each Object entry.


MapInfo Optional

MapInfo
{
 ulong infoType;
 MapData[...];
}

Mapinfo, when it exists, extends to end of file. The sizeof each entry, is determined by it's info type thus:

MapData

MapData
{
 if(infoType in [0,1,2,10,11,13,14,15,16,17,22,23,26,27,30]) MapType1;
 if(infoType in [24,31,32])                                  MapType2;
 if(infoType in [25,33])                                     MapType3;
 if(infoType in [3,4,8,9,18,19,20,28,29])                    MapType4;
 if(infoType in [34])                                        MapType5;
}

MapType1

MapType1 { ulong ObjectId float x, z }

MapType2

MapType2 { ulong ObjectId float Bounds[4][2]; }

MapType3

MapType3 { ulong unknown[2]; float line[2][2];? }

MapType4

MapType4 { ulong ObjectId float Bounds[4][2]; byte Color[4] //rgba }

MapType5

MapType5 { ulong ObjectId float line[2][2];? }

Packed Data

All variables starting with "Packed" are compressed with the common BIS algorithm that is also used in paa and OFP pbo files.