did you try switch from left to right handed matrix.Demonsangel wrote:
Fun part starts again, does anyone know the exact order of calculations for the armature?
if it is using quats you just invert the w.
did you try switch from left to right handed matrix.Demonsangel wrote:
Fun part starts again, does anyone know the exact order of calculations for the armature?
Genious, it worked.chrrox wrote:
did you try switch from left to right handed matrix.
if it is using quats you just invert the w.
That should be the only file reference algorithm, aside from files that just use the plain fileId as an uint32. The bytes you gave are definitely not a file reference. They are easy to spot:Demonsangel wrote:When following the file reference for the animations I got F2 B4 44 58 01 00 (13854.pf)
but it ends on 0100 which according to the algorythm you guys reversed gives an assertion.
Is there another algorythm or did I stumble upon the wrong reference? And if any of you do find the correct one, could you send the file over to me since I don't have the archive.
Code: Select all
==================================================
Chunk: eula (chunkname), versions: 1 (number of versions for this chunk), strucTab: 0x1527F78
==================================================
=> Version: 0 (version 0)
typedef struct
{
byte Language;
wchar_ptr Text;
} PackEulaLanguageV0<optimize=false>;
typedef struct
{
TSTRUCT_ARRAY_PTR_START PackEulaLanguageV0 Language TSTRUCT_ARRAY_PTR_END;
byte Version;
} PackEulaV0<optimize=false>; (last struct in version is the starting struct)
Code: Select all
#include <TypesDef.bt>
#include <PackFile.bt>
<insert the structures you want from the script here...>
PackFile MODLPackFile(0, FileSize()); // Declare and parse the PackFile at offset 0 and of size FileSize()
local uint32 lLoopIndex = 0;
local string lMagic;
while (exists(MODLPackFile.chunk[lLoopIndex])) // Loop on all the chunks
{
FSeek(startof(MODLPackFile.chunk[lLoopIndex].data)); // Put the cursor at the start of the chunk
lMagic = MODLPackFile.chunk[lLoopIndex].header.magic;
if (lMagic == "MODL") // If chunk is MODL apply the right struct
{
ModelFileDataV65 MODLChunk;
}
if (lMagic == "SKEL")
{
ModelFileSkeletonV1 SKELChunk;
}
<blabla...>
lLoopIndex = lLoopIndex + 1;
}
Code: Select all
0A 00 00 00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
for
typedef struct
{
TSTRUCT_PTR_ARRAY_PTR_START ModelAnimationDataV32 animations TSTRUCT_PTR_ARRAY_PTR_END;
TSTRUCT_ARRAY_PTR_START ModelCompoundAnimationDataV24 compoundAnimations TSTRUCT_ARRAY_PTR_END;
TSTRUCT_ARRAY_PTR_START qword fallbacks TSTRUCT_ARRAY_PTR_END;
TSTRUCT_ARRAY_PTR_START ModelAnimationImportDataV32 imports TSTRUCT_ARRAY_PTR_END;
} ModelFileAnimationBankV24<optimize=false>;
Code: Select all
typedef struct
{
filename filename;
TSTRUCT_ARRAY_PTR_START ModelAnimationImportSequenceV24 sequences TSTRUCT_ARRAY_PTR_END;
} ModelAnimationImportDataV32<optimize=false>;
Judging by the bytes you posted, you should be having 10 animations, not 3. The first uint32 is the count for the animations array.Demonsangel wrote:The last 3 don't get parsed because offset and count == 0, so it doesn't parse a filereference. Does it mean the animation data is in the pf file itself?
I did notice a lot of bytes being put into ModelAnimationDataV32, but 3 animations does seem too few for such a model.
Those structs are auto-generated from the exe, so they sometimes require some changes. Another example is in the exe fields can have periods in their names.Demonsangel wrote: And this is just nitpicking but in010 editor doesn't like twice the same name, so filename Filename;Code: Select all
typedef struct { filename filename; TSTRUCT_ARRAY_PTR_START ModelAnimationImportSequenceV24 sequences TSTRUCT_ARRAY_PTR_END; } ModelAnimationImportDataV32<optimize=false>;
Code: Select all
Chunk Header:
41 4E 49 4D BC C6 01 00 18 00 10 00 CC C5 01 00
typedef struct
{
TPTR_START ModelFileAnimationBankV24 bank TPTR_END;
PackGrannyAnimationType anim;
} ModelFileAnimationV24<optimize=false>;
-> in that file: 0C 00 00 00 00 00 00 00 00 00 00 00
ModelFileAnimationBankV24
Offset: 0C 00 00 00
PackGrannyAnimationType:
typedef struct
{
TSTRUCT_ARRAY_PTR_START byte animation TSTRUCT_ARRAY_PTR_END;
} PackGrannyAnimationType<optimize=false>;
animation:
Count:00 00 00 00
Offset: 00 00 00 00
(so no animation data)
ModelFileAnimationBankV24 has an offset so let's go on with that one:
typedef struct
{
TSTRUCT_PTR_ARRAY_PTR_START ModelAnimationDataV32 animations TSTRUCT_PTR_ARRAY_PTR_END;
TSTRUCT_ARRAY_PTR_START ModelCompoundAnimationDataV24 compoundAnimations TSTRUCT_ARRAY_PTR_END;
TSTRUCT_ARRAY_PTR_START qword fallbacks TSTRUCT_ARRAY_PTR_END;
TSTRUCT_ARRAY_PTR_START ModelAnimationImportDataV32 imports TSTRUCT_ARRAY_PTR_END;
} ModelFileAnimationBankV24<optimize=false>;
You know the offset was 0C 00 00 00 (so 12 bytes) and that was at byte 27,952 so now let's go on at byte 27,964:
03 00 00 00 1C 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
So that means for
ModelAnimationDataV32:
count: 03 00 00 00
offset: 1C 00 00 00
ModelCompoundAnimationDataV24
count: 00 00 00 00
offset: 00 00 00 00
(no Data for that)
etc.
Now at that offset the struct ModelAnimationDataV32 starts which is big again etc.
So you have 3 times that ModelAnimationDataV32 struct with a lot of data. And it goes on and on like that till you're done with all structs
That indeed is possible.Demonsangel wrote: unless ofcourse I managed to get a useless npc model at my disposal.