物理エンジンで作る縦の短い動画と、その中の数学

ビー玉のレース、ガルトンボード、跳ねるたびに増えるボール、二重振り子。リールやショートでよく見る物理の縦の動画を、白と黒だけで 4 本作った。画面の中で動いているのは、運動方程式を 1/120 秒や 1/480 秒の刻みで解いた結果である。

運動方程式テイラー展開正規分布二項定理とパスカルの三角形ネイピア数 e振り子の周期
シミュレーション

4 本の動画

どれも縦 1080×1920・30 コマ/秒・30 秒前後で、画面の字幕と声の実況が付く。

4 本の動画(縦 1080×1920・各 30 秒前後)

ビー玉レース 1着はどれ?(Matter.js・乱数の種 75)声 VOICEVOX:玄野武宏・効果音と音楽は合成音
ガルトンボード 300 個の玉はどこに集まる?(Matter.js・乱数の種 3)声 VOICEVOX:玄野武宏・効果音と音楽は合成音
跳ねるたびに 1 個増えるボール(自前の計算・乱数の種 1)声 VOICEVOX:玄野武宏・効果音と音楽は合成音
二重振り子 1000 万分の 1 の差はいつばらける?(自前の計算)声 VOICEVOX:玄野武宏・効果音と音楽は合成音

型は、短い動画でよく見られるものから選んだ。円の中で跳ねるボールは、2023 年 11 月ごろから YouTube ショートで広まった型で、跳ねるたびに曲の音が 1 つずつ鳴り、壁が増えたり壊れたりする[6]。3 本目は、その変形として「跳ねるたびにボールが増える」決まりにした。ビー玉のレースは、2020 年にスポーツの試合が止まった時期に、Jelle's Marble Runs などの動画の再生が伸びた[7]。ガルトンボードと二重振り子は、確率とカオスを見せる定番である。実在の選手名・既存の曲・素材サイトの音は使っていない。

最初の 2 本は物理エンジン Matter.js 0.20 で計算し、あとの 2 本は物理エンジンを使わず、運動方程式を自分で数値積分した。この記事は、その中の数学を順に書く。実況を自動で付ける仕組みは ビー玉レースの実況を自動で付ける に分けた。

証明

運動方程式を小さな刻みで解く

どの動画も、出発点は同じ 1 本の式である。違うのは、それを時間の刻みでどう近似するかだけだ。

  1. 出発点は運動方程式。玉の位置を 、質量を 、はたらく力を とする。

  2. 速度 を使って、2 階の式を 1 階の式の組に直す。加速度は である。

  3. 時間を幅 の刻みに分け、n 番目の値を 、 と書く。刻みの間の変化を始めの値で代表させるのが陽的オイラー法である。

  4. 先に速度を更新し、新しい速度で位置を進めると半陰的オイラー法になる。順番を入れ替えただけだが、性質が変わる(次の章)。跳ねるボールの動画は、この式を 秒で解いた。

  5. テイラー展開で、少し後と少し前の位置を書く。 は加速度の変化の速さである。

  6. 2 つを足すと、奇数の次数の項が消える。速度を使わずに、今と 1 つ前の位置だけで次の位置が決まる。これがベレ法(ベルレ法とも書く)で、L. ベレが 1967 年の分子の計算で使った[1]。1 刻みの誤差は 、長く計算したときにたまる誤差は に比例する。

  7. Matter.js 0.20 の Body.update は、この式の に空気の抵抗の係数を掛けて使う(ソースの src/body/Body.js で確かめた)[5]。係数 は 1/60 秒あたりの割合で、刻みの長さ に合わせて掛け直す( 秒)。ビー玉レースとガルトンボードは 秒、1 コマ(1/30 秒)あたり 4 回の計算で解いた。

  8. 二重振り子は、2 本の腕の角度と角速度 の式 を、4 次のルンゲ・クッタ法で解いた( 秒)。刻みの中の 4 か所で傾きを測り、重みを付けて平均する。1 刻みの誤差は 、長く計算したときの誤差は に比例する。

  9. 4 つの傾きは、始め・中ほど 2 回・終わりで測る。

応用

エネルギーが保たれるか

