Wrp File Format - OPRWv17 to 24: Difference between revisions
m (→Introduction: legend) |
m (re-organised) |
||
Line 1: | Line 1: | ||
{{unsupported-doc}} | {{unsupported-doc}} | ||
==Introduction== | ==Introduction== | ||
For a general description of wrp files see [[Wrp_File_Format_-_8WVR|8WVR]] | |||
===Legend=== | ===Legend=== | ||
[http://en.wikipedia.org/wiki/Endianness#Little-endian Little endian] byte order, lsb first for numeric values, | [http://en.wikipedia.org/wiki/Endianness#Little-endian Little endian] byte order, lsb first for numeric values, | ||
text is stored in [http://en.wikipedia.org/wiki/Endianness#Big-endian Big endian] byte order. | text is stored in [http://en.wikipedia.org/wiki/Endianness#Big-endian Big endian] byte order. | ||
*'''byte''' 8 bits, unsigned. | *'''byte''' 8 bits, unsigned. | ||
Line 13: | Line 13: | ||
*'''float''' 4 bytes, signed. | *'''float''' 4 bytes, signed. | ||
*'''asciiz''' variable length zero terminated string | *'''asciiz''' variable length zero terminated string | ||
*char: ascii character(s) | *char: ascii character(s) | ||
===XYPair=== | ===XYPair=== | ||
Line 29: | Line 20: | ||
ulong x,y; | ulong x,y; | ||
} | } | ||
===XYZTriplet=== | |||
XYZTriplet | |||
{ | |||
float x,y,z; | |||
} | |||
Normally, this structure is normally associated with positional information. | |||
==File Format== | ==File Format== | ||
OPRWv18 | |||
{ | |||
WrpHeader Header; | |||
GridBlock UnknownGrid1; | |||
GridBlock UnknownGrid2; | |||
ushort PackedRandom[ | |||
byte PackedBytes1[ | ulong nPeaks; | ||
float PackedElevation[ | XYZTriplet PeakPositions[nPeaks]; | ||
GridBlock TextureIndex; | |||
ushort PackedRandom[Header.TextureGridSize.y][Header.TextureGridSize.y]; //probably random values needed for calculating clutter models position | |||
ulong SizeOfObjects; | byte PackedBytes1[Header.TerrainGridSize.y][Header.TerrainGridSize.y]; | ||
//seems to be related to clutters or sat mask distance as it is responsible for the [http://tinyurl.com/6b27ed clutterbug] | |||
ulong SizeOfMapInfo; | |||
byte PackedBytes2[ | float PackedElevation[Header.TerrainGridSize.y][Header.TerrainGridSize.y]; | ||
byte PackedBytes3[ | |||
ulong maxObjectID; | ulong nTextures; | ||
ulong | 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[Header.TextureGridSize.y][Header.TextureGridSize.y]; //seems to be connected to roads, runways and special grounds | |||
byte PackedBytes3[Header.TerrainGridSize.y][Header.TerrainGridSize.y]; //unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02 | |||
ulong maxObjectID; | |||
ulong SizeOfRoadNets; //in bytes | |||
RoadNet RoadNets[Header.TextureGridSize.y][Header.TextureGridSize.y]; //probably organized in texture grid cells to realize terrain streaming | |||
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 | |||
{ | |||
//still need to be worked out | |||
} | |||
===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 [[P3D_File_Format_-_ODOLV40_Revised|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. | |||
=== | ===ClassedModel=== | ||
<code><nowiki> | <code><nowiki> | ||
ClassedModel | |||
{ | { | ||
asciiz class_name; // | asciiz class_name; //"Land_Hangar\0" | ||
asciiz model_path; | asciiz model_path; //"ca\buildings\Hangar.p3d" | ||
XYZTriplet Position; | |||
ulong unknown; | ulong unknown; | ||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
===RoadNet=== | |||
=== | |||
<code><nowiki> | <code><nowiki> | ||
RoadNet | |||
{ | { | ||
ulong nRoadParts; // Zero or More... | |||
RoadPart RoadParts[nRoadParts]; | |||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
Every cell on the map contains a '''RoadNet''' entry. If there are no road(s) for that cell, there are no '''RoadParts''' (index =0) | |||
It is probably saved this way to better realize terrain streaming. | It is probably saved this way to better realize terrain streaming. | ||
==== | ====RoadPart==== | ||
<code><nowiki> | <code><nowiki> | ||
RoadPart | |||
{ | { | ||
ushort nRoadPositions; | ushort nRoadPositions; | ||
XYZTriplet RoadPositions[nRoadPositions]; | |||
byte Flags[4]; | byte Flags[4]; | ||
asciiz Model; | asciiz Model; | ||
float matrix[12]; | float matrix[12]; | ||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
===Object Optional=== | |||
=== | |||
<code><nowiki> | <code><nowiki> | ||
Object | |||
{ | { | ||
ulong ObjectID; | ulong ObjectID; | ||
ulong modelIndex; | ulong modelIndex; // into the [[#Models|models path name list]] (1 based) | ||
float | float TransformMatrix[3][4]; // standard directX transform matrix | ||
ulong 0x02; | ulong 0x02; | ||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
*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. | *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==== | ||
<code><nowiki> | <code><nowiki> | ||
MapType1 | |||
{ | { | ||
ulong ObjectId | ulong ObjectId | ||
float x, z | float x, z | ||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
==== | ====MapType2==== | ||
<code><nowiki> | <code><nowiki> | ||
MapType2 | |||
{ | { | ||
ulong ObjectId | |||
float Bounds[4][2]; | |||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
==== | ====MapType3==== | ||
<code><nowiki> | <code><nowiki> | ||
MapType3 | |||
{ | { | ||
ulong unknown[2]; | |||
float line[2][2];? | |||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
==== | ====MapType4==== | ||
<code><nowiki> | <code><nowiki> | ||
MapType4 | |||
{ | { | ||
ulong ObjectId | ulong ObjectId | ||
float[4][2] | float Bounds[4][2]; | ||
byte[4] | byte Color[4] //rgba | ||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
==== | ====MapType5==== | ||
<code><nowiki> | <code><nowiki> | ||
MapType5 | |||
{ | { | ||
ulong ObjectId | |||
float line[2][2];? | |||
} | } | ||
</nowiki></code> | </nowiki></code> |
Revision as of 05:14, 5 February 2009
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
OPRWv18 { WrpHeader Header; GridBlock UnknownGrid1; GridBlock UnknownGrid2; ulong nPeaks; XYZTriplet PeakPositions[nPeaks]; GridBlock TextureIndex; ushort PackedRandom[Header.TextureGridSize.y][Header.TextureGridSize.y]; //probably random values needed for calculating clutter models position byte PackedBytes1[Header.TerrainGridSize.y][Header.TerrainGridSize.y]; //seems to be related to clutters or sat mask distance as it is responsible for the clutterbug float PackedElevation[Header.TerrainGridSize.y][Header.TerrainGridSize.y]; 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[Header.TextureGridSize.y][Header.TextureGridSize.y]; //seems to be connected to roads, runways and special grounds byte PackedBytes3[Header.TerrainGridSize.y][Header.TerrainGridSize.y]; //unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02 ulong maxObjectID; ulong SizeOfRoadNets; //in bytes RoadNet RoadNets[Header.TextureGridSize.y][Header.TextureGridSize.y]; //probably organized in texture grid cells to realize terrain streaming 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 { //still need to be worked out }
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.
ClassedModel
ClassedModel
{
asciiz class_name; //"Land_Hangar\0"
asciiz model_path; //"ca\buildings\Hangar.p3d"
XYZTriplet Position;
ulong unknown;
}
RoadNet
RoadNet
{
ulong nRoadParts; // Zero or More...
RoadPart RoadParts[nRoadParts];
}
Every cell on the map contains a RoadNet entry. If there are no road(s) for that cell, there are no RoadParts (index =0)
It is probably saved this way to better realize terrain streaming.
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.