前回表示したテクスチャを移動と回転させる。
import sys from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * from PIL import Image def load_texture(): img = Image.open("sample1.png") w, h = img.size glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.tobytes()) def display(): glClear(GL_COLOR_BUFFER_BIT) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_BLEND) glEnable(GL_TEXTURE_2D) glPushMatrix() glTranslatef(0.0, 0.5, 0.0) glRotatef(90.0, 0.0, 0.0, 1.0) glBegin(GL_QUADS) glTexCoord2d(0.0, 1.0) glVertex3d(-0.5, -0.5, 0.0) glTexCoord2d(1.0, 1.0) glVertex3d( 0.5, -0.5, 0.0) glTexCoord2d(1.0, 0.0) glVertex3d( 0.5, 0.5, 0.0) glTexCoord2d(0.0, 0.0) glVertex3d(-0.5, 0.5, 0.0) glEnd() glPopMatrix() glDisable(GL_TEXTURE_2D) glDisable(GL_BLEND) glFlush() def main(): glutInit(sys.argv) glutInitDisplayMode(GLUT_RGBA) glutInitWindowSize(300, 300) glutCreateWindow(b"TextureSample1") glutDisplayFunc(display) glClearColor(0.0, 0.0, 1.0, 1.0) load_texture() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glutMainLoop() if __name__ == '__main__': main()
解説
表示するテクスチャを貼った四角の座標はローカル座標系で指定するため、行列スタックを使用して、現在の座標系(この例では、ワールド座標系)を保存する。
glPushMatrix()
ローカル座標系での操作が終わった後、
glPopMatrix()
で保存時の座標系(この例では、ワールド座標系)に復元する。
この例ではローカル座標系は1つしか扱っていないので、保存しなくても問題ない。
2つ以上のローカル座標系を扱う場合や親子関係のオブジェクトを扱う場合は行列スタックが必要になる。
移動は、
glTranslatef(0.0, 0.5, 0.0)
で行う。
回転は、
glRotatef(90.0, 0.0, 0.0, 1.0)
で行う。
この例では、Z軸周りに90度(右回り)回転させて、Y軸方向に0.5移動している。
移動の行列を、回転を、頂点のベクトルをとすると、ローカル座標系からワールド座標系への変換(モデリング変換)は、の式で計算される。
行列の積に交換法則は成立しないので、とを逆にできないことに注意する。
回転してから移動と、移動してから回転では、回転の原点が異なることは直観的に理解できる。
補足
初期状態では、モデリング変換は、単位行列になっている。
何か操作を行った後に、単位行列に初期化したい場合は、
glLoadIdentity()
を実行する。
透視変換の行列の操作をした後は、
glMatrixMode(GL_MODELVIEW)
でモデリング変換の行列を選択することを忘れないようにする。
実行結果