diff pytouhou/utils/matrix.pyx @ 435:878273a984c4

Improve Matrix representation, using float[16] instead of imbricated python lists.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Wed, 07 Aug 2013 11:34:40 +0200
parents f4d76d3d6f2a
children 26c082870dcf
line wrap: on
line diff
--- a/pytouhou/utils/matrix.pyx
+++ b/pytouhou/utils/matrix.pyx
@@ -16,92 +16,116 @@ from libc.math cimport sin, cos
 from libc.stdlib cimport malloc, free
 
 
-cdef float* matrix_to_floats(Matrix self):
-    for i in xrange(4):
-        for j in xrange(4):
-            self.c_data[i*4+j] = self.data[i][j]
-    return self.c_data
-
-
 cdef class Matrix:
-    def __cinit__(self):
-        self.c_data = <float*>malloc(16 * sizeof(float))
+    def __init__(self, data=None):
+        if data is None:
+            data = [1, 0, 0, 0,
+                    0, 1, 0, 0,
+                    0, 0, 1, 0,
+                    0, 0, 0, 1]
+        for i in xrange(4):
+            for j in xrange(4):
+                self.data[i*4+j] = data[4*i+j]
 
 
-    def __init__(self, data=None):
-        self.data = data or [[1, 0, 0, 0],
-                             [0, 1, 0, 0],
-                             [0, 0, 1, 0],
-                             [0, 0, 0, 1]]
+    def __mul__(Matrix self, Matrix other):
+        cdef float *d1, *d2, *d3
 
-
-    def __dealloc__(self):
-        free(self.c_data)
-
-
-    def __mul__(self, Matrix other):
         out = Matrix()
         d1 = self.data
         d2 = other.data
         d3 = out.data
         for i in xrange(4):
             for j in xrange(4):
-                d3[i][j] = sum(d1[i][k] * d2[k][j] for k in xrange(4))
+                d3[4*i+j] = 0
+                for k in xrange(4):
+                    d3[4*i+j] += d1[4*i+k] * d2[4*k+j]
         return out
 
 
-    cpdef flip(self):
+    cdef void flip(self) nogil:
+        cdef float *data
+
         data = self.data
-        a, b, c, d = data[0]
-        data[0] = [-a, -b, -c, -d]
+        for i in xrange(4):
+            data[i] = -data[i]
 
 
-    cpdef 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]]
+    cdef void scale(self, float x, float y, float z) nogil:
+        cdef float *data, coordinate[3]
+
+        data = self.data
+        coordinate[0] = x
+        coordinate[1] = y
+        coordinate[2] = z
+
+        for i in xrange(3):
+            for j in xrange(4):
+                data[4*i+j] *= coordinate[i]
 
 
-    cpdef scale2d(self, x, y):
+    cdef void scale2d(self, float x, float y) nogil:
+        cdef float *data
+
         data = self.data
-        d1a, d1b, d1c, d1d = data[0]
-        d2a, d2b, d2c, d2d = data[1]
-        data[0] = [d1a * x, d1b * x, d1c * x, d1d * x]
-        data[1] = [d2a * y, d2b * y, d2c * y, d2d * y]
+        for i in xrange(4):
+            data[  i] *= x
+            data[4+i] *= y
 
 
-    cpdef translate(self, x, y, z):
+    cdef void translate(self, float x, float y, float z) nogil:
+        cdef float *data, coordinate[3], item[3]
+
         data = self.data
-        a, b, c = data[3][:3]
-        a, b, c = a * x, b * y, c * z
-        d1a, d1b, d1c, d1d = data[0]
-        d2a, d2b, d2c, d2d = data[1]
-        d3a, d3b, d3c, d3d = data[2]
-        data[0] = [d1a + a, d1b + a, d1c + a, d1d + a]
-        data[1] = [d2a + b, d2b + b, d2c + b, d2d + b]
-        data[2] = [d3a + c, d3b + c, d3c + c, d3d + c]
+        coordinate[0] = x
+        coordinate[1] = y
+        coordinate[2] = z
+        for i in xrange(3):
+            item[i] = data[12+i] * coordinate[i]
+
+        for i in xrange(3):
+            for j in xrange(4):
+                data[4*i+j] += item[i]
 
 
-    cpdef rotate_x(self, angle):
-        d1 = self.data
+    cdef void rotate_x(self, float angle) nogil:
+        cdef float cos_a, sin_a
+        cdef float lines[8], *data
+
+        data = self.data
         cos_a = cos(angle)
         sin_a = sin(angle)
-        d1[1], d1[2] = ([cos_a * d1[1][i] - sin_a * d1[2][i] for i in range(4)],
-                        [sin_a * d1[1][i] + cos_a * d1[2][i] for i in range(4)])
+        for i in xrange(8):
+            lines[i] = data[i+4]
+        for i in xrange(4):
+            data[4+i] = cos_a * lines[i] - sin_a * lines[4+i]
+            data[8+i] = sin_a * lines[i] + cos_a * lines[4+i]
 
 
-    cpdef rotate_y(self, angle):
-        d1 = self.data
+    cdef void rotate_y(self, float angle) nogil:
+        cdef float cos_a, sin_a
+        cdef float lines[8], *data
+
+        data = self.data
         cos_a = cos(angle)
         sin_a = sin(angle)
-        d1[0], d1[2] = ([cos_a * d1[0][i] + sin_a * d1[2][i] for i in range(4)],
-                        [- sin_a * d1[0][i] + cos_a * d1[2][i] for i in range(4)])
+        for i in xrange(4):
+            lines[i] = data[i]
+            lines[i+4] = data[i+8]
+        for i in xrange(4):
+            data[  i] =  cos_a * lines[i] + sin_a * lines[4+i]
+            data[8+i] = -sin_a * lines[i] + cos_a * lines[4+i]
 
 
-    cpdef rotate_z(self, angle):
-        d1 = self.data
+    cdef void rotate_z(self, float angle) nogil:
+        cdef float cos_a, sin_a
+        cdef float lines[8], *data
+
+        data = self.data
         cos_a = cos(angle)
         sin_a = sin(angle)
-        d1[0], d1[1] = ([cos_a * d1[0][i] - sin_a * d1[1][i] for i in range(4)],
-                        [sin_a * d1[0][i] + cos_a * d1[1][i] for i in range(4)])
+        for i in xrange(8):
+            lines[i] = data[i]
+        for i in xrange(4):
+            data[  i] = cos_a * lines[i] - sin_a * lines[4+i]
+            data[4+i] = sin_a * lines[i] + cos_a * lines[4+i]