One, we have the lovely 'Ryuou' / 'Valgirt' from Dragon Quest Swords (11k poly, 272 bones):
Two, we have the awesome robotic 'Kiryu' / 'Mechagodzilla' from Godzilla: Unleashed (6k poly, 69 bones):
These pic's don't show much except that the importing is pretty near flawless into blender, including weights and other nifty things.
Side note, I'm using the GLSL display option in blender, and have a script that converts I8A8 normal maps into RGB = XYZ normal maps, so that blender can use them in the shaders it has. Also, the light setup is a new one I'm experimenting with, that has two hemispherical lights always 180 degrees apart, but only one is applying specular components. It is similar to a ambient light, but seems to be a little nicer. Once I finish my CIE Lighting model shader, I'll try making that mess happen.
And, of course, both of these models are copyrighted to their respective owners. Go buy the damn game(1)(2) if you want them yourself!
-Z
Miscellaneous banter, Useful mathematics, game programming tools and the occasional kink or two.
2009-08-16
2009-08-15
Hacking Success; Dragon Quest Swords broken!
Add:
Godzilla: Unleashed
Rampage: Total Destruction
Dragon Quest Swords
Monster Hunter G
Monster Hunter Tri
Super Smash Bros. Brawl
Carnival Games *
Super Mario Galaxy
NiGHTS
ect...
to the list of games I can extract models from.
I wish I knew who to give credit to, but all I needed was this little function here to finally break apart the .fpk / Dragon Quest Swords compression format (I was really close too, ironically)
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
int endian=1;
u32 BE32(u32 data)
{
if(endian)
return ( (data<<24) | ((data<<8)&0x00ff0000) |
((data>>8)&0x0000ff00) | (data>>24) );
else
return data;
}
int blen;
int fbuf;
/* PRS get bit form lsb to msb, FPK get it form msb to lsb */
int get_bits(int n, char *sbuf, int *sptr)
{
int retv;
retv = 0;
while(n){
retv <<= 1;
if(blen==0){
fbuf = sbuf[*sptr];
//if(*sptr<256)
//{ printf("[%02x] ", fbuf&0xff); fflush(0); }
(*sptr)++;
blen = 8;
}
if(fbuf&0x80)
retv |= 1;
fbuf <<= 1;
blen --;
n --;
}
return retv;
}
int uncomp(char *dbuf, int dlen, char *sbuf, int slen)
{
int sptr;
int dptr;
int i, flag, len, pos;
blen = 0;
sptr = 0;
dptr = 0;
while(sptr < slen){
flag = get_bits(1, sbuf, &sptr);
if(flag==1){
//if(sptr<256)
//{ printf("%02x ", (u8)sbuf[sptr]); fflush(0); }
if(dptr < dlen)
dbuf[dptr++] = sbuf[sptr++];
}else{
flag = get_bits(1, sbuf, &sptr);
if(flag==0){
len = get_bits(2, sbuf, &sptr)+2;
pos = sbuf[sptr++]|0xffffff00;
}else{
pos = (sbuf[sptr++]<<8)|0xffff0000;
pos |= sbuf[sptr++]&0xff;
len = pos&0x07;
pos >>= 3;
if(len==0){
len = (sbuf[sptr++]&0xff)+1;
}else{
len += 2;
}
}
//if(sptr < 256)
//{ printf("< %08x(%08x): %08x %d> \n", dptr, dlen, pos, len); fflush(0); }
pos += dptr;
for(i=0; i< len; i++){
if(dptr < dlen)
dbuf[dptr++] = dbuf[pos++];
}
}
}
return dptr;
}
Thanks to that mess, I could use my own BRRESToOBM and the Pipeworks1.4ToOBM converters to completely extract the models and import them into blender.
Why do this, you ask?
Simple! Since NOT A SINGLE DAMN PERSON here is competent enough to help me, my only method of QA/QOS/QMS/verification is checking my work against commercial products. It's a very useful method as you often get to see techniques for animation, texturing and shading that are well known to industry but not well documented, or just plain hard to find.
Some of the cool things I've learned:
*Use additional bones inside of the arm joints on your characters; This allows you to retwist the arm visually while still keeping the IK chain unbroken. This is a classic character animation technique that I never had seen in practice.
*Use lots of matrices and bleed the weights out as much as possible, trying not to exceed 4 weights per vertex; Don't just use 0.5/0.5 blending factors (Valgirt has 272 bones...)
*If you are applying a bump/normal map to a character, use the I8A8 texture format and simply calculate the z component in the shader; This costs no additional instructions AND guarantees a normalized z component which you would have to do anyways.
*Use well painted textures, and don;t be afraid to use non-contiguous models (fins, talons, tongues, even neck/finger joints do not always have to be connected to the base mesh!
*Make sure you add in additional transform bones to characters, such as a Root Node and X/Y rotation nodes.
*for mesh modeling, targeting 3k verticies isn't really an issue.
*Always sort your meshes by: Material, Matrix Deformation Pool, Index array type.
*Always convert your final mesh pools into triangle strips if you can; Avoid quads and triangles. If you must use triangles, sort them in a indexed triangle list so that each next triangle shares adjacent verticies. Note that on file loading, you can always convert strips back to triangles; but not the other way around.
*Matrix deformation systems allow you to do things you could never do with bone animation systems; Since you just get a 3x4 float matrix per 'bone', you can apply translation, rotation, scale, and shear transformations. Since the hardware is unaffected by the values you put in those matrices (same number of ops) you're allowed to really have fun animating and be guaranteed consistent results anywhere.
*Mesh keyframes are A-OK and should be combined into your matrix mesh; for example facial poses and stuff. Simply apply those before running your mesh through the shader; You can get very awesome character animations this way.
*Try and avoid making your matricies match a 'skeleton' of you character; This often results in hard mechanical animation that looks not fun. It also makes your artists have to work harder, because a 'bone' does not behave like a matrix. Usually, with matrix deformations, you want the matrix to be at the 'ring center' of the mesh data, so that scaling and transforms will behave as you expect. Interestingly, since matrices have no constraints, you can always make this look like the hard mechanical, but you can't do that the other way around.
*Add additional target matricies; It only costs a small amount of CPU and gives your models flexibility for grapple animations, picking up objects, and easier cinematic animations
*I've seen 11,000 vertex models fully shaded on the Wii. No kidding. With 200 + bones. Think about that for a second. Think about how much more powerful your PC is than that.
*Most importantly, animate/design for fun. Don't make things realistic; It's a waste of your time because commercial studios can always do that better than you can. And who wants to play a realistic game anyways?
I'll post pics later, today I have more beer to acquire!
-Z
Godzilla: Unleashed
Rampage: Total Destruction
Dragon Quest Swords
Monster Hunter G
Monster Hunter Tri
Super Smash Bros. Brawl
Carnival Games *
Super Mario Galaxy
NiGHTS
ect...
to the list of games I can extract models from.
I wish I knew who to give credit to, but all I needed was this little function here to finally break apart the .fpk / Dragon Quest Swords compression format (I was really close too, ironically)
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
int endian=1;
u32 BE32(u32 data)
{
if(endian)
return ( (data<<24) | ((data<<8)&0x00ff0000) |
((data>>8)&0x0000ff00) | (data>>24) );
else
return data;
}
int blen;
int fbuf;
/* PRS get bit form lsb to msb, FPK get it form msb to lsb */
int get_bits(int n, char *sbuf, int *sptr)
{
int retv;
retv = 0;
while(n){
retv <<= 1;
if(blen==0){
fbuf = sbuf[*sptr];
//if(*sptr<256)
//{ printf("[%02x] ", fbuf&0xff); fflush(0); }
(*sptr)++;
blen = 8;
}
if(fbuf&0x80)
retv |= 1;
fbuf <<= 1;
blen --;
n --;
}
return retv;
}
int uncomp(char *dbuf, int dlen, char *sbuf, int slen)
{
int sptr;
int dptr;
int i, flag, len, pos;
blen = 0;
sptr = 0;
dptr = 0;
while(sptr < slen){
flag = get_bits(1, sbuf, &sptr);
if(flag==1){
//if(sptr<256)
//{ printf("%02x ", (u8)sbuf[sptr]); fflush(0); }
if(dptr < dlen)
dbuf[dptr++] = sbuf[sptr++];
}else{
flag = get_bits(1, sbuf, &sptr);
if(flag==0){
len = get_bits(2, sbuf, &sptr)+2;
pos = sbuf[sptr++]|0xffffff00;
}else{
pos = (sbuf[sptr++]<<8)|0xffff0000;
pos |= sbuf[sptr++]&0xff;
len = pos&0x07;
pos >>= 3;
if(len==0){
len = (sbuf[sptr++]&0xff)+1;
}else{
len += 2;
}
}
//if(sptr < 256)
//{ printf("< %08x(%08x): %08x %d> \n", dptr, dlen, pos, len); fflush(0); }
pos += dptr;
for(i=0; i< len; i++){
if(dptr < dlen)
dbuf[dptr++] = dbuf[pos++];
}
}
}
return dptr;
}
Thanks to that mess, I could use my own BRRESToOBM and the Pipeworks1.4ToOBM converters to completely extract the models and import them into blender.
Why do this, you ask?
Simple! Since NOT A SINGLE DAMN PERSON here is competent enough to help me, my only method of QA/QOS/QMS/verification is checking my work against commercial products. It's a very useful method as you often get to see techniques for animation, texturing and shading that are well known to industry but not well documented, or just plain hard to find.
Some of the cool things I've learned:
*Use additional bones inside of the arm joints on your characters; This allows you to retwist the arm visually while still keeping the IK chain unbroken. This is a classic character animation technique that I never had seen in practice.
*Use lots of matrices and bleed the weights out as much as possible, trying not to exceed 4 weights per vertex; Don't just use 0.5/0.5 blending factors (Valgirt has 272 bones...)
*If you are applying a bump/normal map to a character, use the I8A8 texture format and simply calculate the z component in the shader; This costs no additional instructions AND guarantees a normalized z component which you would have to do anyways.
*Use well painted textures, and don;t be afraid to use non-contiguous models (fins, talons, tongues, even neck/finger joints do not always have to be connected to the base mesh!
*Make sure you add in additional transform bones to characters, such as a Root Node and X/Y rotation nodes.
*for mesh modeling, targeting 3k verticies isn't really an issue.
*Always sort your meshes by: Material, Matrix Deformation Pool, Index array type.
*Always convert your final mesh pools into triangle strips if you can; Avoid quads and triangles. If you must use triangles, sort them in a indexed triangle list so that each next triangle shares adjacent verticies. Note that on file loading, you can always convert strips back to triangles; but not the other way around.
*Matrix deformation systems allow you to do things you could never do with bone animation systems; Since you just get a 3x4 float matrix per 'bone', you can apply translation, rotation, scale, and shear transformations. Since the hardware is unaffected by the values you put in those matrices (same number of ops) you're allowed to really have fun animating and be guaranteed consistent results anywhere.
*Mesh keyframes are A-OK and should be combined into your matrix mesh; for example facial poses and stuff. Simply apply those before running your mesh through the shader; You can get very awesome character animations this way.
*Try and avoid making your matricies match a 'skeleton' of you character; This often results in hard mechanical animation that looks not fun. It also makes your artists have to work harder, because a 'bone' does not behave like a matrix. Usually, with matrix deformations, you want the matrix to be at the 'ring center' of the mesh data, so that scaling and transforms will behave as you expect. Interestingly, since matrices have no constraints, you can always make this look like the hard mechanical, but you can't do that the other way around.
*Add additional target matricies; It only costs a small amount of CPU and gives your models flexibility for grapple animations, picking up objects, and easier cinematic animations
*I've seen 11,000 vertex models fully shaded on the Wii. No kidding. With 200 + bones. Think about that for a second. Think about how much more powerful your PC is than that.
*Most importantly, animate/design for fun. Don't make things realistic; It's a waste of your time because commercial studios can always do that better than you can. And who wants to play a realistic game anyways?
I'll post pics later, today I have more beer to acquire!
-Z
Subscribe to:
Posts (Atom)