Mercurial > touhou
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] |