Gildor's Forums

Author Topic: UT2004 (etc...) SkeletalMesh and MeshAnimation  (Read 10148 times)
Alcatraz
Newbie
*
Posts: 17


View Profile
UT2004 (etc...) SkeletalMesh and MeshAnimation
« on: August 27, 2012, 14:30 »

Hello.
I'm writing small Unreal Packages parser.
I am able to read header, properties, textures and static meshes so far.
I've started working on SkeletalMesh parsing but it seems things goes very BAD after reading first bounding box and bounding sphere.

I have Acordero's old documentation at hand, which seems kinda outdated, I have UE3 beta source, which definitions doesnt seem to match UE3 neither previous version, and I have UShock which lacks even Meshes loading.

Right now, I tried:

Code:

// Note: vers/tris are here a "lazy arrays"
                bb.serialize(p);
bs.serialize(p);

if(p->getVersion() > 61) {
vertsJump = p->readInt();
}

verts.read(p);
if(p->getVersion() > 61) {
trisJump = p->readInt();
}
tris.read(p);

and

Code:
u32 numVertXYZs = p->readCompactInteger();
arraySTD_c<vec3_c> XYZs;
XYZs.resize(numVertXYZs);
vec3_c *pv = XYZs.getArray();
for(u32 i = 0; i < numVertXYZs; i++, pv++) {
int xyz = p->readInt();
printf("UMesh::Serialize: vert %i of %i - %i\n",i,numVertXYZs,xyz);

}
if(p->getVersion() > 61) {
trisJump = p->readInt();
}
u32 numTris = p->readCompactInteger();
for(u32 i = 0; i < numTris; i++) {
u16 i0 = p->readU16();
u16 i1 = p->readU16();
u16 i2 = p->readU16();
byte v0u = p->readByte();
byte v0v = p->readByte();
byte v1u = p->readByte();
byte v1v = p->readByte();
byte v2u = p->readByte();
byte v2v = p->readByte();
int flags = p->readInt();
int texIndex = p->readInt();
printf("tri %i of %i - tex %i, verts %i %i %i\n",i,numTris,texIndex,i0,i1,i2);
}
u32 numSeq = p->readCompactInteger();
for(u32 i = 0; i < numSeq; i++) {

}

Well, I really didnt want to ask for help, but I'm kinda out of options here. I've even tried dissasembling/decompiling to C UModel.exe tool, but the TOTAL lack of string references made it even worse reference than decompiled Unreal Engine itself.
Can you give me any hints, eg, the order of fields and their types in skeleltal models/animations with per-version exceptions? Maybe a revelant code snipper, or just a debug build of UModel so I can tell what's where?

Best regards, Alcatraz.
« Last Edit: August 27, 2012, 14:46 by Alcatraz » Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #1 on: August 27, 2012, 14:49 »

Hello.
Hello.
Quote
I have Acordero's old documentation at hand, which seems kinda outdated
he did not reversed skeletal mesh format
Quote
I have UE3 beta source, which definitions doesnt seem to match UE3 neither previous version
it's not "beta" I think, this source is too old to be UE3; by the way it does not contain UE2 code too
Quote
and I have UShock which lacks even Meshes loading.
UShock is primarily based on UTPackage (Acordero's code), except for level loading code
Quote
Code:
u16 i0 = p->readU16();
u16 i1 = p->readU16();
u16 i2 = p->readU16();
byte v0u = p->readByte();
byte v0v = p->readByte();
byte v1u = p->readByte();
byte v1v = p->readByte();
byte v2u = p->readByte();
byte v2v = p->readByte();
int flags = p->readInt();
int texIndex = p->readInt();
UT2004 has no such structure. It has similar structure (FMeshTri), but
1) it uses float texture coordinates instead of byte (byte is used in UE1)
2) this structure is used in older versions of engine and it's serialization is skipped in versions dated by UT2003/UT2004; I'm using this structure for Splinter Cell only
3) this structure is packed into TArray, not into TLazyArray
Quote
I've even tried dissasembling/decompiling to C UModel.exe tool, but the TOTAL lack of string references made it even worse reference than decompiled Unreal Engine itself.
Hint: try disassembling ut2004 executable for Linix Wink
Logged
Alcatraz
Newbie
*
Posts: 17


View Profile
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #2 on: August 27, 2012, 18:58 »

