P3D Model Info
Model Info
The Model Info structure is last in file for ODOL7 (ofp) and at top of file for ODOL4x (ARMAx)
ModelInfo { float LodTypes[Header.NoOfLods];// alias resolutions ulong Index; // appears to be a bit flag, 512, 256 eg float MemLodSphere; float GeoLodSphere; // mostly same as MemLodSphere ulong PointFlags[3]; // typically 00 00 00 00 00 00 00 00 00 00 0C 00 eg (last is same as user point flags) XYZTriplet Offset1; // model offset (unknown functionality),//mostly same as offset2 ulong mapIconColor; // RGBA 32 color ulong mapSelectedColor; // RGBA 32 color float ViewDensity; //-1 -> default shape values will be used (default value) / 0 -> opaque / 1 -> transparent (DO NOT add this to an opaque object) XYZTriplet bboxMinPosition; // minimum coordinates of bounding box XYZTriplet bboxMaxPosition; // maximum coordinates of bounding box. Generally the complement of the 1st // pew.GeometryBounds in Pew is bboxMinPosition-bboxMaxPosition for X and Z // pew.ResolutionBounds mostly the same XYZTriplet CentreOfGravity; // pew.GeometryAutoCenterPos (and mostly pew.ResolutionAutoCenterPos too) XYZTriplet Offset2; // mostly same as Offset1 often same as CentreOfGravity (but it isn't ResolutionPos) XYZTriplet CogOffset; // see below XYZTriplet ModelMassVectors[3]; // for ODOL7 this is a mixture of floats and index values //// if Arma3 ///////////////// byte ThermalProfile2[24]; /////////////////////////////// TinyBool AutoCenter, lockAutoCenter, canOcclude, canBeOccluded, allowAnimation; ///////////ARMA/VBS2 //////////// bytes UnknownARMAFlags[6]; // byte ThermalProfile[24]; // ulong UnknownLong; // V48 and beyond byte ThermalProfile2[24]; // TOH only (v52) see above for arma3 Skeleton Skeleton; // /////////////////////////////////////// byte UnknownByte; ulong nFloats; // always zero for arma float UnknownFloats[nFloats]; // potentially compressed float Mass; float MassReciprocal; // see note float AltMass; // see note float AltMassReciprocal; // see note IF ARMA3 byte UnknownByteIndices[14] // see note generally FF FF FF FF FF FF FF FF FF FF FF FF ELSE byte UnknownByteIndices[12] // see note generally FF FF FF FF FF FF FF FF FF FF FF FF endif ///////////ARMA (V4x) ONLY //////////// ulong UnknownLong; // often same as NoOfLods TinyBool UnknownBool; // generally set if ascii below has strings asciiz ClassType; // class="House" See Named Properties asciiz DestructType; // damage="Tent" See Named Properties TinyBool UnknownBool2; // rarely true ulong Always0; // IF ARMA3 byte DefaultIndicators[NoOfLods][12]; //generally FF FF FF FF FF FF FF FF FF FF FF FF ENDIF /////////////////////////////////////// }
CentreOfGravity
Coordinates in odols are expressed relative to this value.
Thus
MLOD Points[Any] = ODOL Points[Any] + CentreOfGravity
- RawCentreOfGravity is calculated from the mlod geometry lod
- Asymetrical BoundingBox values are calculated from the TotalMin and TotalMax of all points in all lods (of the mlod).
TotalMinMax=MinMax(lods[AllLods].points[AllValues])
- The odol's CentreOfGravity, bounding box and CogOffset are calculated as follows
// convert mlod to odol relative TotalMin-=RawCentreOfGravity; //asymetrical bounding box TotalMax-=RawCentreOfGravity; //turn asymetrical to symetrical BoundingBoxMax=fabs(TotalMax-TotalMin)/2); BoundingBoxMin=-BoundingBoxMax; // this *is* the odol bbox expressed in relative units CogOffset= BoundingBoxMax-TotalMax+RawCentreOfGravity;// *the* odol CogOffset CentreOfGravity-=CogOffset;//*the* odol cog
- Pew files make use of this information to build p3d model templates. For odol p3d's the information is stored as above, for mlods, it is calculated as above
ODOLV7 BIS
The 24 byte area after the mass float is, as represented, in the supplied, 'official', addons from Bis for ALL game engines.
For V7:
- MOST oem addons subscribe to above.
- SOME oem addons, notably those from VTE, and any with optics, have a varying amount of data after the Mass float. Some less than 24, some, a lot more than 24. CLearly this area needs further work. The models themselves are unlikely to be faulty, and were generated by O2L. There is nothing in previous data structures that would suggest appended or truncated data. Perhaps, like it's MLOD-SP3X equivalent, it has a default file size, and anything 'extra', is tested for.
Odol Explorer
Note that odol explorer from Dschulle reverses -24 bytes from end of file to 'get at' the Mass float. This because at the time, the compressed float array was not understood.
For trunctated data (Odol7 files < 24 bytes) this will clearly be faulty. For excessive files, OdolEX may well indeed be right.
Skeleton
Skeleton { asciiz SkeletonName; //"A10Skeleton" if (SkeletonName != null) { tbool isInherited; ulong NoOfBoneNames; SkeletonBoneName SkeletonBoneNames[NoOfBoneNames]; if (type>40 && ! VBS2) // ie arma2 { byte Always0; } } }
SkeletonBoneName
SkeletonBoneName { asciiz BoneName; //"3dhud" or "Gearlocks" or "Fuel" or ... asciiz ParentBoneName; // "Aeileron_1" }
corresponds to model.cfg
class cfgSkeletons { class SkeletonClassname: Default { skeletonBones[]= { "RightDoor1","", "RightDoor2","", "LeftDoor1","", "LeftDoor2","RightDoor2", etc" }; };
LodTypes
LodTypes are resolutions. Most of them have humanly readable context such as the 'memory' lod. And are selected as such in Oxygen. The are consequently referred to here as 'LodTypes', since the floating point values, although relevant to the engine, are not as immediately apparent to a human.
In this list. there is, undoubtedly, some meaning to the apparent random order of lod types (the order of resolutions). It could simply be 'as presented', 'as discovered', or 'as first created' in O2. It could be something much deeper, res lods followed by geo lods, stencil lods, and etc.
The order is irrelevant to the structure of the file (and probably irrelevant to the engine as well).
The LodTypes array is used in conjunction with the start and ending LodAddressOffsets mentioned above.
Whatever resolution is in LodType[0] THAT LOD will be found at the offsets contained in startaddress[0].
and so on.
In other words, we have a fast indexing service. If the engine is only interested in, or needs to render, shadow lods, it looks for shadow lods (if any) in the list, and 'jumps' to that lod, rather than scanning the entire file.
Resolution Values
Hex | Float | Decimal | Description |
---|---|---|---|
<1,000 | Graphical Lod | ||
Functional Lods | |||
0x447a0000 | 1.0e3 | 1,000 | View Gunner |
0x44898000 | 1.1e3 | 1,100 | View Pilot |
0x44960000 | 1.2e3 | 1,200 | View Cargo |
"" | "" | Shadow Lods | |
0x461c4000 | 1.0e4 | 10,000 | Stencil Shadow |
0x461c6800 | 1.001e4 | 10,010 | Stencil Shadow 2 |
0x462be000 | 1.1e4 | 11000 | Shadow Volume |
0x462c0800 | 1.101e4 | 11010 | Shadow Volume 2 |
0x551184e7 | 1.0e13 | 10,000,000,000,000 | Geometry |
0x58635fa9 | 1.0e15 | 1,000,000,000,000,000 | Memory |
0x58e35fa9 | 2.0e15 | 2,000,000,000,000,000 | Land Contact |
0x592a87bf | 3.0e15 | 3,000,000,000,000,000 | Roadway |
0x59635fa9 | 4.0e15 | 4,000,000,000,000,000 | Paths |
0x598e1bca | 5.0e15 | 5,000,000,000,000,000 | HitPoints |
0x59aa87bf | 6.0e15 | 6,000,000,000,000,000 | View Geometry |
0x59c6f3b4 | 7.0e15 | 7,000,000,000,000,000 | Fire Geometry |
0x59e35fa9 | 8.0e15 | 8,000,000,000,000,000 | View Cargo Geometry |
0x59ffcb9e | 9.0e15 | 9,000,000,000,000,000 | View Cargo Fire Geometry |
0x5a0e1bca | 1.0e16 | 10,000,000,000,000,000 | View Commander |
0x5a1c51c4 | 1.1e16 | 11,000,000,000,000,000 | View Commander Geometry |
0x5a2a87bf | 1.2e16 | 12,000,000,000,000,000 | View Commander Fire Geometry |
0x5a38bdb9 | 1.3e16 | 13,000,000,000,000,000 | View Pilot Geometry |
0x5a46f3b4 | 1.4e16 | 14,000,000,000,000,000 | View Pilot Fire Geometry |
0x5a5529af | 1.5e16 | 15,000,000,000,000,000 | View Gunner Geometry |
0x5a635fa9 | 1.6e16 | 16,000,000,000,000,000 | View Gunner Fire Geometry |
0x5a7195a4 | 1.7e16 | 17,000,000,000,000,000 | Sub Parts |
0x5a7fcb9e | 1.8e16 | 18,000,000,000,000,000 | SHADOW_VOLUME_VIEW_CARGO |
0x5a8700cc | 1.9e16 | 19,000,000,000,000,000 | SHADOW_VOLUME_VIEW_PILOT |
0x5a8e1bca | 2.0e16 | 20,000,000,000,000,000 | SHADOW_VOLUME_VIEW_GUNNER |
0x5a9536c7 | 2.1e16 | 21,000,000,000,000,000 | WRECK
|
If the value is below 1000.0, then the LOD is supposed to be a graphical LOD.
If the value equals or is above 10000.0 and is not one of the functional LODs, it is a shadow LOD.
The LOD selected for displaying if
DistanceToObject * LODCoef * M <= LODResolution
Where:
- LODCoef is value from OFP preferences (I have LODCoef = 0.019).
- M is some value that changed by OFP developers (I use M=1 in WRPEdit and M=2 in P3DEdit).