Home Coding, Scripting, Shaders

File Format Compressing Faces?

Zeealex
polycounter lvl 5
Offline / Send Message
Zeealex polycounter lvl 5
Hey all! so I'm making a set of mod tools for a couple of video games as the tools are either non existent or outdated and no longer work on modern systems.

I'm starting off with a simple converter for the game's model files that will convert them to Wavefront OBJ and then back again.
These are proprietary file formats based off of the old .QOB file format, however they are not the same.

Just a note: This is my first time taking on a project such as this so I apologise if there's something i've missed or if I sound a bit 'nooby'

I've been able to get the converter dumping the correct vertex positions into an OBJ file and I've verified this. However the faces are a little odd/tricky.

I'm testing the converter for one of the file formats on a small sample model which i have access to, and this model is expected to have 30 triangular faces and 28 vertices.
However with the face section of the model, it is impossible for it to have this many faces without some kind of compression/math being applied either on the engine or rendering API level.

The face section is 96 bytes long. With a byte in the geometry properties section of the file stating that the face section length is actually only half that size, at 48 bytes.
Each vertex index definition for the face takes up 2 bytes alone.
Assuming we're dealing with Triangular faces here with no other properties such as normal and UV indices, that gives us a possibility for either 16 faces (assuming a 96 byte section length) or 8 Faces (assuming a 48 byte section length)

Furthermore, spitting these indices into a face section of an OBJ file gives me the following:

f  1 2 3
f  4 5 6
f  7 8 8
f  9 9 10
f  11 10 12
f  13 14 15
f  16 16 17
f  17 14 18
f  12 19 12
f  20 11 20
f  21 19 21
f  22 23 22
f  24 25 24
f  26 2 26

which gives me this when I verify:

The duplication of vertex indices indicates to me that I'm doing something wrong here.

I manually reconstructed the face section and this is what I got:
f  1 2 3
f  2 24 26
f  4 5 6
f  4 27 25
f  4 2 26
f  4 3 2
f  4 3 5
f  6 27 28
f  6 27 4
f  7 6 5
f  8 7 6
f  9 10 11
f  11 10 12
f  13 14 15
f  15 16 14
f  17 14 18
f  12 18 14
f  12 10 13
f  12 13 14
f  18 12 19
f  12 19 20
f  20 11 12
f  20 21 11
f  21 19 20
f  22 21 19
f  21 23 22
f  24 22 23
f  24 25 22
f  24 25 26
f  25 26 4

which gives me:

I've got the original file with some information I've pulled about the file format if needed.

Has anyone seen something like this before? can anyone advise on what else to try? I'm particularly curious about it giving a 48 byte section length as opposed to 96, as in other, larger models it gives the correct section length.

Any help will be appreciated on this side! :D


