Author Topic: How to extract 3d models of gears from Xenogears?  (Read 12193 times)

O01eg

  • *
  • Posts: 23
    • View Profile
I read FS as described in Xeno-gears.htm, found some packs with 5 files, but cannot neither unpack them such LZS nor use them directly.
« Last Edit: 2008-10-06 15:53:32 by O01eg »

Micky

  • *
  • Posts: 300
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #1 on: 2008-10-08 06:53:58 »
That's using a modified LZS as described in xeno-gears.htm . There should be an implementation in the q-gears sourceforge version, but here is the code I'm using:
Code: [Select]
void * decompress_lzs(void * src, unsigned int srcLen, void * dst, unsigned int dstLen)
{
int iofs = 0, oofs = 0;
u8 cmd=0, bit=0;
while ((iofs < srcLen) && (oofs < dstLen)) {
if (bit == 0) {
cmd = ((u8*)src)[iofs++];
bit = 8;
}

if (~cmd&1) {
((u8*)dst)[oofs++]=((u8*)src)[iofs++];
} else {
int a = ((u8*)src)[iofs++];
int b = ((u8*)src)[iofs++];
u16 o = ((u16)(b&0x0F)<<8) | a;
u8 len = ((b&0xF0)>>4)+3;

int rofs = oofs - o;
for (int j=0; j<len; j++) {
if (rofs < 0) {
((u8*)dst)[oofs++]=0;
} else {
((u8*)dst)[oofs++]=((u8*)dst)[rofs];
}
rofs++;
}
}
cmd>>=1;
bit--;
}
return dst;
}
Some blocks start with a u32 with the decompressed length - make sure you skip that! I spent a while trying to match background format with the description only to find out I accidentally decoded the length words as compressed data...

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #2 on: 2008-10-08 12:39:40 »
Where can I get dstLen? First 4 bytes of blocks don't mean uncompressed size.

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #3 on: 2008-10-08 18:29:55 »
For dstLen I use size of buffer for uncompessed data and return oofs to know size of uncompressed file.
I did not attentively look at the received data: 3d models don't keep commpressed and files in dir19 look like 3d models are pack with 4 parts.

Micky

  • *
  • Posts: 300
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #4 on: 2008-10-09 21:27:34 »
Where can I get dstLen? First 4 bytes of blocks don't mean uncompressed size.
I think it is for all files I remember right now. Even for field maps where several compressed files are packed together each individual file starts with the length.
So, compressed size is the file size minus 4, uncompressed size is the little-endian u32 a file starts with.
« Last Edit: 2008-10-11 08:15:31 by Micky »

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #5 on: 2008-10-12 18:59:36 »
I can draw structure of model, but had some problem with texture and hierarcy.
Hierarcy data's length is not divide by 4 without remainder for some files. Also, some textures have bigger size that vram.
http://bin.mypage.sk/FILES/chu-chu.7z
There are some files, which I got from Chu-Chu model (28st file in dir19, sector 0x3ae5d, length 47032). Is X position of textures in vram can be 832 when width of vram is 512?
It's some blocks of model:


Akari

  • *
  • Posts: 766
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #6 on: 2008-10-13 13:34:48 »
There are some files, which I got from Chu-Chu model (28st file in dir19, sector 0x3ae5d, length 47032). Is X position of textures in vram can be 832 when width of vram is 512?

It depends on bpp (bits per pixel). Width of VRAM is 512 in case of 16bpp. Xenogears as I remember mostly use 4bpp so it gives you 2048 pixel width.

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #7 on: 2008-10-14 13:05:18 »
It depends on bpp (bits per pixel). Width of VRAM is 512 in case of 16bpp. Xenogears as I remember mostly use 4bpp so it gives you 2048 pixel width.
Is 4bpp texture use CLUT such pallete? But CLUT have 128 colors (more then 16, which can be address by 4 bits) and you store texures in 32bpp class Surface without converting.

Akari

  • *
  • Posts: 766
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #8 on: 2008-10-14 17:19:55 »
It depends on bpp (bits per pixel). Width of VRAM is 512 in case of 16bpp. Xenogears as I remember mostly use 4bpp so it gives you 2048 pixel width.
Is 4bpp texture use CLUT such pallete? But CLUT have 128 colors (more then 16, which can be address by 4 bits) and you store texures in 32bpp class Surface without converting.