Well, indeed, I've found a bit more info there (function names + argument names). Still, I have made no progress yet. It seems that there's some more unknown bytes after bounding box (6 floats, byte) and a bounding sphere (4 floats) and before vertex positions coded as integers. I tested two skeletons (male and female), it looks like first byte is 4, then three times 0 byte, and then a four bytes (32 bit) integer with 1500~~ value. Then again some unknown bytes, and finally something that looks like vertices.
From dissasembly code, it looks like there is:
1. bounding box
2. bounding sphere
3. two unknown integers (that 4 and 1500~~ ? ) ( __ls__FR8FArchiveRi ; __ls(FArchive &,int &) )
4. and here it seems UT2004 loads vertex array, but in my code readCompactInteger returns 0 here so I've screwed up before

Any more hints?
I'm confused, since the first property says "None" so the properties should be parsed correctly. And, SkeletalMeshes, obviously dont have RF_HasStack flag.
PS: At least I've been able to confirm what you said about vertices. : )
Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #3 on: August 27, 2012, 21:25 »

Yes, vertices are packed into 32-bit unsigned integer. Check UT1 code (headers) which is available in the network for more details.
USkeletalMesh is derived from ULodMesh which is also has some geometry, which will be zero sized. I spent a lot of time finding appropriate set of data to use.
Quote
3. two unknown integers (that 4 and 1500~~ ? ) ( __ls__FR8FArchiveRi ; __ls(FArchive &,int &) )
1st int is "Version" (yes, it is 4 for UT2003 and UT2004) - this field is used alongside with package versions (FileVersion and LicenseeVersion) to distinguish serialization code path. The 2nd integer is NumVerts.
Quote
I'm confused, since the first property says "None" so the properties should be parsed correctly.
USkeletalMesh has no properties.
Quote
And, SkeletalMeshes, obviously dont have RF_HasStack flag.
I think this flag is used in script objects only.
Logged
Alcatraz
Newbie
*
Posts: 17


View Profile
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #4 on: August 29, 2012, 11:21 »

Well, thanks...
Still, I kinda stuck again (with both skeletons and animatioms)

