P3D File Format - ODOLV7: Difference between revisions
Categories:
Shinraiden (talk | contribs) No edit summary |
m (ODOL moved to P3D File Format - ODOLV7: ...) |
(No difference)
| |
Revision as of 17:14, 18 June 2007
Overall
// uint unsigned integer 32bit
// word unsigned short integer 16bit
struct ODOL
{
char Signature[4]; //"ODOL"
uint Version; // 7
uint LodCount; // at least one
struct Lod[LodCount]
{
uint VerticesCount;
uint VerticesAttribs[VerticesCount]; // if VerticesCount > 255 then array is compresed by LZ algorithm. see LZ in ODOL.
uint VerticesCount; // again same value
struct UVset[VerticesCount]; // if VerticesCount > 127 then array is compresed by LZ algorithm. see LZ in ODOL.
uint VerticesCount; // again same value
struct VerticesPosition[VerticesCount];
uint VerticesCount; // again same value
struct VerticesNormal[VerticesCount];
float fvalue[12]; // unknown values // containts some max/min vertices positions and so far
uint TexturesCount;
char Textures[...]; // zero ended 'C' strings 'd','a','t','a','\','1','.','p','a','a','\0','d','a','t','a','\','2','.','p','a','a','\0'...
//read until count of founded char('\0') equil TexturesCount;
uint Table1stCount;
word Table1st[Table1stCount];// if Table1stCount > 511 then array is compresed by LZ algorithm. see LZ in ODOL.
uint Table2ndCount; // Table2ndCount is same value like VerticesCount
word Table2nd[Table2ndCount];// if Table2ndCount > 511 then array is compresed by LZ algorithm. see LZ in ODOL.
//tables can by used to join vertices, each face has got 3 or 4 vertices that are seperated for each face in odol format
//every vertex is owned only by 1 face
//mlodvertexindex = Table1st[ Table2nd[ odolvertexindex ] ];
uint FacesCount;
uint uvalue; // unknown value
struct Face[FacesCount];
uint uvalue2; // unknown value
char uchar[18*uvalue2]; // unknown value
uint NamedSelectionCount
struct NamedSelection[NamedSelectionCount]
uint NamedPropetiesCount;
struct NamedPropeties[NamedPropetiesCount]
uint uvalue7;// unknown value
struct ustruct[uvalue7]; // unknown value
uint ProxiCount;
struct Proxi[ProxiCount];
}; // end of lod
uint ResolutionCount; // same as LODCount
float Resolution[ResolutionCount];
.
.
. // folows some unknow data.
}; // end of ODOL;
Faces
struct Face
{
uint Attribs;
word TextureIndex; //if ((int)TextureIndex==-1) no texture;
char CountOfVertices; // 3 or 4
word VerticesIndex[CountOfVertices]; //! size of array is not constant.
};
NamedSelection
struct NamedSelection
{
char name[...]; // zero ended string
uint VerticesSelectedCount;
word VerticesSelected[VerticesSelectedCount];// if VerticesSelectedCount > 511 then array is compresed by LZ algorithm. see LZ in ODOL.
uint uvalue3; // unknown value
word uarray[uvalue3];// unknown value
uint uvalue4; // unknown value
uint uarray[uvalue4];// unknown value // if VerticesSelectedCount > 255 then array is compresed by LZ algorithm. see LZ in ODOL.
char uchar; // unknown value
uint uvalue5; // unknown value
uint uarray[uvalue5];// unknown value
uint FacesSelectedCount;
word FacessSelected[FacesSelectedCount]// if FacesSelectedCount > 511 then array is compresed by LZ algorithm. see LZ in ODOL.
uint uvalue6; // unknown value
char uarray[uvalue6];// unknown value
};
VerticesPosition
struct VerticesPosition
{
float x,y,z;
};
VerticesNormal
struct VerticesNormal
{
float x,y,z;
};
UVset
struct UVset
{
float U,V;
};
Proxi
struct Proxi
{
char Name[...] // zero ended string
struct ustruct {...};// size same as char[56]; // unknown value
};
ustruct
struct ustruct // unknown value
{
uint uvalue8;// unknown value
uint uvalue9;// unknown value
char uarray[12*uvalue9];// unknown value :-( i know nothing about it
};
NamedPropeties
struct NamedPropeties
{
char Name[...];
char Value[...]; // 'n','o','s','h','a','d','o','w','\0','1','\0'...
};
LZ in ODOL
Lempel-Ziv compression
pascal code
function LZBlockRead(var F:file; var outdata:array of byte;szout:integer):byte;
var
k, r, pr, pi,po,i,j:integer;
flags:word;
buf:array[0..$100e] of byte;
c:byte;
crc:integer;
begin
po:=0;
pi:=0;
flags:=0;
r:=0;
for k := 0 to $100F-1 do buf[k] := $20;
while (po < szout) do
begin
flags:= flags shr 1;
if ((flags and $100)= 0) then
begin
BlockRead(F,c,1); // direct reading from file
inc(pi);
flags := c or $ff00;
end;
if (flags and 1)=1 then
begin
if (po >= szout)then break;
BlockRead(F,c,1); // direct reading from file
inc(pi);
outdata[po] := c;
inc(po);
buf[r] := c;
inc(r);
r :=r and $fff;
end
else
begin
i:=0;
BlockRead(F,i,1); // direct reading from file
inc(pi);
j:=0;
BlockRead(F,j,1); // direct reading from file
inc(pi);
i :=i or ((j and $f0) shl 4);
j := (j and $0f) + 2;
pr := r;
for k := 0 to j do
begin
c := buf[(pr - i + k) and $fff];
if (po >= szout) then break;
outdata[po]:= c;
inc(po);
buf[r]:= c;
inc(r);
r :=r and $fff;
end;
end;
end;
BlockRead(F,crc,4); // unknow 4bytes data on end of record , I suppose that it is some like CRC or MD5 checksum .
result:= pi;
end;
C code
int Decode(unsigned char *in,unsigned char *out,int szin,int szout)
{
szin = szin > 0? szin: 0x7fffffff;
int i, j, k, r = 0, pr, pi = 0,po = 0;
unsigned int flags = 0;
unsigned char buf[0x100F], c;
for (i = 0; i < 0x100F; buf[i] = 0x20, i++);
while (pi < szin && po < szout)
{
if (((flags >>= 1) & 256) == 0)
{
if(pi >= szin)break;
c = in[pi++];
flags = c | 0xff00;
}
if (flags & 1)
{
if(pi >= szin || po >= szout)break;
c = in[pi++];
out[po++] = c;
buf[r++] = c;
r &= 0xfff;
} else
{
if(pi + 1 >= szin)break;
i = in[pi++];
j = in[pi++];
i |= (j & 0xf0) << 4;
j = (j & 0x0f) + 2;
pr = r;
for (k = 0; k <= j; k++)
{
c = buf[(pr - i + k) & 0xfff];
if(po >= szout)break;
out[po++] = c;
buf[r++] = c;
r &= 0xfff;
}
}
}
return pi;
}