Replies

  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    Is it possible it's tri-stripped? 
    You only need 2 verts to define a mid strip Tri if that's the case and might explain the funny numbers.

  • Klunk
    Offline / Send Message
    Klunk ngon master
    can you post the original .QOB file ?
  • Zeealex
    Offline / Send Message
    Zeealex polycounter lvl 5
    Klunk said:
    can you post the original .QOB file ?

    https://drive.google.com/file/d/127FzMskJjBRH6Ga5QvHzmkFNVHRK-PfJ/view?usp=sharing
    I'll get the data types and file information for you shortly. :)

    poopipe said:
    Is it possible it's tri-stripped? 
    You only need 2 verts to define a mid strip Tri if that's the case and might explain the funny numbers.

    Interesting, I thought it may have been defining something similar, I thought it was possibly defining edges though, lol! is there any more information on Tri-stripping and how to program my software to calculate the correct faces anywhere?


  • Zeealex
    Offline / Send Message
    Zeealex polycounter lvl 5

    Hopefully the formatting doesn't bork
    XQOB File

    Header Size – 16 Bytes

    File Structure:

    MEMB

                    MTRL

                    GEOM

                    MESH

                    SLIT

                    MDLT

                    PHYS

                    MODL

    XCHR (XSKA only)

    File Header

     

    Location

    Length

    Type

    Description

    Value

    0

    4

    Unsigned int

    File Length

    Variable

    4-7

    4

    String/Date

    XQOB File Header – Contains Date

    XQOB - 04/03/2005 02:13:44

    2

    4

    Unsigned Int

    Mesh Count

    Usually 2, Sometimes 3

     

    Texture

    Location

    Length

    Type

    Description

    Value

    TXTR+1

    4

    Unsigned Int

    Texture Index 1

    1

    TXTR+4

    4

    Unsigned Int

    Texture 1 Size

    512

    TXTR+5

    4

    Unsigned Int

    Texture Index 2

    2

    TXTR+8

    4

    Unsigned Int

    Texture 2 Size

    512

    TXTR+9

    4

    Unsigned Int

    TextureCount

    Typically, 2

    16

    4

    Unsigned Int

    Section Size for TextureList (In bytes)

    Variable

    36

    4

    Unsigned Int

    Texture 1 Name Length (Bytes)

    Variable

    Variable

    4

    Unsigned Int

    Subsequent Texture Name Lengths occur immediately after Preceding texture name

    Variable

     

     

    Member

    Location

    Length

    Type

    Description

    Value

    MEMB-4

    4

    Unsigned Int

    Section Length

    Variable

    MEMB-8

    4

    Unsigned Int

     

    123456

    MEMB+1

    4

    Unsigned Int

    Object Count

    Variable

    MEMB+24

    4

    Unsigned Int

    Vertex section length

     

    MEMB+80

    4

    float

    First vertex position

    variable

    MEMB+Vertexes

    2

    Ushort

    Face vertex indices

    variable

     

    XQOB File Bytes Per Vertex: 24

    XSKA File Bytes Per Vertex: 48

    Material

    Location

    Length

    Type

    Description

    Value

    MTRL-4

    4

    Unsigned Int

    Section Length

    Variable

    MTRL+1

    4

    Unsigned Int

    Illumination Model

    Typically, 2

    MTRL+9

    16

    Unsigned Int

    Material header

    Variable

    MTRL+24

    80

    Variable

    Material parameters

    Variable

    MTRL+104

    36

    Unsigned Int

    Material Signature

    Variable

     

    Geometry

    Location

    Length

    Type

    Description

    Value

    GEOM-4

    4

    Unsigned Int

    Section Length

    Multiples of 76 depending on number of elements

    GEOM+17

    4

    Unsigned Int

    Vertex Section Length 1 – this is 0 if there is only one object

    Variable

    GEOM+25

    4

    Unsigned Int

    Face Section 1 length

    Variable

    GEOM + 92

    4

    Unsigned Int

    Vertex Section 1 + Face Section 1 + Vertex Section 2

    Variable

    GEOM + 101

    4

    Unsigned Int

    Face Section 2 length + 1

    Variable

    GEOM+9

    2

    Unsigned Short

    Object 1 Vertex Count

    Variable

     

    Mesh

    Location

    Length

    Type

    Description

    Value

    MESH-4

    4

    Unsigned Int

    Section Length

    Variable

     

    SLIT

    Location

    Length

    Type

    Description

    Value

    SLIT-4

    4

    Unsigned Int

    Section Length

    Variable

     

    MDLT – Possible UVW definitions

    Location

    Length

    Type

    Description

    Value

    MDLT-4

    4

    Unsigned Int

    Section Length

    Variable

     

     

    Physics

    Location

    Length

    Type

    Description

    Value

    PHYS-4

    4

    Unsigned Int

    Section Length

    Variable

     

    MODL

    Location

    Length

    Type

    Description

    Value

    MODL-4

    4

    Unsigned Int

    Section Length

    Variable

    MODL+4

    4

    Unsigned Int

     

    256

    MODL+12

    4

    Unsigned Int

     

    -256

     

    XCHR – Skeleton & Weights Definition

    Location

    Length

    Type

    Description

    Value

    XCHR-4

    4

    Unsigned Int

    Section Length

    Variable

     






  • Klunk
    Offline / Send Message
    Klunk ngon master
    are you sure about the file, there's next to nothing in the GEOM or MESH probably not enough data to make a cube.
  • Zeealex
    Offline / Send Message
    Zeealex polycounter lvl 5
    Klunk said:
    are you sure about the file, there's next to nothing in the GEOM or MESH probably not enough data to make a cube.

    Vertices and Faces are in the MEMB section, the first vertex starts 80 bytes after the 'MEMB' string, then the faces start immediately after the vertices. GEOM and MESH are just properties sections.
  • Klunk
    Offline / Send Message
    Klunk ngon master
    it also seems to be in big endian byte order or there is some very odd alignment going on :/

    the raw data suggest first five faces would be...

    1 2 3
    4 5 6
    7 7 8
    8 9 10
    9 11 12

    that's one bad "chunk" file implementation..... the point of the doom chunk file format is the sizeof chunk in bytes (4 bytes after the 4 byte tag)  takes you directly to the start of the next chunk tag without fail.

    so each tag is 16 bytes long... so something like
    <int, int, int(tag data length after tag), 4 char code tag>
  • Zeealex
    Offline / Send Message
    Zeealex polycounter lvl 5
    Interesting! If I switch to big endian though all of the section lengths and properties etc no longer make sense, whereas they do in little endian. I can't imagine the file switches endianness half way through, right?
  • Klunk
    Offline / Send Message
    Klunk ngon master
    it's not big endian, I was expecting at least 2 byte alignment (it makes it easier to "read" in a hex editor)  but it's byte aligned which threw me :) (I think it's because they don't pad the texture name :/
  • Klunk
    Offline / Send Message
    Klunk ngon master
    seems i get the same as you

    can't think of any reason they would want to compress the face indices :/ so i'm not sure whats going on
  • Klunk
    Offline / Send Message
    Klunk ngon master
    yep it's striped

    so the indice
    12345678...
    mean 
    faces
    123
    234
    345
    456
    etc

    the duplications are a way of continuing the strip without the face being visible 


    so it's visible with wireframe


    but not without

    obviously you need to solve the ordering issue .... could be alternating :)
  • Zeealex
    Offline / Send Message
    Zeealex polycounter lvl 5
    Klunk said:
    yep it's striped

    so the indice
    12345678...
    mean 
    faces
    123
    234
    345
    456
    etc

    the duplications are a way of continuing the strip without the face being visible 


    so it's visible with wireframe


    but not without

    You're Awesome! <3 So how would I go about programming the file converter to factor in the tri-stripping so I can convert to OBJ? I've programmed it in C#, I understand probs not the best language to use but it's just file I/O so didn't think much of it :')

    is there a specific algorithm I need to use?
  • Klunk
    Offline / Send Message
    Klunk ngon master
    yep alternating.... my mxs code

    faceindices = for f = 1 to nindices collect ( 1 + ReadShort bstream unsigned; )
    faces = for f = 1 to faceindices.count - 2 collect
    (
        face = [0,0,0];
        face.x = faceindices[f+2];
        face.y = faceindices[f+1];
        face.z = faceindices[f];
        if mod f 2 == 0 then swap face.x face.y
        face
    )



  • Zeealex
    Offline / Send Message
    Zeealex polycounter lvl 5
    Awesome! thanks for the code snippet! Would I also have to factor in something similar for the UV definitions?
  • Klunk
    Offline / Send Message
    Klunk ngon master
    not sure, I didn't delve that far in, that is a rabbit hole for you ;)

    also the 4 bytes after 

    MEMB+24

    4

    Unsigned Int

    Vertex section length


    is the number of face indices (if you didn't know already)
Sign In or Register to comment.