P3D File Format - ODOLV7: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
(moved lod faces to sep page)
m (Text replacement - "{{HashLink" to "{{Link")
 
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{unsupported-doc}}
{{Feature|UnsupportedDoc}}
{{TOC|side}}
= General =
 
 
== Legend ==


===Legend===
see [[Generic FileFormat Data Types]]
see [[Generic FileFormat Data Types]]


===Intro===


====CompressedStruct====
== CompressedStructures ==
 
(potentially) compressed arrays are endemic to most blocks contained in a p3d.


ODOL7 uses (potentially) compressed arrays.
<syntaxhighlight lang="cpp">
CompressedStruct
{
ulong Count;
<type> Array[Count];
};
</syntaxhighlight>


This obviously slows the engine down during loading. At the time of CWC development, game file sizes were important.
if 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)


(potentially) compressed arrays are contained in a CompressedStruct
After decompression, the Count remains the same because it is a count of the arraytype.


CompressedStructs are endemic to most blocks contained in the p3d.
For uncompressed arrays (byte count < 1024) the Count and data are treated 'as is'.


CompressedStruct
{
  ulong  Count;
  <type> Array[Count];
};


Thus for various Array <types>
* ulong Array:    > 255  // 1024 /  sizeof(ulong)
* float thing[2]: > 127  // 1024 / 2*sizeof(float)
* SomeStructure:  >      // count * sizeof (SomeStructure) > 1023


if 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)


After de-compression, the Count remains the same because it is a count of the arraytype.
Note that potentially compressed arrays in these structures only have an known output length. the decompressor therefore must work on infinite input length.


For uncompressed arrays (byte count < 1024) the Count and data are treated 'as is'.


= Odol7Stuct =


Thus for various Array <types>
See [[P3D Model Info]].
*ulong Array:    > 255  // 1024 /  sizeof(ulong)
<syntaxhighlight lang="cpp">
*float thing[2]: > 127  // 1024 / 2*sizeof(float)
ODOLV7
*SomeStructure:  >      // count * sizeof (SomeStructure) > 1023
{
StandardP3DHeader Header;
LodStruct Lods[Header.LodCount];
ModelInfo ModelInfo;
};
</syntaxhighlight>




Note that potentially compressed arrays in these structures only have an known output length.
== StandardP3DHeader ==
the decompressor therefore must work on infinite input length.
see example decompression at end of document


===Odol7Stuct===
<syntaxhighlight lang="cpp">
ODOLV7
StandardP3DHeader
{
{
  StandardP3DHeader Header;
char Signature[4]; //"ODOL" (vs MLOD eg)
  LodStruct Lods[Header.LodCount];
ulong Version; // 7
  struct    ModelInfo;           //see [[P3D Model Info]]
ulong LodCount; // at least one
};
}
</syntaxhighlight>


====StandardP3DHeader====
StandardP3DHeader
{
  char      Signature[4];      ''//"ODOL"''
  ulong    Version;          ''// 7''
  ulong    LodCount;          ''// at least one''
}


===LodStruct===
== LodStruct ==
LodStruct
{
  struct        VertexTable;
  struct        UnknownStruct; // contains some max/min vertices positions
  struct        TexturesStruct;
  struct        VertexIndices;
  ulong          NoOfFaces;
  ulong          OffsetToSectionStruct;
  LodFace        LodFaces[NoOfFaces];    // ie polygons see [[P3D Lod Faces]]
  ulong          nSections;
  LODSection    LODSections[nSections];  // see [[P3D Lod Sections]]
  ulong          nNamedSelections;
  NamedSelection NamedSelections[nNamedSelections]; //See [[P3D Named Selections]]
  ulong          nNamedProperties;
  NamedProperty  NamedProperties[nNamedProperties];
  ulong          nFrames;
  Frame          Frames[nFrames];
  ulong          IconColor;
  ulong          SelectedColor;
  ulong          Unknown;
  ulong          nProxies;
  ProxyStruct    ProxyStructs[nProxies]; 
};


===VertexTable===
See:
  VertexTable