This is my animation parsing code, can you reveal whats the latter serialization order and what are exacly those values in my structures?
Code:
class uAnimBone_c {

};
class uAnalogTrack_c {
public:
float values[4]; // quat or vec3?
};
class uMotionChunk_c {
public:
quat_c q;
int i; // wtf?
u32 ui;
};
class uMeshAnimation_c : public uBase_c {


public:
void read(uPack_c *p) {
// read uBase_c properties
uBase_c::serialize(p);
int i0 = p->readInt();
u32 numRefBones = p->readCompactInteger();
for(u32 i = 0; i < numRefBones; i++) {
uNameRef_c boneName;
p->readNameRef(boneName);
int flags = p->readInt();
// NOTE: even Bip01 bone has parent index '0' here, not -1?
int parent = p->readInt();
                        // yes, boneNames are correnct
printf("Bone %i of %i - %s with flags %i and parent %i\n",i,numRefBones,boneName.c_str(),flags,parent);
}
u32 numMotionChunks = p->readCompactInteger();
for(u32 i = 0; i < numMotionChunks; i++) {
uMotionChunk_c c;
p->readData(&c,sizeof(uMotionChunk_c));
u32 numIntegers = p->readCompactInteger(); // same as number of bones
arraySTD_c<int> ints;
//numIntegers++; // 0, 1, 2, 3, ... 29,30, 31 (the '31' has [numIntegers] indx
ints.resize(numIntegers);
p->readData(ints.getArray(),numIntegers*sizeof(int));

// c.q is 0, 0, 0, 10.f here, so that's not a quat
printf("Chunk %i of %i - q %f %f %f %f, integers %i %i\n",i,numMotionChunks,c.q[0],c.q[1],c.q[2],c.q[3],c.i,c.ui);

int numSMTH = p->readInt(); // same as number of bones (but only for the first frame, because we're delting later?)%
int debugOfs = p->getPos();

/// somethings goes really wrong here below
//int compact = p->readCompactInteger();
//for(u32 j = 0; j < numIntegers; j++) {
// uAnalogTrack_c tr;
// p->readData(&tr,sizeof(tr));
// printf("Analog track %i of %i - %f %f %f %f\n",j,numIntegers,tr.values[0],tr.values[1],tr.values[2],tr.values[3]);
//}
}
}

And here's my mesh reading code, I really made no progress there yet.
Code:
void uMesh_c::read(uPack_c *p) {
// read uBase_c properties
uBase_c::serialize(p);

bb.serialize(p);
bs.serialize(p);
printf("uMesh_c::read: after bounds %i\n",p->getPos());

this->version = p->readInt();
u32 numVerts = p->readInt(); // why isnt it stored in TArray's compactInteger?
printf("uMesh_c::read: version %i numXYz %i ofs %i\n",version,numVerts,p->getPos());

//verts.serialize(p);
// u1.serialize(p);
if(this->version <= 2) {
// read another TArray
//tris.serialize(p);
}
// read array

if(this->version <= 1) {

}
Thanks for any input,
Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #5 on: August 29, 2012, 14:02 »

Animation serialization code in UT2004 quite similar to one used in UT1, you may check it in ut432pubsrc.zip (could be easily found in google).
About the mesh serializer - I see no progress at all.
What's the purpose of what you're doing now?
Logged
Alcatraz
Newbie
*
Posts: 17


View Profile
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #6 on: August 31, 2012, 22:49 »

Well, I wouldnt ask for help here if there was a progress.
I'm just curious about Unreal technology and want to do a simple model viewer.
(Sorry for late reply but I implemented Unreal1 LodMesh parsing and rending, now they are correctly displated with textures. I've also done UPolys rendering and level parsing)

But I've stuck with several things.
1. Where are the skeletal meshes in UnrealTournament (the old game?). I  could'nt find them in UnrealI.u, UnrealShare.u neither in UPak.u.
2. How to decode texture format TEXF_NODATA? I've noticed that the number of mipMap bytes in TEXF_NODATA is equal to width * height (byte per pixel), and the Palette is avaible. I've tried handling TEXF_NODATA the same as classic paletted textures, but it didnt work. So how to decode TEXF_NODATA to classic 32 bit RGBA ?
3. UT2004 SkeletalMesh parsing.

Code:

struct uLoDMeshUNK0_c {
float first[3]; // xyz ?
float second[3]; // normal ?
int ints[3]; // ? ? ? edges?
};

virtual void serialize(uPack_c *p) {
int size_uMeshTri_c = sizeof(uMeshTri_c); // yes, that's 40
if(p->getVersion() > UT99_PACK_VERSION) {
// tested with UT2004 skelmodels
// 082E15F4
// serialize the uBase_c properties
// (uMesh_c serialization code does nothing in UT2004)
uBase_c::serialize(p);
bb.serialize(p);
bs.serialize(p);
this->version = p->readInt();
u32 numVerts = p->readInt();
printf("uLodMesh_c::read: version %i numXYz %i ofs %i\n",version,numVerts,p->getPos());
// for skeletal meshes that's an empty array
verts.serialize(p); // vertices packed to integers (one vertex == 32 bits)
// NOTE: sizeof(uMeshTri_c) == 40 (the one with float texcoords)
if(this->version <= 1) {
// array, struct with 11 members, sizeof(struct) == 40
tris.serialize(p);
} else {
// damn, the contents of those array cant be valid....
// 11 members too, sizeof(struct) == 40 ?
tris.serialize(p);
}
// 3 floats, 3 floats, 3 integers 12+12+12 = 36 bytes
// THE COUNT OF ELEMENT IN THIS ARRAY IS INCORRECT
uRawBytesArray_c<uLoDMeshUNK0_c> unk0;
unk0.serialize(p);
__asm int 3
Can you reveal whats that unknown struct and the rest of serialization path?

4. MeshAnimation parsing:

Code:
// Information about one animation sequence associated with a mesh,
// a group of contiguous frames.
class uMeshAnimSeq_c {
float v115Extra; // looks like animation weight
int name; // Sequence's name.
int group; // Group.
int startFrame; // Starting frame number.
int numFrames; // Number of frames in sequence.
float rate; // Playback rate in frames per second.
uArray_c<uMeshAnimNotify_c> notifys; // Notifications.
public:
// 082E60AC
void serialize(uPack_c *p) {

printf("uMeshAnimSeq_c::serialize: at %i\n",p->getPos());
if(p->getVersion() <= 114) {
v115Extra = 0.f;
} else {
v115Extra = p->readFloat();
}
// SOMETHING'S WRONG HERE BELOW
#if 0
//uRawBytesArray_c<int> ar;
//uRawBytesArray_c<byte> ar;
uRawBytesArray_c<short> ar;
ar.serialize(p);
#elif 0
int num = p->readCompactInteger();
for(u32 i = 0; i < num; i++) {
p->readCompactInteger();
}
#else
name = p->readCompactInteger();
const char *s = p->getNameForIndex(name);
printf("uMeshAnimSeq_c::serialize: name %s\n",s);
group = p->readCompactInteger();
#endif
startFrame = p->readInt(); // ok
numFrames = p->readInt(); // ok

// if(p->getVersion() > 111) {
notifys.serialize(p);

// ok
rate = p->readFloat();
}
};
Whats the extra float (v115Extra ) ? Animation weight? And how to parse the rest of uMeshAnimSeq and substructures?


« Last Edit: August 31, 2012, 23:11 by Alcatraz » Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #7 on: September 01, 2012, 12:28 »

1. Where are the skeletal meshes in UnrealTournament (the old game?). I  could'nt find them in UnrealI.u, UnrealShare.u neither in UPak.u.
Check my screenshots, there's package and mesh names
http://www.gildor.org/gallery/umodel#ut1
Quote
2. How to decode texture format TEXF_NODATA? I've noticed that the number of mipMap bytes in TEXF_NODATA is equal to width * height (byte per pixel), and the Palette is avaible. I've tried handling TEXF_NODATA the same as classic paletted textures, but it didnt work. So how to decode TEXF_NODATA to classic 32 bit RGBA ?
I'm not parsing this format. I think it is not used in the UE2.

Note: UE1 and UE2 has slightly different mesh serialization code, UE2 cannot load meshes from UE1. I'm using 2 different sets of functions - one for UE1 and another one for UE2.

Check modified quotes:
Quote
3. UT2004 SkeletalMesh parsing.

Code:

struct uLoDMeshUNK0_c { -- this is FMeshFace, check UT99 headers for description!
float first[3]; // xyz ?
float second[3]; // normal ?
int ints[3]; // ? ? ? edges?
};

virtual void serialize(uPack_c *p) {
.....
this->version = p->readInt();
u32 numVerts = p->readInt();
printf("uLodMesh_c::read: version %i numXYz %i ofs %i\n",version,numVerts,p->getPos());
// for skeletal meshes that's an empty array
verts.serialize(p); // vertices packed to integers (one vertex == 32 bits)
// NOTE: sizeof(uMeshTri_c) == 40 (the one with float texcoords)
if(this->version <= 1) {
// array, struct with 11 members, sizeof(struct) == 40
tris.serialize(p);
} else { -- there is no "else" here
/* // damn, the contents of those array cant be valid....
// 11 members too, sizeof(struct) == 40 ?
tris.serialize(p); */
}
-- here you must serialize array of UTexture
-- now - MeshScale, MeshOrigin, MeshRotation - FVector, FVector, FRotator --
// 3 floats, 3 floats, 3 integers 12+12+12 = 36 bytes

-- now -- array of "unsigned short" - some data for LODs, I don't use this

-- now - TArray<FMeshFace>
// THE COUNT OF ELEMENT IN THIS ARRAY IS INCORRECT
uRawBytesArray_c<uLoDMeshUNK0_c> unk0;

Both - windows and linux versions - of UT2004 has names of structures you're trying to serialize. I don't understand why you're using "Unk0" etc for them, IDA shows these names. UT99 headers has descriptions of these structures. Sometimes they're differs in UT2004, for example FMeshTri uses byte UVs in UE1 and float UVs for UE2 (I mentioned about this in one of my previous posts).
Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #8 on: September 01, 2012, 12:49 »

Whats the extra float (v115Extra ) ? Animation weight? And how to parse the rest of uMeshAnimSeq and substructures?
I don't know, it does not affects animation.
Logged
Alcatraz
Newbie
*
Posts: 17


View Profile
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #9 on: September 03, 2012, 00:47 »

Thank you! Thanks to you I've been able to make a huge progress. Right now I can display both SkeletalMeshes and MeshAnimation bones, altrough I've stuck with FStaticLODModel struct.

Here's my USkeletalMesh parsing code (again):

http://pastebin.com/mTU09RwB

Could reveal the meaning of unk's and dummies here, and show me the rest (?) of serialization path?

About the textures: Do you have Postal 2? This game's texture files are listed are "Supported" on the UModel compatilibity table, but they are not. Not fully, I mean. A lot of textures has TEXF_NODATA type. I hope that you'll fix it, and (by the way) tell me what is that strange format.

BTW: It's interesting that some binaries have the entire UArray code inlined, while others still have UArray serializing in separate function. The latter are easier for me to study.
« Last Edit: January 26, 2013, 21:00 by Alcatraz » Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #10 on: September 03, 2012, 08:27 »

Could reveal the meaning of unk's and dummies here, and show me the rest (?) of serialization path?
You don't need to understand everything. UE2 has a lot of redundancy in SkeletalMesh data. I'm serializing everything (it's not possible to serialize parts of data) but most of data are not used.
Quote
About the textures: Do you have Postal 2? This game's texture files are listed are "Supported" on the UModel compatilibity table, but they are not. Not fully, I mean. A lot of textures has TEXF_NODATA type. I hope that you'll fix it, and (by the way) tell me what is that strange format.
I've checked UT2004 source code. It has no code to handle TEXF_NODATA format. Engine sets this constant when somebody imports DXT texture in format which is not DXT1, DXT3 or DXT5.
Umodel has no special code for Postal game. This game is supported "as is", and it looks like the engine for this game was not modified.
Quote
BTW: It's interesting that some binaries have the entire UArray code inlined, while others still have UArray serializing in separate function. The latter are easier for me to study.
TArray, not UArray Smiley TArray is a template class, so all it's functions are implemented as inline declaration. It's up to compiler to decide whether it should inline code or not.
Logged
Alcatraz
Newbie
*
Posts: 17


View Profile
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #11 on: September 03, 2012, 11:24 »

You don't need to understand everything. UE2 has a lot of redundancy in SkeletalMesh data. I'm serializing everything (it's not possible to serialize parts of data) but most of data are not used.

I know, it's just that I cant get past first FStaticLODModel.

I've checked UT2004 source code. It has no code to handle TEXF_NODATA format. Engine sets this constant when somebody imports DXT texture in format which is not DXT1, DXT3 or DXT5.
I'll check that again, but it seemed that there are few TEXF_NODATA in game data.

This game is supported "as is", and it looks like the engine for this game was not modified.
I must disagree. The FBspNode serializer (not the hacky UShock garbage, but the UT2004 one - 1:1 translated from assembly code) can't handle nodes of Postal .fuk maps, but works perfectly with UT2004's (its obvious that something goes wrong because second nodes plane equation conatins invalid floating point numbers). I'm fixing it right now.


TArray, not UArray Smiley
I know, I just dont really care about structure names as long as I know their purpose. Like the compiler. Smiley
Logged
Gildor
Administrator
Hero Member
*****
Posts: 7972



View Profile WWW
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #12 on: September 03, 2012, 11:37 »

I must disagree. The FBspNode serializer (not the hacky UShock garbage, but the UT2004 one - 1:1 translated from assembly code) can't handle nodes of Postal .fuk maps, but works perfectly with UT2004's (its obvious that something goes wrong because second nodes plane equation conatins invalid floating point numbers). I'm fixing it right now.
UT2004's code branch is quite different from plain UE2. If you'll make UT2004 support some day your code will not work with UE2Runtime and vice versa - if you'll support UE2Runtime your code will not work with UT2004. I don't think Postal uses UT2004 modifications because Postal's engine is quite old in comparison to UT2004, so UT2004's source code was not available to the engine licensees at that time.
Logged
Alcatraz
Newbie
*
Posts: 17


View Profile
Re: UT2004 (etc...) SkeletalMesh and MeshAnimation
« Reply #13 on: January 26, 2013, 13:46 »

OK I know I havent posted anything in this topic for more than 120 days, but among some success with maps (Postal2 versions of them, too) I have realized what was wrong with the textures. Somehow my TEXF_* enumeration was incorrect. So disregard what I said above.
Logged
Jump to:  

Powered by SMF | SMF © 2006-2009, Simple Machines LLC
Leviathan design by Bloc | XHTML | CSS