O3Dとは
Google O3D はブラウザ上で3Dアニメーションを可能とするプラグインでIE、Firefox、Google Chrome といったブラウザで動作します。リアルタイムに操作可能な3DアニメーションのプログラムをJavaScriptを使って記述します。処理に時間のかかる部分はプラグイン側が担当しているため、JavaScript でも秒間60フレームの高速なアニメーションが可能です。
実際に描画する部分はバーテックスシェーダ、ピクセルシェーダのコードが行います。 例えばHTMLの <textarea> にシェーダコードをテキストで埋め込んだり、テキストファイルを別に置いて読み込んで使うこともできます。
HTML、JavaScript、シェーダコードもすべてテキストファイルなので、エディタさえあればブラウザ上で3Dアニメーションを動作させることができます。ただし、O3D自体は低レベルな機能を提供するだけであるため、柔軟性が高いものの簡単に3Dのプログラムが作成できるわけではありません。O3Dプログラミングに関するドキュメントはhttps://code.google.com/intl/ja/apis/o3d/docs/techoverview.htmlに英語で大量にありますが、あまり分かりやすいものではありません。 https://code.google.com/p/o3d/downloads/listから sample.zip (約40MB) をダウンロードしてサンプルコードとドキュメントを見比べて下さい。そのうち入門用の解説を書くかもしれません。
JavaScript で直接 OpenGL のコードを記述する WebGL と競合する技術ですが、頂点情報をバイナリデータで持てたり、tar.gz で圧縮したデータを扱えたりと複雑なモデルも使用できるため、速度や実用性ではO3Dの方がかなり有利であると思います。
Linux用O3Dプラグイン
O3DプラグインのWindows版とMac版は https://code.google.com/intl/ja/apis/o3d/からダウンロードすれば自動的にインストールされますが、Linuxで使うためには、Subversionでソースを入手し、Googleの専用ツール(depot-tools)を使ってコンパイルする必要があります。
今回、32bitのUbuntu 9.10をクリーンインストールした環境で O3Dをビルドしてみました。
名前空間関連の問題でコンパイルエラーが発生しました。適当にソースを変更(fopenやsetenvなどの関数にグローバル名前空間を指定し、対応するヘッダファイルをインクルード)するとビルドに成功し、動作確認できました。
Windows版とMac版はすでに安定していますが、Linux版は実験段階のようです。 また、すべての機能が実装されているわけではありません。 このページの内容を試すのは自己責任でお願いします。
実行例
https://o3d.googlecode.com/svn/trunk/samples/animated-scene.html
ビルドの準備
Google Code の HowToBuild - o3d - How to get the source and build. を参考に行いました。
パッケージの追加
Ubuntu 9.10(32bit) で O3D をビルドするためには、以下のパッケージをapt-get で導入する必要があります。
apt-get install subversion apt-get install libgtk2.0-dev apt-get install g++-multilib apt-get install libnss3-dev apt-get install libgconf2-dev apt-get install libgl1-mesa-dev apt-get install libglib2.0-dev apt-get install libglu1-mesa-dev apt-get install libglew1.5 apt-get install libx11-dev apt-get install libxt-dev apt-get install sun-java6-jre
パッケージ一覧
導入された開発系のパッケージを見てみます。
root@ubuntu910-32:~/o3d# dpkg-query --show '*-dev' amd64-libs-dev c++abi2-dev cli-common-dev dpkg-dev 1.15.4ubuntu2 dvb-dev erlang-dev freetype0-dev freetype1-dev ivtools-dev lib64c-dev libapt-pkg-dev libasprintf-dev libatk-dev libatk0-dev libatk1.0-dev 1.28.0-0ubuntu1 libatspi-dev libboost-python-dev libboost-python1.35-dev libbrlapi-dev libbrlapi1-dev libc-dev libc0.1-dev libc0.3-dev libc6-dev 2.10.1-0ubuntu15 libc6.1-dev libcairo-dev libcairo-directfb2-dev libcairo0.5.1-dev libcairo0.6.0-dev libcairo0.9.0-dev libcairo2-dev 1.8.8-2ubuntu1 libcwidget-dev libdbus-1-dev 1.2.16-0ubuntu9 libdirectfb-dev 1.2.7-2ubuntu1 libdrm-dev libenchant-dev libexpat-dev libexpat1-dev 2.0.1-4ubuntu1 libfontconfig-dev libfontconfig1-dev 2.6.0-1ubuntu12 libfreetype6-dev 2.3.9-5 libg++2.8-dev libg++27-dev libg++272-dev libgconf2-dev 2.28.0-0ubuntu2 libgettextpo-dev libgl-dev libgl1-mesa-dev 7.6.0-1ubuntu4 libgl1-mesa-dri-dev libgl1-mesa-swx11-dev libglib1.3-dev libglib2.0-dev 2.22.2-0ubuntu1 libglu-dev libglu1-mesa-dev 7.6.0-1ubuntu4 libgnome-pilot0-dev libgsm-dev libgtk2.0-dev 2.18.3-1 libgtksourceview2.0-dev libice-dev 2:1.0.5-1 libidl-dev 0.8.13-0.1 libidn11-dev libidn9-dev libjpeg-dev libjpeg62-dev 6b-14build1 liblinc-dev libmng-dev libmotif-dev libmozjs-dev libmudflap0-4.4-dev libnautilus2-dev libnspr-dev libnspr4-dev 4.8-0ubuntu1 libnss3-dev 3.12.3.1-0ubuntu2 liborbit2-dev 1:2.14.17-0.1 libpam0g-dev libpango-dev libpango1.0-dev 1.26.0-1 libparted1.8-dev libpcap0.8-dev libpcre3-dev libpcsclite-dev libpixman-1-dev 0.14.0-1 libpixman1-dev libpng-dev libpng12-0-dev libpng12-dev 1.2.37-1 libpng2-dev libpng3-dev libpopt-dev libproc-dev libpthread-stubs0-dev 0.1-2 libsm-dev 2:1.1.0-2 libsnmp-dev libsnmp5-dev libsnmp9-dev libssl096-dev libstdc++-dev libstdc++2.10-dev libstdc++2.8-dev libstdc++2.9-dev libstdc++2.9-glibc2.1-dev libstdc++3.0-dev libstdc++6-4.4-dev 4.4.1-4ubuntu8 libsysfs-dev 2.1.0-5 libx11-dev 2:1.2.2-1ubuntu1 libxau-dev 1:1.0.4-2 libxcb-render-util0-dev 0.3.6-1 libxcb-render0-dev 1.4-1 libxcb0-dev libxcb1-dev 1.4-1 libxcomposite-dev 1:0.4.0-4 libxcursor-dev 1:1.1.9-1build1 libxdamage-dev 1:1.1.1-4 libxdmcp-dev 1:1.0.2-3 libxext-dev 2:1.0.99.1-0ubuntu4 libxfixes-dev 1:4.0.3-2build1 libxft-dev 2.1.13-3ubuntu1 libxft2-dev libxi-dev 2:1.2.1-2ubuntu1 libxinerama-dev 2:1.0.3-2 libxkbfile-dev libxrandr-dev 2:1.3.0-2 libxrender-dev 1:0.9.4-2ubuntu1 libxt-dev 1:1.0.5-3ubuntu1 libxtst-dev libxul-dev libz-dev linux-libc-dev 2.6.31-14.48 manpages-dev mesa-common-dev 7.6.0-1ubuntu4 mesa-glide2-dev mesag-dev mesag3+ggi-dev nvu-dev openoffice.org-dev python-gst0.10-dev render-dev x-dev x11proto-composite-dev 1:0.4-2 x11proto-core-dev 7.0.15-1 x11proto-damage-dev 1:1.1.0-2build1 x11proto-fixes-dev 1:4.0-3 x11proto-input-dev 1.5.0-2ubuntu1 x11proto-kb-dev 1.0.3-3ubuntu1 x11proto-panoramix-dev x11proto-randr-dev 1.3.0-1 x11proto-render-dev 2:0.9.3-2 x11proto-xext-dev 7.0.4-2 x11proto-xinerama-dev 1.1.2-5ubuntu1 xlibmesa-dev xlibmesa-gl-dev xlibmesa-glu-dev xlibosmesa-dev xlibs-dev xtrans-dev 1.2.4-1 xviewg-dev zlib1-dev zlib1g-dev 1:1.2.3.3.dfsg-13ubuntu3
作業用のディレクトリの用意
今回は以下のように /home/jun/o3d で作業します。
cd mkdir o3d cd o3d
depot-toolsのインストール
最初に Subversionで Googleのビルドツール(depot-tools)を入手します。スクリプトなので特にコンパイルする必要はありません。
svn co https://src.chromium.org/svn/trunk/tools/depot_tools
depot_toolsでインストールされたファイルの一覧です。gclient と hammer を使います。
jun@ubuntu910-32:~/o3d$ ls depot_tools/ LICENSE drover git-try PRESUBMIT.py drover.bat git_cl_hooks.py README drover.py hammer README.gclient gcl hammer.bat README.git-cl gcl.bat presubmit_canned_checks.py README.git-cl.codereview gcl.py presubmit_support.py WATCHLISTS gclient profile.xml bootstrap gclient.bat revert chrome-update-create-task.bat gclient.py revert.bat chrome-update.bat gclient_scm.py revert.py chrome-update.py gclient_utils.py tests cpplint.bat git-cl trychange.py cpplint.py git-cl-upload-hook upload.py create-chromium-git-src git-gs watchlists.py
コマンド検索パスの追加
depot_toolsの gclient と hammer を使うために検索パスに depot_tools のディレクトリを追加します。
export PATH=$PATH:/home/jun/o3d/depot_tools
o3dのソースの取得
depot_tools の gclient コマンドで o3d のソースを取得します。
gclient config https://src.chromium.org/svn/trunk/src/o3d gclient.py sync
しばらく時間がかかりますが、ソースを取得したら /home/o3d/o3d/build に移動します。
cd o3d/build
ビルド
o3d のビルドはdepot_tools の hammer コマンドを以下のように使います。10分程度でビルドは終了します。
hammer -f o3d_main.scons
ソースの修正
以下の記述は11/17に修正されたため不要です。
2009/11/08時点のソースをLinuxでコンパイルすると、名前空間関連でコンパイルエラーが発生しました。以下に示すようにソースを変更(fopenやsetenvなどの関数にグローバル名前空間を指定し、対応するヘッダファイルをインクルード)する必要がありました。先頭の数字は行番号です。
~/o3d/o3d/import/cross/archive_processor.cc を以下のように修正します。
ヘッダファイルの追加
32 #include <sys/stat.h> 33 #include <stdio.h> 34 35 #include "import/cross/archive_processor.h"
グローバル名前空間を指定
76 FILE *fp = ::fopen(filename, "rb"); 77 if (!fp) return FAILURE; // can't open file! 78 ::fread(p, sizeof(uint8), file_length, fp); 79 ::fclose(fp);
~/o3d/o3d/plugin/linux/envvars.cc を以下のように修正します。
ヘッダファイルの追加
32 #include <stdio.h> 33 #include <string.h> 34 #include <stdlib.h> 35 36 #include "plugin/linux/envvars.h"
グローバル名前空間を指定
63 if (::setenv(buffer, value, 1) != 0) { 64 LOG(ERROR) << "Couldn't add " << buffer << "=" << value 65 << " to environment"; 66 } else { 67 // Custom environment variables could be relevant for debugging 68 // problem reports, so log this too. 69 LOG(INFO) << "Defined " << buffer << "=" << value; 70 }
~/o3d/o3d/import/cross/file_output_stream_processor.cc を以下のように修正します。
ヘッダファイルの追加
34 35 #include <stdio.h> 36 #include "base/logging.h" 37 #include "import/cross/file_output_stream_processor.h"
グローバル名前空間を指定
45 StreamProcessor::Status FileOutputStreamProcessor::ProcessBytes( 46 MemoryReadStream *stream, 47 size_t bytes_to_process) { 48 DCHECK(file_ != NULL); 49 size_t num_written = ::fwrite(stream->GetDirectMemoryPointer(), 50 1, 51 bytes_to_process, 52 file_); 53 return num_written == bytes_to_process ? IN_PROGRESS : FAILURE; 54 } 55 56 void FileOutputStreamProcessor::Close(bool success) { 57 ::fclose(file_); 58 file_ = NULL; 59 }
~/o3d/o3d/import/cross/collada_conditioner.cc を以下のように修正します。
括弧を追加する必要がありました。
135 const PassDeclaration& pass = i->pass[0]; 136 if ((pass.vertex_shader_profile == "vs_2_0" && 137 pass.fragment_shader_profile == "ps_2_0") || 138 (pass.vertex_shader_profile == "arbvp1" && 139 pass.fragment_shader_profile == "arbfp1")) { 140 return &pass; 141 }
ビルドの結果
ビルドが終了すると /home/jun/o3d/sconsbuild/Debug に以下のようにファイルが格納されます。libnpo3dautoplugin.so が O3Dプラグインの本体、libCg.so と libCgGL.so がシェーダコンパイラになります。libnpo3dautoplugin.so は非常に大きいですが strip すると 9MB 程度になります。
jun@ubuntu910-32:~/o3d/sconsbuild/Debug$ ls -l 合計 160016 drwxr-xr-x 2 jun jun 4096 2009-11-08 14:43 archive_files drwxr-xr-x 2 jun jun 4096 2009-11-08 14:43 bitmap_test -rwxr-xr-x 1 jun jun 5392284 2009-11-08 14:13 cgc drwxr-xr-x 2 jun jun 4096 2009-11-08 14:42 lib -rw-r--r-- 1 jun jun 7912580 2009-11-08 14:13 libCg.so -rw-r--r-- 1 jun jun 335124 2009-11-08 14:13 libCgGL.so -rwxr-xr-x 1 jun jun 57653039 2009-11-08 14:34 libnpo3dautoplugin.so -rw-r--r-- 1 jun jun 0 2009-11-08 14:32 linker.lock -rwxr-xr-x 1 jun jun 20998008 2009-11-08 14:32 mksnapshot -rwxr-xr-x 1 jun jun 34387603 2009-11-08 14:42 o3dConverter drwxr-xr-x 28 jun jun 4096 2009-11-08 14:42 obj -rwxr-xr-x 1 jun jun 2575102 2009-11-08 14:15 perceptualdiff drwxr-xr-x 13 jun jun 4096 2009-11-08 14:43 samples drwxr-xr-x 3 jun jun 4096 2009-11-08 14:21 tests -rwxr-xr-x 1 jun jun 34359967 2009-11-08 14:43 unit_tests drwxr-xr-x 2 jun jun 4096 2009-11-08 14:42 unittest_data
libnpo3dautoplugin.so、libCg.so、libCgGL.so がダイナミックリンクしているライブラリを確認しておきます。
jun@ubuntu910-32:~/o3d/sconsbuild/Debug$ ldd libCg.so linux-gate.so.1 => (0xb77d6000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb6ef0000) /lib/ld-linux.so.2 (0xb77d7000) jun@ubuntu910-32:~/o3d/sconsbuild/Debug$ ldd libCgGL.so linux-gate.so.1 => (0xb7753000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb75a9000) /lib/ld-linux.so.2 (0xb7754000) libCg.so => /usr/lib/libCg.so (0xb6e1a000) jun@ubuntu910-32:~/o3d/sconsbuild/Debug$ ldd libnpo3dautoplugin.so linux-gate.so.1 => (0xb77ab000) libCg.so => /usr/lib/libCg.so (0xb673a000) libCgGL.so => /usr/lib/libCgGL.so (0xb66e7000) libGL.so.1 => /usr/lib/libGL.so.1 (0xb6655000) libGLEW.so.1.5 => /usr/lib/libGLEW.so.1.5 (0xb6612000) libX11.so.6 => /usr/lib/libX11.so.6 (0xb64e3000) librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb64da000) libgtk-x11-2.0.so.0 => /usr/lib/libgtk-x11-2.0.so.0 (0xb6119000) libgdk-x11-2.0.so.0 => /usr/lib/libgdk-x11-2.0.so.0 (0xb6084000) libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0 (0xb6066000) libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0xb603d000) libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0 (0xb6023000) libpangocairo-1.0.so.0 => /usr/lib/libpangocairo-1.0.so.0 (0xb6016000) libgio-2.0.so.0 => /usr/lib/libgio-2.0.so.0 (0xb5f80000) libcairo.so.2 => /usr/lib/libcairo.so.2 (0xb5ef8000) libpango-1.0.so.0 => /usr/lib/libpango-1.0.so.0 (0xb5eb0000) libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0xb5e31000) libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0xb5e04000) libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0xb5dc6000) libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0xb5dc0000) libgthread-2.0.so.0 => /usr/lib/libgthread-2.0.so.0 (0xb5dba000) libglib-2.0.so.0 => /lib/libglib-2.0.so.0 (0xb5d04000) libnss3.so => /usr/lib/libnss3.so (0xb5bda000) libnssutil3.so => /usr/lib/libnssutil3.so (0xb5bc0000) libsmime3.so => /usr/lib/libsmime3.so (0xb5b97000) libssl3.so => /usr/lib/libssl3.so (0xb5b62000) libplds4.so => /usr/lib/libplds4.so (0xb5b5d000) libplc4.so => /usr/lib/libplc4.so (0xb5b57000) libnspr4.so => /usr/lib/libnspr4.so (0xb5b1c000) libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb5b03000) libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb5aff000) libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb5ad8000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb59e6000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb59c8000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb5884000) /lib/ld-linux.so.2 (0xb77ac000) libXext.so.6 => /usr/lib/libXext.so.6 (0xb5874000) libXmu.so.6 => /usr/lib/libXmu.so.6 (0xb585a000) libXi.so.6 => /usr/lib/libXi.so.6 (0xb584f000) libGLU.so.1 => /usr/lib/libGLU.so.1 (0xb57df000) libxcb.so.1 => /usr/lib/libxcb.so.1 (0xb57c1000) libXcomposite.so.1 => /usr/lib/libXcomposite.so.1 (0xb57bd000) libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0xb57b9000) libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0xb57b3000) libXrender.so.1 => /usr/lib/libXrender.so.1 (0xb57a9000) libXinerama.so.1 => /usr/lib/libXinerama.so.1 (0xb57a6000) libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0xb579d000) libXcursor.so.1 => /usr/lib/libXcursor.so.1 (0xb5791000) libz.so.1 => /lib/libz.so.1 (0xb577b000) libpcre.so.3 => /lib/libpcre.so.3 (0xb574a000) libresolv.so.2 => /lib/tls/i686/cmov/libresolv.so.2 (0xb5736000) libselinux.so.1 => /lib/libselinux.so.1 (0xb571b000) libpixman-1.so.0 => /usr/lib/libpixman-1.so.0 (0xb56d3000) libdirectfb-1.2.so.0 => /usr/lib/libdirectfb-1.2.so.0 (0xb5659000) libfusion-1.2.so.0 => /usr/lib/libfusion-1.2.so.0 (0xb564f000) libdirect-1.2.so.0 => /usr/lib/libdirect-1.2.so.0 (0xb5637000) libpng12.so.0 => /usr/lib/libpng12.so.0 (0xb560f000) libxcb-render-util.so.0 => /usr/lib/libxcb-render-util.so.0 (0xb5609000) libxcb-render.so.0 => /usr/lib/libxcb-render.so.0 (0xb5600000) libexpat.so.1 => /lib/libexpat.so.1 (0xb55d9000) libXau.so.6 => /usr/lib/libXau.so.6 (0xb55d5000) libXt.so.6 => /usr/lib/libXt.so.6 (0xb5581000) libSM.so.6 => /usr/lib/libSM.so.6 (0xb5578000) libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0xb5573000) libICE.so.6 => /usr/lib/libICE.so.6 (0xb5558000) libuuid.so.1 => /lib/libuuid.so.1 (0xb5552000)
インストール
~/.mozilla/plugins/ に libnpo3dautoplugin.so をコピーします。~/.mozilla/ 以下に plugins ディレクトリが無い場合は作成してください。
cd ~/o3d/sconsbuild/Debug mkdir ~/.mozilla/plugins cp libnpo3dautoplugin.so ~/.mozilla/plugins/
私の場合は libCg.so と libCgGL.so を /usr/lib に直接コピーしました。
sudo cp libCg.so libCgGL.so /usr/lib sudo ldconfig
実行
Firefox を起動して URLに「about:plugins」を入力して、O3Dが有効になっているか確認します。
あとは Google O3D のサンプルを試してみてください。
https://code.google.com/intl/ja/apis/o3d/docs/samplesdirectory.html
Linux版はこれを書いている時点(2009/11/08)では3D画面に重ねてテキストを表示する機能が実装されていません。