diff pytouhou/utils/matrix.py @ 28:f405b947624d

Massive sprite updating/matrix handling optimizations
author Thibaut Girka <thib@sitedethib.com>
date Fri, 12 Aug 2011 21:40:26 +0200
parents 787d2eb13c2d
children e3ba2fa966f6
line wrap: on
line diff
--- a/pytouhou/utils/matrix.py
+++ b/pytouhou/utils/matrix.py
@@ -3,64 +3,102 @@
 from math import sin, cos
 
 class Matrix(object):
-    def __init__(self):
-        self.data = [[0] * 4 for i in xrange(4)]
+    def __init__(self, data=None):
+        self.data = data or [[0] * 4 for i in xrange(4)]
 
 
     def mult(self, other_matrix):
-        result = Matrix()
-        for i in xrange(4):
-            for j in xrange(4):
-                result.data[i][j] = sum(self.data[i][a] * other_matrix.data[a][j] for a in xrange(4))
-        return result
+        d1 = self.data
+        d2 = other_matrix.data
+        return Matrix([[sum(d1[i][a] * d2[a][j] for a in xrange(4)) for j in xrange(4)] for i in xrange(4)])
+
+
+    def flip(self):
+        self.data[0][:] = (-x for x in self.data[0])
+
+
+    def scale(self, x, y, z):
+        d1 = self.data
+        d1[0][:] = (a * x for a in d1[0])
+        d1[1][:] = (a * y for a in d1[1])
+        d1[2][:] = (a * z for a in d1[2])
+
+
+    def translate(self, x, y, z):
+        d1 = self.data
+        a, b, c = (v * m for v, m in zip(d1[3][:3], (x, y, z)))
+        d1[0][:] = (v + a for v in d1[0])
+        d1[1][:] = (v + b for v in d1[1])
+        d1[2][:] = (v + c for v in d1[2])
+
+
+    def rotate_x(self, angle):
+        d1 = self.data
+        cos_a = cos(angle)
+        sin_a = sin(angle)
+        a = [cos_a * d1[1][i] - sin_a * d1[2][i] for i in range(4)]
+        b = [sin_a * d1[1][i] + cos_a * d1[2][i] for i in range(4)]
+        d1[1][:] = a
+        d1[2][:] = b
+
+
+    def rotate_y(self, angle):
+        #TODO: check
+        d1 = self.data
+        cos_a = cos(angle)
+        sin_a = sin(angle)
+        a = [cos_a * d1[0][i] - sin_a * d1[2][i] for i in range(4)]
+        b = [sin_a * d1[0][i] + cos_a * d1[2][i] for i in range(4)]
+        d1[0][:] = a
+        d1[2][:] = b
+
+
+    def rotate_z(self, angle):
+        d1 = self.data
+        cos_a = cos(angle)
+        sin_a = sin(angle)
+        a = [cos_a * d1[0][i] - sin_a * d1[1][i] for i in range(4)]
+        b = [sin_a * d1[0][i] + cos_a * d1[1][i] for i in range(4)]
+        d1[0][:] = a
+        d1[1][:] = b
 
 
     @classmethod
     def get_translation_matrix(cls, x, y, z):
-        matrix = cls()
-        matrix.data[0][0] = 1
-        matrix.data[1][1] = 1
-        matrix.data[2][2] = 1
-        matrix.data[3][3] = 1
-        matrix.data[0][3] = x
-        matrix.data[1][3] = y
-        matrix.data[2][3] = z
-        return matrix
+        return cls([[1., 0., 0., x],
+                    [0., 1., 0., y],
+                    [0., 0., 1., z],
+                    [0., 0., 0., 1.]])
 
 
     @classmethod
     def get_scaling_matrix(cls, x, y, z):
-        matrix = cls()
-        matrix.data[0][0] = x
-        matrix.data[1][1] = y
-        matrix.data[2][2] = z
-        matrix.data[3][3] = 1
-        return matrix
+        return cls([[x,  0., 0., 0.],
+                    [0., y,  0., 0.],
+                    [0., 0., z,  0.],
+                    [0., 0., 0., 1.]])
 
 
     @classmethod
     def get_rotation_matrix(cls, angle, axis):
         """Only handles axis = x, y or z."""
-        matrix = cls()
-        matrix.data[3][3] = 1
+        cos_a = cos(angle)
+        sin_a = sin(angle)
         if axis == 'x':
-            matrix.data[0][0] = 1
-            matrix.data[1][1] = cos(angle)
-            matrix.data[1][2] = -sin(angle)
-            matrix.data[2][1] = sin(angle)
-            matrix.data[2][2] = cos(angle)
+            return Matrix([[    1.,     0.,     0.,     0.],
+                           [    0.,  cos_a, -sin_a,     0.],
+                           [    0.,  sin_a,  cos_a,     0.],
+                           [    0.,     0.,     0.,     1.]])
         elif axis == 'y':
-            matrix.data[0][0] = cos(angle)
-            matrix.data[0][2] = sin(angle)
-            matrix.data[2][0] = -sin(angle)
-            matrix.data[2][2] = cos(angle)
-            matrix.data[1][1] = 1
+            return Matrix([[ cos_a,     0.,  sin_a,     0.],
+                           [    0.,     1.,     0.,     0.],
+                           [-sin_a,     0.,  cos_a,     0.],
+                           [    0.,     0.,     0.,     1.]])
         elif axis == 'z':
-            matrix.data[0][0] = cos(angle)
-            matrix.data[0][1] = -sin(angle)
-            matrix.data[1][0] = sin(angle)
-            matrix.data[1][1] = cos(angle)
-            matrix.data[2][2] = 1
+            return Matrix([[ cos_a, -sin_a,     0.,     0.],
+                           [ sin_a,  cos_a,     0.,     0.],
+                           [    0.,     0.,     1.,     0.],
+                           [    0.,     0.,     0.,     1.]])
         else:
             raise Exception
-        return matrix
+