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