2014年6月2日月曜日

Assimp + Emscripten on Smart Phone without dlopen

AssimpをふつうにEmscripten-1.16.0でビルドした libassimp.so をリンクすればEmscriptenでビルドする任意のアプリケーションでAssimpを凡そ問題無く使えます。でも、これでは対応を諦めかけていたのがスマートフォンプラットフォームのウェブブラウザーたち。

Assimpフルビルド版の.soをリンクすると、例えばWonderland.Rendererのexample-1は24MBの.jsになります。どうやらこの.jsのファイルサイズが問題のようで、AndroidのChrome-35もFirefox-29も、巨大な.jsのロード中に動作停止、Fxに至ってはOSを巻き込んで固まりました…。

そこで、Wonderland.Rendererでは将来的にAssimpを切り離し、必要最小限の3Dモデルのローダーを開発するつもりでいました。当面、ウェブブラウザー版でのスマフォ対応は棚上げの予定としていました。

ところが、動いちゃいました(╹◡╹)


こちらのコメントのやりとりでヒントを頂けました。ありがとうございます(╹◡╹)

Assimpが対応する今回関連するプリプロセッサーの一覧は、最新版リポジトリー(最近Ogre対応が強化されたりしています)のmaster(84eb1930ea78056def5f91a0c2ff94f66694ed18)にて、
ack "#ifndef ASSIMP_BUILD_NO" code/ImporterRegistry.cpp
とかすると、

#ifndef ASSIMP_BUILD_NO_X_IMPORTER
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER

のように得られます。`ack`なにそれ美味しいのという方は`grep`より美味しいのでこの機会にぜひどうぞ(╹◡╹)

そんなわけで、
ack '#ifndef ASSIMP_BUILD_NO' code/ImporterRegistry.cpp | sed -E 's/^#ifndef (.+)/-D\1 /g' | tr -d '\n'
とかすると、
-DASSIMP_BUILD_NO_X_IMPORTER -DASSIMP_BUILD_NO_3DS_IMPORTER -DASSIMP_BUILD_NO_MD3_IMPORTER -DASSIMP_BUILD_NO_MDL_IMPORTER -DASSIMP_BUILD_NO_MD2_IMPORTER -DASSIMP_BUILD_NO_PLY_IMPORTER -DASSIMP_BUILD_NO_ASE_IMPORTER -DASSIMP_BUILD_NO_OBJ_IMPORTER -DASSIMP_BUILD_NO_HMP_IMPORTER -DASSIMP_BUILD_NO_SMD_IMPORTER -DASSIMP_BUILD_NO_MDC_IMPORTER -DASSIMP_BUILD_NO_MD5_IMPORTER -DASSIMP_BUILD_NO_STL_IMPORTER -DASSIMP_BUILD_NO_LWO_IMPORTER -DASSIMP_BUILD_NO_DXF_IMPORTER -DASSIMP_BUILD_NO_NFF_IMPORTER -DASSIMP_BUILD_NO_RAW_IMPORTER -DASSIMP_BUILD_NO_OFF_IMPORTER -DASSIMP_BUILD_NO_AC_IMPORTER -DASSIMP_BUILD_NO_BVH_IMPORTER -DASSIMP_BUILD_NO_IRRMESH_IMPORTER -DASSIMP_BUILD_NO_IRR_IMPORTER -DASSIMP_BUILD_NO_Q3D_IMPORTER -DASSIMP_BUILD_NO_B3D_IMPORTER -DASSIMP_BUILD_NO_COLLADA_IMPORTER -DASSIMP_BUILD_NO_TERRAGEN_IMPORTER -DASSIMP_BUILD_NO_CSM_IMPORTER -DASSIMP_BUILD_NO_3D_IMPORTER -DASSIMP_BUILD_NO_LWS_IMPORTER -DASSIMP_BUILD_NO_OGRE_IMPORTER -DASSIMP_BUILD_NO_MS3D_IMPORTER -DASSIMP_BUILD_NO_COB_IMPORTER -DASSIMP_BUILD_NO_BLEND_IMPORTER -DASSIMP_BUILD_NO_Q3BSP_IMPORTER -DASSIMP_BUILD_NO_NDO_IMPORTER -DASSIMP_BUILD_NO_IFC_IMPORTER -DASSIMP_BUILD_NO_XGL_IMPORTER -DASSIMP_BUILD_NO_FBX_IMPORTER
とりあえず全てのインポーターを無効化するコンパイルオプションが得られます。(この記事の表示上は自動的に改行が入ると思いますが、実際には改行は除去されて出力されます。)

ここから必要なものだけを除外したオプションを cmake に -DCMAKE_CXX_FLAGS= で渡すなりすれば必要最小限のインポーターだけを含めてビルドできます(╹◡╹)

ただ、どうやらAssimpのインポーターは相互に依存性を持ったものもあるようなので、ビルドが通らなくなった場合には依存していそうなインポーターも除外対象から除外する必要があります。

また、Assimp-3.1現在、.Xのみを含めてビルドしたlibassimp.soを用いると、

warning: unresolved symbol: inflateInit2_
warning: unresolved symbol: ConvertUTF16toUTF8
warning: unresolved symbol: inflateEnd
warning: unresolved symbol: inflateReset
warning: unresolved symbol: inflate
warning: unresolved symbol: inflateSetDictionary
warning: unresolved symbol: ConvertUTF32toUTF8

こんな具合にem++がリンク時に警告してきます。実際問題として.xを扱うだけであればこれらのリンク時の警告は無視しても動作はするようなので、これらの使われどころのチェック等はしていません。何か気付けば追記しようと思います。

.Xに機能限定したAssimpをリンクする事で、em++が生成する.jsが24MB→4.2MBまで削減できました。dlopen機能を使っても.jsのサイズが20MBもあってはスマフォのブラウザーでは無理だろうと諦めていたので、そのまま出力した.jsで5MBを切り、実際にスマフォのFirefox-29では動作確認もできた事は嬉しいです(╹◡╹)

…AndroidのChrome-35のデフォルト状態ではcanvas/webglコンテキストをサポートしていないみたいで、これはたぶんflagsをいじらないと動かないとかそういう状態なのは少々残念だったけど。

0 件のコメント:

コメントを投稿