# HG changeset patch # User Emmanuel Gil Peyrot # Date 1387385609 -3600 # Node ID 6e3b3d5d469127ff8d5cc3750daef634ef9323dc # Parent e8496e5ba05660f7f4b24af430e4b7fea887008f Make matrix a struct. diff --git a/pytouhou/ui/opengl/gamerenderer.pxd b/pytouhou/ui/opengl/gamerenderer.pxd --- a/pytouhou/ui/opengl/gamerenderer.pxd +++ b/pytouhou/ui/opengl/gamerenderer.pxd @@ -5,7 +5,7 @@ from .renderer cimport Renderer, Framebu from .shader cimport Shader cdef class GameRenderer(Renderer): - cdef Matrix game_mvp, interface_mvp, proj + cdef Matrix *game_mvp, *interface_mvp, *proj cdef Shader game_shader, background_shader, interface_shader, passthrough_shader cdef Framebuffer framebuffer cdef BackgroundRenderer background_renderer diff --git a/pytouhou/ui/opengl/gamerenderer.pyx b/pytouhou/ui/opengl/gamerenderer.pyx --- a/pytouhou/ui/opengl/gamerenderer.pyx +++ b/pytouhou/ui/opengl/gamerenderer.pyx @@ -12,6 +12,7 @@ ## GNU General Public License for more details. ## +from libc.stdlib cimport free from itertools import chain from pytouhou.lib.opengl cimport \ @@ -21,6 +22,7 @@ from pytouhou.lib.opengl cimport \ GL_FOG_COLOR, GL_COLOR_BUFFER_BIT, GLfloat, glViewport, glScissor, GL_SCISSOR_TEST, GL_DEPTH_BUFFER_BIT) +from pytouhou.utils.matrix cimport mul, new_identity from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d from pytouhou.game.text cimport NativeText, GlyphCollection from .shaders.eosd import GameShader, BackgroundShader, PassthroughShader @@ -46,6 +48,15 @@ cdef class GameRenderer(Renderer): self.framebuffer = Framebuffer(0, 0, 640, 480) + def __dealloc__(self): + if self.game_mvp != NULL: + free(self.game_mvp) + if self.interface_mvp != NULL: + free(self.interface_mvp) + if self.proj != NULL: + free(self.proj) + + property size: # We never need to get back the computed size, so size is write-only. def __set__(self, tuple size): @@ -68,8 +79,8 @@ cdef class GameRenderer(Renderer): def start(self, common): self.proj = perspective(30, float(common.width) / float(common.height), 101010101./2010101., 101010101./10101.) - game_view = setup_camera(0, 0, 1) - self.game_mvp = game_view * self.proj + self.game_mvp = setup_camera(0, 0, 1) + mul(self.game_mvp, self.proj) self.interface_mvp = ortho_2d(0., float(common.interface.width), float(common.interface.height), 0.) @@ -92,7 +103,7 @@ cdef class GameRenderer(Renderer): cdef long game_x, game_y cdef float x, y, z, dx, dy, dz, fog_data[4], fog_start, fog_end cdef unsigned char fog_r, fog_g, fog_b - cdef Matrix mvp + cdef Matrix *mvp game_x, game_y = game.interface.game_pos glViewport(game_x, game_y, game.width, game.height) @@ -107,7 +118,7 @@ cdef class GameRenderer(Renderer): if game is not None and game.spellcard_effect is not None: if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.game_mvp.data) + glLoadMatrixf(self.game_mvp) glDisable(GL_FOG) else: self.game_shader.bind() @@ -129,16 +140,19 @@ cdef class GameRenderer(Renderer): fog_start -= 101010101./2010101. fog_end -= 101010101./2010101. - model = Matrix() - model.data[12] = -x - model.data[13] = -y - model.data[14] = -z + mvp = new_identity() + mvp_data = mvp + mvp_data[12] = -x + mvp_data[13] = -y + mvp_data[14] = -z view = setup_camera(dx, dy, dz) - mvp = model * view * self.proj + mul(mvp, view) + free(view) + mul(mvp, self.proj) if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(mvp.data) + glLoadMatrixf(mvp_data) glEnable(GL_FOG) glFogi(GL_FOG_MODE, GL_LINEAR) @@ -158,6 +172,7 @@ cdef class GameRenderer(Renderer): self.background_shader.uniform_1('fog_end', fog_end) self.background_shader.uniform_4('fog_color', fog_r / 255., fog_g / 255., fog_b / 255., 1.) + free(mvp) self.background_renderer.render_background() else: glClear(GL_COLOR_BUFFER_BIT) @@ -165,7 +180,7 @@ cdef class GameRenderer(Renderer): if game is not None: if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.game_mvp.data) + glLoadMatrixf(self.game_mvp) glDisable(GL_FOG) else: self.game_shader.bind() @@ -220,7 +235,7 @@ cdef class GameRenderer(Renderer): if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.interface_mvp.data) + glLoadMatrixf(self.interface_mvp) glDisable(GL_FOG) else: self.interface_shader.bind() diff --git a/pytouhou/ui/opengl/shader.pxd b/pytouhou/ui/opengl/shader.pxd --- a/pytouhou/ui/opengl/shader.pxd +++ b/pytouhou/ui/opengl/shader.pxd @@ -12,4 +12,4 @@ cdef class Shader: cdef void bind(self) nogil cdef void uniform_1(self, name, GLfloat val) except * cdef void uniform_4(self, name, GLfloat a, GLfloat b, GLfloat c, GLfloat d) except * - cdef void uniform_matrix(self, name, Matrix mat) except * + cdef void uniform_matrix(self, name, Matrix *mat) except * diff --git a/pytouhou/ui/opengl/shader.pyx b/pytouhou/ui/opengl/shader.pyx --- a/pytouhou/ui/opengl/shader.pyx +++ b/pytouhou/ui/opengl/shader.pyx @@ -135,8 +135,8 @@ cdef class Shader: # upload a uniform matrix # works with matrices stored as lists, # as well as euclid matrices - cdef void uniform_matrix(self, name, Matrix mat): + cdef void uniform_matrix(self, name, Matrix *mat): # obtain the uniform location loc = self.get_uniform_location(name) # uplaod the 4x4 floating point matrix - glUniformMatrix4fv(loc, 1, False, mat.data) + glUniformMatrix4fv(loc, 1, False, mat) diff --git a/pytouhou/ui/opengl/sprite.pyx b/pytouhou/ui/opengl/sprite.pyx --- a/pytouhou/ui/opengl/sprite.pyx +++ b/pytouhou/ui/opengl/sprite.pyx @@ -15,29 +15,30 @@ from libc.math cimport M_PI as pi -from pytouhou.utils.matrix cimport Matrix +from pytouhou.utils.matrix cimport Matrix, scale2d, flip, rotate_x, rotate_y, rotate_z, translate, translate2d from .renderer cimport Texture #XXX cpdef tuple get_sprite_rendering_data(Sprite sprite): cdef double tx, ty, tw, th, sx, sy, rx, ry, rz, tox, toy + cdef Matrix vertmat 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 width = sprite.width_override or (tw * sx) height = sprite.height_override or (th * sy) - vertmat.scale2d(width, height) + scale2d(&vertmat, width, height) if sprite.mirrored: - vertmat.flip() + flip(&vertmat) rx, ry, rz = sprite.rotations_3d if sprite.automatic_orientation: @@ -46,15 +47,15 @@ cpdef tuple get_sprite_rendering_data(Sp rz += sprite.angle if rx: - vertmat.rotate_x(-rx) + rotate_x(&vertmat, -rx) if ry: - vertmat.rotate_y(ry) + rotate_y(&vertmat, ry) if rz: - vertmat.rotate_z(-rz) #TODO: minus, really? + rotate_z(&vertmat, -rz) #TODO: minus, really? if sprite.allow_dest_offset: - vertmat.translate(sprite.dest_offset[0], sprite.dest_offset[1], sprite.dest_offset[2]) + translate(&vertmat, sprite.dest_offset[0], sprite.dest_offset[1], sprite.dest_offset[2]) if sprite.corner_relative_placement: # Reposition - vertmat.translate(width / 2, height / 2, 0) + translate2d(&vertmat, width / 2, height / 2) size = sprite.anm.size x_1 = 1 / size[0] @@ -67,7 +68,7 @@ cpdef tuple get_sprite_rendering_data(Sp key = ((sprite.anm.texture).key << 1) | sprite.blendfunc r, g, b = sprite.color - values = tuple([x for x in vertmat.data[:12]]), uvs, (r, g, b, sprite.alpha) + values = tuple([x for x in (&vertmat)[:12]]), uvs, (r, g, b, sprite.alpha) sprite._rendering_data = key, values sprite.changed = False diff --git a/pytouhou/utils/maths.pxd b/pytouhou/utils/maths.pxd --- a/pytouhou/utils/maths.pxd +++ b/pytouhou/utils/maths.pxd @@ -1,5 +1,5 @@ from .matrix cimport Matrix -cdef Matrix ortho_2d(float left, float right, float bottom, float top) -cdef Matrix perspective(float fovy, float aspect, float zNear, float zFar) -cdef Matrix setup_camera(float dx, float dy, float dz) +cdef Matrix *ortho_2d(float left, float right, float bottom, float top) +cdef Matrix *perspective(float fovy, float aspect, float zNear, float zFar) +cdef Matrix *setup_camera(float dx, float dy, float dz) diff --git a/pytouhou/utils/maths.pyx b/pytouhou/utils/maths.pyx --- a/pytouhou/utils/maths.pyx +++ b/pytouhou/utils/maths.pyx @@ -14,6 +14,7 @@ from libc.math cimport tan, M_PI as pi +from .matrix cimport new_matrix, new_identity from .vector cimport Vector, normalize, cross, dot @@ -21,11 +22,9 @@ cdef double radians(double degrees) nogi return degrees * pi / 180 -cdef Matrix ortho_2d(float left, float right, float bottom, float top): - cdef float *data - - mat = Matrix() - data = mat.data +cdef Matrix *ortho_2d(float left, float right, float bottom, float top): + mat = new_identity() + data = mat data[4*0+0] = 2 / (right - left) data[4*1+1] = 2 / (top - bottom) data[4*2+2] = -1 @@ -34,28 +33,30 @@ cdef Matrix ortho_2d(float left, float r return mat -cdef Matrix look_at(Vector eye, Vector center, Vector up): +cdef Matrix *look_at(Vector eye, Vector center, Vector up): + cdef Matrix mat + f = normalize(center.sub(eye)) u = normalize(up) s = normalize(cross(f, u)) u = cross(s, f) - return Matrix([s.x, u.x, -f.x, 0, - s.y, u.y, -f.y, 0, - s.z, u.z, -f.z, 0, - -dot(s, eye), -dot(u, eye), dot(f, eye), 1]) + mat = Matrix(s.x, u.x, -f.x, 0, + s.y, u.y, -f.y, 0, + s.z, u.z, -f.z, 0, + -dot(s, eye), -dot(u, eye), dot(f, eye), 1) + + return new_matrix(&mat) -cdef Matrix perspective(float fovy, float aspect, float z_near, float z_far): - cdef float *data - +cdef Matrix *perspective(float fovy, float aspect, float z_near, float z_far): top = tan(radians(fovy / 2)) * z_near bottom = -top left = -top * aspect right = top * aspect - mat = Matrix() - data = mat.data + mat = new_identity() + data = mat 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) @@ -65,7 +66,7 @@ cdef Matrix perspective(float fovy, floa return mat -cdef Matrix setup_camera(float dx, float dy, float dz): +cdef Matrix *setup_camera(float dx, float dy, float dz): # Some explanations on the magic constants: # 192. = 384. / 2. = width / 2. # 224. = 448. / 2. = height / 2. diff --git a/pytouhou/utils/matrix.pxd b/pytouhou/utils/matrix.pxd --- a/pytouhou/utils/matrix.pxd +++ b/pytouhou/utils/matrix.pxd @@ -1,10 +1,18 @@ -cdef class Matrix: - cdef float data[16] +ctypedef struct Matrix: + float a, b, c, d + float e, f, g, h + float i, j, k, l + float m, n, o, p + +cdef Matrix *new_matrix(Matrix *data) nogil +cdef Matrix *new_identity() nogil - 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 +cdef void mul(Matrix *mat1, Matrix *mat2) nogil +cdef void flip(Matrix *mat) nogil +cdef void scale(Matrix *mat, float x, float y, float z) nogil +cdef void scale2d(Matrix *mat, float x, float y) nogil +cdef void translate(Matrix *mat, float x, float y, float z) nogil +cdef void translate2d(Matrix *mat, float x, float y) nogil +cdef void rotate_x(Matrix *mat, float angle) nogil +cdef void rotate_y(Matrix *mat, float angle) nogil +cdef void rotate_z(Matrix *mat, 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 @@ -17,120 +17,123 @@ from libc.stdlib cimport malloc, free from libc.string cimport memcpy -cdef float[16] identity -identity[:] = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1] +cdef Matrix identity +identity = Matrix(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1) -cdef class Matrix: - def __init__(self, data=None): - if data is not None: - for i in xrange(16): - self.data[i] = data[i] - else: - memcpy(self.data, identity, 16 * sizeof(float)) +cdef Matrix *new_matrix(Matrix *data) nogil: + mat = malloc(sizeof(Matrix)) + memcpy(mat, data, sizeof(Matrix)) + return mat + + +cdef Matrix *new_identity() nogil: + return new_matrix(&identity) - def __mul__(Matrix self, Matrix other): - cdef float *d1, *d2, *d3 +cdef void mul(Matrix *mat1, Matrix *mat2) nogil: + cdef float *d3 - out = Matrix() - d1 = self.data - d2 = other.data - d3 = out.data - for i in xrange(4): - for j 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 + out = malloc(sizeof(Matrix)) + d1 = mat1 + d2 = mat2 + d3 = out + for i in xrange(4): + for j 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] + memcpy(mat1, out, sizeof(Matrix)) + free(out) - cdef void flip(self) nogil: - cdef float *data - - data = self.data - for i in xrange(4): - data[i] = -data[i] +cdef void flip(Matrix *mat) nogil: + data = mat + for i in xrange(4): + data[i] = -data[i] - cdef void scale(self, float x, float y, float z) nogil: - cdef float *data, coordinate[3] +cdef void scale(Matrix *mat, float x, float y, float z) nogil: + cdef float coordinate[3] + + data = mat + coordinate[0] = x + coordinate[1] = y + coordinate[2] = z - 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] + - for i in xrange(3): - for j in xrange(4): - data[4*i+j] *= coordinate[i] +cdef void scale2d(Matrix *mat, float x, float y) nogil: + data = mat + for i in xrange(4): + data[ i] *= x + data[4+i] *= y - cdef void scale2d(self, float x, float y) nogil: - cdef float *data +cdef void translate(Matrix *mat, float x, float y, float z) nogil: + cdef float offset[3], item[3] + + offset[0] = x + offset[1] = y + offset[2] = z - data = self.data - for i in xrange(4): - data[ i] *= x - data[4+i] *= y + data = mat + for i in xrange(3): + item[i] = data[12+i] * offset[i] + + for i in xrange(3): + for j in xrange(4): + data[4*i+j] += item[i] - cdef void translate(self, float x, float y, float z) nogil: - cdef float *data, coordinate[3], item[3] - - data = self.data - 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] +cdef void translate2d(Matrix *mat, float x, float y) nogil: + translate(mat, x, y, 0) - cdef void rotate_x(self, float angle) nogil: - cdef float cos_a, sin_a - cdef float lines[8], *data +cdef void rotate_x(Matrix *mat, float angle) nogil: + cdef float cos_a, sin_a + cdef float lines[8] - data = self.data - cos_a = cos(angle) - sin_a = sin(angle) - 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] + data = mat + cos_a = cos(angle) + sin_a = sin(angle) + 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] - cdef void rotate_y(self, float angle) nogil: - cdef float cos_a, sin_a - cdef float lines[8], *data +cdef void rotate_y(Matrix *mat, float angle) nogil: + cdef float cos_a, sin_a + cdef float lines[8] - data = self.data - cos_a = cos(angle) - sin_a = sin(angle) - 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] + data = mat + cos_a = cos(angle) + sin_a = sin(angle) + 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] - cdef void rotate_z(self, float angle) nogil: - cdef float cos_a, sin_a - cdef float lines[8], *data +cdef void rotate_z(Matrix *mat, float angle) nogil: + cdef float cos_a, sin_a + cdef float lines[8] - data = self.data - cos_a = cos(angle) - sin_a = sin(angle) - 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] + data = mat + cos_a = cos(angle) + sin_a = sin(angle) + 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]