Three.js + Cannon.js でゴゴゴとドドドを物理演算してみるテスト
以前、2D 物理演算でゴゴゴとドドドを落下させてみましたが、3D 物理演算でも試してみました。
JavaScript の 3D 物理演算ライブラリとして
あたりが有名なようです。
今回は、Cannon.js を使ってみました。
ゴゴゴとドドド
ゴゴゴのコード(抜粋)
基本形のオブジェクト(立方体や球体など)を使う場合と比較して、複数のオブジェクトをまとめて物理演算する場合は、多少ハードルが高い(複雑さが増す)のですが、Cannon.js には、その問題を解決する仕組みが用意されているようです。
Cannon.js の場合、CANNON.Compound() を使うことで、複合オブジェクトとして使えるようです。
demo.addScene("GOGOGO", function () { var world = setupWorld(demo); // 複合オブジェクトを作成する var compoundShape = new CANNON.Compound(); var s = 1.5; // 複合オブジェクトに各パーツを紐づける compoundShape.addChild(new CANNON.Box(new CANNON.Vec3(1.8, 0.3, 0.3)), new CANNON.Vec3(0.0, 1.5, 0.0)); compoundShape.addChild(new CANNON.Box(new CANNON.Vec3(0.3, 1.5, 0.3)), new CANNON.Vec3(1.5, 0.0, 0.0)); compoundShape.addChild(new CANNON.Box(new CANNON.Vec3(1.8, 0.3, 0.3)), new CANNON.Vec3(0.0,-1.5, 0.0)); compoundShape.addChild(new CANNON.Box(new CANNON.Vec3(0.2, 0.6, 0.3)), new CANNON.Vec3(2.0, 1.5, 0.0)); compoundShape.addChild(new CANNON.Box(new CANNON.Vec3(0.2, 0.6, 0.3)), new CANNON.Vec3(2.5, 1.5, 0.0)); // 複合オブジェクトの剛体を作成する var interval; var mass = 10; var size = 1; var bodies = []; var i = 0; interval = setInterval(function(){ i++; // 剛体を作成する var body = new CANNON.RigidBody(mass, compoundShape); // 表示位置 body.position.set(2 * size * Math.sin(i), 2 * size * Math.cos(i), 7 * 2 * size); // 角度調整 body.quaternion.set(0, 1, 1, 0.2); world.add(body); // 剛体に対応したシェイプを作成する demo.addVisual(body); // 剛体を配列にに追加する bodies.push(body); // 限度数を超えた場合古いオブジェクトを削除する if(bodies.length > 20){ var b = bodies.shift(); demo.removeVisual(b); world.remove(b); } },200); });
cannon.demo.js のソースを確認したところ「物理演算用の剛体」→「表示用のシェイプ」の変換は demo.addVisual() によって行われているようです。
/** * @class CANNON.Demo * @brief Demo framework class. If you want to learn how to connect Cannon.js with Three.js, please look at the examples/ instead. * @param Object options */ CANNON.Demo = function(options){ : function addVisual(body){ // What geometry should be used? var mesh; if(body instanceof CANNON.RigidBody) mesh = shape2mesh(body.shape); else if(body instanceof CANNON.Particle){ mesh = new THREE.Mesh( particleGeo, particleMaterial ); mesh.scale.set(settings.particleSize,settings.particleSize,settings.particleSize); } if(mesh) { // Add body bodies.push(body); visuals.push(mesh); body.visualref = mesh; body.visualref.visualId = bodies.length - 1; mesh.useQuaternion = true; scene.add(mesh); } }; : }
この仕組みを用いれば、様々な形のオブジェクトを物理演算させることが出来そうです。
球体や立方体だけでなく、何か変わったものを物理演算させてみるのも面白いかも知れません。