# HG changeset patch # User Emmanuel Gil Peyrot # Date 1375868080 -7200 # Node ID 878273a984c42a31c611d1c7017da77c97c58c41 # Parent 18e4b121646b834d4c05096ebf3a84142a655b54 Improve Matrix representation, using float[16] instead of imbricated python lists. diff --git a/pytouhou/ui/background.pyx b/pytouhou/ui/background.pyx --- a/pytouhou/ui/background.pyx +++ b/pytouhou/ui/background.pyx @@ -79,7 +79,7 @@ cdef class BackgroundRenderer: for ox2, oy2, oz2, width_override, height_override, sprite in model: #TODO: view frustum culling key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite) - (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices + x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4 = vertices left, right, bottom, top = uvs r, g, b, a = colors diff --git a/pytouhou/ui/gamerenderer.pyx b/pytouhou/ui/gamerenderer.pyx --- a/pytouhou/ui/gamerenderer.pyx +++ b/pytouhou/ui/gamerenderer.pyx @@ -12,7 +12,6 @@ ## GNU General Public License for more details. ## -from libc.stdlib cimport malloc, free from itertools import chain from pytouhou.lib.opengl cimport \ @@ -21,7 +20,7 @@ from pytouhou.lib.opengl cimport \ GL_PROJECTION, GL_MODELVIEW, GL_FOG, GL_FOG_MODE, GL_LINEAR, GL_FOG_START, GL_FOG_END, GL_FOG_COLOR, GL_COLOR_BUFFER_BIT, GLfloat) -from pytouhou.utils.matrix cimport Matrix, matrix_to_floats +from pytouhou.utils.matrix cimport Matrix from pytouhou.utils.maths cimport setup_camera from .renderer import Renderer @@ -34,7 +33,8 @@ class GameRenderer(Renderer): def render(self): - cdef float* fog_data + cdef float fog_data[4] + cdef Matrix view, mvp back = self.background game = self.game @@ -46,7 +46,7 @@ class GameRenderer(Renderer): if game is not None and game.spellcard_effect is not None: if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(matrix_to_floats(self.game_mvp)) + glLoadMatrixf((self.game_mvp).data) glDisable(GL_FOG) else: self.game_shader.bind() @@ -68,26 +68,26 @@ class GameRenderer(Renderer): fog_end -= 101010101./2010101. model = Matrix() - model.data[3] = [-x, -y, -z, 1] + model.data[12] = -x + model.data[13] = -y + model.data[14] = -z view = setup_camera(dx, dy, dz) mvp = model * view * self.proj if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(matrix_to_floats(mvp)) + glLoadMatrixf(mvp.data) glEnable(GL_FOG) glFogi(GL_FOG_MODE, GL_LINEAR) glFogf(GL_FOG_START, fog_start) glFogf(GL_FOG_END, fog_end) - fog_data = malloc(4 * sizeof(float)) fog_data[0] = fog_r / 255. fog_data[1] = fog_g / 255. fog_data[2] = fog_b / 255. fog_data[3] = 1. glFogfv(GL_FOG_COLOR, fog_data) - free(fog_data) else: self.background_shader.bind() self.background_shader.uniform_matrix('mvp', mvp) @@ -103,7 +103,7 @@ class GameRenderer(Renderer): if game is not None: if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(matrix_to_floats(self.game_mvp)) + glLoadMatrixf((self.game_mvp).data) glDisable(GL_FOG) else: self.game_shader.bind() diff --git a/pytouhou/ui/gamerunner.pyx b/pytouhou/ui/gamerunner.pyx --- a/pytouhou/ui/gamerunner.pyx +++ b/pytouhou/ui/gamerunner.pyx @@ -21,7 +21,7 @@ from pytouhou.lib.opengl cimport \ from pytouhou.utils.helpers import get_logger from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d -from pytouhou.utils.matrix cimport matrix_to_floats +from pytouhou.utils.matrix cimport Matrix from .gamerenderer import GameRenderer from .background import BackgroundRenderer @@ -182,7 +182,7 @@ class GameRunner(GameRenderer): if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(matrix_to_floats(self.interface_mvp)) + glLoadMatrixf((self.interface_mvp).data) glDisable(GL_FOG) else: self.interface_shader.bind() diff --git a/pytouhou/ui/renderer.pyx b/pytouhou/ui/renderer.pyx --- a/pytouhou/ui/renderer.pyx +++ b/pytouhou/ui/renderer.pyx @@ -67,7 +67,7 @@ cdef class Renderer: rec = indices_by_texture.setdefault(key, []) # Pack data in buffer - (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices + x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4 = vertices left, right, bottom, top = uvs r, g, b, a = colors self.vertex_buffer[nb_vertices] = Vertex(x1 + ox, y1 + oy, z1, left, bottom, r, g, b, a) diff --git a/pytouhou/ui/shader.pyx b/pytouhou/ui/shader.pyx --- a/pytouhou/ui/shader.pyx +++ b/pytouhou/ui/shader.pyx @@ -19,7 +19,7 @@ from pytouhou.lib.opengl cimport \ GLuint, GLchar, GLfloat, GLenum) from libc.stdlib cimport malloc, free -from pytouhou.utils.matrix cimport Matrix, matrix_to_floats +from pytouhou.utils.matrix cimport Matrix class GLSLException(Exception): @@ -145,4 +145,4 @@ cdef class Shader: # obtain the uniform location loc = self.get_uniform_location(name) # uplaod the 4x4 floating point matrix - glUniformMatrix4fv(loc, 1, False, matrix_to_floats(mat)) + glUniformMatrix4fv(loc, 1, False, mat.data) diff --git a/pytouhou/ui/sprite.pyx b/pytouhou/ui/sprite.pyx --- a/pytouhou/ui/sprite.pyx +++ b/pytouhou/ui/sprite.pyx @@ -24,10 +24,10 @@ cpdef object get_sprite_rendering_data(o if not sprite.changed: return sprite._rendering_data - vertmat = Matrix([[-.5, .5, .5, -.5], - [-.5, -.5, .5, .5], - [ .0, .0, .0, .0], - [ 1., 1., 1., 1.]]) + vertmat = Matrix([-.5, .5, .5, -.5, + -.5, -.5, .5, .5, + .0, .0, .0, .0, + 1., 1., 1., 1.]) tx, ty, tw, th = sprite.texcoords sx, sy = sprite.rescale @@ -64,11 +64,9 @@ cpdef object get_sprite_rendering_data(o ty * y_1 + toy, (ty + th) * y_1 + toy) - (x1, x2 , x3, x4), (y1, y2, y3, y4), (z1, z2, z3, z4), _ = vertmat.data - key = sprite.anm.texture, sprite.blendfunc r, g, b = sprite.color - values = ((x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4)), uvs, (r, g, b, sprite.alpha) + values = tuple([x for x in vertmat.data[:12]]), uvs, (r, g, b, sprite.alpha) sprite._rendering_data = key, values sprite.changed = False diff --git a/pytouhou/utils/maths.pyx b/pytouhou/utils/maths.pyx --- a/pytouhou/utils/maths.pyx +++ b/pytouhou/utils/maths.pyx @@ -20,13 +20,15 @@ from .vector import Vector, normalize, c cpdef ortho_2d(left, right, bottom, top): + cdef float *data + mat = Matrix() data = mat.data - data[0][0] = 2 / (right - left) - data[1][1] = 2 / (top - bottom) - data[2][2] = -1 - data[3][0] = -(right + left) / (right - left) - data[3][1] = -(top + bottom) / (top - bottom) + data[4*0+0] = 2 / (right - left) + data[4*1+1] = 2 / (top - bottom) + data[4*2+2] = -1 + data[4*3+0] = -(right + left) / (right - left) + data[4*3+1] = -(top + bottom) / (top - bottom) return mat @@ -40,13 +42,15 @@ cpdef look_at(eye, center, up): s = normalize(cross(f, u)) u = cross(s, f) - return Matrix([[s[0], u[0], -f[0], 0], - [s[1], u[1], -f[1], 0], - [s[2], u[2], -f[2], 0], - [-dot(s, eye), -dot(u, eye), dot(f, eye), 1]]) + return Matrix([s[0], u[0], -f[0], 0, + s[1], u[1], -f[1], 0, + s[2], u[2], -f[2], 0, + -dot(s, eye), -dot(u, eye), dot(f, eye), 1]) cpdef perspective(fovy, aspect, z_near, z_far): + cdef float *data + top = tan(radians(fovy / 2)) * z_near bottom = -top left = -top * aspect @@ -54,12 +58,12 @@ cpdef perspective(fovy, aspect, z_near, mat = Matrix() data = mat.data - data[0][0] = (2 * z_near) / (right - left) - data[1][1] = (2 * z_near) / (top - bottom) - data[2][2] = -(z_far + z_near) / (z_far - z_near) - data[2][3] = -1 - data[3][2] = -(2 * z_far * z_near) / (z_far - z_near) - data[3][3] = 0 + data[4*0+0] = (2 * z_near) / (right - left) + data[4*1+1] = (2 * z_near) / (top - bottom) + data[4*2+2] = -(z_far + z_near) / (z_far - z_near) + data[4*2+3] = -1 + data[4*3+2] = -(2 * z_far * z_near) / (z_far - z_near) + data[4*3+3] = 0 return mat diff --git a/pytouhou/utils/matrix.pxd b/pytouhou/utils/matrix.pxd --- a/pytouhou/utils/matrix.pxd +++ b/pytouhou/utils/matrix.pxd @@ -1,13 +1,10 @@ -cdef float* matrix_to_floats(Matrix self) - cdef class Matrix: - cdef public list data - cdef float *c_data + cdef float data[16] - cpdef flip(self) - cpdef scale(self, x, y, z) - cpdef scale2d(self, x, y) - cpdef translate(self, x, y, z) - cpdef rotate_x(self, angle) - cpdef rotate_y(self, angle) - cpdef rotate_z(self, angle) + cdef void flip(self) nogil + cdef void scale(self, float x, float y, float z) nogil + cdef void scale2d(self, float x, float y) nogil + cdef void translate(self, float x, float y, float z) nogil + cdef void rotate_x(self, float angle) nogil + cdef void rotate_y(self, float angle) nogil + cdef void rotate_z(self, float angle) nogil diff --git a/pytouhou/utils/matrix.pyx b/pytouhou/utils/matrix.pyx --- 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 = 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]