(3) gluLookAt はどんな matrix を生成するのか? | Chandler@Berlin

Chandler@Berlin

ベルリン在住

gluLookAt implementation in python

gluLookAt matrix の私の python (numpy) での実装と,その test を以下に示す.この実装はわかりやすさを主にしているので matrix 乗算とtranspose が入っているが,もちろんこれらを省略するような実装も可能である.Test の結果,2つの matrix は私が試した限りでは,1.0e-6 以下の誤差で一致する.(Ubuntu 10.04, python 2.6, glx version 1.4)


# Copyright (C) 2010 H. Yamauchi
# under New (3-clause) BSD license

#
# get lookat matrix (gluLookAt compatible matrix) python, numpy
#
# \param[in] _eye eye point
# \param[in] _lookat lookat point
# \param[in] _up up vector
# \return 4x4 gluLookAt matrix
def getLookAtMatrix(_eye, _lookat, _up):
ez = _eye - _lookat
ez = ez / numpy.linalg.norm(ez)

ex = numpy.cross(_up, ez)
ex = ex / numpy.linalg.norm(ex)

ey = numpy.cross(ez, ex)
ey = ey / numpy.linalg.norm(ey)

rmat = numpy.eye(4)
rmat[0][0] = ex[0]
rmat[0][1] = ex[1]
rmat[0][2] = ex[2]

rmat[1][0] = ey[0]
rmat[1][1] = ey[1]
rmat[1][2] = ey[2]

rmat[2][0] = ez[0]
rmat[2][1] = ez[1]
rmat[2][2] = ez[2]

tmat = numpy.eye(4)
tmat[0][3] = -_eye[0]
tmat[1][3] = -_eye[1]
tmat[2][3] = -_eye[2]

# numpy.array * is element-wise multiplication, use dot()
lookatmat = numpy.dot(rmat, tmat).transpose()

return lookatmat


#
# test getLookAtMatrix routine
#
# generate two matrices, glmat by gluLookAt, mat by getLookAtMatrix.
# Then compare them. (To run this test, You need OpenGL bindings and
# also your Camera implementation that provides eye, lookat, up.)
#
def test_gluLookAt_matrix():

GL.glLoadIdentity()

# This is your camera. It tells eye, lookat, up.
[ep, at, up] = gl_camera.get_lookat()
GLU.gluLookAt(ep[0], ep[1], ep[2],
at[0], at[1], at[2],
up[0], up[1], up[2])

# OpenGL gluLookAt matrix
glmat = None
glmat = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)

# my matrix
mat = getLookAtMatrix(ep, at, up)

# debug output
print 'glmat'
print glmat
print 'mat'
print mat

# compare glmat and mat
for i in range(4):
for j in range(4):
if(math.fabs(glmat[i][j] - mat[i][j]) > 1.0e-6):
raise StandardError ('matrix does not match.')