手始めに見た目が楽な移動行列。
まずソース
#!/usr/bin/python
# coding: utf-8
from OpenGL.GL import *
import glut_ui
import glbase
import baseview
import triangle
class Translation(baseview.BaseView):
def __init__(self):
super(Translation, self).__init__()
self.pos_x=0
self.pos_y=0
def onMotion(self, x, y):
# マウスカーソルの座標を左右-1〜+1、上下-1〜+1の範囲に変換する
self.pos_x=float(x)/self.w*2-1
self.pos_y=-(float(y)/self.h*2-1)
# 再描画したいのでTrueを返す
return True
def updateView(self):
print("## IDENTITY ##")
self.printMatrix(glGetFloatv(GL_MODELVIEW_MATRIX))
glTranslate(self.pos_x, self.pos_y, 0)
print "## GL_MODELVIEW_MATRIX ##", self.pos_x, self.pos_y
self.printMatrix(glGetFloatv(GL_MODELVIEW_MATRIX))
if __name__=="__main__":
glut_ui.run(glbase.BaseController(Translation(), triangle.Triangle()))
実行して適当にドラッグしてみる(左・中・右の区別なし)。 マウスドラッグにあわせてビュー行列の移動値が変更され、結果的に三角形が移動する。
## IDENTITY ##
(1.0, 0.0, 0.0, 0.0)
(0.0, 1.0, 0.0, 0.0)
(0.0, 0.0, 1.0, 0.0)
(0.0, 0.0, 0.0, 1.0)
## GL_MODELVIEW_MATRIX ## 0.440625 -0.758333333333
(1.0, 0.0, 0.0, 0.0)
(0.0, 1.0, 0.0, 0.0)
(0.0, 0.0, 1.0, 0.0)
(0.44062501192092896, -0.75833332538604736, 0.0, 1.0)
OpenGLでは、3次元の移動に4x4の行列を使う。 GL_MODELVIEW_MATRIXの第4行の第1、第2、第3列は移動のx, y, zをあらわす。
http://pyopengl.sourceforge.net/documentation/manual-3.0/glTranslate.xhtml には、以下の形式の行列が載っている。
これは、今回printした形式と順番が異なる(転置関係)。
行列の格納方法と、数学での表記方法の対応関係について簡単に説明する。
という風に数学の教科書などで採用される列ベクトルで記述している(赤本や先のリファレンスページなど)。 一方、APIの実装では、glGetFloatv関数で取得したものをprintしたものからわかるように、添字の番号順(列優先)で配列に格納されている。
このチュートリアル(あるいはDirectX方式)では、
という風に行ベクトルで記述し、行優先でデータを格納するという考え方を採用する。
結果的に転置の転置は同じなので、行列のメモリ配列は同じになるのに注意。
#!/usr/bin/python
# coding: utf-8
#!/usr/bin/python
# coding: utf-8
from OpenGL.GL import *
import glut_ui
import glbase
import baseview
class Rotation(baseview.BaseView):
def __init__(self):
super(Rotation, self).__init__()
self.head=0
def onMotion(self, x, y):
# 回転角度
self.head+=x-self.x
self.x=x
self.y=y
# 再描画したいのでTrueを返す
return True
def updateView(self):
glRotate(self.head, 0, 1, 0)
print "## GL_MODELVIEW_MATRIX ##", self.head
self.printMatrix(glGetFloatv(GL_MODELVIEW_MATRIX))
if __name__=="__main__":
import triangle
glut_ui.run(glbase.BaseController(Rotation(), triangle.Triangle()))
今度は回転行列。
## GL_MODELVIEW_MATRIX ## 30
(0.86602538824081421, 0.0, -0.5, 0.0)
(0.0, 1.0, 0.0, 0.0)
(0.5, 0.0, 0.86602538824081421, 0.0)
(0.0, 0.0, 0.0, 1.0)
分かりやすいようにY軸での30度回転の結果。 sin30度=0.5 cos30度=0.866025404 なのでだいたいこんな感じに。