読者です 読者をやめる 読者になる 読者になる

衝突時の反射処理

C++ OpenGL


試験中になると捗るプログラミングのせいで、珍しく2日連続で投下。
動画で大方の状況は説明したので、いきなり解説。
ちなみに、動画中の左上に出ていた数字は、衝突した瞬間の速度。
(本当は動画中に書きたかったんだけど、iMovieではそこまで高度な編集ができなかった)

最初の方は、衝突時に安直に反転させる方法。
つまり

v = -v * 1.0;

という感じの処理(実際にほぼこれと同一のコード)。
こうするとなぜ速度が増えてしまうのかというと、コールバックでr(座標),v(速度),a(加速度)を一定間隔で更新するときに同時にボールと地面の衝突判定も行っているんだけれど、先にポリゴンを動かしてみて衝突しているかどうかを判定しているので、その無駄に動いた分が速度の増分になってる。

なので、後者ではエネルギー保存則を使って衝突時の反射速度を導きだしてる。
何も難しいことはなくて
E=\frac{1}{2}m\left(\frac{d r_y}{dt}\right)^2+mgr_y
を変形して
v_y=\sqrt{\frac{2}{m}E-2gr_y}
で求めてるだけ。
ポリゴンの初期条件を設定したときに予めエネルギーを計算しておいて、それを使って計算してる。

それでも若干速度がゆらいでるのは、やっぱりさっきのコールバックを定期的に呼ぶところに問題がある。
どうしても離散間隔でしかコールバックできないので、座標や速度の変化は実際には連続的なものではなく離散的になってしまう。
そのため、座標(r_y)の方の微妙な誤差が速度の方にも伝播してしまっている。
本当はもっといいアルゴリズムがあったり、あとはdouble型じゃなくてもっと高精度の小数を使ったりしてるんだろうけど、暗中模索だったので仕方ない。
この期にPhysXとかかじってみるのも面白いかもしれない。