LoginSignup
10
6

More than 5 years have passed since last update.

FBX解読②

Last updated at Posted at 2017-07-18

http://qiita.com/gshirato/items/87586421de0ec37e46a6
のつづき

なんかタイヤの発明になってないか心配な今日この頃ですが、他にソース見つかんないんだからしょうがないよね

ねらい

バイナリからテキストへ
前回の簡訳があらすぎたため例を交えて紹介。

実現したいこと

FBX解読→Meshデータを読み込む→Unity上で再現??

参考にするドキュメント

AutodeskのFBXガイド
http://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_274163DA_9E89_4DCC_8AF6_10B0C498582E_htm

使った3Dモデル

BlenderでCubeを作成、fbxエクスポート。

構造

最初の27バイトは略
前記事 http://qiita.com/gshirato/items/87586421de0ec37e46a6 を参考

ノードレコード

名前→終端オフセット→プロパティの順に紹介しているが実際のバイナリ上での並びとは異なるので注意。

前記事より、最初の27バイトの後すぐにこのノードレコードが始まると考えて良い。

FBXHeaderExtension\

最初の4バイトは終端オフセットで0d 09 00 >00→0x0000090d→2317(リトルエンディアン)

終端オフセットはこのノードレコードが終わった直後の数字が何バイト目かを表すためこのノードレコード自体は2316バイト目で終わることがわかる。プロパティがない場合はネストされたリストの親と考えることができそう。
バイトのインデックスは0から始まっているようなので数える際には注意。

逆にここで指定されたバイト数までのすべての要素をリストの子要素として考えることができそう。

後の8バイトは4バイト(プロパティの数)+4バイト(プロパティのバイト長)でそれぞれ0。
次に見えるのは名前18FBXHeaderExtension\
18FBXHeaderExtensionの文字数。\には通常プロパティ名(floatならF等)が入るが今回はプロパティゼロなためバックスラッシュ。 超勘違い。プロパティがないから普通に次のOffsetが入ります。全ノードレコードにはOffsetから名前までしっかりあります。(基本)

FBXHeaderVersion

**** **** **** **** **** 5c00 0000 0100
0000 0500 0000 1046 4258 4865 6164 6572
5665 7273 696f 6e49 eb03 0000 **** ****

Offset:92(5c00 0000)
プロパティ:1(0100 0000)
プロパティ容量:5byte(0500 0000)
名前の大きさ:16(1byteで表現0x10)
名前:FBXHeaderVersion(46 4258 4865 6164 6572
5665 7273 696f 6e
)
型: I (0x49)
Version: 1003(eb03 0000)

少し丁寧に
基本数値の読み込みはリトルエンディアン(要検証)

16FBXHeaderVersion I 0x03eb

新しいのはI0x03eb(バイナリ上だとeb03)
Iはこの次のeb03が整数型であることを表している。ちなみにプロパティが5バイトなのはデータ型表すための1バイトと整数型を入れるための4バイトの和であるため。

03eb→1003ということでAutodeskのHPで答え合わせができる。

FBXHeaderExtension:  {
       ; header information: global file information.
    FBXHeaderVersion: 1003
    FBXVersion: 7100
    CreationTimeStamp:  {
        Version: 1000
        Year: 2010
        Month: 1
        Day: 19
        Hour: 16
        Minute: 30
        Second: 28
        Millisecond: 884
    }
    Creator: "FBX SDK/FBX Plugins version 2011.2"
    SceneInfo: "SceneInfo::GlobalInfo", "UserData" {
...

FBXVersion

同じように読める
0x49 = I
0x03eb = 7400

EncryptionType

暗号化のタイプ = 0

CreationTimeStamp

Offset = 385(親ノードレコードが終わる位置)
プロパティ無し→よって親ノードレコード

Version

Offset 207
Value 1000

Year

Offset 229
Value 2017

...とこんなふうに続いて行きます。

MillisecondとNull-record

Millisecond

Offset:372で、<385(CreationTimeStamp)となる最後の要素

よって、この位置でCreationTimeStampは終了するが注目すべきはその後で
Null-recordが挿入されている。(13個分の0バイト)

https://wiki.rogiken.org/specifications/file-format/fbx/7400/structure/ によれば「子ノードを持たず、かつnode propertyを1つ以上持つようなノードのノードレコード末尾でのみ、NULL-recordが省略される」

Creator

プロパティ数:1
プロパティバイト数:41(TypeCode:1 + Length:4 + Data:36)
7CreatorS36→Sはstring型より、その後の数値はDataの長さ
その直後にstringの情報が入る。Blender (stable FBX IO) - 2.78 (sub 0) - 3.7.7

SceneInfo

Offset: 2304
FBXHeaderExtensionのOffset値に近づいてきました。
プロパティ数:2
プロパティバイト数:39

ここでプロパティ数2です。バイナリを解読するときにここの数字に合わせてバイナリファイルの読み方を変えなければいけません。

名前1:SceneInfo
型1:S 文字数1:21
内容1:GlobalInfo01SceneInfo

名前1:UserData
型1:S 文字数1:8
内容1:UserData

こんな感じでがつがつとデータを読んでいきます。

その他データ型

D: double

→8バイト倍精度浮動小数点数型(どっかで8バイト単精度浮動小数点数って見た気がするんですが8バイトである限り倍精度っていう解釈であってますか?)
倍精度浮動小数点数として8バイト分、64ビット分のバイナリを計算する。

L:Long

なっがい整数型 同じく8バイト
数値が大きくなりやすく、10進数で表したところで意味のある形で現れる可能性が低いのでToString("x")などを使って16進数表記で表すほうがベターかも。

d:Array of double

i:Array of int

次回で解説。fbxのどの属性についている配列化によって若干扱いが変わる。

次回

http://qiita.com/gshirato/items/87a14ffd9844dd474b72
ヘッダが何たるか、メインコンテンツの大体の読み方がわかったと思います。
次回はメインコンテンツの中から立方体描画の際に重要そうな情報をピックアップして見ていきます。

HoloLensアプリ開発記事一覧

http://qiita.com/gshirato/items/6c026f2c67dc332f829b から

10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6