BabylonJS Playground上の物理演算で樋に球を転がす

# BabylonJS 6 からの物理演算

BabylonJS では [PhysicsImpostor](https://doc.babylonjs.com/typedoc/classes/BABYLON.PhysicsImpostor) などを用いる物理演算 Version 1 が使用できますが
BabylonJS 6 になってからは 物理エンジン Version 2 として Havok エンジンが使用できるようになりました。

[Babylon.js Playground](https://playground.babylonjs.com/) で Havok エンジンを用いた物理演算を実行してみます。
球を転がす樋を作成するために [`ExtrudeShape`](https://doc.babylonjs.com/typedoc/modules/BABYLON#ExtrudeShape-2) を用います。

以下のコードは 2023年12月7日の [Babylon.js Playground](https://playground.babylonjs.com/) 6.33.0(WebGL2) Javascript で動作したことがあります。

```js
var createScene = async function () {
    const scene = new BABYLON.Scene(engine);
// 物理エンジン
    const instance = await HavokPhysics();
    const plugin = new BABYLON.HavokPlugin(true, instance);
    scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), plugin);

// 樋
    const spiralR = 1;
    const shape = [];
    const path = [];
    for (let i = 0; i <= 9; ++i) {
        const r = 0.2;
        const ang = Math.PI * 2 * (i + 9) / 16;
        const p = new BABYLON.Vector3(Math.cos(ang), Math.sin(ang), 0);
        shape.push(p.scale(r));
    }
    {
        const p = new BABYLON.Vector3(0, -0.06, 1);
        path.push(p);
    }
    for (let i = 0; i <= 32; ++i) {
        let y = i * 0.06;
        const r = spiralR * (Math.max(i, 20) + 20) / 52;
        const ang = Math.PI * 2 * (i + 1) / 16;
        const p = new BABYLON.Vector3(Math.sin(ang), y, Math.cos(ang));
        path.push(p.scale(r));
    }

    const opt = { shape, path };
    const custom = BABYLON.ExtrudeShape('custom2',
        opt, scene);
    const mtl2 = new BABYLON.StandardMaterial('mtl2', scene);
    mtl2.backFaceCulling = false;
    mtl2.twoSidedLighting = true;
    custom.material = mtl2;

    const opt2 = {
        mass: 0, friction: 0, restitution: 0,
    };
    const agg2 = new BABYLON.PhysicsAggregate(custom,
        BABYLON.PhysicsShapeType.MESH,
        opt2, scene);

// 球
    const sphere = BABYLON.MeshBuilder.CreateSphere('sphere1',
        { diameter: 0.22 }, scene);
    sphere.setAbsolutePosition(new BABYLON.Vector3(0, 4, spiralR));

    const opt1 = {
        mass: 2, friction: 0, restitution: 0,
    };
    const agg1 = new BABYLON.PhysicsAggregate(sphere,
        BABYLON.PhysicsShapeType.SPHERE,
        opt1, scene);
// カメラ
    const camera = new BABYLON.ArcRotateCamera('camera1',
        0, 0, 1,
        new BABYLON.Vector3(0, 0, 0), scene);
    camera.position = new BABYLON.Vector3(1, 4, 4);
    camera.wheelPrecision = 0.01;
    camera.wheelDeltaPercentage = 0.01;

    camera.attachControl();

    const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);
    light.intensity = 0.7;
    return scene;
};
```

|実行結果1|
|:-:|
|![baphy1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213145/ca4f51a3-1ea7-3c0a-b0ec-c56d6cfdfef9.png)|
|くるくる、、、|

|実行結果2|
|:-:|
|![baphy3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213145/45d84040-f025-998c-4d6d-11bc8f5f1e21.png)|
|ぽいっ|


# リンク

- Physics     
https://doc.babylonjs.com/features/featuresDeepDive/physics
物理演算

- Migrate from Physics V1
https://doc.babylonjs.com/features/featuresDeepDive/physics/migrate
物理演算 Version 1 を 物理演算 Version 2 へ書き換える手引き