{"name":"P3D Named Selections","title":"P3D Named Selections","type":"topic","url":"https://community.bistudio.com/wiki/P3D_Named_Selections","revid":373434,"updated":"2025-05-08T11:27:13Z","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## Intro\n\nplaceholder till better organsied\n\n## MLOD\n\nNamed Selections are contained in the Taggs structure in MLOD file format. Every Tagg-name that doesn't have the form #Name# is a named selection. The name\nof the selection is simply the Tagg-name.\n\n```\n   ulong      NoOfBytes;            //eg. Will always be lod.NoOfPoints + lod.NoOfFaces\n   byte       SelectedWeightedPoints[NoOfPoints];\n   byte       SelectedFaces[NoOfFaces];\n```\n\nThe weights are 'compressed' floating point values; the following functions may be used to encode/decode those values. The conversion functions were found by experimenting and are not guaranteed to yield the correct results.\n\nNB: The byte array's indicate a zero-based offset into the corresponding **Points** & **Faces** structures.\n\nTo clarify, the purpose of this 'chunk' is to denote which points & faces belong to a given 'Named Selection' and also to denote the 'per-point-weight' associated with this selection.\n\nEach *byte* in the SelectedWeightedPoints array denotes a value 0 to 255 (0 to FF hex).\n\nAnd, serves a dual purpose in...\n\n1. Denoting the *selectedness* and\n\n2. Denoting per point weighting.\n\n- Zero (0) or 0x00 hex indicates the corresponding point in the LODs Points array ***is not selected***.\n\nAny value other than zero indicates that the point is not only part of the selection but also has a weighting value.\n\n- One (1) or 0x01 hex indicates the corresponding point in the LODs Points array is ***selected and has 100% weighting***.\n\nEvery value between 2 and 255 (0x02 to 0xFF hex) indicates the percentage ***weight*** of the corresponding point and that it is part of the selection.\nTwo (2) being almost 100% weighted and 255 being almost 0% weighted.\n\nfloat32 byte2weight = (256 - weight)/255;\nif (byte2weight > 1.0) then byte2weight = 0;\n\nWhere 'weight' is a unit8 (single byte) in the range... 0 >= weight <= 255 or 0x00 >= weight <= 0xFF.\n\n```\n float decodeWeight( uint8 b )\n {\n   if( b == 0 ) return  0.0f;\n   else if( b == 2 ) return 1.0f;\n   else if( b > 2 ) return 1.0f - round( (b-2) / 2.55555f )*0.01f;\n   else if( b < 0 ) return -round( b / 2.55555f ) * 0.01f;\n   else assert(false); // b == 1 does not occur?\n }\n```\n\nunit8 weight2byte = round(256 - (255 x weight),0);\nif (weight2byte == 256) then weight2byte = 0;\n\nWhere 'weight' is a float32 in the range... 0.0 >= weight <= 1.0.\n\n```\n uint8 encodeWeight( float f )\n {\n   // assume clamped value from 0.0 to 1.0\n   if( f < 0.01 ) return 0;\n   else if( f > 0.99 ) return 2;\n   else if( f > 0.5 ) return 0xff & (int)floor((1.0f - f) * 255.55f + 2);\n   else if( f > 0.49 ) return -127;\n   else return 0xff & (int)floor(f*2.5555f);\n }\n```\n\n## ODOL\n\nAll arrays are subject to the 1024 rule. Which type of compression depends on odol version\n\n- ODOL7 and ODOL40: LZSS compressed\n- Arma2: LZO compressed.\n\n```\n LodNamedSelection\n {\n   asciiz      SelectedName;                       // \"rightleg\" or \"neck\" eg\n   ulong       NoOfFaces;\n   ushort      FaceIndexes[NoOfFaces];             // indexing into the LodFaces Table\n   ulong       Always0Count;\n   unknownType Array[Always0Count]                 //IsSectional must be true\n   ///// ODOL7 only ///////////////////\n   ulong       Count;\n   ulong       UnknownV7Array[Count];\n   ////////////////////////////////////\n   tbool       IsSectional;                       //Appears in the sections[]= list of a model.cfg\n   ulong       NoOfUlongs;\n   ulong       SectionIndex[NoOfUlongs];          //IsSectional must be true. Indexes into the LodSections Table\n   ulong       nVertices;\n   ushort      VertexTableIndexes[nVertices];\n   ulong       nTextureWeights;\n   byte        VerticesWeights[nTextureWeights];  // if present they correspond to (are exentsions of) the VertexTableIndexes\n }\n```","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":"Intro","level":2,"markdown":"placeholder till better organsied"},{"heading":"MLOD","level":2,"markdown":"Named Selections are contained in the Taggs structure in MLOD file format. Every Tagg-name that doesn't have the form #Name# is a named selection. The name\nof the selection is simply the Tagg-name.\n\n```\n   ulong      NoOfBytes;            //eg. Will always be lod.NoOfPoints + lod.NoOfFaces\n   byte       SelectedWeightedPoints[NoOfPoints];\n   byte       SelectedFaces[NoOfFaces];\n```\n\nThe weights are 'compressed' floating point values; the following functions may be used to encode/decode those values. The conversion functions were found by experimenting and are not guaranteed to yield the correct results.\n\nNB: The byte array's indicate a zero-based offset into the corresponding **Points** & **Faces** structures.\n\nTo clarify, the purpose of this 'chunk' is to denote which points & faces belong to a given 'Named Selection' and also to denote the 'per-point-weight' associated with this selection.\n\nEach *byte* in the SelectedWeightedPoints array denotes a value 0 to 255 (0 to FF hex).\n\nAnd, serves a dual purpose in...\n\n1. Denoting the *selectedness* and\n\n2. Denoting per point weighting.\n\n- Zero (0) or 0x00 hex indicates the corresponding point in the LODs Points array ***is not selected***.\n\nAny value other than zero indicates that the point is not only part of the selection but also has a weighting value.\n\n- One (1) or 0x01 hex indicates the corresponding point in the LODs Points array is ***selected and has 100% weighting***.\n\nEvery value between 2 and 255 (0x02 to 0xFF hex) indicates the percentage ***weight*** of the corresponding point and that it is part of the selection.\nTwo (2) being almost 100% weighted and 255 being almost 0% weighted.\n\nfloat32 byte2weight = (256 - weight)/255;\nif (byte2weight > 1.0) then byte2weight = 0;\n\nWhere 'weight' is a unit8 (single byte) in the range... 0 >= weight <= 255 or 0x00 >= weight <= 0xFF.\n\n```\n float decodeWeight( uint8 b )\n {\n   if( b == 0 ) return  0.0f;\n   else if( b == 2 ) return 1.0f;\n   else if( b > 2 ) return 1.0f - round( (b-2) / 2.55555f )*0.01f;\n   else if( b < 0 ) return -round( b / 2.55555f ) * 0.01f;\n   else assert(false); // b == 1 does not occur?\n }\n```\n\nunit8 weight2byte = round(256 - (255 x weight),0);\nif (weight2byte == 256) then weight2byte = 0;\n\nWhere 'weight' is a float32 in the range... 0.0 >= weight <= 1.0.\n\n```\n uint8 encodeWeight( float f )\n {\n   // assume clamped value from 0.0 to 1.0\n   if( f < 0.01 ) return 0;\n   else if( f > 0.99 ) return 2;\n   else if( f > 0.5 ) return 0xff & (int)floor((1.0f - f) * 255.55f + 2);\n   else if( f > 0.49 ) return -127;\n   else return 0xff & (int)floor(f*2.5555f);\n }\n```"},{"heading":"ODOL","level":2,"markdown":"All arrays are subject to the 1024 rule. Which type of compression depends on odol version\n\n- ODOL7 and ODOL40: LZSS compressed\n- Arma2: LZO compressed.\n\n```\n LodNamedSelection\n {\n   asciiz      SelectedName;                       // \"rightleg\" or \"neck\" eg\n   ulong       NoOfFaces;\n   ushort      FaceIndexes[NoOfFaces];             // indexing into the LodFaces Table\n   ulong       Always0Count;\n   unknownType Array[Always0Count]                 //IsSectional must be true\n   ///// ODOL7 only ///////////////////\n   ulong       Count;\n   ulong       UnknownV7Array[Count];\n   ////////////////////////////////////\n   tbool       IsSectional;                       //Appears in the sections[]= list of a model.cfg\n   ulong       NoOfUlongs;\n   ulong       SectionIndex[NoOfUlongs];          //IsSectional must be true. Indexes into the LodSections Table\n   ulong       nVertices;\n   ushort      VertexTableIndexes[nVertices];\n   ulong       nTextureWeights;\n   byte        VerticesWeights[nTextureWeights];  // if present they correspond to (are exentsions of) the VertexTableIndexes\n }\n```"}],"categories":["ArmA: Armed Assault: File Formats","Real Virtuality File Formats"],"groups":["Tools and File Formats"]}