Yes it use palette. CLUT can have 16 or 256 colours.
I don't know whick source you look at (cause I have at least two readers for xeno texture) but both has functions to construct texture from data and palette.

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #9 on: 2008-10-14 18:51:20 »
{SVN Q-gears}/trunk/src/xeno/filetypes/model/TextureFile.cpp:
Code: [Select]
void
TextureFile::GetSurfaces(Surface* pClut, Surface* pVram)
{
    TextureHeader* texture_header = (TextureHeader*)(mpBuffer);

    // palette
    if (texture_header->id == 0x00001101)
    {
        u16 vram_x = texture_header->vram_x + texture_header->move_x;
        u16 vram_y = texture_header->vram_y + texture_header->move_y;

        for (int y = vram_y; y < vram_y + texture_header->height; ++y)
        {
            for (int x = vram_x; x < vram_x + texture_header->width; ++x)
            {
                u16 src1 = GetU16LE(0x10 + (x - vram_x) * 0x02 + (y - vram_y) * texture_header->width * 0x02);

                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 0) = ((src1      ) & 31) * 255 / 31;
                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 1) = ((src1 >>  5) & 31) * 255 / 31;
                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 2) = ((src1 >> 10) & 31) * 255 / 31;
                // set alpha only for first entry in clut if byte is set or all zero
                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 3) = (x == vram_x && (src1 & 0x8000) || (src1 == 0)) ? 0 : 255;
            }
        }
    }

    // textures
    else if (texture_header->id == 0x00001100)
    {
        u16 vram_x = texture_header->vram_x + texture_header->move_x;
        u16 vram_y = texture_header->vram_y + texture_header->move_y;

        for (int y = vram_y; y < vram_y + texture_header->height; y++)
        {
            for (int x = vram_x * 2; x < vram_x * 2 + texture_header->width * 2; x++)
            {
                *(pVram->pixels + x + pVram->width * 4 * y) = GetU8(0x10 + (x - vram_x * 2) + (y - vram_y) * texture_header->width * 2);
            }
        }
    }
}
And for Surface::pixels you create array of heigth*width*4 size, I understood that you use 32bpp. I clearly see converting to 32bpp in CLUT's part of code.
« Last Edit: 2008-10-14 19:19:15 by O01eg »

Akari

  • *
  • Posts: 766
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #10 on: 2008-10-15 03:25:07 »
{SVN Q-gears}/trunk/src/xeno/filetypes/model/TextureFile.cpp:
Code: [Select]
void
TextureFile::GetSurfaces(Surface* pClut, Surface* pVram)
{
    TextureHeader* texture_header = (TextureHeader*)(mpBuffer);

    // palette
    if (texture_header->id == 0x00001101)
    {
        u16 vram_x = texture_header->vram_x + texture_header->move_x;
        u16 vram_y = texture_header->vram_y + texture_header->move_y;

        for (int y = vram_y; y < vram_y + texture_header->height; ++y)
        {
            for (int x = vram_x; x < vram_x + texture_header->width; ++x)
            {
                u16 src1 = GetU16LE(0x10 + (x - vram_x) * 0x02 + (y - vram_y) * texture_header->width * 0x02);

                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 0) = ((src1      ) & 31) * 255 / 31;
                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 1) = ((src1 >>  5) & 31) * 255 / 31;
                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 2) = ((src1 >> 10) & 31) * 255 / 31;
                // set alpha only for first entry in clut if byte is set or all zero
                *(pClut->pixels + x * 4 + pClut->width * 4 * y + 3) = (x == vram_x && (src1 & 0x8000) || (src1 == 0)) ? 0 : 255;
            }
        }
    }

    // textures
    else if (texture_header->id == 0x00001100)
    {
        u16 vram_x = texture_header->vram_x + texture_header->move_x;
        u16 vram_y = texture_header->vram_y + texture_header->move_y;

        for (int y = vram_y; y < vram_y + texture_header->height; y++)
        {
            for (int x = vram_x * 2; x < vram_x * 2 + texture_header->width * 2; x++)
            {
                *(pVram->pixels + x + pVram->width * 4 * y) = GetU8(0x10 + (x - vram_x * 2) + (y - vram_y) * texture_header->width * 2);
            }
        }
    }
}
And for Surface::pixels you create array of heigth*width*4 size, I understood that you use 32bpp. I clearly see converting to 32bpp in CLUT's part of code.

Yup this is where it is converted.

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #11 on: 2008-10-15 20:00:47 »
I'm not fully understand converting textures but found ModelUtilites::Gen256x256Tex and ModelUtilites::Gen8bppTex. Also, how to read description block? When I read each 4 bytes for mesh (except with 0x25 and 0x2D id) I got that some triangles had description for quads and some quads had description for triangles. Does id 0x25 and 0x2D really store in 7-0 bits of Uint32 or store in 31-24 bits as other ids?

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #12 on: 2008-10-17 20:01:19 »
I upload some files what I got when read 3d model. There are file, textures, CLUT and output of my program:
http://bin.mypage.sk/FILES/Chu-Chu.7z - sector 0x3ae5d, length 47032 bytes
http://bin.mypage.sk/FILES/AnyMech.7z - sector 0x3af98, length 56664 bytes

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #13 on: 2008-11-03 19:14:18 »
I simply copied your code for load textures and texture coordinates and got rigth model.
Also I read "1st Animation" and can make model:

How to get number of animations? Is it Uint32 by offset 0x0?
And does only "1st Animation" start with "Animation Format" block?

Micky

  • *
  • Posts: 300
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #14 on: 2008-11-07 07:22:41 »
That looks great!

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #15 on: 2008-11-07 10:50:22 »
That looks great!
It'll look greater when I'll apply alpha channel and remove invisible blocks, but information about this is in unknown parts of animation files.

O01eg

  • *
  • Posts: 23
    • View Profile
Re: How to extract 3d models of gears from Xenogears?
« Reply #16 on: 2008-12-26 01:07:17 »
Thanks for your work with Xenogears, Akari. It's my coursework based on your code:
http://www.mediafire.com/?sharekey=1895602d1e3e55a8d2db6fb9a8902bda
WASD and arrows - camera
L - light
Space, "<", ">" - mech