刻みの式の違いは、長く計算したときに出る。跳ねるボールの動画と同じ条件(重力 300 px/s²・円の半径 380 px・反発係数 1)で、1 個のボールだけを 120 秒計算し、力学的エネルギーが始めからどれだけずれたかを測った。反発係数 1 なので、正しい答えではエネルギーは変わらない(位置エネルギーの 0 は円の中心の高さに置き、始めのエネルギーに対する割合で表した)。

陽的オイラー法と半陰的オイラー法で、1 個のボールのエネルギーのずれを 120 秒まで比べた図。実線が陽的オイラー法、破線が半陰的オイラー法。
計算のしかた10 秒30 秒60 秒120 秒
陽的オイラー法+7.2%+18.6%+37.0%+75.8%
半陰的オイラー法−0.8%+0.6%−2.4%−2.3%

陽的オイラー法では、エネルギーが増え続け、120 秒で 1.76 倍になった。ボールは跳ねるたびに高く上がっていく。半陰的オイラー法のずれは、刻みごとに見ても −6.0% から +1.5% の間にとどまり、増え続けない。

なぜこう分かれるのかは、空中の 1 刻みを計算すると分かる。下向きを正にとり、上下の速さを とすると、1 刻みでのエネルギー の変化は、どの刻みでも同じ大きさになる。

どちらも空中だけなら 120 秒で 40% ぶん動く大きさである。半陰的オイラー法では、代わりに少しだけ形の違う量が空中でぴったり保たれる。

と の差は に比例する小さな量なので、 は のまわりで揺れるだけになる。このように、本当のエネルギーにごく近い別の量を長い時間保つ性質は、シンプレクティックと呼ばれる積分法(半陰的オイラー法・ベレ法など)に共通する[2]。

ただし壁での跳ね返りは、この性質の外にある。跳ね返りは刻みの終わりにまとめて行うので、本当にぶつかった瞬間とずれる。この動画では、壁にめり込んだ分を鏡のように内側へ戻す処理(次の章)が、そのずれをおおよそ打ち消している。戻す処理を外して同じ計算をすると、半陰的オイラー法でもずれは 120 秒で −40% まで広がった。陽的オイラー法の +75.8% のうち、空中の分は +40.2% で、残りは壁の処理との組み合わせで増えた分である。

4 次のルンゲ・クッタ法はシンプレクティックではないが、誤差がとても小さい。二重振り子を 秒で、放してから動画の終わりまで(約 29 秒)計算したとき、エネルギーのずれは最大でも (相対)だった。

証明

衝突と反発係数

  1. 玉が壁や別の玉にぶつかる瞬間、変わるのは接触面に垂直な向き(法線 )の速さだけとする。反発係数 は、ぶつかる前と後の法線方向の速さの比である。

  2. 速度を法線方向と接線方向に分ける。摩擦を考えなければ接線方向は変わらないので、ぶつかった後の速度は次の式になる。

  3. 円の内側で跳ねるボールでは、法線は円の中心 からボールへの向きである。反発係数は 1 にしたので、壁に向かう速さの向きだけが反転する。

  4. 刻みの途中で壁にめり込んだ深さを とすると、鏡に映すように同じ深さだけ内側へ戻した。 は円の半径、 はボールの半径である。

  5. Matter.js は、2 つの物体の反発係数のうち大きいほうを使い、法線方向の力積を 倍のかたちで与える(src/collision/Pair.js と Resolver.js)[5]。ビー玉は 0.42、坂は 0.2 にしたので、ビー玉と坂の衝突は 0.42 で計算される。

応用

ガルトンボードと二項分布

ガルトンボードの名は、イギリスのフランシス・ゴルトン(Galton)から来ている。ゴルトンは 1870 年代に、釘を互い違いに並べた板を作り、1889 年の著書『Natural Inheritance』で、玉の山が釣り鐘の形になる様子を説明した[3]。

釘に当たるたびに玉が右か左へ半々で分かれるなら、14 段を通ったあとの箱の番号 (左から 0〜14)は二項分布に従う。係数は二項定理とパスカルの三角形の、いちばん上を 0 段目として 14 段目の数である。

平均と標準偏差は次のとおり。段の数を増やすと、この形は正規分布に近づく(ド・モアブル=ラプラスの定理)。

ただし、物理エンジンの玉が釘 1 本ごとにきれいに半々で分かれるとは限らない。反発係数と空気の抵抗(Matter.js の frictionAir の値)を変えて 300 個ずつ落とし(乱数の種 1)、ばらつき(標準偏差・単位は箱の数)を測った。よく跳ねるほど山は広く、勢いを止めるほど狭くなった。

