Yes!ボクセル宣言

これはクリスマスセール中なので買うならチャンスな3d-coat Advent Calendar 2016の記事です。

お待たせしました It's SHOW TIME!

そういうの求めてないからと言われそうですが3D-Coatの3Bファイルのボクセルデータの構造について書いておくことにしました。 3D-Coatの記事がまとまる機会なんてそうそうないからね!

さて、3D-Coatはボクセルスカルプトアプリケーションです。 今の3DCGの世の中はポリゴンモデルが大勢なのでリトポして出力することが多いですが、3D-Coatから持っているボクセルデータを取り出すこともできます。 とりあえず2つの方法があります。

ファイルメニューのエクスポート

一番簡単なのが素直にメニューの ファイル/エクスポート/未加工ボクセルをエクスポート を使うことです。

f:id:c5h12:20151224061604j:plain

書いてある通り、今作業中のボクセルオブジェクトを出力します。 『1セットの値として』というのは3D-Coatはボクセルを"セル"と呼ぶ8x8x8の単位で管理しています。 おなじみの"セルを隠す"というツールでごそっと消えるあの単位です。

f:id:c5h12:20151224061709j:plain

それをまとめて1つにして出力するということです。

そして出力される形式は独自(?)の構造で、内訳もダイアログに出てくる親切設計です。

f:id:c5h12:20151224061617j:plain

これをそのまま使えるツールがあるかは知りませんが、シンプルな形式なので使い勝手は悪くないと思います。

3Bファイルを直接読む

実は3Bファイルの構造はフォーラムのResources & Development / SDK, Plugins and Programming にある 3B file format specificationで部分的に公開されています。

中の人の『ちょっと今から3Bファイルのとっても面白いボクセルのところだけ解説するぜ!』という書き出しからはじまり、ファイルの構造のdocファイルと簡単なデモプログラム、それから解説用の画像がついています。

全部をドキュメントにするのは大変だけどここで質問すれば他のデータのところも教えてくれる、とは言っているのですが、最近頂点カラーについての質問に複雑すぎるからobjでやりとりしたほうが幸せになれるとか言っていたりするちょっとお茶目なスレッドです。

この 3B_file_format_specification-changed2.doc を見ればだいたいわかります。 以下はこのファイルをざっと解説したものです。

ファイル開始部分

4byte 4byte ...
MESH 1 ...

3Bファイルはマジック"MESH"から始まります。ボクセルが売りなのにMESHです。なお3Bファイルのマジックは文字列ではなく4バイトの値で、リトルエンディアンなのでhexdumpでは逆さに見えます。

00000000  48 53 45 4d 01 00 00 00  52 44 4e 52 08 00 00 00  |HSEM....RDNR....|
...

そのあとはデータのチャンクが続きます。

チャンク

4byte 4byte ...
チャンクID チャンクサイズ データ

チャンクはマジックとサイズにデータが続くシンプルな構造です。 マジックを見るとなんとなく内容の見当がつくものもつかないものもあります。

ボクセルチャンク

ボクセルデータはチャンクIDが"VOL3"のものです。

4byte 4byte 4byte 4byte ...
VOL3 size フラグ ボリュームの数 ...

フラグの内容はビットごとに

0-6bit 7,8,9bit 10-31bit
バージョン サーフェイスモードのフラグ 未使用

となっています。

バージョンはデータのバージョンです。基本は5で、-32768から3276の範囲に収まらないボクセルが現れたら6になります。

サーフェイスモードのフラグというのはグローバルインデックスかカラーがあるかのフラグ、と書いてあるのですがどのような時にオンになるのかは未確認です。 リトポせずに頂点ペイントに入った場合に使われるのではないかと思いましたがそうでもないようです。

ボリュームの数というのは要はボクセルツリーのレイヤーのうち、オブジェクトがあるレイヤーの数です。

ボリューム

主にユーザーがアプリケーション内で操作する、多くの3DCGソフトで『オブジェクト』と呼ばれる単位に近いものです。

4byte 4byte*16 4byte 1byte*N
ID トランスフォーム行列 名前の長さ 名前
4byte 4byte 4byte
デフォルトカラー モード 隠したセルの数+1
4byte 1byte*N 4byte ...
シェーダーデータの長さ シェーダーデータ セルの数 ...

名前やトランスフォームなど、レイヤー上から操作できるパラメーターが見えます。 モードはボクセルモード(0)かサーフェイスモード(255)かで、隠したセルの数というのは"隠す"ツールで隠したセルの数です。

シェーダーデータというのはシェーダーの名前の文字列とそのXML形式のパラメーターをつないだものです。

セル

やっとボクセルデータの本体にたどり着きました。 前にも書きましたが、3D-Coatは8x8x8単位のボクセルをセルと呼んでいます。

バージョン5

2byte 2byte 2byte
X Y Z

バージョン6

4byte 4byte 4byte 4byte
0xCE11 X Y Z

最初にセルの位置があるのですが、ここだけフォーマットのバージョンによって異なります。 6のほうがより大きいボクセルデータを表現できるようになっています。

注意すべきはこの位置というのはセル単位の位置なので、実際に配置されるべきボクセル上の位置は8倍して算出しなければなりません。

続きのデータはバージョン間で共通です。

1byte 1byte 1byte 2byte*N
ボクセルの数(9) セルのフラグ データのフラグ ボクセルデータ

ボクセルの数というのはセルの一つの方向(例えばX)が持っているボクセルの数で、今のところ 9 です。

8x8x8で管理していると言ってたじゃないかと言われそうですが、メッシュ化する際に便利なように隣と重複する1ボクセルを持っています。

フォーラムのスレッドに添付されている画像を見るとなんとなくわかるのではないかと思います。

セルのフラグの内訳は下です。

1bit 2bit 3bit 4bit
0を持っている 0ではない値を持っている 非表示(3.00.08J以降不使用) サーフェイスモードの面を持っている

データのフラグは0なら全て同じ値、1ならそうではないというフラグです。 全てのセルが同じ値の場合には、データ部分は1つの値だけが入れられます。 そうでない場合にはドキュメントに書いてあるような圧縮がかけられたボクセルデータが入り、9x9x9=729個分のボクセルデータが埋まるまで展開しながら読みだします。

この後にはサーフェイスモードのフラグが立っていたら面の情報が続きます。 が、ちょっと長くなっているので今回はボクセルの話ということで割愛します。後日追記するかもしれませんが。

なお3D-Coatは16bitで表されるボクセルの値が半分の32767の位置に面を張ります。 また、面の法線は近傍のボクセルの勾配を使って求めて頂点に格納しておくそうです。

セルのデータの後

ここにはXML形式でボクセルツリーの情報が格納されています。

4byte 1byte*N
データの長さ XMLデータ

3D-Coat内のような親子関係まで再現しようと思ったらこのデータを読んでツリーを作る必要があります。

以上がファイル構造の解説です。

実はずっと前にPythonで書いたものがこんなところにあったりします。 ただ少し前のドキュメントを参考にしているため、今回最新版のものを見てちょっと直さなきゃなと思っていますがもし必要なら参考にしてください。

また最近リリースされたUnityの3BファイルインポーターではボクセルルームのものではないメッシュやUVを読み込んでるのが見られるのでそちらも必見です。

若干消化不良感はありますがとりあえずこんなところで。