comparison 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
comparison
equal deleted inserted replaced
434:18e4b121646b 435:878273a984c4
14 14
15 from libc.math cimport sin, cos 15 from libc.math cimport sin, cos
16 from libc.stdlib cimport malloc, free 16 from libc.stdlib cimport malloc, free
17 17
18 18
19 cdef float* matrix_to_floats(Matrix self): 19 cdef class Matrix:
20 for i in xrange(4): 20 def __init__(self, data=None):
21 for j in xrange(4): 21 if data is None:
22 self.c_data[i*4+j] = self.data[i][j] 22 data = [1, 0, 0, 0,
23 return self.c_data 23 0, 1, 0, 0,
24 0, 0, 1, 0,
25 0, 0, 0, 1]
26 for i in xrange(4):
27 for j in xrange(4):
28 self.data[i*4+j] = data[4*i+j]
24 29
25 30
26 cdef class Matrix: 31 def __mul__(Matrix self, Matrix other):
27 def __cinit__(self): 32 cdef float *d1, *d2, *d3
28 self.c_data = <float*>malloc(16 * sizeof(float))
29 33
30
31 def __init__(self, data=None):
32 self.data = data or [[1, 0, 0, 0],
33 [0, 1, 0, 0],
34 [0, 0, 1, 0],
35 [0, 0, 0, 1]]
36
37
38 def __dealloc__(self):
39 free(self.c_data)
40
41
42 def __mul__(self, Matrix other):
43 out = Matrix() 34 out = Matrix()
44 d1 = self.data 35 d1 = self.data
45 d2 = other.data 36 d2 = other.data
46 d3 = out.data 37 d3 = out.data
47 for i in xrange(4): 38 for i in xrange(4):
48 for j in xrange(4): 39 for j in xrange(4):
49 d3[i][j] = sum(d1[i][k] * d2[k][j] for k in xrange(4)) 40 d3[4*i+j] = 0
41 for k in xrange(4):
42 d3[4*i+j] += d1[4*i+k] * d2[4*k+j]
50 return out 43 return out
51 44
52 45
53 cpdef flip(self): 46 cdef void flip(self) nogil:
47 cdef float *data
48
54 data = self.data 49 data = self.data
55 a, b, c, d = data[0] 50 for i in xrange(4):
56 data[0] = [-a, -b, -c, -d] 51 data[i] = -data[i]
57 52
58 53
59 cpdef scale(self, x, y, z): 54 cdef void scale(self, float x, float y, float z) nogil:
60 d1 = self.data 55 cdef float *data, coordinate[3]
61 d1[0] = [a * x for a in d1[0]] 56
62 d1[1] = [a * y for a in d1[1]] 57 data = self.data
63 d1[2] = [a * z for a in d1[2]] 58 coordinate[0] = x
59 coordinate[1] = y
60 coordinate[2] = z
61
62 for i in xrange(3):
63 for j in xrange(4):
64 data[4*i+j] *= coordinate[i]
64 65
65 66
66 cpdef scale2d(self, x, y): 67 cdef void scale2d(self, float x, float y) nogil:
68 cdef float *data
69
67 data = self.data 70 data = self.data
68 d1a, d1b, d1c, d1d = data[0] 71 for i in xrange(4):
69 d2a, d2b, d2c, d2d = data[1] 72 data[ i] *= x
70 data[0] = [d1a * x, d1b * x, d1c * x, d1d * x] 73 data[4+i] *= y
71 data[1] = [d2a * y, d2b * y, d2c * y, d2d * y]
72 74
73 75
74 cpdef translate(self, x, y, z): 76 cdef void translate(self, float x, float y, float z) nogil:
77 cdef float *data, coordinate[3], item[3]
78
75 data = self.data 79 data = self.data
76 a, b, c = data[3][:3] 80 coordinate[0] = x
77 a, b, c = a * x, b * y, c * z 81 coordinate[1] = y
78 d1a, d1b, d1c, d1d = data[0] 82 coordinate[2] = z
79 d2a, d2b, d2c, d2d = data[1] 83 for i in xrange(3):
80 d3a, d3b, d3c, d3d = data[2] 84 item[i] = data[12+i] * coordinate[i]
81 data[0] = [d1a + a, d1b + a, d1c + a, d1d + a] 85
82 data[1] = [d2a + b, d2b + b, d2c + b, d2d + b] 86 for i in xrange(3):
83 data[2] = [d3a + c, d3b + c, d3c + c, d3d + c] 87 for j in xrange(4):
88 data[4*i+j] += item[i]
84 89
85 90
86 cpdef rotate_x(self, angle): 91 cdef void rotate_x(self, float angle) nogil:
87 d1 = self.data 92 cdef float cos_a, sin_a
93 cdef float lines[8], *data
94
95 data = self.data
88 cos_a = cos(angle) 96 cos_a = cos(angle)
89 sin_a = sin(angle) 97 sin_a = sin(angle)
90 d1[1], d1[2] = ([cos_a * d1[1][i] - sin_a * d1[2][i] for i in range(4)], 98 for i in xrange(8):
91 [sin_a * d1[1][i] + cos_a * d1[2][i] for i in range(4)]) 99 lines[i] = data[i+4]
100 for i in xrange(4):
101 data[4+i] = cos_a * lines[i] - sin_a * lines[4+i]
102 data[8+i] = sin_a * lines[i] + cos_a * lines[4+i]
92 103
93 104
94 cpdef rotate_y(self, angle): 105 cdef void rotate_y(self, float angle) nogil:
95 d1 = self.data 106 cdef float cos_a, sin_a
107 cdef float lines[8], *data
108
109 data = self.data
96 cos_a = cos(angle) 110 cos_a = cos(angle)
97 sin_a = sin(angle) 111 sin_a = sin(angle)
98 d1[0], d1[2] = ([cos_a * d1[0][i] + sin_a * d1[2][i] for i in range(4)], 112 for i in xrange(4):
99 [- sin_a * d1[0][i] + cos_a * d1[2][i] for i in range(4)]) 113 lines[i] = data[i]
114 lines[i+4] = data[i+8]
115 for i in xrange(4):
116 data[ i] = cos_a * lines[i] + sin_a * lines[4+i]
117 data[8+i] = -sin_a * lines[i] + cos_a * lines[4+i]
100 118
101 119
102 cpdef rotate_z(self, angle): 120 cdef void rotate_z(self, float angle) nogil:
103 d1 = self.data 121 cdef float cos_a, sin_a
122 cdef float lines[8], *data
123
124 data = self.data
104 cos_a = cos(angle) 125 cos_a = cos(angle)
105 sin_a = sin(angle) 126 sin_a = sin(angle)
106 d1[0], d1[1] = ([cos_a * d1[0][i] - sin_a * d1[1][i] for i in range(4)], 127 for i in xrange(8):
107 [sin_a * d1[0][i] + cos_a * d1[1][i] for i in range(4)]) 128 lines[i] = data[i]
129 for i in xrange(4):
130 data[ i] = cos_a * lines[i] - sin_a * lines[4+i]
131 data[4+i] = sin_a * lines[i] + cos_a * lines[4+i]