このセクションでは、物理法則を使ってリアルなアニメーションを作成する基礎を学びます。
等速直線運動とは、一定の速度で直線的に移動する運動のことです。
速さとは、$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
}
})