* {{Link|#VertexTable}}
  {  
* {{Link|#Textures}}
    CompressedStruct PointFlags //(vertices)
* [[P3D Lod Edges]]
    {
* [[P3D Lod Faces]]
    ulong Count;              // see [[P3D Point(Vertex) Flags]]
* [[P3D Lod Sections]]
    ulong PointFlag[Count];   
* [[P3D Named Selections]]
    }
* {{Link|#NamedProperty}}
    CompressedStruct UVset
* [[P3D Lod Frames]]
    {
* [[P3D Lod Proxies]]
    ulong  Count;              ''// if > 127 then array is compressed
    UVPair UVsets[Count];     
    }
    struct Points // (Vertices)
    {
    ulong      Count;             
    XYZTriplet Point[Count];
    }
    struct Normals
    {
    '''ulong''' Count;           
    '''float''' Normals[Count][3];  ''// XZY
    }
  }


*Count is the same value for all four tables.
*The Position and Normals tables appear to be always uncompressed raw data.


====UVPair====
<syntaxhighlight lang="cpp">
UVSet
LodStruct
{
{
  float U,V;
VertexTable VertexTable;
}
float UnknownFloat1;
===UnKnownStruct===
float UnknownFloat2;
UnKnownStruct
XYZTriplet MinPos;
{
XYZTriplet MaxPos;
  UVPair      UnknownUV; // just a guess         
XYZTriplet AutoCenterPos;
  XYZTriplet   MinPos;
float UnknownFloat3;
  XYZTriplet   MaxPos;
Textures Textures;
  XYZTriplet   AutoCenterPos;
LodEdges LodEdges;
  float       UnknownFloat;
ulong NoOfFaces;
}
ulong OffsetToLodSections;
LodFace LodFaces[NoOfFaces]; // ie polygons
ulong nSections;
LODSection LODSections[nSections];
ulong nNamedSelections;
NamedSelection NamedSelections[nNamedSelections];
ulong nTokens;
NamedProperty NamedProperties[nTokens];
ulong nFrames;
Frame Frames[nFrames];
ulong IconColor;
ulong SelectedColor;
ulong Unknown;
ulong nProxies;
LodProxy LodProxies[nProxies];
};
</syntaxhighlight>


===TexturesStruct===
=== VertexTable ===
  struct Textures
  {
  '''ulong'''  Count;
  '''asciiz''' Textures[...];          ''// "data/1.paa\0data/2.paa\0"...
  }


Count corresponds to the number of concatenated strings. It is required, since, architecturally at least, one of more of the asciiz strings could be null.
See [[P3D Point and Face Flags]].
<syntaxhighlight lang="cpp">
struct
{
ulong Count;
ulong PointFlags[Count]; // compressed
ulong Count;
UVPair UV1[Count]; // compressed
ulong Count;
XYZTriplet Points[Count]; // UNcompressed
ulong Count;
XYZTriplet Normals[Count]; // UNcompressed
}
</syntaxhighlight>


===VertexIndices===
*Count is the same value for all four tables.
VertexIndices
{
  CompressedStruct
  {
  '''ulong'''  Count;            ''// if > 511 etc'' 
  '''ushort''' MlodIndex[Count];
  }
  CompressedStruct
  {
  '''ulong'''  nVerticesStructs;          ''// same value as any of the VerticesStruct.Counts''
  '''ushort''' VerticesStructNum[nVerticesStructs];
  }
}


For each of the VerticesStructs (0..Count-1) there is a lookup into the MlodIndex
=== Textures ===
'''MLOD'''vertexindex = MlodIndex[ VerticesStructNum[Count] ];''


Tables are used to join vertices. Each face has got 3 or 4 vertices that are unique for each face Eg. Every vertex is owned only by 1 face.
<syntaxhighlight lang="cpp">
struct
{
ulong Count;
asciiz Textures[...]; // "data/1.paa\0data/2.paa\0"...
}
</syntaxhighlight>


===NamedProperty===
Count corresponds to the number of concatenated strings. It is required, since, architecturally at least, one of more of the asciiz strings could be null.


  NamedProperty
=== NamedProperty ===
  {
    '''asciiz''' Name;  ''// "noshadow\0"
    '''asciiz''' Value; ''//"1\0"'
  };


===Frame===
<syntaxhighlight lang="cpp">
    Frame
struct
    {
{
      float      FrameTime;
Asciiz Property; // e.g "noshadow" = "1"
      ulong      nBones;      //same as any  VerticesStruct.Count
Asciiz Value;
      XYZTriplet BonePos[nBones];
}
    };
</syntaxhighlight>


===ProxyStruct===
ProxyStruct
{
  asciiz          Name;
  TransformMatrix Transform;//see [[Generic FileFormat Data Types]]
  ulong          Indices[2];
}


= Related Page(s) =


== LZ in ODOL ==


=Related Page(s)=
==LZ in ODOL==
see [[Compressed LZSS File Format]]
see [[Compressed LZSS File Format]]


[[BIS_File_Formats#3D_Model_File_Formats|Model File Formats]]
[[BIS File Formats#3D Model File Formats|Model File Formats]]
 
 
[[Category:BIS_File_Formats]]
[[Category:BIS_File_Formats]]

Latest revision as of 17:43, 4 January 2023

bi symbol white.png
Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.

This page contains unofficial information.

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.
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.

General

Legend

see Generic FileFormat Data Types


CompressedStructures

(potentially) compressed arrays are endemic to most blocks contained in a p3d.

CompressedStruct
{
	ulong	Count;
	<type>	Array[Count];
};

if 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)

After decompression, the Count remains the same because it is a count of the arraytype.

For uncompressed arrays (byte count < 1024) the Count and data are treated 'as is'.


Thus for various Array <types>

  • ulong Array: > 255 // 1024 / sizeof(ulong)
  • float thing[2]: > 127 // 1024 / 2*sizeof(float)
  • SomeStructure: > // count * sizeof (SomeStructure) > 1023


Note that potentially compressed arrays in these structures only have an known output length. the decompressor therefore must work on infinite input length.


Odol7Stuct

See P3D Model Info.

ODOLV7
{
	StandardP3DHeader	Header;
	LodStruct			Lods[Header.LodCount];
	ModelInfo			ModelInfo;
};


StandardP3DHeader

StandardP3DHeader
{
	char	Signature[4];	//"ODOL" (vs MLOD eg)
	ulong	Version;		// 7
	ulong	LodCount;		// at least one
}


LodStruct

See:


LodStruct
{
	VertexTable		VertexTable;
	float			UnknownFloat1;
	float			UnknownFloat2;
	XYZTriplet		MinPos;
	XYZTriplet		MaxPos;
	XYZTriplet		AutoCenterPos;
	float			UnknownFloat3;
	Textures		Textures;
	LodEdges		LodEdges;
	ulong			NoOfFaces;
	ulong			OffsetToLodSections;
	LodFace			LodFaces[NoOfFaces]; // ie polygons
	ulong			nSections;
	LODSection		LODSections[nSections];
	ulong			nNamedSelections;
	NamedSelection	NamedSelections[nNamedSelections];
	ulong			nTokens;
	NamedProperty	NamedProperties[nTokens];
	ulong			nFrames;
	Frame			Frames[nFrames];
	ulong			IconColor;
	ulong			SelectedColor;
	ulong			Unknown;
	ulong			nProxies;
	LodProxy		LodProxies[nProxies];
};

VertexTable

See P3D Point and Face Flags.

	struct
	{ 
	ulong		Count;
	ulong		PointFlags[Count];	// compressed
	ulong		Count;
	UVPair		UV1[Count];			// compressed 
	ulong		Count;
	XYZTriplet	Points[Count];		// UNcompressed
	ulong		Count;
	XYZTriplet	Normals[Count];		// UNcompressed
	}
  • Count is the same value for all four tables.

Textures

struct
{
ulong	Count;
asciiz	Textures[...]; // "data/1.paa\0data/2.paa\0"...
}

Count corresponds to the number of concatenated strings. It is required, since, architecturally at least, one of more of the asciiz strings could be null.

NamedProperty

struct
{
	Asciiz Property; // e.g "noshadow" = "1"
	Asciiz Value;
}


Related Page(s)

LZ in ODOL

see Compressed LZSS File Format

Model File Formats