2019年の3D物理演算ライブラリ状況

これは [Three.js Advent Calendar 2019](https://qiita.com/advent-calendar/2019/threejs) の8日目の記事です。
Three.js Meetup Tokyo #0で「`Oimo.js`がシンプルで使いやすくてオススメ！」と言ったけど、色々と考慮すると`Cannon.js` または `Ammo.js`の方が良いという話です。

# メジャーな3D物理演算ライブラリ
2019年現在でThree.jsと組み合わせやすい物理演算ライブラリは、主に以下があります（更新日順）

| ライブラリ名 | サイズ | 最終更新日 |
|---|---|---|
| [Ammo.js](https://github.com/kripken/ammo.js) | 1.68MB | 2019/11/16 |
| [Oimo.js](https://github.com/lo-th/Oimo.js) | 352KB | 2019/01/22 |
| [Cannon.js](https://github.com/schteppe/cannon.js) | 384KB | 2016/05/03 |
| [Physijs](https://github.com/chandlerprall/Physijs) | 43KB | 2015/10/20 |

現状でメンテされているのは`Ammo.js`ですね（npmの [ammo.js](https://www.npmjs.com/package/ammo.js) は4年前から更新されてないけど）
`Cannon.js`や`Physijs`は3年以上更新されてない状況です。

オススメの物理演算ライブラリの話は [three.js forum](https://discourse.threejs.org/) でも議論されてます。
`Cannon.js` はドキュメントが整備されており使いやすいがメンテされてない、`Ammo.js` はメンテされているがファイルサイズが大きいと言ってる人もいますね。

- [three.js forum - Preferred physics engine (cannon.js, ammo.js, DIY…)](https://discourse.threejs.org/t/preferred-physics-engine-cannon-js-ammo-js-diy/1565/9)
<img width="761" alt="スクリーンショット 2019-12-08 17.43.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15028/11714d42-8e84-7df1-4933-42a2b628eeb5.png">


ちなみにBabylon.jsでは`Cannon.js`、`Oimo.js`、`Energy.js`、`Ammo.js`と幅広くサポートしてます。
しかも物理演算用のInterfaceが提供されているので、どのライブラリを選択してもほぼ同じコードで動くという（babylon.js強い！）

- [babylon.js document - Use a Physics Engine](https://doc.babylonjs.com/how_to/using_the_physics_engine)
<img width="657" alt="スクリーンショット 2019-12-08 17.46.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15028/06ff39e7-d2be-edf6-8c33-d414240cadf5.png">

```typescript:Babylon.jsでCannon.jsを使う場合
const scene = new BABYLON.Scene(engine);
const gravityVector = new BABYLON.Vector3(0, -9.81, 0);
const physicsPlugin = new BABYLON.CannonJSPlugin();
scene.enablePhysics(gravityVector, physicsPlugin);
```

# APIドキュメント
- `Ammo.js`
 - ドキュメントなし。本家の[Bullet physics](https://pybullet.org/Bullet/BulletFull/annotated.html)やexamplesコードをみる必要あり。
 - Three.js examplesの[physicsシリーズ](https://github.com/mrdoob/three.js/blob/dev/examples/webgl_physics_cloth.html)で`Ammo.js`を使ってるのでそれを見ればいける
- `Oimo.js`
 - ドキュメントなし。シンプルなのでReadmeとdemosコードでいける
- `Cannon.js`
 - [ドキュメント](http://schteppe.github.io/cannon.js/)あり。ググっても情報がたくさんある
- `Physijs`
 - Wikiに[ドキュメント](https://github.com/chandlerprall/Physijs/wiki/Basic-Setup)あり

# TypeScript対応
[TypeSearch](https://microsoft.github.io/TypeSearch/)で調べると、現状は[Cannon.js](https://www.npmjs.com/package/@types/cannon)と[Pyshijs](https://www.npmjs.com/package/@types/physijs)が対応していました。
`Oimo.js`は対応する方向がなさそうですね。

 - [Oimo.js Issue - TypeScript declarations](https://github.com/lo-th/Oimo.js/issues/87)

`Ammon.js`はTypeSearchでヒットしないが、有志の方が対応してくれてます。

 - [Ammo.js Issue - TypeScript declarations?](https://github.com/kripken/ammo.js/issues/233)
 - [npm - ammojs-typed](https://www.npmjs.com/package/ammojs-typed)

# その他ライブラリなどの物理演算の採用状況
- [PlayCanvas](https://github.com/playcanvas/engine)：OSSのゲームエンジン
  - 物理演算に`Ammo.js`を使用
   - [PlayCanvas Forum - Why ammo.js? Cannon.js looks great!](https://forum.playcanvas.com/t/why-ammo-js-cannon-js-looks-great/971)
   - [PlayCanvas Manual - Physics Basics](https://developer.playcanvas.com/en/user-manual/physics/physics-basics/)

- [A-Frame](https://github.com/aframevr/aframe)：WebXR用のフレームワーク
  - [aframe-physics-components](https://github.com/ngokevin/aframe-physics-components): `Cannon.js`サポートのPluginあり
  - [aframe-physics-system](https://github.com/donmccurdy/aframe-physics-system): `Cannon.js`と`Ammo.js`サポートのPluginあり

- [nunuStudio](https://github.com/tentone/nunuStudio)：Three.jsベースのOSSゲームエンジン
  - 物理演算に`Cannon.js`を使用（ReadMeに記述あり）
- [WhitestormJS](https://github.com/WhitestormJS/whs.js)：物理演算サポートのComponentベースのフレームワーク
  - `Ammo.js`を使用（ReadMeに記述あり）

- [React-Three-Fiber](https://github.com/react-spring/react-three-fiber)：React製のThree.jsライブラリ
  - サンプルで`Cannon.js`のReact Custom Hooksあり

# まとめ
更新が止まってるのは少し不安ですが、お手軽に使うなら`Canno.js`がベストかと思います。
保守性を求めてガッツリ作るなら`Ammo.js`が良いかと思います。
以上、読んで頂きありがとうございました。

# 参考
- [WebGLと3D物理演算ライブラリの組み合わせを試してみる](https://qiita.com/cx20/items/3ebed669fb9c9e797935)
- [javascriptで使える3D物理シミュレーションの感想](http://kzntov.seesaa.net/article/460552318.html)