====== OFP WRP File Format OPRW2 & 3 ====== [[https://www.pmctactical.org/forum/viewforum.php?f=43|OFP Forum]], [[:ofp|OFP Home]], [[ofp:file_formats|OFP File Formats]], [[ofp:tools|OFP Tools]], [[ofp:missions|OFP Missions]], [[ofp:modeling|OFP 3D Modeling]], [[ofp:terrain|OFP Terrain]] **Operation Flashpoint (OFP)** aka ArmA: Cold War Assault (CWA) ====== General ====== Flashpoint wrp files use two different file formats to contain the data. This document contains information on OPRW format as used by WrpEdit, and as supplied in the standard BI Islands of Malden, Nogova and etc. OPRW files are, essentially, binarised. This document does not provide information on the better known 4WVR format. See Island File Formats for more info Several versions of OPRW format exist. * Version2: Cold War Crisis. The original. * Version3: Resistance. * Version17: Elite * Version18: General Arma editing. * Version20: Arma's sara.pbo (at least) This document describes ONLY Versions 2 & 3. The only difference between these two formats is a 16 byte added terrain dimension size inserted towards beginning of header. Since all BI islands, including Resistance's Nogova, are 256 x 256 cells square, the information is redundant in terms of the 'official' terrains. However this feature has been exploited heavily by terrain editors to make some huge territories. Cat Afghansitan, and PMC Vietnam to name but two ====== Conventions ====== Little endian byte order, lsb first for numeric values, text is stored in Big endian byte order. byte = 1 char = 8 bits ulong = unsigned long, 4 bytes ushort= unsigned short 2 bytes asciiz= variable length zero terminated string. float= 4byte (single precision) ====== XYPair ====== XYPair { ulong x,y; } ====== XYZTriplet ====== XYZTriplet { float x,y,z; } Normally, this structure is normally associated with positional information. ====== Structure ====== OPRWv2_3 { WrpHeader Header; ulong PackedCellBitFlags[256][256]; byte PackedCellEnvSounds[256][256]; ulong nPeaks; XYZTriplet Peaks[nPeaks]; ushort PackedCellTextureIndexes[256][256]; ulong PackedCellExtFlags[256][256]; float PackedCellElevations[256][256]; ulong nTextures; Texture Textures[nTextures]; // At least 1 ulong nModels; Model Models[nModels]; //can be zero Object Objects{...}; //56 byte records long EndOfObjects; //always -1 }; ====== WRPHeader ====== WrpHeader { char Signature[4]; //"OPRW" ulong Version; // 2 or 3 3 == Resistance if (Resistance) { XYPair TextureGridSize; // 256 x 256 eg XYPair TerrainGridSize; // ditto } } This is a fairly common header througout all wrp formats (including WVR types). There are wrinkles to each one, so check the documentation for each. ====== CellBitFlags ====== Bits 31->9 ?????????????????iiiddgg??RF?Gaa * iii incline 0->7 * dd damage 0->3 * gg geometry levels 0->3 (plus G bit) * F forest bit * R roadway bit * G extended geom flag * aa enum surfacetype {Ground,Coast,Beach,Sea}; ====== CellEnvSounds ====== corresponds to Config.cpp CfgEnvSounds class. * 0 none * 1 sea * 2 tree * 3 meadow * 4 hill * 5 rain * 0ther... ====== Peaks ====== /*If present, XZY values for each peak (X and Z must be aligned to cells (50.0) Ignored. OFP recalculates them at loading-time. */ ====== CellTextureIndexes ====== Each value is index into the Asciiz Textures List. index = 0 has a corresponding entry in the Textures List, but is not used. ====== CellExtFlags ====== XXXXabcc Contains 3 subsections: * cc 0-FF Random values (0..255) * b signed 7 -> -8 Random values, depends on texture color * a signed Random value, depends on texture color flag Ignored. OFP recalculates them at loading-time. Section can be filled with zero. ====== CellElevations ====== Values of vertices of 257x257 mesh (cells - 256x256). Last right column, and last top row of this mesh (257x257) contains 0.0 and is not included in this section. No restriction for min/max values but recommended values: from -50.0 to 1000.0 ====== Texture ====== Texture { asciiz Filename; byte Color; } Like all similar formats, there is a minimum of one entry. The 1st entry is a dummy and never accessed but typically contains the string "data\more_anim.01.pac". This is the transparent index value. Most of the other textures have color values. Although unusual, other entries could contain empty names. Where encountered, they would never be referenced. ====== Model ====== Model { asciiz Filename; //"data3d\thing.p3d" } ====== Object ====== Object { ulong ObjectID; //garanteed unique for each entry ulong ModelIndex; //The index number to use from the model list above to obtain the filename. float Transform[4][3]; //This is the traditional 9 cell vertex to orient and rotate a model. } Objects, if any, are indexes into the models named above (if any). Objects, and the models they refer to, are the way to place buildings, trees, etc on the terrain. The ObjectID is a unique (but somewhat random) value that identifies this PineTree Transform[4][3]; This is the transform matrix used directly by Microsoft DirectX engines. In fact, the 'correct' matrix is actually 4 x 4, but the last column always represents 0,0,0,1 thus M11,M12 M13 (0.0) M21,M22,M23 (0.0) M31,M32,M33 (0.0) M41,M42,M43 (1.0) and so is never stored. This identical matrix is used for WRP files (both formats) and RTM files. The last row (M41...) happens to be the position of the object X Z Y co-ordinates, and is often referred to separately. For further information visit [[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/transforms/transforms.asp|Microsoft]]. ====== File Packing ====== n order to conserve space, where, the majority of cells will contain identical information (if not zero, then an awful lot of 'sea' texture). run length packing is used. The algorithm is identical to that used in pbo compression. Principally, a flag byte followed by mixtures of 8 raw bytes and 2byte pointers. Each of the array[ ][ ] entries above are packed. They are treated as separate compressed blocks each with their own checksum. Since the desired size is known (256x256), unpacking consists of decoding the file up to that limit then checking the checksum. The next 'block' ie, the next array is then treated in a similar manner. For further information on this packing method see PBO File Format.