dbones2cpp: DragonBones のアーマチュアを C++ コードに変換する
bin/dbones2cpp は DragonBones 5.x のデータ (*_ske.json と画像、追加の *.dbani) を、
ボーンアニメーション (rig) で動かせる static const データ一式のヘッダに変換します。
python3 -m pip install -r bin/requirements.txt # Pillow, numpy
bin/dbones2cpp chara_ske.json chara.hpp # 名前空間 chara
bin/dbones2cpp --scale 0.5 chara_ske.json walk.dbani chara.hpp
bin/dbones2cpp --out-format rgb565_swapped --out-key '#FF00FF' chara_ske.json chara.hpp
引数は入力の _ske.json、追加のアニメーション (.dbani など、0 個以上)、出力ヘッダの順です。
オプション
オプション |
既定値 |
説明 |
|---|---|---|
|
入力名から |
生成物の名前空間 ( |
|
先頭 |
変換するアーマチュア |
|
先頭 |
変換するスキン (他のスキンは警告して無視) |
|
1 |
画像と全座標 (ボーン、display、キーの位置、境界) の縮尺。角度と倍率は変わらない |
|
|
追加アニメーションの位置の縮尺。 |
|
なし (α を使う) |
入力画像でこの色のピクセルを透明にしてから処理する |
|
|
|
|
5 |
|
|
|
キーカラー出力で透明部分を塗る色。 |
|
128 |
キーカラー出力で不透明とみなす α (0..255) |
|
|
画素変換のディザ ( |
|
|
アトラスの幅 (64〜2048 の 2 の冪)。 |
|
|
フォルダ形式の画像の場所 |
|
なし |
各画像を、不透明部分が矩形にいちばん収まる向きに回して余白を落とす (1 回の bicubic 再サンプリング)。面積の削減が |
|
3 |
回転する価値があるとみなす面積の削減率 |
|
8 |
不透明部分を囲む凸多角形の最大頂点数 (3〜16)。描画はこの内側だけを走査する。 |
|
なし |
|
|
なし |
全アニメーションの姿勢を |
COLOR は #FF8000、F80、orange などの書式です。
入力
アニメーションの形式: 5.0 (ボーンごとに全チャネルを持つ
frame) と 5.5 以降 (translateFrame/rotateFrame/scaleFrame、スロットのdisplayFrame/colorFrame) の 両方を読みます。描画順のzOrderタイムラインも読みます。画像:
<name>_tex.jsonと<name>_tex.png(テクスチャアトラス、トリミング・回転したサブテクスチャ可) が あればそれを、なければ<name>_texture/<display の path>.pngを使います。ボーン は親が前に来るよう並べ替え、スロット は
zで並べます (これが基本の描画順)。カーブ:
curve(3 次ベジェ、区分ベジェ) とtweenEasingを 17 点の表にし、同じ表は共有します。tweenEasingもcurveもないキーは次のキーまで保持します (DragonBones と同じ)。全キーがバインドポーズと同じチャネルは省きます。
.dbaniは同じアーマチュア (ボーン名とスロット名が同じ) のアニメーションとして取り込み、ske のアニメーションの 後ろに並べます (同名は置き換え)。位置の縮尺が違うファイルは--anim-scale autoが合わせます。
透過の扱い
入力と出力を別々に指定します。
入力: 画像の α をそのまま使うか、
--in-keyの色を透明にします。出力:
argb4444(既定) は α を 4 ビットで持ちます。rgb565_swapped/rgb565は α が--alpha-threshold未満のピクセルを--out-keyの色で塗り、Armature::colorKeyEnabledを立てます (Instance::draw()が描画中だけそのキーカラーを設定します)。不透明なピクセルが量子化でキーカラーと 一致したときは青の最下位ビットを反転して逃がします (件数を警告)。
縮小は乗算済み α で行うので、透明部分の色がにじみません。
--out-format auto は画像ごとに形式を選びます。半透明のピクセル (4 ビット量子化後の α が 1〜14) のうち、
透明なピクセルに隣接するものはアンチエイリアスの縁で、キーカラー化するとくっきりするだけです。隣接しないものは
透けて見せるためのものなので、それが可視ピクセルの --auto-alpha (5%) を超える画像は argb4444 のまま、
残りは rgb565_swapped + キーカラーにします (rgb_chan では tie と bracelet の 8 枚が argb4444、33 枚が
キーカラー)。キーカラーの画像はブレンドでなくコピーで描かれるので速く (回転描画の 1 ピクセルが透明・不透明とも
約 20 命令。ARGB4444 は 25 / 50 / 70)、そのぶん縁のアンチエイリアスがなくなります。
形式が混ざるとアトラスは atlas (ARGB4444) と atlasKeyed の 2 枚になり、--atlas-width 0 なら
テクスチャごとの形式になります。Instance::draw() はキーカラーのテクスチャを描く間だけキーを設定します。
--preview はキーカラーの画像の縁を実機と同じように硬くして描きます。
アトラス
縮尺後の画像を高さの順に棚詰めし (隙間なし)、幅は面積が最小になる 2 の冪を選びます。
行ストライドが 2 の冪になるので、RP2040 / RP2350 では全パーツが SHAPOGFX2D_RP2_INTERP の描画パスに乗ります。
余白の削減
回転・拡大した drawImage() は矩形の内側を 1 ピクセルずつ歩くので、透明な余白にも走査と α 判定のコストが
かかります (x86-64 で透明 1 ピクセルあたり約 25 命令。不透明は約 50)。詰めるためにアトラスに入れる前の
各画像に次の処理をします。
トリミング (常に): 不透明なピクセル (
argb4444では α ≥ 9、キーカラー出力では--alpha-threshold以上) を囲む矩形で切り出し、ずれはAttachment::localに畳み込みます。回転 (
--fit-rotate): 不透明ピクセルの凸包の、面積最小の外接矩形を求め (回転キャリパー法)、 それが水平になる角度に画像を回して余白を落とします。縮小と回転を 1 回のアフィン変換 (bicubic、乗算済み α) で元画像から再サンプリングし、bicubic のリンギングで縁から 1 ピクセルより外に出た薄いピクセルは消します。 回転はlocalに畳み込むので、ボーンやアニメーションのデータは変わらず、見た目の位置も変わりません。 面積の削減が--fit-min-gainに満たない画像はぼけるだけなので回しません。凸包 (
--hull): 残った画像の不透明ピクセルの凸包を、隣り合う辺の交点で辺を置き換える (増える面積が 最小のものから) 方法でN頂点以下に単純化し、重心から外向きに整数に丸め、全ての不透明ピクセルを含むことを 確かめてからhull_<画像名>として出力します (矩形の 98% 以上を占めるものは出しません)。Instance::draw()はdrawImage()にこの多角形を渡し、その内側だけを走査します。
demorig の rgb_chan では、凸包で 320x240 のフレームが 5.5% (640x360 で 8.6%、2 倍ズームで 10%) 軽くなり、
--fit-rotate でアトラスが 338 KB から 296 KB に減ります。効果は画像の形によります。
ヘッダ先頭のコメントに、削減後のピクセル数、回した画像の数、凸包の数と面積を書き出します。
出力の構成
名前 |
内容 |
|---|---|
|
アトラスのピクセル配列と |
|
スロットのアタッチメント配列 |
|
ボーン、スロット、 |
|
|
|
|
|
全アニメーションへのポインタ配列とその数 |
識別子にできない名前は _ に置き換え、重複には番号を付けます。先頭のコメントに入力ファイル、縮尺、出力形式、
アトラスの大きさ、概算バイト数、警告の一覧が入ります。
対応していない機能
メッシュ・FFD、IK、入れ子のアーマチュア、イベント、スロットの RGB の色変換、追加の回転数
(clockwise / tweenRotate)、回転や拡大を継承しないボーン、複数のスキンは警告して無視します。
メッシュなど画像以外の display は、添字がずれないよう「描かないアタッチメント」として残します。
性能のためのオプションの選び方
描画コストはほぼ「歩いたピクセル数 × ピクセルの種類ごとの単価」で決まり (x86-64 で透明 25、不透明 50、 半透明 70 命令程度)、それに加えてパーツをフラッシュから読むキャッシュミスがかかります。 数字は demorig の rgb_chan (縮尺 0.8、29 ボーン 41 スロット) の 320x240 のフレームでの実測です。
まず、テクスチャがキャッシュに収まるかどうかを見てください。パーツはフレームごとに 1 回ずつ読まれるので、
全パーツの合計がフラッシュの手前のキャッシュより大きいと、毎フレーム全てをフラッシュから読み直すことになり、
命令数の削減と同じくらい効きます。M5Stack Tab5 (ESP32-P4、L2 256 KB) では、アトラスの行が触れる 321 KB では
30 fps、画像ごとのテクスチャで 216 KB になると 42 fps でした。CoreS3 (ESP32-S3、64 KB) にはどちらも収まらず
変化なしです。合計を減らす手段は --scale (面積に比例)、--fit-rotate (余白)、--atlas-width 0
(行の余白) で、目安はヘッダ先頭のコメントの「pixels」× 2 バイトです。
オプション |
効くところ |
効きやすい状況 |
代償 |
|---|---|---|---|
|
透明なピクセルの走査を省く。フレーム −5.5% (640x360 で −9%、2 倍ズームで −10%) |
パーツの形が矩形から遠いほど (手足、髪、斜めのもの)。矩形のパーツには付かないので損はしない |
アタッチメント 1 つあたり 4 バイト × 頂点数と、パーツ 1 枚につき行ごとの積和が数十命令 |
|
余白を落としてアトラスを縮める (338 KB → 296 KB)。時間は |
細長いパーツが斜めに描かれている絵。フラッシュやキャッシュに収めたいとき |
回したパーツは 1 回再サンプリングされてわずかにぼける。元の解像度が低いと目立つので、アセットを表示の 2 倍で描いて |
|
行の余白がなくなり、フレームあたりのキャッシュラインが 3 分の 1 減る (64 バイト 5133 → 3464 ライン)。ヘッダも小さい (296 KB → 227 KB) |
パーツがフラッシュにあり、詰めた合計がキャッシュに収まるとき。M5Stack Tab5 (L2 256 KB) では 30 → 42 fps、CoreS3 (64 KB、どちらも収まらない) では変化なし |
RP2040 / RP2350 では |
|
縁以外に半透明のないパーツをキーカラーにする。不透明なピクセルがブレンドでなくコピーになり、フレーム −30% (3.90M → 2.73M 命令、640x360 で −35%)。実機では CoreS3 24 → 27 fps、Tab5 42 → 56 fps |
速度が最優先で、縁のギザギザを許せるとき。半透明のパーツ (rgb_chan の tie や bracelet) は ARGB4444 のまま残る |
キーカラーになったパーツは縁のアンチエイリアスが消える (α が |
|
全パーツをキーカラーに。フレーム −33% |
半透明のパーツがない絵、速度が最優先のとき |
半透明のパーツが表現できない |
|
フラッシュとキャッシュの使用量 (面積に比例)。描画時間は画面上のピクセル数で決まるので、ほぼ変わらない |
キャラクタを画面に等倍で出す縮尺に合わせる。キャッシュに収めるために少し小さくするのも手 |
ズームインしたときに粗くなる |
組み合わせの目安:
ESP32-S3 / ESP32-P4:
--fit-rotate --atlas-width 0。速さが画質に優先するなら--out-format autoも。RP2040 / RP2350: アトラス (既定) のまま
--fit-rotate。interpolator の経路を保つ。キャッシュのないマイコンや RAM に置ける小さなキャラクタ: 並べ方は速度に影響しない。
並べ方 (描画順に沿って並べる、縦に積むなど) は効きません。キャッシュは 64 バイト単位でしか読まず、 1 フレームに全パーツを 1 回ずつ読むので、パーツ同士の位置関係より、行の端で余計に読むバイト数と合計が キャッシュに収まるかどうかで決まります。
ワークフローの例
demorig のキャラクタは次のコマンドで作られています (make -C example/wasm/demorig model)。
bin/dbones2cpp --scale 0.4 --fit-rotate assets/2d/rgb_chan/rgb_chan_ske.json \
assets/2d/rgb_chan/Armature_animtion0.dbani example/common/demorig/model/rgb_chan.hpp
bin/dbones2cpp --scale 0.4 --fit-rotate --atlas-width 0 assets/2d/rgb_chan/rgb_chan_ske.json \
assets/2d/rgb_chan/Armature_animtion0.dbani example/common/demorig/model/rgb_chan_sep.hpp # M5Stack 版
アセットは表示の 2 倍の解像度で描かれており、--scale 0.4 で 480x320 の画面の大きさになります。
--fit-rotate の再サンプリングが細かい元絵からになるので、回したパーツのぼけが目立ちません。
変換結果は --preview の PNG で確認できます。プレビューは変換後のデータ (量子化した角度・倍率・カーブ) から
描くので、実機の姿勢と一致します。