# HG changeset patch # User Thibaut Girka # Date 1313178026 -7200 # Node ID f405b947624d6025c347afc58824ba2d3051e276 # Parent b65d6bc557939d260cb29150ef86ed40d9cb6755 Massive sprite updating/matrix handling optimizations diff --git a/pytouhou/game/sprite.py b/pytouhou/game/sprite.py --- a/pytouhou/game/sprite.py +++ b/pytouhou/game/sprite.py @@ -30,39 +30,29 @@ class Sprite(object): def update_uvs_vertices(self, override_width=0, override_height=0): - vertmat = Matrix() - vertmat.data[0][0] = -.5 - vertmat.data[1][0] = -.5 - - vertmat.data[0][1] = .5 - vertmat.data[1][1] = -.5 - - vertmat.data[0][2] = .5 - vertmat.data[1][2] = .5 - - vertmat.data[0][3] = -.5 - vertmat.data[1][3] = .5 - - for i in range(4): - vertmat.data[2][i] = 0. - vertmat.data[3][i] = 1. + vertmat = Matrix([[-.5, .5, .5, -.5], + [-.5, -.5, .5, .5], + [ .0, .0, .0, .0], + [ 1., 1., 1., 1.]]) tx, ty, tw, th = self.texcoords sx, sy = self.rescale width = override_width or (tw * sx) height = override_height or (th * sy) - transform = Matrix.get_scaling_matrix(width, height, 1.) + vertmat.scale(width, height, 1.) if self.mirrored: - transform = Matrix.get_scaling_matrix(-1., 1., 1.).mult(transform) + vertmat.flip() if self.rotations_3d != (0., 0., 0.): rx, ry, rz = self.rotations_3d - transform = Matrix.get_rotation_matrix(-rx, 'x').mult(transform) - transform = Matrix.get_rotation_matrix(ry, 'y').mult(transform) - transform = Matrix.get_rotation_matrix(-rz, 'z').mult(transform) #TODO: minus, really? + if rx: + vertmat.rotate_x(-rx) + if ry: + vertmat.rotate_y(ry) + if rz: + vertmat.rotate_z(-rz) #TODO: minus, really? if self.corner_relative_placement: # Reposition - transform = Matrix.get_translation_matrix(width / 2., height / 2., 0.).mult(transform) - vertmat = transform.mult(vertmat) + vertmat.translate(width / 2., height / 2., 0.) uvs = [(tx / self.anm.size[0], 1. - (ty / self.anm.size[1])), ((tx + tw) / self.anm.size[0], 1. - (ty / self.anm.size[1])), diff --git a/pytouhou/utils/matrix.py b/pytouhou/utils/matrix.py --- 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 +