hamish-milne / FbxWriter

An FBX reader and writer for .NET
174 stars 44 forks source link

Strict checking of footer bytes is inaccurate #5

Open aholkner opened 5 years ago

aholkner commented 5 years ago

I'm not sure that the currently logic for the number of null bytes between the footer code and version (footerZeroes1) is correct. I have a number of FBX files of different versions, and each version seems to have its own number of zeroes here. Some examples I've found:

FbxBinary current value: 20 (which version was this checked against?)
FBX 7500: 14
FBX 7400: 19
FBX 7300: 6

I haven't conducted a very exhaustive search of FBX files besides opening a handful and checking by hand, so I'm not sure yet if the number is dependent on the FBX version number, the exporter used, or something else.

I've also noticed that writing out any number of zeroes in a version 7500 file doesn't impede Autodesk FBX Review or Unity from opening the files.

UkooLabs commented 5 years ago

@aholkner just as some info did some digging and based on your values, it appears not consitant

Heres my findings...

if (version == FbxVersion.v6_0) { //unknown } else if (version == FbxVersion.v6_1) { zeroCount = 15; } else if (version == FbxVersion.v7_0) { //unknown } else if (version == FbxVersion.v7_1) { zeroCount = 19; } else if (version == FbxVersion.v7_2) { zeroCount = 19; } else if (version == FbxVersion.v7_3) { zeroCount = 19; } else if (version == FbxVersion.v7_4) { zeroCount = 15; } else if (version == FbxVersion.v7_5) { zeroCount = 6; }

UkooLabs commented 5 years ago

@hamish-milne @aholkner

Finally sussed correct footer check similar would need to be done for writer...

protected bool CheckFooter(BinaryReader stream, FbxVersion version)
{
    var position = stream.BaseStream.Position;
    var paddingLength = (int)(16 - (position % 16));
    if (paddingLength == 0)
    {
        paddingLength = 16;
    }
    paddingLength += 4;
    var buffer = new byte[Math.Max(paddingLength, footerZeroes2)];
    stream.Read(buffer, 0, paddingLength);
    bool correct = AllZero(buffer);
    var readVersion = stream.ReadInt32();
    correct &= (readVersion == (int)version);
    stream.Read(buffer, 0, footerZeroes2);
    correct &= AllZero(buffer);
    stream.Read(buffer, 0, extension.Length);
    correct &= CheckEqual(buffer, extension);
    return correct;
}