反発係数空気の抵抗ばらつき
0.30.033.23
0.20.042.16
0.20.0451.89
0.150.0451.68
0.20.051.55

動画では、理論の 1.87 にいちばん近かった反発係数 0.2・空気の抵抗 0.045 を使った。つまり、理論に合うように物理の値を選んでいる。乱数の種 3 で落とした 300 個は、左の箱から 0, 1, 2, 6, 22, 37, 57, 60, 52, 30, 18, 9, 4, 1, 1 個になった。平均は 6.99、ばらつきは 2.04 で、理論の 7 と 1.87 に近い。

いちばん右の箱にも 1 個入った。理想の板なら 1 個の玉がそこに入る確率は 16384 分の 1 で、300 個のうち 1 個でも両端に入る確率は約 3.6% である。ただし、この種は端に入る玉があるものを選んでいる。同じ値で種 1 では、ばらつきは 1.89 で、両端の 2 箱ずつには 1 個も入らなかった。300 個を 1 回落としただけでは、この板が理想より端に転がりやすいかどうかは言えない。

応用

倍々に増えるボール

跳ねるボールの中心の決まりは「壁に当たるたびに、その場所から 1 個増える」である。新しいボールは、跳ね返った向きを 0.06〜0.22 ラジアン(乱数で決める)回した向きに飛ぶ。

ボール 1 個が、増える当たりを平均して 秒に 1 回起こすとすると、 個のボールは 秒でおよそ 個増える。増え方は今の数に比例する。

はネイピア数、 は数が倍になる時間である。動画の記録から、8 個・16 個・…・1024 個になった時刻を取り、 と時間に直線を当てはめると、 秒になった。1 個から 1024 個()までは 17.6 秒で、 より少し長い。最初の 1 個から 8 個までに 5.9 秒(倍になるのに 1 回あたり約 2.0 秒)かかったためである。数が少ないうちは、当たる間隔のばらつきがそのまま出る。動画の最後のグラフで、個数の対数がほぼ 1 本の直線に並ぶのは、この式のためである。

決まりには細かい条件を 2 つ付けた。壁へ向かう速さが 120 px/s に満たない当たりでは増やさない。同じボールは 0.25 秒あける。同じ種で計算し直すと、2 つとも外したときは 64 個から 1024 個まで 1.1 秒(条件ありは 7.0 秒)、1 個から 1024 個まで 10.9 秒で増えた。120 px/s の条件だけを外すと 15.5 秒、0.25 秒の条件だけを外すと 17.6 秒のままだった。弱い当たりが続けて起きたとき、2 つの条件がそろって増えすぎを止めている。

本物の生き物の数は、こうして倍々に増え続けることはなく、やがて頭打ちになる(ロジスティック方程式)。動画では 1024 個で増えるのを止め、壁を開いて終わりにした。

応用

二重振り子とカオス

二重振り子は、振り子の先にもう 1 本の振り子をつないだものである。1 本の振り子は、揺れが小さければ同じ周期で規則正しく揺れる。2 本つなぐと、動きは初めの角度のわずかな差で大きく変わる。

2 つのおもりの質量と 2 本の腕の長さ を同じにし(腕の重さは考えない)、角度は真下から測る。角度の差を 、角速度を とすると、ラグランジュの方程式から角加速度は次の形になる。

動画の 7 本は、上の腕 1.9 ラジアン・下の腕 2.9 ラジアンから放した。違うのは下の腕の角度だけで、隣どうし ラジアン(1000 万分の 1)ずつずらした。この記事の「差」は、7 本の下の腕の角度のうち、いちばん離れた 2 本の差である(1 回転の違いは数えない)。始めは ラジアンである。

カオスでは、差がおよそ一定の割合で増えていく。

はリアプノフ指数と呼ばれ、正なら近い 2 つの動きが指数関数的に離れる。差の対数と時間に、放して 0.5 秒後から差が 0.1 ラジアンになるまでの区間で直線を当てはめると、 /秒だった。差は約 2.83 秒ごとに 10 倍になる。差が 0.01 ラジアンになったのは放してから 10.5 秒後、1.5 ラジアンで 13.4 秒後である。この は、この初めの角度と短い区間で測った目安の値である。カオスの振り子の実験と計算は、Shinbrot らの論文がくわしい[4]。近い 2 つの初めの値の差が指数関数的に広がる点は、ロジスティック写像のカオスと同じである。

