mieki256's diary



2022/09/18() [n年前の日記]

#1 [python] PyOpenGLでボールが跳ね回るスクリプトを作成

PyOpenGL を使って、ボールが箱の中で跳ね回るスクリプトを書いてみた。

動作確認環境は以下。
動かすとこんな感じ。




以下のキーが有効。 FPS表示時の赤い線は、期待した60FPSに対して実際何FPS出ているかを、箱の一辺の長さとの比較で表示している。60FPSが出ていれば、赤い線は箱の一辺と同じ長さになるし、それより少ないFPSなら、箱の一辺より短く表示される。

ソース。 :

ソースは GitHub Gist にアップロードしてみた。このページにも埋め込めるだろうか…。どうかな…。

_01_bound_ball.py (Gist)


以降、ソースの中身について、少しだけ解説。

FPSの計測について。 :

FPSの計測は、1秒間に何回画面を書き換えたかをカウントする方法で調べた。init_count_fps()、calc_fps() を見れば、どうやっているか分かるかなと…。

時間の取得には、time.time() を使った。import time をすれば使えるようになる。time.time() を呼ぶと、その時点の時刻が、秒単位(小数点以下も含む状態)で得られるらしい。

Python 2.7.18 32bitの場合、time.time() の返り値は小数点以下3桁まで含んでいる。ミリ秒まで分かるのだろう…。
>>> import time
>>> time.time()
1663505711.946
>>> time.time()
1663505714.521

Python 3.9.13 64bitの場合、time.time() の返り値は、小数点以下7桁まで得られる模様。もしかすると、マイクロ秒まで得られる…?
>>> import time
>>> time.time()
1663505644.9368925
>>> time.time()
1663505648.3456943

まあ、Python 2.7 の場合を考えて、time.time() は少なくともミリ秒まで分かると思って使えばいいのかなと。

ちなみに、最初は時間の取得に time.perf_counter() を使っていたのだけど。time.perf_counter() は Python 3.3 で実装されたメソッドだから Python 2.7 では動かなくて、time.time() で置き換えることになった。

文字描画について。 :

OpenGL で画面に文字を描画するあたりは、GLUT (freeglut) の glutBitmapCharacter() を利用した。GLUT (freeglut) を利用できる状況じゃないと使えないけれど…。

_情報メディア実験
_glutBitmapCharacter : PyOpenGL 3.1.0 GLUT Man Pages
_~mcfletch/openglcontext/trunk : contents of tests/glutbitmapcharacter.py at revision 699
_python - pyopengl How to render text - Stack Overflow

文字を描画する際の位置決めは、最初、glRasterPos3f(x, y, z) を使ってみたのだけど、glWindowPos2f(x, y) というメソッドもあると知って、そちらを使うようにしてみた。

_glRasterPos : PyOpenGL 3.1.0 GL Man Pages
_glWindowPos : PyOpenGL 3.1.0 GL Man Pages

この glWindowPos2f() を使えば、3D空間内の位置ではなく、ウインドウ上の2D的な感覚で座標指定ができる。

ただし、注意点が2つほどある。
  • 画面左下が (0, 0) になっている。
  • OpenGL 1.4 から追加されたメソッドなので、OpenGL 1.1 等では使えない。
例えば、Windows に標準で入ってる OpenGL は 1.1 対応だそうで、そのせいか、C/C++ で書いたプログラム等で glWindowPos2f() を使おうとすると「そんなAPIは無い」と言われてしまう。

もっとも、今時のPCなら、ビデオドライバはもっと後の OpenGLバージョンにも対応してるだろうから…。もしかすると、PyOpenGLを使う時はそのあたりを上手い具合に変更してくれて、それで今回 glWindowPos2f() が使えているのかもしれない。たぶん。分からんけど。

アニメーション処理について。 :

アニメーションをするためには一定の時間間隔で処理を呼ばないといけないけれど、そのあたりは glutTimerFunc() で指定している。

_glutTimerFunc : PyOpenGL 3.1.0 GLUT Man Pages
_GLUT のイベント

巷の解説ページでは glutIdleFunc() を使う場合が多いのだけど…。glutIdleFunc() に渡す関数は引数を取らないけれど、glutTimerFunc() に渡す関数は引数を1つ取るので、その点はちょっとだけ注意。

以上です。

過去ログ表示

Prev - 2022/09 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project