Wrp File Format - OPRWv17 to 24: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
(new structure (not complete now))
m (Text replacement - "\[ *(https?:\/\/[^ = ]+) +([^= ]+) *\]" to "{{Link|$1|$2}}")
 
(72 intermediate revisions by 6 users not shown)
Line 1: Line 1:
[[Category:Sandbox]]
{{Feature|UnsupportedDoc}}


{{unsupported-doc}}
== Introduction ==


==Introduction==
For a general description of wrp files see [[Wrp_File_Format_-_8WVR|8WVR]]
=== Legend ===
see [[Generic FileFormat Data Types]]


===Legend===
*'''byte''' 8 bits, unsigned.
*'''ushort''' 2 bytes, unsigned.
*'''ulong''' 4 bytes, unsigned.
*'''float''' 4 bytes, signed.






==File Format==
<code><nowiki>
structHeader Header;


//still unknown stuff here
== File Format ==
//followed by


structPeaks Peaks;
*Layer and Map Sizes are derived from the header.
structTextureGridMaterials MaterialIndices; //see discussion below. Not fully defined (yet)


ushort PackedRandom[texZ][texX] //probably random values needed for calculating clutter models position
This document is based on analysis of arma1 wrps (OPRW18). The following are known differences between them, and later versions


byte  PackedUnknown[gridZ][gridX] // seems to be related to clutters or sat mask distance as it is responsible for the </nowiki>[http://tinyurl.com/6b27ed clutterbug]<nowiki>
::*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


float PackedElevation[gridZ][gridX]//
  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 {{Link|http://tinyurl.com/6b27ed|clutterbug}}
  else
    bytes      RandomClutter[MapSize];    //compressed
  endif


/* packed data corresponds to the standard pbo compression format */
 
      bytes        CompressedBytes1[MapSize];    //compressed


structMaterials Materials;
  endif
structModels Models;
structClassedModels ClassedModels;
  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[...];
}


//something grid related[size unknown]
*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.
// followed by:
*Similarly, SizeOfObjects can be used to skip to the MapInfo


byte[texZ][texX] bytes2 //seems to be connected to roads, runways and special grounds
=== ClutterMask ===
byte[gridZ][gridX] bytes3 //unknown but 0x00 for forests and roads and sea, mostly 0x03 and rarely 0x02


ulong maxObjectID //not number of objects
Each byte represents the intensity or, number of clutter objects for that area of '''terrain'''
ulong ObjectBlockOffset //amount of bytes used for RoadNets
*Sea and road terrain have zilch.
*desert terrain have very low values


structRoadNet RoadNets[texZ,texX]; //probably organized in texture grid cells to realize terrain streaming
=== WrpHeader ===
structObject Objects[unknown];


structMapInfo MapInfos[unknown];
WrpHeader   
</nowiki></code>
{
  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)
}


==Structures==
This is a traditional wrp header endemic to most wrp formats. The LayerCellSize was introduced during Elite. The MapCellSize can be derived as follows:


===structHeader===
MapCellSize= LayerCellSize * LayerSizeX / MapSizeX, and is 10m for SaraLite and Intro.
<code><nowiki>
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)
}
</nowiki></code>
----
----


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


----
Each cell in the grid references a (series of) rvmat texture(s) for it is surface. The RvmatLayerIndex is an index to these filenames.
===structPeaks===
 
<code><nowiki>
Thus, '''each''' entry of this materials list consists of concatenated asciiz strings in the form
structPeaks
{
ulong nPeaks;
float XZY[nPeaks][3]; //Position of the Peak  (Z is height)
}
</nowiki></code>
----


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


----
Ie, the end of '''this''' entry = \0\0
===structTextureGridMaterials===
<code><nowiki>
structTextureGridMaterials
{
//still need to be worked out
}
</nowiki></code>
----


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
===structMaterials===