同じことは計算の誤差にも起きる。刻みを半分の 1/960 秒にして計算し直すと、1 本ごとの下の腕の角度は、放して 10 秒で ラジアン、20 秒で 0.7 ラジアン変わった。誤差も で増えるため、放して 20 秒を過ぎた動きは、細かいところまでは正しくない。それでも、ばらけるまでの時刻(10.5 秒・13.4 秒)と は刻みを半分にしても同じだった。刻みの誤差は 7 本にほぼ同じように乗るので、差の広がり方は追える。

動画の音は、7 本の下の腕の角速度の大きさに比例して高くした音である。そろっている間は 1 つの音に聞こえ、ばらけると 7 つの音に分かれる。

ノート

乱数の種と、同じ映像の作り直し

乱数は Math.random を使わず、種から決まった列を出す mulberry32 という短い関数で作った。同じ種なら、何度計算しても同じ列が出る。

  • ビー玉レース: 8 つの玉の並び順・最初の向き・位置の ±2 px のずれ(種 75)。実況の言い回しの選び方にも、種から作った別の列を使う
  • ガルトンボード: 落とす口の ±1.5 px のずれ(種 3)
  • 跳ねるボール: 最初の向きと、増えたボールの向きの回し方(種 1)
  • 二重振り子: 乱数を使わない(初めの角度だけで決まる)

同じ種・同じ版の Node.js(24)と Matter.js(0.20.0)なら、最後のコマのすべての位置が一致することを、2 回計算して確かめた。種を 1 つ変えるとレースは別の展開になる。ただし、JavaScript の処理系や版が変わると、三角関数の最後の桁が変わることがあり、カオスを含む計算ではそれが大きな差に育つ。種で作り直せるのは、同じ環境の中だけである。

種は選んでいる。ビー玉レースは種 1〜80 を計算し、全員がゴールする・先頭が 4 回入れ替わる・1 着と 2 着の差が 0.35 秒の種 75 を使った。ガルトンボードは、端の箱に入る玉がある種 3 を使った。動画には種の番号を出している。

応用

縦の動画にする

コマは Node.js の canvas(@napi-rs/canvas)で描き、色は黒 #0a0a0a と白 #f6f6f4 だけにした。数式は KaTeX で組み、Chrome で透明な画像にして重ねた。描いたコマを 1 枚ずつ ffmpeg に渡し、H.264(縦 1080×1920・30 コマ/秒)と AAC の mp4 にした。音の大きさは -14 LUFS にそろえた(実測 -15.4〜-14.8 LUFS)。

縦の動画は、上と下に再生の操作やアカウント名が重なる。重なる範囲は資料によって数字が違う(上 108〜269 px・下 320〜672 px)。この動画では、文字を上 250 px・下 420 px・左 80 px・右 150 px より内側に置いた。

効果音と BGM は、すべてプログラムで合成した音である。ガラス玉の当たる音は 2 つの高い音と短い雑音、釘の音ははじく音を 5 音の音階で鳴らした。素材サイトの音を使うときは、商用利用とクレジットの決まりがサイトごとに違う。比べた表は、サービス・システム大全の効果音の素材サイト 12 選にある。

参考文献

  1. L. Verlet, "Computer 'Experiments' on Classical Fluids. I. Thermodynamical Properties of Lennard-Jones Molecules", Physical Review 159, 98〜103 (1967).
  2. E. Hairer, C. Lubich, G. Wanner, Geometric Numerical Integration, 2nd ed., Springer (2006).
  3. F. Galton, Natural Inheritance, Macmillan (1889). galton.org
  4. T. Shinbrot, C. Grebogi, J. Wisdom, J. A. Yorke, "Chaos in a double pendulum", American Journal of Physics 60, 491〜499 (1992).
  5. Matter.js 0.20.0 のソース(src/body/Body.js・src/collision/Pair.js・src/collision/Resolver.js). GitHub liabru/matter-js
  6. Know Your Meme, Will the Ball Escape? / Ball Bouncing Brainrot. knowyourmeme.com
  7. YPulse, Desperate Sports Fans Are Watching Marbles Race On The Viral List (2020-03-20). ypulse.com

姉妹サイト

株式会社Game が運営するメディアです。