はじめに
解説を入れていますが、備忘録的な感じで書いています。
ファイルフォーマットをある程度解析できる人でないと理解は難しいかもしれません。
また、用途は決まっているため不要なデータは解読せずそのままスキップします。
.havokファイルとは
.havokファイルとは、Havok社が開発した物理エンジンで利用されるファイルです。
Fallout 4やSkyrimでも利用されていますが、拡張子は異なり.hkxとなります。
ファイルフォーマットにも何種類かあり、バージョンによって異なります。
元々ワールドオブタンクスでは戦車の装甲圧計算に戦車のビジュアルに用いられていた.modelが利用されていました。
しかし、アップデート1.18でhavokに置き換えられたようです。
データは、各Tier毎に分けられたvehicles_level_XX-PartN.pkgアーカイブのvehiclesフォルダ以下にcollision_clientフォルダでまとめられています。
ここではバージョン1.23.1.1のデータを元に構造を解析していきます。
最終的には他の形式に変換したいので、C++を使ってParserを実装します。
ファイル構造を調べる
基本的な構造は以下のソースコードの通りです。
HavokLib/source/format_new.cpp at master · PredatorCZ/HavokLib · GitHub
GitHub - blueskythlikesclouds/TagTools: Tools for editing Havok 2015/2016 binary tag files (See Havoc branch for reference)
なお、WoTに使われているHavokはバージョンが新しいようでTST1チャンクとTNA1チャンクが追加されています。
以下のページで記載されていますが名前が違うだけでTST1はTSTR、TNA1はTNAMと構造が一緒のようです。
https://koreanrandom.com/forum/topic/43667-%D0%BA%D0%B0%D0%BA-%D0%B2%D1%81%D0%BA%D1%80%D1%8B%D1%82%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB-%D1%81-%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B5%D0%BC-havok/page/3/?ct=1707143296
あくまでもWoTは衝突などの判定に用いているだけのため以下のチャンクのみが用いられています。
TAG0
SDKV
DATA
TYPE
TST1
TNA1
FST1
TBDY
TPAD
INDX
ITEM
ここまでは既存のソースコードとバイナリを見ればすぐ分かりますが、
上記ソースコードには詳しい実装がなかった項目が2つあります。
DATAチャンク
TagToolsではチャンクサイズ分データを読み取るだけで中身は解析していません。
HavokLibではDATAチャンクを用いてデータを取っている箇所がありましたが、PTCHチャンクの読み取りに用いていただけでした。
DATAチャンク内に文字列が含まれていることや、他のチャンクが頂点データ等と関連性がなかったことから実際のデータが格納されていると思われます。
ITEMチャンク
HavokLibで読み取るデータのバイト数は分かりますが、読み込んだデータを見る限りだと変数名と一致しているようには見えませんでした。
しかしDATAチャンクを参照するためのデータが他のチャンクには見つけられないことから、ITEMチャンクとDATAチャンクが関連してると想定して解析を進めます。
ITEMチャンクの解析
以下がITEMチャンクのデータです。
変数名からある程度分かるかもしれませんが、データが何を指すのかまでは解析済みです。
項目の解説を行います。
TypeIndexAndFlagsは、フラグとデータ型の情報を持ちます。
TypeIndexAndFlags & 0xFFFFFFしたものがデータ型です。
フラグの方ですが、現時点では何を意味するのかは分かっていません。
Offsetは名前の通り、データの開始位置です。
DATAチャンクの開始位置を0として計算します。
Countはデータの数です。
データの数は、データ型によって実際のサイズが異なります。
上記画像の例で見ると、0x4の配列のデータは、Countが8です。
このデータはchar型なので、Countがそのままバイト数になります。
現状はここまでです。
データ型は構造体のようなデータもあるため、その場合は複雑になります。
データ型はTNA1チャンクで読み取るので気になったら参考にしたgithubのコードを見てみてください。