JavaScript
CANNON.js
Web3D
Mithril.js
Solufa

Solufaで物理エンジンを扱う

More than 1 year has passed since last update.


導入

cannon.jsを使ってSolufa上で物理エンジンを使います。

今回もPlayGround内に書いていきます。

Solufaではまだcannonのラップが全て実装されているわけではなく、重さのみ指定できます。(v0.3.1時点)

当たり判定はあるので何かに使えたら使ってみましょう。


物理エンジンを使うには

物理エンジン(cannon.js)を使うにはS(function(m){});内で

S.initPhysics( "https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js" );

と定義してください。

cannon.jsのバージョンは上記のURLが確実に動くものです。(v0.3.1時点)


床を作る

まずは床を作ります。

床自体はデフォルトでPlane定義されているようです。現状変更する術が見当たりません(v0.3.1時点)

見た目上は何も見えないのでPlaneを置きます。


Controller

まずはPlaneとそのマテリアルを定義していきます。

controller: function() {

return {
planeGeo: {
type: "Plane",
value: [ 20, 20 ]
},
planeMtl: {
type: "MeshStandard",
value: { color: "#888", side: 2 }
},
};
},


View

Planeを設置します。

地面となるオブジェクト(重力をかけたくないオブジェクト)にはphysics={{ mass: 0 }}の属性を付けます。

massは重さです(kg)。

重さのない物体は重力の影響を受けません。(現実にそんなものはありませんが...)

view: function( ctrl ) {

return <scene>
<mesh geo={ ctrl.planeGeo } mtl={ ctrl.planeMtl } physics={{ mass: 0 }} style={{ rotateX:Math.PI/-2 }}/>
<cam id="cam" style={{posZ: 10}}/>
<light init={{ type: "Dir" }} style={{pos: [ 20, 20, 20 ]}}/>
<light init={{ type: "Amb" }}/>
</scene>;
}

このようになればOKです。

スクリーンショット 2016-06-16 22.18.25.png


物体を落下させる

先ほどから述べている通り、物理エンジンを使っているので重力が効いています。

なので床より上にオブジェクトを置くと落下してきます。

今回は球を上から落下させます。


Controller

球のオブジェクトとマテリアルを追加で定義します。

controller: function() {

return {
planeGeo: {
type: "Plane",
value: [ 20, 20 ]
},
planeMtl: {
type: "MeshStandard",
value: { color: "#888", side: 2 }
},
sphereGeo: {
type: "Sphere",
value: [ .5, 64, 64 ]
},
sphereMtl: {
type: "MeshStandard",
value: {
color: "#0ff"
}
},
};
},


View

重さ1の球を描画します。

落下させるために初期Y座標を5にしています。

view: function( ctrl ) {

return <scene>
<mesh geo={ ctrl.sphereGeo } mtl={ ctrl.sphereMtl } physics={{mass:1}} style={{ posY: 5 }}/>
<mesh geo={ ctrl.planeGeo } mtl={ ctrl.planeMtl } physics={{ mass: 0 }} style={{ rotateX:Math.PI/-2 }}/>
<cam id="cam" style={{posZ: 10}}/>
<light init={{ type: "Dir" }} style={{pos: [ 20, 20, 20 ]}}/>
<light init={{ type: "Amb" }}/>
</scene>;
}

このようになれば完成です。


完成コード

S( function( m ) {

S.initPhysics( "https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js" );

var App = {
controller: function() {
return {
planeGeo: {
type: "Plane",
value: [ 20, 20 ]
},
planeMtl: {
type: "MeshStandard",
value: { color: "#888", side: 2 }
},
sphereGeo: {
type: "Sphere",
value: [ .5, 64, 64 ]
},
sphereMtl: {
type: "MeshStandard",
value: {
color: "#0ff"
}
},
};
},
view: function( ctrl ) {
return <scene>
<obj>
<mesh physics={{mass:1}} geo={ ctrl.sphereGeo } mtl={ ctrl.sphereMtl } style={{ posY: 5 }}/>
<mesh geo={ ctrl.planeGeo } mtl={ ctrl.planeMtl } physics={{ mass: 0 }} style={{ rotateX:Math.PI/-2 }}/>
</obj>
<cam id="cam" style={{pos: [0,5,10]}}/>
<light init={{ type: "Dir" }} style={{pos: [ 20, 20, 20 ]}}/>
<light init={{ type: "Amb" }}/>
</scene>;
}
};

m.mount( S.document.body, App );
m.render( S.document.head,
<rdr init={{ frame: "#solufa", antialias: true, preserveDrawingBuffer: true }} >
<OrbitVp cam="#cam"/>
</rdr>
);
});


最後に

今回は簡単にですが物理エンジンを使ってみました。

摩擦などはまだ実装されていないのでできることも少なく、球が転がりだしたら止まりません。

今後のアップデートに期待しましょう!

サンプルにも物理を使ったものがあるので時間があったら見てみましょう