昔は CG を扱おうとすると大変でした。
(一度C++で OpenGLとか書いたことあるけど、意味不明のキワミ)
でも今は WebGL が標準化してきたので、"行列計算" とか "法線" とか良く分からないことしなくても、ブラウザさえあれば3D表現が簡単になってきてます。
あと three.js とかのライブラリも沢山あって開発もしやすいです。
自分もWebGLを使ったアプリが作ってみたいので、
Android環境で WebView + WebGL(three.js) を動かしてみました。
このページの目次
手始めにWebViewに three.js(WebGL)で赤球を表示してみた
まずは3DCG入門とかでよく見る、球体を表示してみることに・・・
▼ 主な手順
- WebGLを動かすHTMLファイル作成
- アセットにそのHTMLファイル埋め込み
- WebViewから球体を表示
Android Studio の場合、次の手順で表示できました。
1.まず three.js で球を表示するHTMLファイルを作成
初めに three.js で球体を表示するHTML作成
自分は three.js に詳しくないから、次ページを元に作成させてもらいました。
ここを参考に、球体をキャンバス表示するHTMLを書いてみます。
実際に作ったのは app.html という名前の次のHTMLです。
▼ その three.js を含むHTMLは次の通り
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"/> <script src="three.min.js"></script> </head> <body> <!-- ここにレンダリング --> <canvas id="appCanvas"></canvas> <script type="text/javascript"> window.addEventListener('load', init); // サイズを指定 const width = window.innerWidth; const height = window.innerHeight; function init() { // レンダラーを作成 const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('#appCanvas') }); renderer.setSize(width, height); // シーンを作成 const scene = new THREE.Scene(); // カメラを作成 const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000); camera.position.set(0, 0, +1500); // 赤い球体を作成 const geometry = new THREE.SphereGeometry(300, 20, 20); const material = new THREE.MeshStandardMaterial({color: 0xFF0000}); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // 平行光源 const directionalLight = new THREE.DirectionalLight(0xFFFFFF); directionalLight.position.set(0, 0, 1); scene.add(directionalLight); tick(); // 毎フレーム時に実行 function tick() { // メッシュを回転させる mesh.rotation.y += 0.01; // レンダリング renderer.render(scene, camera); requestAnimationFrame(tick); } } </script> </body> </html> |
まず一意なID(ここでは #appCanvas )を持つcanvas要素を作成
そこにシーン・カメラを用意し、レンダリングしていくのが three.js の基本的な書き方です。
2.assetsディレクトリにHTML・JSファイルを追加
こっからがAndroidアプリ開発で重要な部分
次は assets ディレクトリを作り、HTMLリソースを追加します。
Android Studio の場合、assets は次の操作で作れます。
- 左クリックし「New」=>「Folder」を選択
- その中で「Assets Folder」をクリック
- assetsという名前のディレクトリが作られる
そして assetsフォルダを作成したら、その中に次の2つを貼り付け
- app.html(さっき作ったやつ)
- three.min.js(公式からDL)
ちなみに three.min.js についてはCDN経由で埋め込むことも可能です。
3.WebViewからWebGLを呼び出す
最後に WebView を含む適当なActivityを作成
その中で WebView からassetsに配置した app.html を呼び出せばいいだけです。
▼ 例えば自分が書いたコードはこういう感じ(Java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class MainActivity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById( R.id.web_view ); /// Init WebView settings. WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled( true ); /// 球体表示するHTMLファイルを読み込み webView.loadUrl( "file:///android_asset/app.html" ); } } |
ここで大事なポイントは次の2つ
- 必ずJavaScriptを有効にする
このコードの settings.setJavaScriptEnabled( true ); の部分。これを有効にしておかないと three.js も何も動かない
- HTMLファイルをassetsから読み込み
この読み込みは "file:///android_asset/app.html" のようにしてassetsディレクトリ以下のファイルを参照することが可能(もちろんディレクトリも参照できる)
以上でシンプルだけど。、WebGLが動かせるアプリの完成
実際にできあがったアプリはこんな感じです。
なんかシュールだけど、一応表示できたということで、、、
あと画像だと分からないですが、実際のアプリだと球体が回転して表示されてます。
お次はテクスチャ付きの球体(木星)を表示してみた
何か楽しくなってきたので、色々試してみます。
次は マテリアル付きで球体 を表示してみることにしました。
ただthree.js について全くの素人なので、今度も次のページを参考にさせてもらってます。
このサイトだと月のマテリアル画像を用意しておき、それを球体にマテリアルとして貼り付けて月を表示してるみたいです。
でも同じだと面白くなから、
ここでは次みたいな 木星のマテリアル画像 をDL
URL : http://planetpixelemporium.com/jupiter.html
そして球体の表面にこのマテリアル画像を貼り付けるコードを書いてみました。
▼ そのコードがコチラ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"/> <script src="three.min.js"></script> </head> <body> <!-- ここにレンダリング --> <canvas id="appCanvas"></canvas> <script type="text/javascript"> // ページの読み込みを待つ window.addEventListener('load', init); // サイズを指定 const width = window.innerWidth; const height = window.innerHeight; function init() { // レンダラーを作成 const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('#appCanvas') }); renderer.setSize(width, height); // シーンを作成 const scene = new THREE.Scene(); // カメラを作成 const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000); camera.position.set(0, 0, +1500); // 木星テクスチャの球体を作成 const geometry = new THREE.SphereGeometry(300, 20, 20); const loader = new THREE.TextureLoader(); const texture = loader.load('jupitermap.jpg'); const material = new THREE.MeshStandardMaterial({ map: texture }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // 平行光源 const directionalLight = new THREE.DirectionalLight(0xFFFFFF); directionalLight.position.set(0, 0, 1); scene.add(directionalLight); tick(); // 毎フレーム時に実行されるループイベントです function tick() { // メッシュを回転させる mesh.rotation.y += 0.01; // レンダリング renderer.render(scene, camera); requestAnimationFrame(tick); } } </script> </body> </html> |
マテリアルの貼り方とは詳しく解説されてるページがあるので省きます。
そしてさっきと同じ方法でWebViewから表示してみました。
すると・・・
アレ?木星が表示されるはずなのに・・・
なぜか真っ黒になってしまってます。
画像の読み込みはWebViewで設定が必要だった
どうやら file: で始まる画像はそのままだと読み込めないみたいでした。
そこで色々調べてみると、WebViewに次の設定が必要だったこと が判明
1 2 3 4 5 |
webView = findViewById( R.id.web_view_tool ); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled( true ); settings.setAllowFileAccessFromFileURLs(true); settings.setAllowUniversalAccessFromFileURLs(true); |
これで http や https 以外のローカルなファイル( 例 : file:/// から始まるもの)でも問題なく読み込めるようになったはずです。
これで動くはずだけど、果たして結果は・・・
▼ 実際に表示されたアプリ画面は次の通り
画像だと止まったままだけど、実際は ☯ぐるぐるぐるぐる☯ 回ってます。
書いたのはたった数十行のHTMLファイルと数十行のJavaコードだけ。
それでもここまで簡単に表示できるのが感動しました。
最後に。WebGL(three.js)は開発工程を大幅に減らせそう
もし手軽にCGを扱いたいなら・・・three.jsは重宝すること間違いなしです。
ちなみに自分自身も three.jsを使ってアプリ開発 に取り組んでます。
▼ コチラの記事で紹介したボクセルアート投稿アプリ
現在オープンベータ版。
Androidをお持ちの方は是非どうぞ。フィードバック募集中です。
蛇足でしたが Androidでの three.js の動かし方でした。ではまた (^_^)/~