教育機関向け活用例

6. アニメーションと物理

このセクションでは、物理法則を使ってリアルなアニメーションを作成する基礎を学びます。

等速直線運動

等速直線運動とは、一定の速度で直線的に移動する運動のことです。

速さとは、$1$ の時間で進む距離のことです。
通常、物理では $m/s$ が速さの単位として使われますが、これは$1$ 秒間に進む距離(メートル)のことです。

つまり、 経過時間を $t$ 、速度を $v$ とすると、 進む距離 $x$ は次のように表されます。

\[x = v t\]

animate 関数内では、 前フレームからの経過時時間 delta、 現在の時間 time が取得できます。

animate(({ time, delta }) => {
  // ここで、
  // 前フレームからの経過時間 delta と
  // 現在の時間 time
  // を使える
})

つまり、1秒間に3メートル進む $3m/s$ の物体を作るには、次のように記述します。
(ここでは、3D空間の距離1を1mとしています)

const { camera, create, helper, animate } = init();

helper.grid()
helper.axes()
camera.position.set(0, 2, 4)
create.ambientLight()
create.directionalLight()
const cube = create.cube({ position: [-3, 0, 0] })

const v = 3; // 速さ

animate(({ delta }) => {
  // 1秒間に3メートル進む (v * delta ずつ進む)
  cube.position.x += v * delta
})

等加速直線運動

等加速直線運動とは、一定の加速度で直線的に移動する運動のことです。

加速度とは、$1$ の時間で速度が変化する量のことです。
通常、物理では $m/s^2$ が速さの単位として使われますが、これは$1$ 秒間に増える速さのことです。

つまり、 経過時間を $t$ 、 加速度を $a$ 、 はじめの速さを $v_0$ とすると、 速さ $v$ と進む距離 $x$ は次のように表されます。

\[v = v_0 + a t\]\[x = v_0 t + \displaystyle\ rac{1}{2}a t^2\]

つまり、1秒間に3 $m/s$ ずつ早くなる $3m/s^2$ の物体を作るには、次のように記述します。
(ここでは、3D空間の距離1を1mとしています)

const { camera, create, helper, animate } = init();

helper.grid()
helper.axes()
camera.position.set(0, 2, 4)
create.ambientLight()
create.directionalLight()
const cube = create.cube({ position: [-3, 0, 0] })

const a = 3;// 加速度
let v = 0;// 速さ

animate(({ delta }) => {
  // 1秒間に3メートルずつ早くなる (a * delta ずつ速くなる)
  v += a * delta
  cube.position.x += v * delta
})

ここで、 const ではなく let を使っていますが、const は変数の再代入を禁止するもので、let は再代入を許可するものです。

鉛直投げ上げ

鉛直投げ上げとは、上方に投げ上げた物体が地面に落ちるまでの運動のことです。

地球上の物体は、重力によって下方向に $9.8m/s^2$ 加速されます。
これを考慮すると、鉛直投げ上げのプログラムは次のようになります。

const { camera, create, helper, animate } = init();

helper.grid()
helper.axes()
camera.position.set(0, 2, 4)
create.ambientLight()
create.directionalLight()
const cube = create.cube({ position: [0, 0, 0] })

const g = -9.8;// 重力加速度
let v = 8;// 投げる速さ

animate(({ delta }) => {
  // 重力による速度の変化
  v += g * delta
  cube.position.y += v * delta
})

ここで、cubeはどこまでも落ちていきます。
これは、止まる条件を設定していないためです。

例えば、次のように設定すると、y = 0の地面でぶつかって止まります。
(cubeの位置はその中心なので、y = 0は地面に半分だけ埋まっていることになります。)

const { camera, create, helper, animate } = init();

helper.grid()
helper.axes()
camera.position.set(0, 2, 4)
create.ambientLight()
create.directionalLight()
const cube = create.cube({ position: [0, 0.5, 0] })

const g = -9.8;// 重力加速度
let v = 8;// 投げる速さ

animate(({ delta }) => {
  // 重力による速度の変化
  v += g * delta
  cube.position.y += v * delta
  // 地面にあたったら止まる
  if (cube.position.y < 0.5) {
    cube.position.y = 0.5
    v = 0
  }
})

地面にぶつかったとき、跳ね返るようにするには、次のようにします。

const { camera, create, helper, animate } = init();

helper.grid()
helper.axes()
camera.position.set(0, 2, 4)
create.ambientLight()
create.directionalLight()
const cube = create.cube({ position: [0, 0.5, 0] })

const g = -9.8;// 重力加速度
let v = 8;// 投げる速さ

animate(({ delta }) => {
  // 重力による速度の変化
  v += g * delta
  cube.position.y += v * delta
  // 地面にあたったら止まる
  if (cube.position.y < 0.5) {
    cube.position.y = 0.5
    v = -v
  }
})