Physi.jsとは
Three.jsを触り出して、少し経ったので物理シミュレーションをやってみたくなった。
少し調べてみたところ、Physi.jsというJavaScriptライブラリに行き着いたので、触ってみたメモ.
JavaScriptによる3次元物理シミュレーションのライブラリには、ammo.js(BulletのJavaScript実装)があるが、Physi.jsはこれを利用したThree.jsのプラグインである。
特徴的なのは、WebWorkers APIを利用して、ammo.jsによる演算は、rendererが動作するスレッドと分離されている点。
取りあえず動かしてみよう.
https://github.com/chandlerprall/Physijs/wiki/Basic-Setup に組み込み方が書いてあるので、この通りにやってみる.
-
http://chandlerprall.github.io/Physijs からを落としてきて、htmlに
<script src="physijs.js">
タグを記述(もちろんthree.jsも読み込む).
- ちなみにBowerを使っているのであれば、
bower install physijs --save
で簡単に入手できるが、ammo.jsの扱いに注意する必要あり(後述).
- WebWorkersの設定を行う。
Physijs.scripts.worker
及び、Physijs.scripts.ammo
にそれぞれphysijs_worker.jsとammo.jsのurlを指定する。
- なお、URLを相対パスで記述する場合、physijs_worker.jsは、htmlからの相対パスで構わないが、ammo.jsはphysijs_worker.jsが配置されているディレクトリからの相対パスで記載する点に注意(WebWorkers APIのimportScripts()メソッドの仕様です).
-
Three.scene
を使う代わりに、Physijs.scene
を利用して、Three.jsの空間を作成する. - MeshもThree.Meshを使う代わりに、Physijs.BoxMeshやPhysijs.SphereMesh, Physijs.ConvexMeshを使ってMeshを作成する.
- アニメーションの処理毎に
scene.simulate()
を実行することで、物理演算が実行される
ただ物体が落ちてきて床にぶつかるだけのサンプルのコードを後方に貼っておく.
実際、やってみるとすげぇ簡単。
http://javascript.g.hatena.ne.jp/edvakf/20111213/1323802428 等の記事で触れられているが、Physi.jsを使わずに生ammo.jsを利用することを考えるとかなり楽である.
付録
動かしたコード
'use strict';
(function(THREE, Physijs){
var initScene, render, renderer, scene, camera, box, light;
Physijs.scripts.worker = 'bower_components/physijs/physijs_worker.js';
Physijs.scripts.ammo = 'examples/js/ammo.js';
initScene = function() {
var ground, groundMaterial;
var width = window.innerWidth, height = window.innerHeight;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.shadowMapEnabled = true;
renderer.setSize(width, height);
document.getRootElementById('render_area').appendChild(renderer.domElement);
// !Three.Sceneでない点に注意!
scene = new Physijs.Scene();
// Camera
camera = new THREE.PerspectiveCamera( 35, width / height, 1, 1000);
camera.position.set( 60, 50, 60 );
camera.lookAt( scene.position );
scene.add( camera );
// Light
light = new THREE.SpotLight(0xffffff, 5, 1000, Math.PI / 2, 1);
light.position.set(0, 100, 80);
light.castShadow = true;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
scene.add(light);
// Box !Three.Meshでない点に注意!
box = new Physijs.BoxMesh(
new THREE.CubeGeometry( 5, 5, 5 ),
new THREE.MeshBasicMaterial({ color: 0xff8020 })
);
box.position.set(0, 20, 0);
box.castShadow = true;
scene.add( box );
// Ground
groundMaterial = Physijs.createMaterial(new THREE.MeshBasicMaterial({ color: 0xffffff }), 0.8, 0.3);
ground = new Physijs.BoxMesh(new THREE.CubeGeometry(100, 1, 100), groundMaterial, 0);
ground.receiveShadow = true;
scene.add(ground);
render();
};
render = function() {
scene.simulate();
control.update();
renderer.render(scene, camera);
window.requestAnimationFrame(render);
};
initScene();
})(THREE, Physijs);
<!doctype html>
<html>
<body>
<div id="rendering"></div>
<script src="bower_components/threejs/build/three.js"></script>
<script src="bower_components/physijs/physi.js"></script>
<script src="scripts/main.js"></script>
</body>
</html>
bower利用時の注意点
bowerでPhysi.jsを落とした場合、Physi.jsが依存するammo.jsパッケージもinstallされるが、このammo.jsを利用するとエラーとなるため、Physi.jsのExampleに同梱されていたものを利用している。
このissueにも上がっているが、2014/7/17時点ではopenのままであるので注意されたし。