Wrp File Format - OPRWv17 to 24: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (→‎File Format: elite = same format (almost))
m (Text replacement - "\[ *(https?:\/\/[^ = ]+) +([^= ]+) *\]" to "{{Link|$1|$2}}")
 
(32 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{unsupported-doc}}
{{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 ===
[http://en.wikipedia.org/wiki/Endianness#Little-endian Little endian] byte order, lsb first for numeric values,
see [[Generic FileFormat Data Types]]
text is stored in [http://en.wikipedia.org/wiki/Endianness#Big-endian 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.


*OPRW17 (Elite) does not have the PackedBytes1
== File Format ==
*OPRW20 (sara and desert pbo's) :So far, this is the SAME format as 18
 
*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:
  OPRWv17://elite
  OPRWv18:
  OPRWv18://arma1
  OPRWv20  
  OPRWv20://arma1 sara
OPRWv23://vbs2_lite
OPRWv24://arma2
  {
  {
   WrpHeader    Header;
   WrpHeader    Header;
 
   ushort        UnknownGrid1[TextureCellSizeXY]; // a gridblock
   ushort        GridBlock_CellEnv[MapSize];     // a gridblock containing cellenv bits (16 bits per terrain cell).
   byte          UnknownGrid2[TextureCellSizeXY]; // a gridblock // mostly the value 0x03 and probablay related to Config.cpp CfgEnvSounds class
                                                // 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        TextureIndex[TextureCellSizeXY]; // a gridblock
   ushort        GridBlock_RvmatLayerIndex[LayerSize];
   ushort        PackedRandom[TextureGridSizeXY]; //probably random values needed for calculating clutter models position
    
   if !Elite
   if !Elite
   byte        PackedBytes1[TerrainGridSizeXY]; //seems to be related to clutters or sat mask distance as it is
   if ArmaOne
  endif                                          responsible for the [http://tinyurl.com/6b27ed clutterbug]
    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        PackedElevation[TerrainGridSizeXY];
   float        Elevation[MapSize];             //compressed
   
   
   ulong        nTextures;
   ulong        nRvmats;
   Texture      Textures[nTextures];             //"PrefixRoot\data\layers\some.rvmat\0\0"
   Texture      Textures[nRvmats];               //"PrefixRoot\data\layers\some.rvmat\0\0"
   
   
   ulong        nModels;
   ulong        nModels;
   asciiz        modelPaths[nModels];         //"ca\buildings\kostelik.p3d\0"
   asciiz        modelPaths[nModels];         //"ca\buildings\kostelik.p3d\0"
   
   
Line 63: Line 64:
   ClassedModel  Models[nClassedModels];          //"Land_Hangar\0" : "ca\buildings\Hangar.p3d\0"
   ClassedModel  Models[nClassedModels];          //"Land_Hangar\0" : "ca\buildings\Hangar.p3d\0"
   
   
   byte          UnknownGrid3[TextureCellSizeXY]; // a gridblock
   ushort        GridBlock_UnknownGrid3[MapSize];
   
   
   ulong        SizeOfObjects;                  //in bytes
   ulong        SizeOfObjects;                  //in bytes
   
   
   byte          UnknownGrid4[TextureCellSizeXY]; // a gridblock
   ushort        GridBlock_UnknownGrid4[MapSize];
   
   
   ulong        SizeOfMapInfo;                  //in bytes
   ulong        SizeOfMapInfo;                  //in bytes
   
   
   byte          PackedBytes2[TextureGridSizeXY]; //seems to be connected to roads, runways and special grounds
   byte          CompressedBytes2[LayerSize];     // 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
   byte          CompressedBytes3[MapSize];       // unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02
   ulong        maxObjectID;
   ulong        maxObjectID;
   
   
   ulong        SizeOfRoadNets;                  //in bytes
   ulong        SizeOfRoadNets;                  //in bytes
   RoadNet      RoadNets[SizeOfRoadNets];  
   RoadNet      RoadNets[SizeOfRoadNets];
   
   
   Object        Objects[SizeOfObjects/SizeOfObject]; // SizeOfObject ==60
   Object        Objects[SizeOfObjects/SizeOfObject]; // SizeOfObject ==60
Line 86: 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 92: Line 99:
   char    Filetype;        // "OPWR"
   char    Filetype;        // "OPWR"
   ulong  version;        // 0x12 = 18
   ulong  version;        // 0x12 = 18
   XYPair  TextureGridSize; // 256 x 256 eg
   XYPair  LayerSize;       // 256 x 256 (SaraLite), 128 x 128 (Intro)
   XYPair  TerrainGridSize; // ditto
   XYPair  MapSize;         // 1024 x 1024 (SaraLite), 512 x 512 (Intro)
   float  CellSize;       // generally 50.0 meters
   float  LayerCellSize;   // Layer cell size in meters (40m)
  }
  }


This is a traditional wrp header endemic to most wrp formats. The CellSize was introduced during Elite
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 the Header's TextureGridSizeXY, at the TypeSize specified. Eg be it byte, or ushort.
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)
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 null GridBlock exists
*when a default fill GridBlock exists
  {
  {
   byte  flag;    // =0
   byte  flag;    // =0
   ulong NullBits; // = 0
   ulong FillBits; // = almost always zero
  }
  }
 
GridBlock is currently in the 'discussion tab'.
GridBlock is currently in the 'discussion tab'.


===Texture===
=== Texture ===
  Texture
  Texture
  {
  {
   Concatenated Asciiz rvmat_paths; //"PrefixRoot\data\layers\some.rvmat\0\0"
   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)
  }
  }


*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.
*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's surface. The TextureIndex is an index into these material names.  
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 133: Line 146:
Ie, the end of '''this''' entry = \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.
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 142: 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.


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.
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.


The ushort Textureindices (once decomposed from a GridBlock) contain references to a 'texture'. no index value of zero can exist. (The first texture of the list is always a dummy entry)


===ClassedModel===
 
<code><nowiki>
=== ClassedModel ===
<code style="display: block"><nowiki>
  ClassedModel
  ClassedModel
  {
  {
Line 159: 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];
  } TextureGridSizeXY];
  } [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];
asciiz     Model;
        if WrpType==24
float      matrix[12];
          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 198: Line 215:
*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.
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 210: Line 227:
  }
  }


