Main Menu

HOB Loader

Started by AGP, November 23, 2015, 05:17:47 AM

Previous topic - Next topic

AGP

Egon, would you be so kind as to write me a quick-and-dirty loader for a file format specified in the following description? I'd do it if I completely understood it. :- )

Quote
4B object count OF. 0 in empty files
4B simple offset to vertices/faces - doesn't work all the time. Probably useless...

OF * object header 116B
{
  16B name
  4B int facegroups offset
  4B int facegroup header offset
  4B int facegroup header 2 offset
  12B zero
  4B int ? 94, 0xD4
  4B int ? 98, 0x100
  4B int ? 9C, 0x104
  4B float ?:
      -bark_moon, cldcar: 1.0
      -sky, e_cor: 0.2
      -wmvwing: 1.25
  12B zero
  5x4B floats ?
  4B int offset before 0xFFFFFFFF header end marker
  6x 4B float ?
}

OF * facegroup header
{
  2B number of facegroups NOF
  2B NX ?
  NOF * facegroup/meshdef0 offset {
    4B int ?
    4B int facegroup/meshdef0 offset
  }
  2B NOF again
  2B NX ? 
  NX * offsets + zeros
  NOF * name {
    2B facegroup number
    8B char
  }

  4B 0xFFFFFFFF header end marker
}

NOF * facegroup/meshdef0 (fg/m0) 132B
{
  4B int offset to next fg/m0, 0 if there's no next, or in some other circumstances
  4B int offset to prev?
  4B int offset to beginning if this is not first fg/m0?
  4B int offset to end if offset to next = 0
  4B int offset to meshdef1 + 4
  8B zero
  48B 3 * {
    4B float 1.0
    12B zero
  }
  4B int
  3 * 4B float
  3 * 4B float 1.0
  28B zero
}

NOF * facegroup/meshdef1 96B
{
  4B int facedef end offset
  20B zero
  4B int vertices used
  4B int ?
  4B zero
  4B int face def offset
  4B int vertex def offset
  52B zero
}
 
NOF * face block
{
  8B zero
  4B int filepos + 4
  4B int face count FC
  FC * face
  {
    4B int face flags
        - bits 0, 1 unknown
        - if bit 2 is set, face has texture coordinates (uv-s)   
        - if bit 3 is set, the face is a quad, otherwise it's a triangle
        - if bit 4 is set, face has separate colors for each vertex
        - if bit 5 is set, face has color
        - if bit 6 is set, face has extra 8 bytes before vertex colors
        - bits 7-10 unknown. higher bits don't seem to be set
    1B int ? 46/49/4B
    1B int ? 51/71
    1B int ? 0C
    1B int face block size divided by 4
        - A = 40B, 9 = 36, etc.
    2B int zero
    2B int material index
    4x 2B vertex indices, relative to the face group. The last index is zero in triangle faces
    if (face has extra 8 bytes) {
        8B extra bytes
    }
    if (face has color) {
        if (face has vertex colors) {
            3/4 * 4B RGBA vertex color
        } else {   
            4B RGBA color
        }
    }
    if (face has texture coordinates) {
        3/4 * {
            2B int horizontal texture coord
            2B int vertical texture coord
        }
    }
  }
}

Vertices
{
  2B int X
  2B int Y
  2B int Z
  2B int ?
}


EgonOlsen

Well....no, I can't. I don't have time for that especially since this is some strange format that no other user would benefit from (I assume that this is this Star Trek game spaceship format!?).

Apart from that, I don't see why I should be better in understanding this format than you are. It basically looks like a list of chunks with lots of unknown elements...If somebody reverse engineered this thing, isn't there some loader/converter for it available already?

AGP

There isn't. Why would you guess Star Trek? At any rate, any format benefits everyone. jpct is a little lacking in loaders, really (most of the time obj does the trick for static objects, but sometimes I run into problems at the exporter end, and others it doesn't cut it for other reasons).

At the very least you'd be better at the jpct end. Beyond that, you've written your share of loaders. I'll try my hand at it when I wake up, then.

EgonOlsen

I googled for HOB and I found that it's the format of some ship meshes in some Star Trek game. If it's not that, what is it then?

AGP

There's a series of late 1990s, early 2000s, games that used it. In this particular case it's Star Wars. LOL

AGP

Given the following definitions, assuming I'm filling them right (I'm not able to compile it just yet but my main concern is with Java's signed bytes and ints, otherwise it should be right tomorrow morning), how do I build the Object3Ds?


class THobFile {
     protected int obj_count;
     protected THobObject[] objects;
     public THobFile() {
objects = new THobObject[2];
     }
     public void setLength(int length) {
THobObject[] newObjects = new THobObject[length];
for (int i = 0; i < length && i < objects.length; i++)
     newObjects[i] = objects[i];
objects = newObjects;
     }
}
class THobObject {
     byte[] name = new byte[16];
     int face_group_offset, face_group_header_offset, face_group_header2_offset;
     int face_group_count, face_group_count0;
     protected THobFaceGroup[] face_groups;
     public THobObject() {
face_groups = new THobFaceGroup[2];
     }
     public void setLength(int length) {
THobFaceGroup[] newFaces = new THobFaceGroup[length];
for (int i = 0; i < length && i < face_groups.length; i++)
     newFaces[i] = face_groups[i];
face_groups = newFaces;
     }
}
class THobFaceGroup {
     protected int meshdef1_offset, face_block_end_offset, face_block_offset, vertex_block_offset;
     protected int face_count;
     protected THobFace[] faces;

     protected int vertex_count;
     protected Vector[] vertices;
     public THobFaceGroup() {
faces = new THobFace[2];
     }
     public void setLength(int length) {
THobFace[] newFaces = new THobFace[length];
for (int i = 0; i < length && i < faces.length; i++)
     newFaces[i] = faces[i];
faces = newFaces;
     }
     public void setVerticesLength(int length) {
Vector[] newVertices = new Vector[length];
for (int i = 0; i < length && i < vertices.length; i++)
     newVertices[i] = vertices[i];
vertices = newVertices;
     }
}
class THobFace {
     protected int flags;
     protected byte b1, b2, b3;
     protected byte bsize;
     protected byte ftype; //3 - tri, 4 - quad
     protected short material_index;
     protected short[] indices = new short[4];
     protected TRGBA[] vertex_colors = new TRGBA[4];
     protected TTexCoord[] tex_coords = new TTexCoord[4];
}
class TTexCoord {
     protected short u, v;
}
class Vector {
     protected float x, y, z, unknown;
     public SimpleVector getSimpleVector() {
return new SimpleVector(x, y, z);
     }
}

AGP

TRGBA is just an int, by the way.


class TRGBA {
     protected int color;
}

EgonOlsen

I usually read such stuff and store it in some intermediate data structure from which I then, after reading it all in, create Object3Ds with addTriangle. Another option would be to store in a basic array structure and use Object3D's bulk constructor. raft did that on some occasions, but I usually don't.

AGP

OK, I need to triangulate the mesh, now. The first triangle of every square is obviously easy: any three vertices. Of the second I have the first vertex (the unused one). How do I find the other two?

EgonOlsen

The other two are shared with the other triangle. If you have all four points of the square and know the order in which they are connected, it's really simple. Just draw it on paper to see for yourself. 5 points on the other...that's a different question. I don't support this either, because it's not trivial anymore.

AGP

It's simple if you have the edges. Is there a way to figure out the other two without them?

EgonOlsen

You have to have some edge information somehow. Without it, you can't even build a square. This is usually modelled as an index list that points into the vertex list.