<code><nowiki>
"AnRvmatFile\0\0"
structMaterials
{
ulong nMaterials; //Number of Rvmat entries (at least one)
structMaterial Materials[nMaterials];
}
</nowiki></code>
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====
There is always, at least one materials entry. The 1st entry.
<code><nowiki>
The first entry (effectively index 0) is a dummy, with an empty path, because it will never be accessed. Indexes start at 1.
structMaterial
{
asciiz rvmat_path;
byte 0x00;
}
</nowiki></code>
----


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.
===structModels===
<code><nowiki>
structModels
{
ulong nModels;         //number of models
asciiz model_path[nModels]; //e.g. ca\buildings\kostelik.p3d
}
</nowiki></code>
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===
<code><nowiki>
structClassedModels
{
ulong nClassedModels; //number of classed models
structClassedModel Models[nClassedModels];
}
</nowiki></code>


====structClassedModel====
=== ClassedModel ===
<code><nowiki>
<code style="display: block"><nowiki>
structClassedModel
ClassedModel
{
{
asciiz class_name; //e.g. Land_Hangar
asciiz     class_name; //"Land_Hangar\0"
asciiz model_path;       //e.g. ca\buildings\kostelik.p3d
asciiz     model_path; //"ca\buildings\Hangar.p3d"
float pos[3];           //XZY
XYZTriplet Position;
ulong unknown;
ulong     unknown;
}
}
</nowiki></code>
</nowiki></code>
----


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 ===
===structRoadNet===
<code style="display: block"><nowiki>
<code><nowiki>
RoadNet
structRoadNet
{
{
  ulong   nRoadParts; // Zero or More...  
ulong nRoadParts; // Zero or More...  
  RoadPart RoadParts[nRoadParts];
structRoadPart RoadParts[nRoadParts];
} [LayerSize];
}
</nowiki></code>
</nowiki></code>
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
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)
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.
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.


