PEW File Format: Difference between revisions
(massive grammar and formatting cleanup; also removing some "of course", "by inference", etc., since that assumes I can infer ;-)) |
(minor misinterpretation fix) |
||
Line 103: | Line 103: | ||
RVMAT file references in the Layers structure are listed as ''relative'' addresses to the Island Data Path. Traditionally, an RVMAT data path is declared as "Layers\some.rvmat". It is expected, therefore, that you do indeed have a "P:\SomePboPrefix\SomeIsland\data\Layers" folder. Put another way, the ''prefix'' of the PBO must be "SomePboPrefix\SomeIsland". | RVMAT file references in the Layers structure are listed as ''relative'' addresses to the Island Data Path. Traditionally, an RVMAT data path is declared as "Layers\some.rvmat". It is expected, therefore, that you do indeed have a "P:\SomePboPrefix\SomeIsland\data\Layers" folder. Put another way, the ''prefix'' of the PBO must be "SomePboPrefix\SomeIsland". | ||
All RVMAT files must be located in '''one''' PBO (generally, but not necessarily, within the the same PBO as the WRP file). With the above mechanism, you cannot pull RVMAT data from multiple PBOs. This is in contradiction to most of the engine mechanics where everything is a hard reference to any PBO of your choosing | All RVMAT files must be located in '''one''' PBO (generally, but not necessarily, within the the same PBO as the WRP file). With the above mechanism, you cannot pull RVMAT data from multiple PBOs. This is in contradiction to most of the engine mechanics where everything is a hard reference to any PBO of your choosing (like with P3D files). | ||
*IslandObjectPath | *IslandObjectPath |
Revision as of 22:21, 9 November 2009
Introduction
PEW files are Visitor's project files. Visitor is BI's tool for creating Islands.
Visitor is a GUI tool interface that interacts with Bulldozer, an in-built 'world' viewer inside any Armed Assault engine.
The contents of the PEW project file are not directly related to the ultimate output, a WRP file. However, that data contains all similar elements, such as road networks, elevations, cell matrices, models (P3D files) and textures (RVMAT files).
Exporting a PEW file into WRP format involves the use of Bulldozer, since it is Bulldozer that decides how it wants that data presented rather than anything Visitor might like to decide. It is Bulldozer that determines the format and version of the resulting WRP file (in 8WVR format), so the WRP version is based on the version of the Real Virtuality engine used to create it.
While there have been several PEW versions, the ones listed here are:
- POSEW59 and
- POSEW60
There are only a few subtle differences to their makeup.
Legend
See Generic FileFormat Data Types
File Format
- This file format is principally used with Armed Assault v1.09 and later, with the ArmA Tools Suite final release (v1.14).
POSEW59 POSEW60 { PoseHeader Header; ulong nOFPTextures // none in Arma; OFPTexture OFPTextures[nOFPTextures]; ulong nObjectTemplates; ObjectTemplate ObjectTemplates[nObjectTemplates]; shortBool NoOfpTerrains; if (!NoOfpTerrains) { ulong nOFPTerrains; // none in Arma; OFPTerrain OFPTerrains[nOFPTerrains]; } shortBool NoOFPForests; // none in Arma; if (!NoOFPForests) { ulong nOFPForests; OFPForest OFPForests[nOFPForests]; } RoadNets RoadNets[...]; Elevation Elevation[...]; ulong NoOfObjects; Object Objects[NoOfObjects]; ulong NoOfLayers; String LayerName; //"Base" Layer Layers[[NoOfLayers] ; if (POSEW60) { ulong Unknown; } else // pose59 { ulong nNamedZones; NamedZone NamedZones[nNamedZones]; } ulong nRoadBlocks; RoadBlock RoadBlocks[nRoadBlocks]; if (POSEW60) { ulong nNamedZones; NamedZone NamedZones[nNamedZones]; } else // pose59 { ulong Unknown; } ulong nKeyPoints; KeyPoint KeyPoints[nKeyPoints]; ulong NoOfBackgrounds; Background Backgrounds[NoOfBackgrounds] ;// not checked for 59 ulong TotalSizeOfSelections; // from here, to end of file ulong nSelections; Selection Selections[nSelections]; }
PoseHeader
Header { char Signature[7]; // "POSEW59" or "POSEW60" note: NOT null terminated ulong Length; // of PEW file; ulong UnknownLong; // typically 0 String IslandDataPath; //"SomePboPrefix\SomeIsland\data\0" see below String IslandObjectPath; //"" float GridSize; //50.0 float SegmentSize; //400.0 (==SegmentSize - SegmentOverlap) String IslandClassname; //"" };
- IslandDataPath
RVMAT file references in the Layers structure are listed as relative addresses to the Island Data Path. Traditionally, an RVMAT data path is declared as "Layers\some.rvmat". It is expected, therefore, that you do indeed have a "P:\SomePboPrefix\SomeIsland\data\Layers" folder. Put another way, the prefix of the PBO must be "SomePboPrefix\SomeIsland".
All RVMAT files must be located in one PBO (generally, but not necessarily, within the the same PBO as the WRP file). With the above mechanism, you cannot pull RVMAT data from multiple PBOs. This is in contradiction to most of the engine mechanics where everything is a hard reference to any PBO of your choosing (like with P3D files).
- IslandObjectPath
- IslandClassname
IslandObjectPath uses the same mechanics as above. However, since P3D files can be declared from multiple locations (any PBO, including the base 'CA' PBO included in the game) its use is probably deprecated.
PEW files are not known to contain anything in IslandObjectPath or IslandClassname.
OFPTexture
OFPTexture { ulong TextureID; String TextureFileName; // "snih3.paa" String TextureName; // "snih3" String RvmatName; // "snih3.rvmat" byte UnknownBytes[14]; // (typically 0) RGBAColor Colour; }
ObjectTemplate
ObjectTemplate { String ModelFilename; //"SomePrefixRoot\data\jablon.p3d\0" String ModelName; //"jablon" ulong ObjectType; // 0..5 // 0 Natural // 1 Artificial // 2 ??? // 3 Road (RoadFlag will be true) // 4 ??? // 5 ArtificialAndDefinedInRoad RGBAColor OutlineColour; RGBAColor ObjectColour; double GeometryBounds[2]; // 50.0 ulong ModelID; // uniqueID, used by objects to lookup this model(p3d) XYZTriplet GeometryAutocenterPos; double ResolutionBounds[2]; // 50.0 XYZTriplet ResolutionAutoCenterPos; shortBool Generally0x01; shortBool RandomScaleFlag; double RandomScaleMinMax[2]; // 50.0 shortBool RandomRotateFlag; double RandomRotateMinMax[2]; // 20.0 shortBool RandomOrientationFlag; double RanmdomOrientationMinMax[2]; // 180.0 shortBool RoadFlag; if (RoadFlag) { TransformMatrix RoadNamedSelections; // (LB, PB, LE, PE) TransformMatrix XRoadNamedSelections;// (LD, LH, PD, PH) }; ulong nArtificialObjects; ArtificialObject ArtificialObjects[nArtificialObjects]; ulong MarkerType; // Rectangular = 0, Elliptical = 1 }
As opposed to layers (material RVMAT surfaces), 'objects' are instances of models placed onto the map. Irrespective of the number of objects there is only one reference to the model used, which is then referenced as often as needed.
ModelFilename, ModelName, and ModelID are unique unduplicated entries.
The ModelID is not zero based; its value is incremental according to the number of times any model has been added while editing, even if previous models have been deleted; model IDs do not rearrange themselves and deleted IDs are not recycled for re-use. The ObjectID illustrated on maps is, in contrast, the unique InstanceID of each object in the objects structure below.
ArtificialObject
ArtificialObject { String Name; //"pohrada" LongBool Unknown; ulong nTriplets; // always 2 XYZTriplet StartEndPos[nTriplets]; }
OFPTerrain
OFPTerrain { String TerrainName; byte UnknownBytes[11]; ulong nSurfaces; OFPSurface OFPSurfaces[nSurfaces]; }
OFPSurface
OFPSurface { String SurfaceName; float Surfacefloat[4]; byte UnknownBytes[16]; }
OFPForest
OFPForest { String ForestName; RGBAColor OutlineColour; RGBAColor ObjectColour; ulong SquareFillModelID; ulong SquareModelID; ulong TriangleModelID; ulong Unknown1; // (typically 0) ulong Unknown2; // (typically 0) }
RoadNet
shortBool NoRoads; if (!NoRoads) { ulong nTypes; RoadType RoadTypes[nTypes]; ulong nXRoads; XRoad XRoads[nXRoads]; }
RoadType
RoadType { String FamilyName; // "cesta","silnice",etc RGBA KeyPartsColour; RGBA NormalPartsColour; shortBool FilledLine; // 0 or 1 double MaxAngle; // 25.0 degrees double MaxBankAngle; // 5.0 degrees ulong nStraights; RoadList Straights[nStraights]; ulong nCurves; RoadList Curves[nCurves]; ulong nSpecials; RoadList Specials[nSpecials]; ulong nTerminators; RoadList Terminators[nTerminators]; } }
RoadList
RoadList { String ModelName; // "cesta25" ulong ObjectID; // in the model list ushort MeterType; // 0,1,2,3 not present for Terminators shortBool CanChangeAngle; // not present for Terminators or Curves }
MeterType Values | ||
---|---|---|
Type | Straights | Curves |
0 | 6 m | 25 m |
1 | 12 m | 50 m |
2 | 25 m | 75 m |
3 | 100 m |
Broadly speaking, there are a few basic road types:
- asfalt: Bitumen
- silnice: Paved
- cesta: Dirt
Each RoadType describes the general characteristics of the corresponding road, and can have multiple curved, straight, special, and termination P3D models associated with it.
Generally speaking, there are:
- 3 'straight' models, approximately 6, 12, and 25 meters long respectively.
- 4 'curved' models, approximately 25, 50, 75, and 100 meters long.
- 1 'termination' type.
The termination type is a road like any other but tends to be a fixed 6 meter fade out of the general road texture.
XRoad
XRoad { String Name; //kr_asfaltka_asfaltka_t. ushort Shape; //1 or 3 RGBA color; //FF FF FF FF shortBool CanChangeBankAngle; ulong ObjectID; String Intersections[4]; //"asfaltka","silnice","cesta",Type=3 "silnice" else "" }
Although "CrossRoads" could conceivably have any number of intersections, only two types are handled.
- Type 1: A T_Junction (3 intersections)
- Type 3: A genuine crossroad (4 way intersection)
For T_Junctions, there is obviously no 4th intersection and this is null filled.
Without taking too literal an interpretation, there are some major types of road.
- asfaltka:bitumen (sealed)
- silnice: Paved
- cesta: Dirt
Thus the names of each intersection reflect the road type of that intersection, sometimes resulting in (up to) four identical names.
The overall name of the crossroad itself, tries to reflect the nature of it's makeup thus kr_asfaltka_asfaltka_t: an bitumen T_Junction kr_silince_x_cesta: a crossroad of paved and dirt roads.
Elevation
Elevation { XYPair GridSize; // 256 x 256 eg float Heights[GridSize]; float BlueEdgeTerrainHeights[NoOfBlueFloats] ; //Always zero values // NoOfBlueFloats = (GridSize_Y * GridSize_X)/16; ulong Always0; }
Object
Object
{
ShortBool IsPresent;
if (IsPresent)
{
ShortBool Moveable; // always 0
ulong ObjectID; // See Below
float TransformColumn[3][4]; // this is a standard DirectX Transform matrix but in COLUMN format
double ObjectRelativeSize; // decimal percentage
String InstanceName; // "" mostly. "minimalStrelPos" eg for artifical objects
float RelativeSurfaceElevation;
RGBA OutlineColour;
RGBA ObjectColour;
ulong ModelID; // See below
};
};
- ObjectID
Every object entry has a zero-based, linear sequential ObjectID. ObjectID is unique for every object and is the value displayed on a map for all models placed on it (including roads, grass, etc.). Thus, every tree and every road section has its own unique ObjectID.
The first Object in the PEW file is ObjectID==0, the next 1,2,3,4 etc.
If an object has been deleted, that entry retains its unique object ID, even though the ObjectID is no longer stored. If an object is not present (IsPresent is false), the ObjectID is calculated based on the last used object ID. The next real object (IsPresent is true) will always be the Nth ObjectID because the number always increases by the number of object entries, present or not. The reason for this is to maintain consistent IDs for objects so that missions can rely on a bush having the same NearestObject ID as it always had, irrespective of map upgrades.
When you add a new object, it is thus always is added to end of table with a new object ID. When you remove an object, the object ID remains reserved even though the object no longer exists.
This mechanism works well within the ArmA engine, but fails to help at all for conversion of OFP islands unless you methodically and manually enter all of the entries in the correct order. With upwards of 100,000 entries per island, this is practically impossible.
- ModelID
Note that this is the unique ID of the ModelID in the object Template. It is not an index into the template structures. Unusual, and slow as a result.
Layer
Layer { ulong SizeType; //0..2 //see below String Name; //"Base" shortBool DefaultIndicator; // 0 ... 1 if (DefaultIndicator == 0) { ulong SurfaceTable[TableSize.x*y]; ulong TextureTable[TableSize.x*y]; byte UnknownTable[(TableSize.x*y/4)]; ushort UnknownShort; }; if (DefaultIndicator == 1) { ulong NoOfTerrainMaterials; TerrainMaterial[NoOfTerrainMaterials] { ulong BitFlags; // 1 = label, 0x40 = rvmatfile,,,, String MaterialName; // "---sea---","Layers\P_000-000_L00.rvmat" ulong TypeID; // 0..3 }; ulong RvmatTable[TableSize.x*y]; }; };
TableSize = Terrain.GridSize>> SizeType;
RoadBlock
RoadBlock { ShortBool IsPresent; if IsPresent { ShortBool Always1; ulong Unknown[12]; /* typical data ** 00 00 00 00 00 00 00 F0 ** 2C 46 00 98 23 46 C6 6F ** C6 42 0E 01 00 00 01 00 ** 00 F0 2C 46 00 98 23 46 ** C6 6F C6 42 0E 01 00 00 ** 4B 00 00 00 00 00 00 00 */ ushort Type; // 0,1,2,3 String RoadFamilyName; //"hlavni silnice" String RoadModelName; //"kr_silnice_cesta_t" RGBA color; ShortBool Always1; ulong Count; FamilyList FamilyLists[Count]; ulong Unknown[27]; /* typical data ** FA D4 30 BF 94 58 08 3D 00 00 C8 C0 00 00 60 C0 ** 00 00 00 00 00 00 48 C1 00 00 60 40 00 00 00 00 ** 00 00 48 C1 00 00 60 C0 00 00 00 00 00 00 00 00 ** 00 00 60 40 00 00 00 00 00 00 00 00 00 00 C8 C0 ** 00 00 00 00 00 00 30 C0 00 00 C8 C0 00 00 00 00 ** 00 00 1C C1 04 01 00 00 00 00 00 00 00 00 00 00 ** 09 00 00 00 0B 80 00 00 04 00 00 00 */ ulong Count; ModelList ModelLists[Count]; } }
Type | Description | |
---|---|---|
0 | Road Ending with FamilyName and its ModelName_konec | |
1 | TJunction ModelName Only | |
2 | Road similar to type 0 | |
3 | Xroad with ModelName Only |
FamilyList
FamilyList { ulong Unknown[4];// Typically 00 00 C8 C0 00 00 C8 C0 00 00 00 00 0E 01 00 00 String Name; // "silnice hlavni silnic\0" }
This struct is principally used for XRoads and T_Junctions. It typically lists the order of all RoadFamilyName values required.
ModelList
ModelList { ulong Count; //for example, 15 BlockModel BlockModel[Count]; String FamilyName; //"silnice hlavni silnic\0" ulong Unknown[4]; //Typically 00 00 C8 C0 00 00 C8 C0 00 00 00 00 0E 01 00 00 RGBA color[2]; ShortBool Always01; //01 ulong buf2[4]; // Typically 00 00 00 00 00 00 39 40 00 00 00 00 00 00 24 40 }
BlockModel
BlockModel { ulong ModelFlag; // 0x000001 ... 0x00010001 XYZTriplet Position; // Model coordinates float ModelDirection; ulong ObjectID; ushort Type; //0,1,2,3 String ModelName; //"silnice10 100\0" ulong unknown[25]; /*typical data **00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **C4 76 C2 3F 0E EB 8A C1 00 00 00 00 BE 00 00 00 **CC ED 26 BE CA 0F 12 40 56 30 28 3F 00 00 00 00 **18 CA 04 C1 48 8B 3D C0 00 00 00 00 2D 3D 91 C1 **06 01 C0 40 00 00 00 00 EE 98 84 C1 99 99 91 C0 **00 00 00 00 64 4A 5F 35 99 99 91 40 00 00 00 00 **64 4A 5F B5 01 00 */ ShortBool ok; // 0 or 1 }
NamedZone
NamedZone { ShortBool IsPresent; if IsPresent { ShortBool Movable; // Always0; BisString Name1; //"Les_new" ulong AreaColor,OutlineColor; ulong DisplayStyle; ulong nPoints; PointsRectangle { float TopLeft.xy; float BottomRight.xy; }[nPoints/4]; /* Typical Data **00 00 61 45 00 78 1B 46 00 20 64 45 00 20 19 46 **00 20 64 45 00 78 1B 46 00 40 67 45 00 58 18 46 **00 40 67 45 00 78 1B 46 00 60 6A 45 00 58 18 46 **00 60 6A 45 00 78 1B 46 00 80 6D 45 00 90 17 46 **00 80 6D 45 00 B0 1A 46 00 A0 70 45 00 C8 16 46 **00 A0 70 45 00 E8 19 46 00 C0 73 45 00 00 16 46 */ ulong ID; // 0,1,2,3,4.... if POSEW60 { LongBool Visible; // always } else { BisString Name2; //Les_new Name2==Name1 } } };
KeyPoint
KeyPoint { LongBool Always1; String ClassName; //"Noe_Lany" RGBA AreaColor,OutlineColor; ulong DisplayStyle; ShortBool Visible; float Offset[2]; // map relative float Size[2]; // 250 x 250.0 eg (width and height) ulong ID; // 0,1,2,3,4,5,6.... BisString TownName; //"Lipany", "Hill" BisString LocaleType; //"NameCity" NameCityCapital, NameVillage, NameLocal, VegetationBroadLeaf,Hill,Marine,ViewPoint BisString ClassText; // "canOcclude=1; BumbleButt='FlowControl2"; ++=)#4555Semi" }
Each of these locales have a LocaleType. Some of which are:
- NameCity
- NameCityCapital
- NameVillage
- VegetationBroadLeaf (Forest)
There is always a classname associated with this locale,
- Forest_Owls
- Abel_LaTrinite
and in most cases a text name
"La Refuge Des Chassuers"
Viewpoint and Marine types do not have names associated with them. There is no "place" in the sea.
Background
Background // this structure has not been seen { String BackgroundFilename;//"sat_lco.bmp" String BackgroundName; //"overlay1" float OffsetXY[2]; float SizeXY[2]; ulong Transparency; shortBool Visible; // or ulong? }
Selection
Selection { ushort strlen; char[] SelectionName[strlen]; // NOT null terminated ulong nSubSelections; SubSelection SubSelections[nSubSelections] }
SubSelection
SubSelection { ulong ObjectId; byte Type; byte Unknown[7];
}
Enums
ObjectClassEnum
enum ObjectClassEnum
{
Natural = 1,
Artificial = 2,
Road = 3,
Forest = 4,
ArtificialAndDefinedInRoad = 5
}
MarkerTypeEnum
enum MarkerTypeEnum
{
Rectangular = 0,
Elliptical = 1
}