diff --git a/README.md b/README.md index b2e5d88..db2f864 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Use recent Lazarus (1.2.x) with Freepascal (2.6.x) to compile. TODO ----------- -* hmt parser: decode textures -* hob parser: parse more header fields, parse UV data +* hmt parser: decode all image subtypes +* hob parser: parse more header fields * mesh viewer: reuse hmt & hob parsers to display data * bundle repack: extract & compile bundle.00x archives diff --git a/doc/file_hob_spec.txt b/doc/file_hob_spec.txt index af209c3..a7298eb 100644 --- a/doc/file_hob_spec.txt +++ b/doc/file_hob_spec.txt @@ -69,15 +69,27 @@ NOF * face block 4B int face count FC FC * face { - 4B int face flags? if bit 3 is set, the face is a quad, otherwise triangle + 4B int face flags + - if bit 3 is set, the face is a quad, otherwise triangle + - if bit 2 is set, face has texture coordinates (uv-s) + - if bit 6 is set, face has extra 8 bytes before vertex colors 1B int 46/49/4B 1B int 51/71 1B int 0C 1B int block size / 4: A = 40B, 9 = 36, etc. 2B int zero? - 2B int texture/material index? + 2B int material index? 4x 2B vertex indices, relative to the face group. The last index is zero in triangle faces - x bytes until block size: most probably texture coordinates and some other stuff? + if (face has extra 8 bytes) { + 8B extra bytes + } + 3/4 * 4B RGBA vertex color + if (face has texture coordinates) { + 3/4 * { + 2B int u + 2B int v + } + } } } diff --git a/hob_parser/hob_parser.pas b/hob_parser/hob_parser.pas index 9096957..e496f55 100644 --- a/hob_parser/hob_parser.pas +++ b/hob_parser/hob_parser.pas @@ -7,13 +7,24 @@ uses Classes, SysUtils; type + TRGBA = record + color: integer; + end; + + TTexCoord = record + u, v: integer; + end; + THobFace = record flags: integer; b1, b2, b3: byte; bsize: byte; ftype: byte; //3 - tri, 4 - quad - tex_index: word; + has_uv: boolean; + material_index: word; indices: array[0..3] of word; + vertex_colors: array[0..3] of TRGBA; + tex_coords: array[0..3] of TTexCoord; end; THobFaceGroup = record @@ -55,7 +66,7 @@ function ParseHobFile(const fname: string): THobFile; implementation const - DumpFaces = false; + DumpFaces = true; function NameToString(name: array of byte): string; var @@ -74,7 +85,6 @@ var face: THobFace; unknown: integer; file_pos: integer; - buf: array[0..255] of byte; begin unknown := f.ReadDWord; if (unknown <> 0) then @@ -101,16 +111,8 @@ begin if (unknown <> 0) then writeln('unusual file: unknown'); - face.tex_index := f.ReadWord; - - //read vertex indices - for k := 0 to 3 do - face.indices[k] := f.ReadWord; - - //read rest of the face block - unknown := file_pos + face.bsize - f.Position; - for k := 0 to unknown - 1 do - buf[k] := f.ReadByte; + //material index + face.material_index := f.ReadWord; //face type: quad or triangle if face.flags and %1000 > 0 then @@ -118,18 +120,46 @@ begin else face.ftype := 3; + //read vertex indices + for k := 0 to 3 do + face.indices[k] := f.ReadWord; + + //ext0 + if face.flags and %1000000 > 0 then begin + f.ReadDWord; + f.ReadDWord; + end; + + //vertex colors + for k := 0 to face.ftype - 1 do + face.vertex_colors[k].color := f.ReadDWord; + + //uv coords + face.has_uv := face.flags and %100 > 0; + if face.has_uv then begin + for k := 0 to face.ftype - 1 do begin + face.tex_coords[k].u := f.ReadWord; + face.tex_coords[k].v := f.ReadWord; + end; + end; + group.faces[i] := face; if DumpFaces then begin if face.ftype = 3 then write('t') else write('q'); write(face.flags:5, face.b1:3, face.b2:3, face.b3:3, face.bsize:3); - write(' ti: ', face.tex_index); - write(' coords: '); + write(' mat: ', face.material_index); + write(' verts: '); for k := 0 to 3 do write(face.indices[k]:4); - write(' rest: '); - for k := 0 to unknown - 1 do - write(buf[k]:4); + write(' colors: '); + for k := 0 to face.ftype - 1 do + write(IntToHex(face.vertex_colors[k].color, 8), ' '); + if face.has_uv then begin + write(' uvs: '); + for k := 0 to face.ftype - 1 do + write('(', face.tex_coords[k].u, ', ', face.tex_coords[k].v, ') '); + end; writeln; end; end;