2022/09/18(日) [n年前の日記]
#1 [python] PyOpenGLでボールが跳ね回るスクリプトを作成
PyOpenGL を使って、ボールが箱の中で跳ね回るスクリプトを書いてみた。
動作確認環境は以下。
動かすとこんな感じ。
以下のキーが有効。
動作確認環境は以下。
- Windows10 x64 21H2
- Python 3.9.13 64bit + PyOpenGL 3.1.6
- Python 2.7.18 32bit + PyOpenGL 3.1.0
動かすとこんな感じ。
以下のキーが有効。
- ESC / q キー : スクリプト終了。
- f キー : FPSを表示。「FPS: xx」と、赤い線が表示される。
◎ ソース。 :
ソースは GitHub Gist にアップロードしてみた。このページにも埋め込めるだろうか…。どうかな…。
_01_bound_ball.py (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桁まで含んでいる。ミリ秒まで分かるのだろう…。
Python 3.9.13 64bitの場合、time.time() の返り値は、小数点以下7桁まで得られる模様。もしかすると、マイクロ秒まで得られる…?
まあ、Python 2.7 の場合を考えて、time.time() は少なくともミリ秒まで分かると思って使えばいいのかなと。
ちなみに、最初は時間の取得に time.perf_counter() を使っていたのだけど。time.perf_counter() は Python 3.3 で実装されたメソッドだから Python 2.7 では動かなくて、time.time() で置き換えることになった。
時間の取得には、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つほどある。
もっとも、今時のPCなら、ビデオドライバはもっと後の OpenGLバージョンにも対応してるだろうから…。もしかすると、PyOpenGLを使う時はそのあたりを上手い具合に変更してくれて、それで今回 glWindowPos2f() が使えているのかもしれない。たぶん。分からんけど。
_情報メディア実験
_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 等では使えない。
もっとも、今時のPCなら、ビデオドライバはもっと後の OpenGLバージョンにも対応してるだろうから…。もしかすると、PyOpenGLを使う時はそのあたりを上手い具合に変更してくれて、それで今回 glWindowPos2f() が使えているのかもしれない。たぶん。分からんけど。
◎ アニメーション処理について。 :
アニメーションをするためには一定の時間間隔で処理を呼ばないといけないけれど、そのあたりは glutTimerFunc() で指定している。
_glutTimerFunc : PyOpenGL 3.1.0 GLUT Man Pages
_GLUT のイベント
巷の解説ページでは glutIdleFunc() を使う場合が多いのだけど…。glutIdleFunc() に渡す関数は引数を取らないけれど、glutTimerFunc() に渡す関数は引数を1つ取るので、その点はちょっとだけ注意。
_glutTimerFunc : PyOpenGL 3.1.0 GLUT Man Pages
_GLUT のイベント
巷の解説ページでは glutIdleFunc() を使う場合が多いのだけど…。glutIdleFunc() に渡す関数は引数を取らないけれど、glutTimerFunc() に渡す関数は引数を1つ取るので、その点はちょっとだけ注意。
[ ツッコむ ]
以上です。