Table Of Contents

Previous topic

Framework

Next topic

Vertex Array

This Page

Model View Matrix

移動行列(translation)

手始めに見た目が楽な移動行列。

まずソース

Translation.py

#!/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をあらわす。

glTranslateリファレンス

http://pyopengl.sourceforge.net/documentation/manual-3.0/glTranslate.xhtml には、以下の形式の行列が載っている。

\begin{pmatrix}
1 &0 &0 &x \\
0 &1 &0 &y \\
0 &0 &1 &z \\
0 &0 &0 &1 \\
\end{pmatrix}

これは、今回printした形式と順番が異なる(転置関係)。

\left(
\begin{array}{cccc}
1 &0 &0 &0 \\
0 &1 &0 &0 \\
0 &0 &1 &0 \\
x &y &z &1 \\
\end{array}
\right)

行列の格納方法と、数学での表記方法の対応関係について簡単に説明する。

OpenGLのドキュメントでのベクトル・行列の記述

v_{dst}=
\left(\begin{array}{c}x_{dst} \\ y_{dst} \\  z_{dst} \\  w_{dst}\end{array}\right)=
\begin{pmatrix}
m_{0} &m_{4} &m_{8} &m_{12} \\
m_{1} &m_{5} &m_{9} &m_{13} \\
m_{2} &m_{6} &m_{10} &m_{14} \\
m_{3} &m_{7} &m_{11} &m_{15} \\
\end{pmatrix}
\left(\begin{array}{c}x \\ y \\  z \\  w\end{array}\right)

という風に数学の教科書などで採用される列ベクトルで記述している(赤本や先のリファレンスページなど)。 一方、APIの実装では、glGetFloatv関数で取得したものをprintしたものからわかるように、添字の番号順(列優先)で配列に格納されている。

  • 列ベクトル+列優先
  • 数学の教科書と同じ表記になる
  • 列優先の格納
  • 複数の行列を順に適用する時に左にかけねばならない

このチュートリアル(あるいはDirectX方式)でのベクトル・行列の記述

このチュートリアル(あるいはDirectX方式)では、

v_{dst}=
\left(\begin{array}{cccc}x_{dst} &y_{dst} &z_{dst} &w_{dst}\end{array}\right)=
\left(\begin{array}{cccc}x &y &z &w\end{array}\right)
\begin{pmatrix}
m_{0} &m_{1} &m_{2} &m_{3} \\
m_{4} &m_{5} &m_{6} &m_{7} \\
m_{8} &m_{9} &m_{10} &m_{11} \\
m_{12} &m_{13} &m_{14} &m_{15} \\
\end{pmatrix}

という風に行ベクトルで記述し、行優先でデータを格納するという考え方を採用する。

  • 行ベクトル+行優先
  • 数学の教科書と同じ表記にならない
  • 行優先の格納(わかりやすい)
  • 複数の行列を順に適用する時に右にかけねばならない(わかりやすい)

結果的に転置の転置は同じなので、行列のメモリ配列は同じになるのに注意。

回転行列(rotation)

Rotation.py

#!/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 なのでだいたいこんな感じに。

inserted by FC2 system