{"name":"P3D Model Info","title":"P3D Model Info","type":"topic","url":"https://community.bistudio.com/wiki/P3D_Model_Info","revid":373430,"updated":"2025-05-08T11:27:12Z","aliases":[],"markdown":"> **Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.**\n>\n> This page contains unofficial information.\n>\n> 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.\n> 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.\n\n## Model Info\n\nThe Model Info structure is last in file for ODOL7 (ofp) and at top of file for ODOL4x (ARMAx)\n\n```\nModelInfo\n{\n  float      resolutions[Header.NoOfLods];// alias resolutions\n  ulong      Index;                    // appears to be a bit flag, 512, 256 eg\n  float      MemLodSphere;\n  float      GeoLodSphere;             // mostly same as MemLodSphere\n  ulong      Remarks;            // typically 00 00 00 00  00 00 00 00 00 00 0C 00 eg (last is same as user point flags)\n  ulong      andHints;\n  ulong      orHints;\n  XYZTriplet geo_offset;               // model offset (unknown functionality),//mostly same as offset2\n  rgba       mapIconColor;             // RGBA 32 color\n  rgba       mapSelectedColor;         // RGBA 32 color\n  float      ViewDensity;              //-1 -> default shape values will be used (default value)  / 0 -> opaque / 1 -> transparent (DO NOT add this to an opaque object)\n  XYZTriplet bboxMinPosition;          // minimum coordinates of bounding box\n  XYZTriplet bboxMaxPosition;          // maximum coordinates of bounding box. Generally the complement of the 1st\n                                       // pew.GeometryBounds in Pew is bboxMinPosition-bboxMaxPosition for X and Z\n                                       // pew.ResolutionBounds mostly the same\n  if version >=70\n    float lodDensityCoef;\n  if version >=71\n    float drawImportance;\n  if version >=52\n    MinMaxVectors visual_bounds;\n  XYZTriplet boundingCenter;          // pew.GeometryAutoCenterPos (and mostly pew.ResolutionAutoCenterPos too)\n  XYZTriplet geometryCenter;                  // mostly same as Offset1 often same as (but it isn't ResolutionPos)\n  XYZTriplet centerOfMass;             //CogOffset see below\n  XYZTriplet p3dinfo_invInertia[3];      // for ODOL7 this is a mixture of floats and index values\n\n  TinyBool   AutoCenter,\n             lockAutoCenter,\n             canOcclude,\n             canBeOccluded,\n             allowAnimation;\n  if version>=73 || dayz\n    TinyBool   disableCover;\n\n  float ThermalProfile[24];       //\n  if dayz\n     float     dayz_thermal_extra\n  ulong      forceNotAlphaModel;              // V48 and beyond\n  ulong      sbSource;\n  TinyBool   prefershadowvolume;\n  if version==48\n   float shadowOffset;\n  bool   allowAnimation;\n  byte   mapType;\n  if dayz\n   dayz_mass_array[];\n\n  float      Mass;\n  float      MassReciprocal;           // see note\n  float      ArmorMass;                  // see note\n  float      ArmorReciprocal;        // see note\n  if version>=72\n    float     explosionshielding\n   if version>=56\n    byte       UnknownByteIndices[14]    // see note generally FF FF FF FF FF FF FF FF FF FF FF FF\n  else\n    byte       UnknownByteIndices[12]    // see note generally FF FF FF FF FF FF FF FF FF FF FF FF\n  ///////////ARMA (V4x) ONLY ////////////\n  ulong      UnknownLong;              // often same as NoOfLods\n  TinyBool   canBlend;                 // generally set if ascii below has strings\n  if (dayz==54\n    byte dayzv126;\n  asciiz     ClassType;                // class=\"House\" See Named Properties\n  asciiz     DestructType;             // damage=\"Tent\" See Named Properties\n  TinyBool   frequent;                 // rarely true\n  ulong      Always0;                  //\n  if version >= 54\n      byte   preferred_shadows[NoOfLods][12]; //generally FF FF FF FF FF FF FF FF FF FF FF FF\n   ///////////////////////////////////////\n}\n```\n\nCoordinates in odols are expressed **relative** to this value.\n\nThus\n\n```\nMLOD Points[Any] = ODOL Points[Any] + CentreOfGravity\n```\n\n- RawCentreOfGravity is calculated from the mlod geometry lod\n\n- Asymetrical BoundingBox values are calculated from the TotalMin and TotalMax of all points in all lods (of the mlod).\n\n```\nTotalMinMax=MinMax(lods[AllLods].points[AllValues])\n```\n\n- The odol's CentreOfGravity, bounding box and CogOffset are calculated as follows\n\n```\n// convert mlod to odol relative\n\nTotalMin-=RawCentreOfGravity; //asymetrical bounding box\nTotalMax-=RawCentreOfGravity;\n\n//turn asymetrical to symetrical\nBoundingBoxMax=fabs(TotalMax-TotalMin)/2);\nBoundingBoxMin=-BoundingBoxMax; // this *is* the odol bbox expressed in relative units\n\nCogOffset= BoundingBoxMax-TotalMax+RawCentreOfGravity;// *the* odol CogOffset\n\nCentreOfGravity-=CogOffset;//*the* odol cog\n```\n\n- 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\n\n#### ODOLV7 BIS\n\nThe 24 byte area after the mass float is, as represented, in the supplied, 'official', addons from Bis for ALL game engines.\n\nFor V7:\n\n- MOST oem addons subscribe to above.\n\n- 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 is MLOD-SP3X equivalent, it has a default file size, and anything 'extra', is tested for.\n\n##### Odol Explorer\n\nNote 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.\n\nFor trunctated data (Odol7 files < 24 bytes) this will clearly be faulty. For excessive files, OdolEX may well indeed be right.\n\n### Skeleton\n\n```\n Skeleton\n {\n   asciiz                    SkeletonName;  //\"A10Skeleton\"\n   if (SkeletonName != null)\n   {\n     tbool                   isInherited;\n     ulong                   NoOfBoneNames;\n     SkeletonBoneName        SkeletonBoneNames[NoOfBoneNames];\n     if (type>40 && ! VBS2) // ie arma2\n     {\n     byte                    Always0;\n     }\n   }\n }\n```\n\n#### SkeletonBoneName\n\n```\n SkeletonBoneName\n {\n   asciiz BoneName;            //\"3dhud\" or \"Gearlocks\" or \"Fuel\" or ...\n   asciiz ParentBoneName;      // \"Aeileron_1\"\n }\n```\n\ncorresponds to model.cfg\n\n```\n class cfgSkeletons\n {\n    class SkeletonClassname : Default\n    {\n        skeletonBones[]=\n        {\n            \"RightDoor1\",\"\",\n            \"RightDoor2\",\"\",\n            \"LeftDoor1\",\"\",\n            \"LeftDoor2\",\"RightDoor2\",\n            etc\"\n        };\n    };\n```\n\n### resolutions\n\nMost 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 'resolutions', since the floating point values, although relevant to the engine, are not as immediately apparent to a human.\n\nIn 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.\n\nThe order is irrelevant to the structure of the file (and probably irrelevant to the engine as well).\n\nThe resolutions array is used in conjunction with the start and ending LodAddressOffsets mentioned above.\n\nWhatever resolution is in resolutions[0] **THAT** LOD will be found at the offsets contained in startaddress[0].\n\nand so on.\n\nIn 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.\n\n#### Resolution Values\n\n| Hex | Float | Decimal | Description |\n|---|---|---|---|\n|  |  | <1,000 | Graphical Lod |\n|  |  |  | Functional Lods |\n| 0x447a0000 | 1.0e3 | 1,000 | View Gunner |\n| 0x44898000 | 1.1e3 | 1,100 | View Pilot |\n| 0x44960000 | 1.2e3 | 1,200 | View Cargo |\n| \"\" | \"\" |  | Shadow Lods |\n| 0x461c4000 | 1.0e4 | 10,000 | Shadow Volume |\n| 0x461c6800 | 1.001e4 | 10,010 | Shadow Volume 2 |\n| 0x462be000 | 1.1e4 | 11000 | Stencil Shadow |\n| 0x462c0800 | 1.101e4 | 11010 | Stencil Shadow 2 |\n| 0x551184e7 | 1.0e13 | 10,000,000,000,000 | Geometry |\n| 0x58635fa9 | 1.0e15 | 1,000,000,000,000,000 | Memory |\n| 0x58e35fa9 | 2.0e15 | 2,000,000,000,000,000 | Land Contact |\n| 0x592a87bf | 3.0e15 | 3,000,000,000,000,000 | Roadway |\n| 0x59635fa9 | 4.0e15 | 4,000,000,000,000,000 | Paths |\n| 0x598e1bca | 5.0e15 | 5,000,000,000,000,000 | HitPoints |\n| 0x59aa87bf | 6.0e15 | 6,000,000,000,000,000 | View Geometry |\n| 0x59c6f3b4 | 7.0e15 | 7,000,000,000,000,000 | Fire Geometry |\n| 0x59e35fa9 | 8.0e15 | 8,000,000,000,000,000 | View Cargo Geometry |\n| 0x59ffcb9e | 9.0e15 | 9,000,000,000,000,000 | View Cargo Fire Geometry |\n| 0x5a0e1bca | 1.0e16 | 10,000,000,000,000,000 | View Commander |\n| 0x5a1c51c4 | 1.1e16 | 11,000,000,000,000,000 | View Commander Geometry |\n| 0x5a2a87bf | 1.2e16 | 12,000,000,000,000,000 | View Commander Fire Geometry |\n| 0x5a38bdb9 | 1.3e16 | 13,000,000,000,000,000 | View Pilot Geometry |\n| 0x5a46f3b4 | 1.4e16 | 14,000,000,000,000,000 | View Pilot Fire Geometry |\n| 0x5a5529af | 1.5e16 | 15,000,000,000,000,000 | View Gunner Geometry |\n| 0x5a635fa9 | 1.6e16 | 16,000,000,000,000,000 | View Gunner Fire Geometry |\n| 0x5a7195a4 | 1.7e16 | 17,000,000,000,000,000 | Sub Parts |\n| 0x5a7fcb9e | 1.8e16 | 18,000,000,000,000,000 | SHADOW_VOLUME_VIEW_CARGO |\n| 0x5a8700cc | 1.9e16 | 19,000,000,000,000,000 | SHADOW_VOLUME_VIEW_PILOT |\n| 0x5a8e1bca | 2.0e16 | 20,000,000,000,000,000 | SHADOW_VOLUME_VIEW_GUNNER |\n| 0x5a9536c7 | 2.1e16 | 21,000,000,000,000,000 | WRECK |\n\nIf the value is below 1000.0, then the LOD is supposed to be a graphical LOD.\nIf the value equals or is above 10000.0 and is not one of the functional LODs, it is a shadow LOD.\n\nThe LOD selected for displaying if\n\n```\nDistanceToObject * LODCoef * M <= LODResolution\n```\n\nWhere:\n\n- LODCoef is value from OFP preferences (I have LODCoef = 0.019).\n- M is some value that changed by OFP developers (I use M=1 in WRPEdit and M=2 in P3DEdit).\n\n## Related Page(s)\n\nModel File Formats","sections":[{"heading":null,"level":1,"markdown":"> **Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.**\n>\n> This page contains unofficial information.\n>\n> 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.\n> 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."},{"heading":"Model Info","level":2,"markdown":"The Model Info structure is last in file for ODOL7 (ofp) and at top of file for ODOL4x (ARMAx)\n\n```\nModelInfo\n{\n  float      resolutions[Header.NoOfLods];// alias resolutions\n  ulong      Index;                    // appears to be a bit flag, 512, 256 eg\n  float      MemLodSphere;\n  float      GeoLodSphere;             // mostly same as MemLodSphere\n  ulong      Remarks;            // typically 00 00 00 00  00 00 00 00 00 00 0C 00 eg (last is same as user point flags)\n  ulong      andHints;\n  ulong      orHints;\n  XYZTriplet geo_offset;               // model offset (unknown functionality),//mostly same as offset2\n  rgba       mapIconColor;             // RGBA 32 color\n  rgba       mapSelectedColor;         // RGBA 32 color\n  float      ViewDensity;              //-1 -> default shape values will be used (default value)  / 0 -> opaque / 1 -> transparent (DO NOT add this to an opaque object)\n  XYZTriplet bboxMinPosition;          // minimum coordinates of bounding box\n  XYZTriplet bboxMaxPosition;          // maximum coordinates of bounding box. Generally the complement of the 1st\n                                       // pew.GeometryBounds in Pew is bboxMinPosition-bboxMaxPosition for X and Z\n                                       // pew.ResolutionBounds mostly the same\n  if version >=70\n    float lodDensityCoef;\n  if version >=71\n    float drawImportance;\n  if version >=52\n    MinMaxVectors visual_bounds;\n  XYZTriplet boundingCenter;          // pew.GeometryAutoCenterPos (and mostly pew.ResolutionAutoCenterPos too)\n  XYZTriplet geometryCenter;                  // mostly same as Offset1 often same as (but it isn't ResolutionPos)\n  XYZTriplet centerOfMass;             //CogOffset see below\n  XYZTriplet p3dinfo_invInertia[3];      // for ODOL7 this is a mixture of floats and index values\n\n  TinyBool   AutoCenter,\n             lockAutoCenter,\n             canOcclude,\n             canBeOccluded,\n             allowAnimation;\n  if version>=73 || dayz\n    TinyBool   disableCover;\n\n  float ThermalProfile[24];       //\n  if dayz\n     float     dayz_thermal_extra\n  ulong      forceNotAlphaModel;              // V48 and beyond\n  ulong      sbSource;\n  TinyBool   prefershadowvolume;\n  if version==48\n   float shadowOffset;\n  bool   allowAnimation;\n  byte   mapType;\n  if dayz\n   dayz_mass_array[];\n\n  float      Mass;\n  float      MassReciprocal;           // see note\n  float      ArmorMass;                  // see note\n  float      ArmorReciprocal;        // see note\n  if version>=72\n    float     explosionshielding\n   if version>=56\n    byte       UnknownByteIndices[14]    // see note generally FF FF FF FF FF FF FF FF FF FF FF FF\n  else\n    byte       UnknownByteIndices[12]    // see note generally FF FF FF FF FF FF FF FF FF FF FF FF\n  ///////////ARMA (V4x) ONLY ////////////\n  ulong      UnknownLong;              // often same as NoOfLods\n  TinyBool   canBlend;                 // generally set if ascii below has strings\n  if (dayz==54\n    byte dayzv126;\n  asciiz     ClassType;                // class=\"House\" See Named Properties\n  asciiz     DestructType;             // damage=\"Tent\" See Named Properties\n  TinyBool   frequent;                 // rarely true\n  ulong      Always0;                  //\n  if version >= 54\n      byte   preferred_shadows[NoOfLods][12]; //generally FF FF FF FF FF FF FF FF FF FF FF FF\n   ///////////////////////////////////////\n}\n```\n\nCoordinates in odols are expressed **relative** to this value.\n\nThus\n\n```\nMLOD Points[Any] = ODOL Points[Any] + CentreOfGravity\n```\n\n- RawCentreOfGravity is calculated from the mlod geometry lod\n\n- Asymetrical BoundingBox values are calculated from the TotalMin and TotalMax of all points in all lods (of the mlod).\n\n```\nTotalMinMax=MinMax(lods[AllLods].points[AllValues])\n```\n\n- The odol's CentreOfGravity, bounding box and CogOffset are calculated as follows\n\n```\n// convert mlod to odol relative\n\nTotalMin-=RawCentreOfGravity; //asymetrical bounding box\nTotalMax-=RawCentreOfGravity;\n\n//turn asymetrical to symetrical\nBoundingBoxMax=fabs(TotalMax-TotalMin)/2);\nBoundingBoxMin=-BoundingBoxMax; // this *is* the odol bbox expressed in relative units\n\nCogOffset= BoundingBoxMax-TotalMax+RawCentreOfGravity;// *the* odol CogOffset\n\nCentreOfGravity-=CogOffset;//*the* odol cog\n```\n\n- 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"},{"heading":"ODOLV7 BIS","level":4,"markdown":"The 24 byte area after the mass float is, as represented, in the supplied, 'official', addons from Bis for ALL game engines.\n\nFor V7:\n\n- MOST oem addons subscribe to above.\n\n- 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 is MLOD-SP3X equivalent, it has a default file size, and anything 'extra', is tested for."},{"heading":"Odol Explorer","level":5,"markdown":"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.\n\nFor trunctated data (Odol7 files < 24 bytes) this will clearly be faulty. For excessive files, OdolEX may well indeed be right."},{"heading":"Skeleton","level":3,"markdown":"```\n Skeleton\n {\n   asciiz                    SkeletonName;  //\"A10Skeleton\"\n   if (SkeletonName != null)\n   {\n     tbool                   isInherited;\n     ulong                   NoOfBoneNames;\n     SkeletonBoneName        SkeletonBoneNames[NoOfBoneNames];\n     if (type>40 && ! VBS2) // ie arma2\n     {\n     byte                    Always0;\n     }\n   }\n }\n```"},{"heading":"SkeletonBoneName","level":4,"markdown":"```\n SkeletonBoneName\n {\n   asciiz BoneName;            //\"3dhud\" or \"Gearlocks\" or \"Fuel\" or ...\n   asciiz ParentBoneName;      // \"Aeileron_1\"\n }\n```\n\ncorresponds to model.cfg\n\n```\n class cfgSkeletons\n {\n    class SkeletonClassname : Default\n    {\n        skeletonBones[]=\n        {\n            \"RightDoor1\",\"\",\n            \"RightDoor2\",\"\",\n            \"LeftDoor1\",\"\",\n            \"LeftDoor2\",\"RightDoor2\",\n            etc\"\n        };\n    };\n```"},{"heading":"resolutions","level":3,"markdown":"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 'resolutions', since the floating point values, although relevant to the engine, are not as immediately apparent to a human.\n\nIn 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.\n\nThe order is irrelevant to the structure of the file (and probably irrelevant to the engine as well).\n\nThe resolutions array is used in conjunction with the start and ending LodAddressOffsets mentioned above.\n\nWhatever resolution is in resolutions[0] **THAT** LOD will be found at the offsets contained in startaddress[0].\n\nand so on.\n\nIn 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."},{"heading":"Resolution Values","level":4,"markdown":"| Hex | Float | Decimal | Description |\n|---|---|---|---|\n|  |  | <1,000 | Graphical Lod |\n|  |  |  | Functional Lods |\n| 0x447a0000 | 1.0e3 | 1,000 | View Gunner |\n| 0x44898000 | 1.1e3 | 1,100 | View Pilot |\n| 0x44960000 | 1.2e3 | 1,200 | View Cargo |\n| \"\" | \"\" |  | Shadow Lods |\n| 0x461c4000 | 1.0e4 | 10,000 | Shadow Volume |\n| 0x461c6800 | 1.001e4 | 10,010 | Shadow Volume 2 |\n| 0x462be000 | 1.1e4 | 11000 | Stencil Shadow |\n| 0x462c0800 | 1.101e4 | 11010 | Stencil Shadow 2 |\n| 0x551184e7 | 1.0e13 | 10,000,000,000,000 | Geometry |\n| 0x58635fa9 | 1.0e15 | 1,000,000,000,000,000 | Memory |\n| 0x58e35fa9 | 2.0e15 | 2,000,000,000,000,000 | Land Contact |\n| 0x592a87bf | 3.0e15 | 3,000,000,000,000,000 | Roadway |\n| 0x59635fa9 | 4.0e15 | 4,000,000,000,000,000 | Paths |\n| 0x598e1bca | 5.0e15 | 5,000,000,000,000,000 | HitPoints |\n| 0x59aa87bf | 6.0e15 | 6,000,000,000,000,000 | View Geometry |\n| 0x59c6f3b4 | 7.0e15 | 7,000,000,000,000,000 | Fire Geometry |\n| 0x59e35fa9 | 8.0e15 | 8,000,000,000,000,000 | View Cargo Geometry |\n| 0x59ffcb9e | 9.0e15 | 9,000,000,000,000,000 | View Cargo Fire Geometry |\n| 0x5a0e1bca | 1.0e16 | 10,000,000,000,000,000 | View Commander |\n| 0x5a1c51c4 | 1.1e16 | 11,000,000,000,000,000 | View Commander Geometry |\n| 0x5a2a87bf | 1.2e16 | 12,000,000,000,000,000 | View Commander Fire Geometry |\n| 0x5a38bdb9 | 1.3e16 | 13,000,000,000,000,000 | View Pilot Geometry |\n| 0x5a46f3b4 | 1.4e16 | 14,000,000,000,000,000 | View Pilot Fire Geometry |\n| 0x5a5529af | 1.5e16 | 15,000,000,000,000,000 | View Gunner Geometry |\n| 0x5a635fa9 | 1.6e16 | 16,000,000,000,000,000 | View Gunner Fire Geometry |\n| 0x5a7195a4 | 1.7e16 | 17,000,000,000,000,000 | Sub Parts |\n| 0x5a7fcb9e | 1.8e16 | 18,000,000,000,000,000 | SHADOW_VOLUME_VIEW_CARGO |\n| 0x5a8700cc | 1.9e16 | 19,000,000,000,000,000 | SHADOW_VOLUME_VIEW_PILOT |\n| 0x5a8e1bca | 2.0e16 | 20,000,000,000,000,000 | SHADOW_VOLUME_VIEW_GUNNER |\n| 0x5a9536c7 | 2.1e16 | 21,000,000,000,000,000 | WRECK |\n\nIf the value is below 1000.0, then the LOD is supposed to be a graphical LOD.\nIf the value equals or is above 10000.0 and is not one of the functional LODs, it is a shadow LOD.\n\nThe LOD selected for displaying if\n\n```\nDistanceToObject * LODCoef * M <= LODResolution\n```\n\nWhere:\n\n- LODCoef is value from OFP preferences (I have LODCoef = 0.019).\n- M is some value that changed by OFP developers (I use M=1 in WRPEdit and M=2 in P3DEdit)."},{"heading":"Related Page(s)","level":2,"markdown":"Model File Formats"}],"categories":["ArmA: Armed Assault: File Formats","Real Virtuality File Formats"],"groups":["Tools and File Formats"]}