====structRoadPart====
==== RoadPart ====
<code><nowiki>
<code style="display: block"><nowiki>
structRoadPart
RoadPart
{
{
ushort nRoadPositions;
ushort     nRoadPositions;// at least 1? sometimes 0
float RoadPositions[nRoadPositions][3]; //XYZ
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 ===
----
<code style="display: block"><nowiki>
===structObject===
Object
<code><nowiki>
{
structObject
{
ulong ObjectID;
ulong ObjectID;
ulong modelIndex;
ulong modelIndex; // into the [[#Models|models path name list]] (1 based)
float matrix[12];
float TransformMatrix[3][4]; // standard directX RowFormat 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.
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 ===


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
MapInfo
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
  ulong infoType;
used many times on the island at different locations. Thus many object entries contain the same modelIndex. Eg, the same, p3d tree.
  MapData[...];
----
}


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


----
==== MapData ====
===structMapInfo===
MapData
<code><nowiki>
{
structMapInfo
  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;
ulong infoType;
  if(infoType in [25,33])                                     MapType3;
  if(infoType in [3,4,8,9,18,19,20,21,28,29])                 MapType4;
if(infoType in [0,1,2,10,11,13,14,15,16,17,22,23,26,27,30]) structType1 type1;
  if(infoType in [34])                                       MapType5;
if(infoType in [24,31,32]) structType2 type2;
  if(infoType in [35])                                        MapType35;
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;
}
}
</nowiki></code>


====structType1====
==== MapType1 ====
<code><nowiki>
<code style="display: block"><nowiki>
structType1
MapType1
{
{
ulong ObjectId
ulong ObjectId
float x, z
float x, z
}
}
</nowiki></code>
 
==== MapType2 ====
<code style="display: block"><nowiki>
MapType2
{
  ulong ObjectId
  float Bounds[4][2];
}
</nowiki></code>
</nowiki></code>


====structType2====
==== MapType3 ====
<code><nowiki>
<code style="display: block"><nowiki>
structType2
MapType3
{
{
ulong ObjectId
ulong color; // maybe. or default ind of 0xFFFFFFF generally
float[4][2] Bounds
ulong indicator; // typically 0x01010000
float [4]       // typically 0.5,1.0.1,5.3.0 always 'integers'
}
}
</nowiki></code>
</nowiki></code>


====structType3====
==== MapType4 ====
<code><nowiki>
<code style="display: block"><nowiki>
structType3
MapType4
{
{
long[2] unknown
ulong ObjectId
float[2][2] line?
float Bounds[4][2];
byte  Color[4] //rgba
}
}
</nowiki></code>
</nowiki></code>


====structType4====
==== MapType5 ====
<code><nowiki>
<code style="display: block"><nowiki>
structType4
MapType5
{
{
ulong ObjectId
  ulong ObjectId
float[4][2] Bounds
  float line[2][2];?
byte[4] Color //rgba
}
}
</nowiki></code>
</nowiki></code>
 
==== MapType35 ====
====structType5====
<code style="display: block"><nowiki>
<code><nowiki>
MapType35  // found in chernarus
structType5
{
{
ulong ObjectId
  ulong ObjectId
float[2][2] line?
  float line[3][2];?
  byte  unknown;
}
}
</nowiki></code>
</nowiki></code>


Type 35 is also found in oprw23 formats but is currently indecipherable and may, in fact, be an error


----
== Packed Data ==
'''Discussion'''
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}}
:For the TextureIndices block I found out that it is organized in 8x4 blocks. If the block starts with 0x00 you just read in 32 short values describing the block. Otherwise you mostly see 2 identical short values describing one 8x4 block filled just with this value. Sometimes instead of the 0x00 value or the 2 identical short values, other values occur probably describing what sort of data follows and what position the next 8x4 block in the whole ''texX'' x ''texZ'' block has. But I am still not sure what order these 8x4 blocks follow. The TextureIndices block also seems to start with some "header" data which I couldnt identify so far. --[[User:T D|T_D]] 12:11, 13 October 2008 (CEST)
[[Category:BIS_File_Formats]]
 
 
:The unknown int in the the TextureGridRoads block is the checksum of the packed data before so it does not belong to the TextureGridRoads block --[[User:T D|T_D]] 14:54, 17 October 2008 (CEST)
 
::Agreed, yeah... saw that, also, maxObjectID isn't part of the TextureGridRoads structure and it will probably end up really being NoOfObjects.
 
::No it is not NoOfObjects. Already checked that by reading objects from 8WVR and comparing readed objects with this value --[[User:T D|T_D]] 04:33, 18 October 2008 (CEST)
 
::Experience has taught me that one can never be to certain about these things until one is certain, if you know what I mean... :)
::It maybe MaxObjectId it maybe not... time will tell.
 
::Building the standard SampleMap.pew into a 8wvr.wrp yeilds 5134 obejcts, then into a oprw18.wrp yeilds 5132 in the MaxOjectId/NoOfObjects field. If you add 1 to this value this is the number of obejcts that happens to be in the array of objects in this particular file.
::However, this senario doesn't hold true for a certain 'ca' mod oprw18.wrp. That value (as I mentioned earlier) is 637,876 and the number of actual objects in the list array is 602,481.
::This may be because there is a prior structure in the file that denotes out of the 637,876 objects ones that are not specified in the Objects array... dunno, well see if that pans out.
::The most logical senario is that this is the NoOfObjects less some other structure count = ObejctList count.
::If this isn't the senario then there maybe another ObjectCount item lying around the file somewhere that does indicate how many objects are in the objects list array.
 
 
:this block ''ushort[gridZ][gridX] unknown //packed'' seems to consist of random numbers. So my guess is, that these random values are used to calculate the positions of the clutter models, so that the island is always looking the same without saving the pos of every grass model. Could this be the case? --[[User:T D|T_D]] 13:50, 19 October 2008 (CEST)

Latest revision as of 16: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.