Wrp File Format - OPRWv17 to 24: Difference between revisions
m (→ClassedModel) |
Lou Montana (talk | contribs) m (Text replacement - "\[ *(https?:\/\/[^ = ]+) +([^= ]+) *\]" to "{{Link|$1|$2}}") |
||
(44 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
{{ | {{Feature|UnsupportedDoc}} | ||
==Introduction== | == Introduction == | ||
For a general description of wrp files see [[Wrp_File_Format_-_8WVR|8WVR]] | For a general description of wrp files see [[Wrp_File_Format_-_8WVR|8WVR]] | ||
===Legend=== | === Legend === | ||
[ | see [[Generic FileFormat Data Types]] | ||
==File Format== | |||
OPRWv18 | |||
== File Format == | |||
*Layer and Map Sizes are derived from the header. | |||
This document is based on analysis of arma1 wrps (OPRW18). The following are known differences between them, and later versions | |||
::*OPRW17 (Elite) does not have the clutter | |||
::*OPRW20 (sara and desert pbo's) :So far, this is the SAME format as 18 except PackedBytes1 | |||
::*OPRW23 (vbs2lite us) :So far, this is the SAME format as 20 | |||
::*OPRW24 (arma2)uses lzo compresion, not, lzss | |||
OPRWv17://elite | |||
OPRWv18://arma1 | |||
OPRWv20://arma1 sara | |||
OPRWv23://vbs2_lite | |||
OPRWv24://arma2 | |||
{ | { | ||
WrpHeader Header; | WrpHeader Header; | ||
ushort GridBlock_CellEnv[MapSize]; // a gridblock containing cellenv bits (16 bits per terrain cell). | |||
// Bits 0-2 are ground (0x0), coast (0x1), beach (0x2) and sea (0x3). Bit 4 indicates road/airstrip. | |||
byte GridBlock_CfgEnvSounds[MapSize]; // a gridblock. mostly the value 0x03 and probably related to Config.cpp CfgEnvSounds class | |||
ulong nPeaks; | ulong nPeaks; | ||
XYZTriplet PeakPositions[nPeaks]; | XYZTriplet PeakPositions[nPeaks]; //see http://en.wikipedia.org/wiki/Maxima_and_minima | ||
ushort GridBlock_RvmatLayerIndex[LayerSize]; | |||
if !Elite | |||
if ArmaOne | |||
ushort RandomClutter[LayerSize]; //compressed. probably random values needed for calculating clutter models position | |||
//seems to be related to clutters or sat mask distance as it is | |||
//responsible for the {{Link|http://tinyurl.com/6b27ed|clutterbug}} | |||
else | |||
bytes RandomClutter[MapSize]; //compressed | |||
endif | |||
bytes CompressedBytes1[MapSize]; //compressed | |||
endif | |||
float Elevation[MapSize]; //compressed | |||
ulong nRvmats; | |||
Texture Textures[nRvmats]; //"PrefixRoot\data\layers\some.rvmat\0\0" | |||
ulong nModels; | |||
asciiz modelPaths[nModels]; //"ca\buildings\kostelik.p3d\0" | |||
ulong nModels; | |||
asciiz modelPaths[nModels]; | |||
ulong nClassedModels; | ulong nClassedModels; | ||
ClassedModel Models[nClassedModels]; | ClassedModel Models[nClassedModels]; //"Land_Hangar\0" : "ca\buildings\Hangar.p3d\0" | ||
ushort GridBlock_UnknownGrid3[MapSize]; | |||
ulong SizeOfObjects; | ulong SizeOfObjects; //in bytes | ||
ushort GridBlock_UnknownGrid4[MapSize]; | |||
ulong SizeOfMapInfo; | ulong SizeOfMapInfo; //in bytes | ||
byte | byte CompressedBytes2[LayerSize]; // seems to be connected to roads, runways and special grounds | ||
byte | byte CompressedBytes3[MapSize]; // unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02 | ||
ulong maxObjectID; | ulong maxObjectID; | ||
ulong SizeOfRoadNets; | ulong SizeOfRoadNets; //in bytes | ||
RoadNet RoadNets[ | RoadNet RoadNets[SizeOfRoadNets]; | ||
Object Objects[SizeOfObjects/SizeOfObject]; // SizeOfObject ==60 | Object Objects[SizeOfObjects/SizeOfObject]; // SizeOfObject ==60 | ||
Line 78: | Line 87: | ||
*Similarly, SizeOfObjects can be used to skip to the MapInfo | *Similarly, SizeOfObjects can be used to skip to the MapInfo | ||
===WrpHeader=== | === ClutterMask === | ||
Each byte represents the intensity or, number of clutter objects for that area of '''terrain''' | |||
*Sea and road terrain have zilch. | |||
*desert terrain have very low values | |||
=== WrpHeader === | |||
WrpHeader | WrpHeader | ||
Line 84: | Line 99: | ||
char Filetype; // "OPWR" | char Filetype; // "OPWR" | ||
ulong version; // 0x12 = 18 | ulong version; // 0x12 = 18 | ||
XYPair | XYPair LayerSize; // 256 x 256 (SaraLite), 128 x 128 (Intro) | ||
XYPair | XYPair MapSize; // 1024 x 1024 (SaraLite), 512 x 512 (Intro) | ||
float | float LayerCellSize; // Layer cell size in meters (40m) | ||
} | } | ||
This is a traditional wrp header endemic to most wrp formats. The | This is a traditional wrp header endemic to most wrp formats. The LayerCellSize was introduced during Elite. The MapCellSize can be derived as follows: | ||
MapCellSize= LayerCellSize * LayerSizeX / MapSizeX, and is 10m for SaraLite and Intro. | |||
---- | ---- | ||
===GridBlock=== | === GridBlock === | ||
The result of decompressing any GridBlock is to produce an array the size of either the Header's LayerSize or MapSize, at the TypeSize specified. Eg be it byte, or ushort. | |||
There are five gridblocks in the file, two ushort arrays, and 3 byte arrays(if present) | |||
*when present, the leading flag = 0x01 | *when the grid is present, the leading flag = 0x01 | ||
*when a | *when a default fill GridBlock exists | ||
{ | { | ||
byte flag; // =0 | byte flag; // =0 | ||
ulong | ulong FillBits; // = almost always zero | ||
} | } | ||
GridBlock is currently in the 'discussion tab'. | |||
=== Texture === | |||
Texture | |||
=== | |||
{ | { | ||
// | Concatenated Asciiz TextureFilenames; //"PrefixRoot\data\layers\some.rvmat\0\0" (Arma) | ||
//"PrefixRoot\desert\data\pt.bimpas\0\0" (ELite) | |||
//"PboRoot\more_anim.01.pac\0" (OFP)(by way of example) | |||
} | } | ||
*The {{ofp}} entry is solely here by way of example. No such entry exists in arma/Elite format. | |||
In all cases (bimpas,ofp,rvmat) they devolve, ultimately, to (a series of) pac/paa texture files. | |||
*see [[P3D_File_Format_-_ODOLV40_Revised|PrefixRoot\]] description. Essentially, it is a reference to a pbo. | *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 | Each cell in the grid references a (series of) rvmat texture(s) for it is surface. The RvmatLayerIndex is an index to these filenames. | ||
Thus, '''each''' entry of this materials list consists of concatenated asciiz strings in the form | Thus, '''each''' entry of this materials list consists of concatenated asciiz strings in the form | ||
Line 131: | Line 146: | ||
Ie, the end of '''this''' entry = \0\0 | Ie, the end of '''this''' entry = \0\0 | ||
It so happens that only one, | It so happens that only one, single rvmat file, is used per cell, but, the construct is there to have any amount. | ||
therefore, this list is of the form | therefore, this list is of the form | ||
Line 140: | Line 155: | ||
The first entry (effectively index 0) is a dummy, with an empty path, because it will never be accessed. Indexes start at 1. | The first entry (effectively index 0) is a dummy, with an empty path, because it will never be accessed. Indexes start at 1. | ||
===ClassedModel=== | The ushort GridBlock RvmatIndices (once decomposed) contain index entries to specific rvmat files. No index value of zero exists. (The first texture of the list is always a dummy entry) | ||
<code><nowiki> | |||
Similar to it is 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 === | |||
<code style="display: block"><nowiki> | |||
ClassedModel | ClassedModel | ||
{ | { | ||
Line 153: | Line 174: | ||
This is a fairly repetitious list of often identically named class and model, used as an index from an as yet unknown grid table. | 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 === | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
RoadNet | RoadNet | ||
{ | { | ||
ulong nRoadParts; // Zero or More... | ulong nRoadParts; // Zero or More... | ||
RoadPart RoadParts[nRoadParts]; | RoadPart RoadParts[nRoadParts]; | ||
}[ | } [LayerSize]; | ||
</nowiki></code> | </nowiki></code> | ||
Every cell on the map has a '''RoadNet''' entry. If there are no road(s) for that cell, there are no '''RoadParts''' (nRoadParts=0) | Every Layer 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. | 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 ==== | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
RoadPart | RoadPart | ||
{ | { | ||
ushort nRoadPositions; | ushort nRoadPositions;// at least 1? sometimes 0 | ||
XYZTriplet RoadPositions[nRoadPositions]; | XYZTriplet RoadPositions[nRoadPositions]; | ||
byte Flags[4]; | byte Flags[4]; | ||
if WrpType==24 | |||
byte MoreFlags[nRoadPositions]; | |||
Asciiz P3DModel; | |||
XYZTransform Transform[12]; // the averaged position of all the roads in this cell of this type | |||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
===Object Optional=== | === Object Optional === | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
Object | Object | ||
{ | { | ||
ulong ObjectID; | ulong ObjectID; | ||
ulong modelIndex; // into the [[#Models|models path name list]] (1 based) | ulong modelIndex; // into the [[#Models|models path name list]] (1 based) | ||
float TransformMatrix[3][4]; // standard directX transform matrix | float TransformMatrix[3][4]; // standard directX RowFormat transform matrix | ||
ulong 0x02; | ulong 0x02; | ||
} | } | ||
Line 192: | Line 215: | ||
*If ''SizeOfObjects'' above == 0 then there are no objects. | *If ''SizeOfObjects'' above == 0 then there are no objects. | ||
Note that unlike it | Note that unlike it is 4/8WVR cousin, where each Object entry contains (an often) repetitious list of p3d files. The same construct is (now) used similar to Rvamts and Indexes. | ||
Namely, a common list of models is indexed into, by each Object entry. | Namely, a common list of models is indexed into, by each Object entry. | ||
===MapInfo Optional=== | === MapInfo Optional === | ||
MapInfo | MapInfo | ||
Line 204: | Line 227: | ||
} | } | ||
Mapinfo, when it exists, extends to end of file. The sizeof each entry, is determined by it | Mapinfo, when it exists, extends to end of file. The sizeof each entry, is determined by it is info type thus: | ||
====MapData==== | ==== MapData ==== | ||
MapData | MapData | ||
{ | { | ||
Line 212: | Line 235: | ||
if(infoType in [24,31,32]) MapType2; | if(infoType in [24,31,32]) MapType2; | ||
if(infoType in [25,33]) MapType3; | if(infoType in [25,33]) MapType3; | ||
if(infoType in [3,4,8,9,18,19,20,28,29]) | if(infoType in [3,4,8,9,18,19,20,21,28,29]) MapType4; | ||
if(infoType in [34]) MapType5; | if(infoType in [34]) MapType5; | ||
if(infoType in [35]) MapType35; | |||
} | |||
====MapType1==== | ==== MapType1 ==== | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
MapType1 | MapType1 | ||
{ | { | ||
Line 225: | Line 249: | ||
</nowiki></code> | </nowiki></code> | ||
====MapType2==== | ==== MapType2 ==== | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
MapType2 | MapType2 | ||
{ | { | ||
Line 234: | Line 258: | ||
</nowiki></code> | </nowiki></code> | ||
====MapType3==== | ==== MapType3 ==== | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
MapType3 | MapType3 | ||
{ | { | ||
ulong | ulong color; // maybe. or default ind of 0xFFFFFFF generally | ||
float | ulong indicator; // typically 0x01010000 | ||
float [4] // typically 0.5,1.0.1,5.3.0 always 'integers' | |||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
====MapType4==== | ==== MapType4 ==== | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
MapType4 | MapType4 | ||
{ | { | ||
Line 253: | Line 278: | ||
</nowiki></code> | </nowiki></code> | ||
====MapType5==== | ==== MapType5 ==== | ||
<code><nowiki> | <code style="display: block"><nowiki> | ||
MapType5 | MapType5 | ||
{ | { | ||
Line 261: | Line 286: | ||
} | } | ||
</nowiki></code> | </nowiki></code> | ||
==== MapType35 ==== | |||
<code style="display: block"><nowiki> | |||
MapType35 // found in chernarus | |||
{ | |||
ulong ObjectId | |||
float line[3][2];? | |||
byte unknown; | |||
} | |||
</nowiki></code> | |||
Type 35 is also found in oprw23 formats but is currently indecipherable and may, in fact, be an error | |||
==Packed Data== | == Packed Data == | ||
All variables starting with "Packed" are compressed with the common BIS algorithm that is also used in [[PAA File Format|paa]] and OFP [[PBO File Format|pbo]] files. | All variables starting with "Packed" are compressed with the common BIS algorithm that is also used in [[PAA File Format|paa]] and OFP [[PBO File Format|pbo]] files. | ||
{{GameCategory|ofp|Modelling}} | |||
[[Category:BIS_File_Formats]] | [[Category:BIS_File_Formats]] |
Latest revision as of 15:11, 28 April 2023
Introduction
For a general description of wrp files see 8WVR
Legend
see Generic FileFormat Data Types
File Format
- Layer and Map Sizes are derived from the header.
This document is based on analysis of arma1 wrps (OPRW18). The following are known differences between them, and later versions
- OPRW17 (Elite) does not have the clutter
- OPRW20 (sara and desert pbo's) :So far, this is the SAME format as 18 except PackedBytes1
- OPRW23 (vbs2lite us) :So far, this is the SAME format as 20
- OPRW24 (arma2)uses lzo compresion, not, lzss
OPRWv17://elite OPRWv18://arma1 OPRWv20://arma1 sara OPRWv23://vbs2_lite OPRWv24://arma2 { WrpHeader Header; ushort GridBlock_CellEnv[MapSize]; // a gridblock containing cellenv bits (16 bits per terrain cell). // Bits 0-2 are ground (0x0), coast (0x1), beach (0x2) and sea (0x3). Bit 4 indicates road/airstrip. byte GridBlock_CfgEnvSounds[MapSize]; // a gridblock. mostly the value 0x03 and probably related to Config.cpp CfgEnvSounds class ulong nPeaks; XYZTriplet PeakPositions[nPeaks]; //see http://en.wikipedia.org/wiki/Maxima_and_minima ushort GridBlock_RvmatLayerIndex[LayerSize]; if !Elite if ArmaOne ushort RandomClutter[LayerSize]; //compressed. probably random values needed for calculating clutter models position //seems to be related to clutters or sat mask distance as it is //responsible for the clutterbug else bytes RandomClutter[MapSize]; //compressed endif
bytes CompressedBytes1[MapSize]; //compressed
endif float Elevation[MapSize]; //compressed ulong nRvmats; Texture Textures[nRvmats]; //"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" ushort GridBlock_UnknownGrid3[MapSize]; ulong SizeOfObjects; //in bytes ushort GridBlock_UnknownGrid4[MapSize]; ulong SizeOfMapInfo; //in bytes byte CompressedBytes2[LayerSize]; // seems to be connected to roads, runways and special grounds byte CompressedBytes3[MapSize]; // 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
ClutterMask
Each byte represents the intensity or, number of clutter objects for that area of terrain
- Sea and road terrain have zilch.
- desert terrain have very low values
WrpHeader
WrpHeader { char Filetype; // "OPWR" ulong version; // 0x12 = 18 XYPair LayerSize; // 256 x 256 (SaraLite), 128 x 128 (Intro) XYPair MapSize; // 1024 x 1024 (SaraLite), 512 x 512 (Intro) float LayerCellSize; // Layer cell size in meters (40m) }
This is a traditional wrp header endemic to most wrp formats. The LayerCellSize was introduced during Elite. The MapCellSize can be derived as follows:
MapCellSize= LayerCellSize * LayerSizeX / MapSizeX, and is 10m for SaraLite and Intro.
GridBlock
The result of decompressing any GridBlock is to produce an array the size of either the Header's LayerSize or MapSize, at the TypeSize specified. Eg be it byte, or ushort.
There are five gridblocks in the file, two ushort arrays, and 3 byte arrays(if present)
- when the grid is present, the leading flag = 0x01
- when a default fill GridBlock exists
{ byte flag; // =0 ulong FillBits; // = almost always zero }
GridBlock is currently in the 'discussion tab'.
Texture
Texture { Concatenated Asciiz TextureFilenames; //"PrefixRoot\data\layers\some.rvmat\0\0" (Arma) //"PrefixRoot\desert\data\pt.bimpas\0\0" (ELite) //"PboRoot\more_anim.01.pac\0" (OFP)(by way of example) }
- The Operation Flashpoint entry is solely here by way of example. No such entry exists in arma/Elite format.
In all cases (bimpas,ofp,rvmat) they devolve, ultimately, to (a series of) pac/paa texture files.
- see PrefixRoot\ description. Essentially, it is a reference to a pbo.
Each cell in the grid references a (series of) rvmat texture(s) for it is surface. The RvmatLayerIndex is an index to these filenames.
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 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.
The ushort GridBlock RvmatIndices (once decomposed) contain index entries to specific rvmat files. No index value of zero exists. (The first texture of the list is always a dummy entry)
Similar to it is 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];
} [LayerSize];
Every Layer 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;// at least 1? sometimes 0
XYZTriplet RoadPositions[nRoadPositions];
byte Flags[4];
if WrpType==24
byte MoreFlags[nRoadPositions];
Asciiz P3DModel;
XYZTransform Transform[12]; // the averaged position of all the roads in this cell of this type
}
Object Optional
Object
{
ulong ObjectID;
ulong modelIndex; // into the [[#Models|models path name list]] (1 based)
float TransformMatrix[3][4]; // standard directX RowFormat 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 is 4/8WVR cousin, where each Object entry contains (an often) repetitious list of p3d files. The same construct is (now) used similar to Rvamts 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 is 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,21,28,29]) MapType4; if(infoType in [34]) MapType5; if(infoType in [35]) MapType35;
}
MapType1
MapType1
{
ulong ObjectId
float x, z
}
MapType2
MapType2
{
ulong ObjectId
float Bounds[4][2];
}
MapType3
MapType3
{
ulong color; // maybe. or default ind of 0xFFFFFFF generally
ulong indicator; // typically 0x01010000
float [4] // typically 0.5,1.0.1,5.3.0 always 'integers'
}
MapType4
MapType4
{
ulong ObjectId
float Bounds[4][2];
byte Color[4] //rgba
}
MapType5
MapType5
{
ulong ObjectId
float line[2][2];?
}
MapType35
MapType35 // found in chernarus
{
ulong ObjectId
float line[3][2];?
byte unknown;
}
Type 35 is also found in oprw23 formats but is currently indecipherable and may, in fact, be an error
Packed Data
All variables starting with "Packed" are compressed with the common BIS algorithm that is also used in paa and OFP pbo files.