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\
18
はFBXHeaderExtension
の文字数。 超勘違い。プロパティがないから普通に次のOffsetが入ります。全ノードレコードにはOffsetから名前までしっかりあります。(基本)\
には通常プロパティ名(floatならF
等)が入るが今回はプロパティゼロなためバックスラッシュ。
###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
新しいのはI
と0x03eb
(バイナリ上だと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 から