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つ取るので、その点はちょっとだけ注意。
[ ツッコむ ]
#2 [prog] C言語とOpenGLでボールが跳ね回るプログラムを作成
_PyOpenGLを使ってボールが箱の中で跳ね回るスクリプトを書いた
わけだけど、これをC言語 + OpenGL で動くように移植してみた。
環境は、Windows10 x64 21H2 + MinGW (gcc 9.2.0) + freeglut 3.0.0。MSYS2 + MinGW-w64 ではなくて、MinGW + MSYS でコンパイルしている。
MinGW用の freeglut 3.0.0 バイナリ (freeglut-MinGW-3.0.0-1.mp.zip) は、以下から入手させてもらった。ありがたや。
_freeglut Windows Development Libraries
動作画面は PyOpenGL版と大体同じ。
以下のキーを受け付ける。
環境は、Windows10 x64 21H2 + MinGW (gcc 9.2.0) + freeglut 3.0.0。MSYS2 + MinGW-w64 ではなくて、MinGW + MSYS でコンパイルしている。
MinGW用の freeglut 3.0.0 バイナリ (freeglut-MinGW-3.0.0-1.mp.zip) は、以下から入手させてもらった。ありがたや。
_freeglut Windows Development Libraries
動作画面は PyOpenGL版と大体同じ。
以下のキーを受け付ける。
- ESC / qキー : 終了。
- fキー : FPS表示。
◎ ソース。 :
◎ コンパイル。 :
Makefile があるので、make と打てばコンパイルできるだろうけど…。一応、コンパイルは以下。01_gl_bound_ball.exe が生成される。
01_gl_bound_ball.exe を実行すれば、PyOpenGL版と同じ見た目のウインドウが開くかと。
gcc 01_gl_bound_ball.c -o 01_gl_bound_ball.exe -static -D FREEGLUT_STATIC -lfreeglut_static -lopengl32 -lglu32 -lwinmm -lgdi32 -mwindows
01_gl_bound_ball.exe を実行すれば、PyOpenGL版と同じ見た目のウインドウが開くかと。
◎ 覚書。 :
FPS表示時に、一応「FPS: xx」の文字描画もしてみたけれど、glWindowPos2f() が使えなかったので、
*1
glRasterPos3f() を使うことになった。そのせいで、箱の上のほうに「FPS: xx」がくっついて動いてる表示になってしまった。ちょっとダサイ。ウインドウの特定の位置に固定して表示したかったのだけど、このあたり本来はどうやって解決すればいいのやら。
一般的に、C言語で円周率を使いたい時は、math.h をインクルードして(#include <math.h>)、M_PI を利用するらしいのだけど。試してみたら Visual Studio Code 上で「このシンボルは見当たらないよ」と言われてしまった。math.h を include する前に、「#define _USE_MATH_DEFINES」を書いておけば、その手のマクロが使えるようになるらしい。ただ、移植性は落ちるそうで…。
_定数M_PIが使えない - 需要のないページ
_プログラミングメモ日記 C++での数学定数の利用について
_M_PI ‐ 通信用語の基礎知識
_C言語(標準)にM_PIは無い - 簡潔なQ
_math.h の M_PI などは仕様外だった - GUST NOTCH? DIARY
一般的に、C言語で円周率を使いたい時は、math.h をインクルードして(#include <math.h>)、M_PI を利用するらしいのだけど。試してみたら Visual Studio Code 上で「このシンボルは見当たらないよ」と言われてしまった。math.h を include する前に、「#define _USE_MATH_DEFINES」を書いておけば、その手のマクロが使えるようになるらしい。ただ、移植性は落ちるそうで…。
_定数M_PIが使えない - 需要のないページ
_プログラミングメモ日記 C++での数学定数の利用について
_M_PI ‐ 通信用語の基礎知識
_C言語(標準)にM_PIは無い - 簡潔なQ
_math.h の M_PI などは仕様外だった - GUST NOTCH? DIARY
*1: glWindowPos2f() は OpenGL 1.4 から使える。OpenGL 1.1 では使えない。
[ ツッコむ ]
以上、1 日分です。