4次正方行列m1とm2の積mのi行j列目の計算は以下のようになります。
m[i][j] = m1[i][0]*m2[0][j] + m1[i][1]*m2[1][j] + m1[i][2]*m2[2][j] + m1[i][3]*m2[3][j]
上のiとjを0から3までくりかえします。
頂点座標p1と4次正方行列mの積p2のi列目の計算は以下のようになります。
ただし、p1は[x, y, z, 1]の形をしている斉次座標です。
p2[i] = p1[0]*m[0][i] + p1[1]*m[1][i] + p1[2]*m[2][i] + p1[3]*m[3][i]
上のiを0から3までくりかえします。
以下の関数を作成してください。
matmul(m1, m2)
pmatmul(p, m)
(計算例)
p = [5, 6, 7, 1]
m1 = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]]
m2 = [[21,22, 23, 24],
[25, 26, 27, 28],
[29, 30, 31, 32],
[33, 34, 35, 36]]
m = matmul(m1, m2)
print m
print pmatmul(p, m)
とするとm1とm2の積、pとの積が以下のように出力されるようにします。
移動、回転、スケールを行う行列は以下のように定義します。
t = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[tx, ty, tz, 1]]
import math
s = math.sin(r)
c = math.cos(r)
rx = [[1, 0, 0, 0],
[0, c, s, 0],
[0, s, c, 0],
[0, 0, 0, 1]]
import math
s = math.sin(r)
c = math.cos(r)
rx = [[c, 0, -s, 0],
[0, 1, 0, 0],
[s, 0, c, 0],
[0, 0, 0, 1]]
import math
s = math.sin(r)
c = math.cos(r)
rx = [[c, s, 0, 0],
[-s, c, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
s = [[sx, 0, 0, 0],
[0, sy, 0, 0],
[0, 0, sz, 0],
[0, 0, 0, 1]]
頂点p=[1, 2, 3]をX軸まわりに60度(3.14/3ラジアン)回転してから(2, 3, 4)だけスケールをして(5, 6, 7)移動するには以下のように計算します。
import math
p1 = [1, 2, 3, 1]
s = math.sin(3.14/3)
c = math.cos(3.14/3)
rx = [[1, 0, 0, 0],
[0, c, s, 0],
[0, s, c, 0],
[0, 0, 0, 1]]
s = [[2, 0, 0, 0],
[0, 3, 0, 0],
[0, 0, 4, 0],
[0, 0, 0, 1]]
t = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[5, 6, 7, 1]]
# p*rx*s*t
p2 = pmatmul(p1, rx)
p2 = pmatmul(p2, s)
p2 = pmatmul(p2, t)
print p2
# p*(rx*s*t)
m = matmul(rx, s)
m = matmul(m, t)
p3 = pmatmul(p1, m)
print p3
# p2とp3は同じ値が表示される
結果は以下のように出力されます。
以下のクラスをmatrix.pyというファイル名で作成してください。
class Coodinate4(object):
class Matrix4(object):
class TranslateM(Matrix4):
class RotateXM(Matrix4):
class RotateYM(Matrix4):
class RotateZM(Matrix4):
class ScaleM(Matrix4):
(計算例)
p = Coodinate4(1, 2, 0) rx = RotateXM(3.14/2) ry = RotateYM(3.14/2) rz = RotateZM(3.14/2) print p*rx # -> [1, 0.0015926534214665267, 1.9999993658636692, 1] print p*ry # -> [0.00079632671073326335, 2, -0.99999968293183461, 1] print p*rz # -> [-1.9992030391529361, 1.001592336353301, 0, 1] p = Coodinate4(1, 2, 3) rx = RotateXM(3.14/3) ry = RotateYM(3.14/3) rz = RotateZM(3.14/3) s = ScaleM(2, 3, 4) t = TranslateM(5, 6, 7) print p*rx*ry*rz*s*t # -> [2.0720547618139817, 19.971655947266981, 10.008702646121966, 1.0] print p*(rx*ry*rz*s*t) # -> [2.0720547618139817, 19.971655947266981, 10.008702646121966, 1.0]