Mapinfo, when it exists, extends to end of file. The sizeof each entry, is determined by it's info type thus:
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 218: 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])                   MapType4;
   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 231: Line 249:
</nowiki></code>
</nowiki></code>


====MapType2====
==== MapType2 ====
<code><nowiki>
<code style="display: block"><nowiki>
  MapType2
  MapType2
  {
  {
Line 240: Line 258:
</nowiki></code>
</nowiki></code>


====MapType3====
==== MapType3 ====
<code><nowiki>
<code style="display: block"><nowiki>
MapType3
MapType3
{
{
  ulong unknown[2];  
  ulong color; // maybe. or default ind of 0xFFFFFFF generally
  float line[2][2];?
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 259: Line 278:
</nowiki></code>
</nowiki></code>


====MapType5====
==== MapType5 ====
<code><nowiki>
<code style="display: block"><nowiki>
MapType5
MapType5
{
{
Line 267: 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.
[[category:Operation Flashpoint: Modelling]]
{{GameCategory|ofp|Modelling}}
[[Category:BIS_File_Formats]]
[[Category:BIS_File_Formats]]

Latest revision as of 15:11, 28 April 2023

bi symbol white.png
Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.

This page contains unofficial information.

Some usage of this information may constitute a violation of the rights of Bohemia Interactive and is in no way endorsed or recommended by Bohemia Interactive.
Bohemia Interactive is not willing to tolerate use of such tools if it contravenes any general licenses granted to end users of this community wiki or BI products.

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.