{"name":"P3D File Format - ODOLV7","title":"P3D File Format - ODOLV7","type":"topic","url":"https://community.bistudio.com/wiki/P3D_File_Format_-_ODOLV7","revid":373442,"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## General\n\n### Legend\n\nsee Generic FileFormat Data Types\n\n### CompressedStructures\n\n(potentially) compressed arrays are endemic to most blocks contained in a p3d.\n\n```cpp\nCompressedStruct\n{\n    ulong    Count;\n    <type>    Array[Count];\n};\n```\n\nif Count * sizeof(<type>) exceeds 1023 bytes the array is compressed. The **resulting** array will be expanded using lzh compression exactly as found in pbo's (for instance)\n\nAfter decompression, the Count remains the same because it is a count of the arraytype.\n\nFor uncompressed arrays (byte count < 1024) the Count and data are treated 'as is'.\n\nThus for various Array <types>\n\n- ulong Array: > 255 // 1024 / sizeof(ulong)\n- float thing[2]: > 127 // 1024 / 2*sizeof(float)\n- SomeStructure: > // count * sizeof (SomeStructure) > 1023\n\nNote that potentially compressed arrays in these structures only have an known output length. the decompressor therefore must work on infinite input length.\n\n## Odol7Stuct\n\nSee P3D Model Info.\n\n```cpp\nODOLV7\n{\n    StandardP3DHeader    Header;\n    LodStruct            Lods[Header.LodCount];\n    ModelInfo            ModelInfo;\n};\n```\n\n### StandardP3DHeader\n\n```cpp\nStandardP3DHeader\n{\n    char    Signature[4];    //\"ODOL\" (vs MLOD eg)\n    ulong    Version;        // 7\n    ulong    LodCount;        // at least one\n}\n```\n\n### LodStruct\n\nSee:\n\n- VertexTable\n- Textures\n- P3D Lod Edges\n- P3D Lod Faces\n- P3D Lod Sections\n- P3D Named Selections\n- NamedProperty\n- P3D Lod Frames\n- P3D Lod Proxies\n\n```cpp\nLodStruct\n{\n    VertexTable        VertexTable;\n    float            UnknownFloat1;\n    float            UnknownFloat2;\n    XYZTriplet        MinPos;\n    XYZTriplet        MaxPos;\n    XYZTriplet        AutoCenterPos;\n    float            UnknownFloat3;\n    Textures        Textures;\n    LodEdges        LodEdges;\n    ulong            NoOfFaces;\n    ulong            OffsetToLodSections;\n    LodFace            LodFaces[NoOfFaces]; // ie polygons\n    ulong            nSections;\n    LODSection        LODSections[nSections];\n    ulong            nNamedSelections;\n    NamedSelection    NamedSelections[nNamedSelections];\n    ulong            nTokens;\n    NamedProperty    NamedProperties[nTokens];\n    ulong            nFrames;\n    Frame            Frames[nFrames];\n    ulong            IconColor;\n    ulong            SelectedColor;\n    ulong            Unknown;\n    ulong            nProxies;\n    LodProxy        LodProxies[nProxies];\n};\n```\n\n#### VertexTable\n\nSee P3D Point and Face Flags.\n\n```cpp\n    struct\n    {\n    ulong        Count;\n    ulong        PointFlags[Count];    // compressed\n    ulong        Count;\n    UVPair        UV1[Count];            // compressed\n    ulong        Count;\n    XYZTriplet    Points[Count];        // UNcompressed\n    ulong        Count;\n    XYZTriplet    Normals[Count];        // UNcompressed\n    }\n```\n\n- Count is the same value for all four tables.\n\n#### Textures\n\n```cpp\nstruct\n{\nulong    Count;\nasciiz    Textures[...]; // \"data/1.paa\\0data/2.paa\\0\"...\n}\n```\n\nCount corresponds to the number of concatenated strings. It is required, since, architecturally at least, one of more of the asciiz strings could be null.\n\n#### NamedProperty\n\n```cpp\nstruct\n{\n    Asciiz Property; // e.g \"noshadow\" = \"1\"\n    Asciiz Value;\n}\n```\n\n## Related Page(s)\n\n### LZ in ODOL\n\nsee Compressed LZSS File Format\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":"General","level":2,"markdown":""},{"heading":"Legend","level":3,"markdown":"see Generic FileFormat Data Types"},{"heading":"CompressedStructures","level":3,"markdown":"(potentially) compressed arrays are endemic to most blocks contained in a p3d.\n\n```cpp\nCompressedStruct\n{\n    ulong    Count;\n    <type>    Array[Count];\n};\n```\n\nif Count * sizeof(<type>) exceeds 1023 bytes the array is compressed. The **resulting** array will be expanded using lzh compression exactly as found in pbo's (for instance)\n\nAfter decompression, the Count remains the same because it is a count of the arraytype.\n\nFor uncompressed arrays (byte count < 1024) the Count and data are treated 'as is'.\n\nThus for various Array <types>\n\n- ulong Array: > 255 // 1024 / sizeof(ulong)\n- float thing[2]: > 127 // 1024 / 2*sizeof(float)\n- SomeStructure: > // count * sizeof (SomeStructure) > 1023\n\nNote that potentially compressed arrays in these structures only have an known output length. the decompressor therefore must work on infinite input length."},{"heading":"Odol7Stuct","level":2,"markdown":"See P3D Model Info.\n\n```cpp\nODOLV7\n{\n    StandardP3DHeader    Header;\n    LodStruct            Lods[Header.LodCount];\n    ModelInfo            ModelInfo;\n};\n```"},{"heading":"StandardP3DHeader","level":3,"markdown":"```cpp\nStandardP3DHeader\n{\n    char    Signature[4];    //\"ODOL\" (vs MLOD eg)\n    ulong    Version;        // 7\n    ulong    LodCount;        // at least one\n}\n```"},{"heading":"LodStruct","level":3,"markdown":"See:\n\n- VertexTable\n- Textures\n- P3D Lod Edges\n- P3D Lod Faces\n- P3D Lod Sections\n- P3D Named Selections\n- NamedProperty\n- P3D Lod Frames\n- P3D Lod Proxies\n\n```cpp\nLodStruct\n{\n    VertexTable        VertexTable;\n    float            UnknownFloat1;\n    float            UnknownFloat2;\n    XYZTriplet        MinPos;\n    XYZTriplet        MaxPos;\n    XYZTriplet        AutoCenterPos;\n    float            UnknownFloat3;\n    Textures        Textures;\n    LodEdges        LodEdges;\n    ulong            NoOfFaces;\n    ulong            OffsetToLodSections;\n    LodFace            LodFaces[NoOfFaces]; // ie polygons\n    ulong            nSections;\n    LODSection        LODSections[nSections];\n    ulong            nNamedSelections;\n    NamedSelection    NamedSelections[nNamedSelections];\n    ulong            nTokens;\n    NamedProperty    NamedProperties[nTokens];\n    ulong            nFrames;\n    Frame            Frames[nFrames];\n    ulong            IconColor;\n    ulong            SelectedColor;\n    ulong            Unknown;\n    ulong            nProxies;\n    LodProxy        LodProxies[nProxies];\n};\n```"},{"heading":"VertexTable","level":4,"markdown":"See P3D Point and Face Flags.\n\n```cpp\n    struct\n    {\n    ulong        Count;\n    ulong        PointFlags[Count];    // compressed\n    ulong        Count;\n    UVPair        UV1[Count];            // compressed\n    ulong        Count;\n    XYZTriplet    Points[Count];        // UNcompressed\n    ulong        Count;\n    XYZTriplet    Normals[Count];        // UNcompressed\n    }\n```\n\n- Count is the same value for all four tables."},{"heading":"Textures","level":4,"markdown":"```cpp\nstruct\n{\nulong    Count;\nasciiz    Textures[...]; // \"data/1.paa\\0data/2.paa\\0\"...\n}\n```\n\nCount corresponds to the number of concatenated strings. It is required, since, architecturally at least, one of more of the asciiz strings could be null."},{"heading":"NamedProperty","level":4,"markdown":"```cpp\nstruct\n{\n    Asciiz Property; // e.g \"noshadow\" = \"1\"\n    Asciiz Value;\n}\n```"},{"heading":"Related Page(s)","level":2,"markdown":""},{"heading":"LZ in ODOL","level":3,"markdown":"see Compressed LZSS File Format\n\nModel File Formats"}],"categories":["Real Virtuality File Formats"],"groups":["Tools and File Formats"]}