Skip to content

Commit 531c701

Browse files
committed
matrix: rewrite in pure Python, optimize for 2D affine matrices
This is faster than NumPy...
1 parent 282b178 commit 531c701

File tree

3 files changed

+105
-26
lines changed

3 files changed

+105
-26
lines changed

blitzloop/backend/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def set_aspect(self, aspect):
7373
self.aspect_cache[self.aspect] = matrix
7474

7575
def commit_matrix(self, uniform):
76-
m = self.viewmatrix.m * self.matrix.m
77-
self.gl.glUniformMatrix4fv(uniform, 1, False, m.transpose())
76+
m = self.viewmatrix * self.matrix
77+
self.gl.glUniformMatrix4fv(uniform, 1, False, m.m)
7878

7979
def set_render_gen(self, gen):
8080
self.frames = gen()

blitzloop/matrix.py

Lines changed: 102 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,118 @@
1616
# along with this program; if not, write to the Free Software
1717
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1818

19-
20-
import numpy as np
21-
2219
class Matrix(object):
23-
def __init__(self):
20+
def __init__(self, other=None, nice=None):
2421
self.stack = []
25-
self.reset()
22+
if other is not None:
23+
if isinstance(other, list):
24+
self.m = other
25+
self.nice = False
26+
else:
27+
self.m = list(other.m)
28+
self.nice = other.nice
29+
else:
30+
self.reset()
31+
32+
if nice is not None:
33+
self.nice = nice
2634

2735
def reset(self):
28-
self.m = np.matrix([
29-
[1,0,0,0],
30-
[0,1,0,0],
31-
[0,0,1,0],
32-
[0,0,0,1]], float)
36+
self.m = [
37+
1.0,0.0,0.0,0.0,
38+
0.0,1.0,0.0,0.0,
39+
0.0,0.0,1.0,0.0,
40+
0.0,0.0,0.0,1.0
41+
]
42+
self.nice = True
3343

3444
def push(self):
35-
self.stack.append(self.m.copy())
45+
self.stack.append((self.m, self.nice))
46+
self.m = list(self.m)
3647

3748
def pop(self):
38-
self.m = self.stack.pop()
49+
self.m, self.nice = self.stack.pop()
3950

4051
def scale(self, sx, sy, sz=1.0):
41-
self.m *= [
42-
[sx, 0, 0, 0],
43-
[0, sy, 0, 0],
44-
[0, 0, sz, 0],
45-
[0, 0, 0, 1],
46-
]
52+
if not self.nice:
53+
self *= Matrix().scale(sx, sy, sz)
54+
return self
55+
else:
56+
self.m[0] *= sx
57+
self.m[5] *= sy
58+
self.m[10] *= sz
59+
return self
4760

4861
def translate(self, tx, ty, tz=0.0):
49-
self.m *= [
50-
[1, 0, 0, tx],
51-
[0, 1, 0, ty],
52-
[0, 0, 1, tz],
53-
[0, 0, 0, 1],
62+
if not self.nice:
63+
self *= Matrix().translate(tx, ty, tz)
64+
return self
65+
self.m[12] += tx * self.m[0]
66+
self.m[13] += ty * self.m[5]
67+
self.m[14] += tz * self.m[10]
68+
return self
69+
70+
def __mul__(self, other):
71+
if self.nice and other.nice:
72+
return Matrix(self._nicemult(self.m, other.m), True)
73+
else:
74+
return Matrix(self._mult(self.m, other.m), False)
75+
76+
def __imul__(self, other):
77+
if self.nice and other.nice:
78+
self.m = self._nicemult(self.m, other.m)
79+
else:
80+
self.m = self._mult(self.m, other.m)
81+
self.nice = False
82+
return self
83+
84+
@staticmethod
85+
def _mult(B, A):
86+
C = [
87+
A[0] * B[0] + A[1] * B[4] + A[2] * B[8] + A[3] * B[12],
88+
A[0] * B[1] + A[1] * B[5] + A[2] * B[9] + A[3] * B[13],
89+
A[0] * B[2] + A[1] * B[6] + A[2] * B[10] + A[3] * B[14],
90+
A[0] * B[3] + A[1] * B[7] + A[2] * B[11] + A[3] * B[15],
91+
A[4] * B[0] + A[5] * B[4] + A[6] * B[8] + A[7] * B[12],
92+
A[4] * B[1] + A[5] * B[5] + A[6] * B[9] + A[7] * B[13],
93+
A[4] * B[2] + A[5] * B[6] + A[6] * B[10] + A[7] * B[14],
94+
A[4] * B[3] + A[5] * B[7] + A[6] * B[11] + A[7] * B[15],
95+
A[8] * B[0] + A[9] * B[4] + A[10] * B[8] + A[11] * B[12],
96+
A[8] * B[1] + A[9] * B[5] + A[10] * B[9] + A[11] * B[13],
97+
A[8] * B[2] + A[9] * B[6] + A[10] * B[10] + A[11] * B[14],
98+
A[8] * B[3] + A[9] * B[7] + A[10] * B[11] + A[11] * B[15],
99+
A[12] * B[0] + A[13] * B[4] + A[14] * B[8] + A[15] * B[12],
100+
A[12] * B[1] + A[13] * B[5] + A[14] * B[9] + A[15] * B[13],
101+
A[12] * B[2] + A[13] * B[6] + A[14] * B[10] + A[15] * B[14],
102+
A[12] * B[3] + A[13] * B[7] + A[14] * B[11] + A[15] * B[15],
103+
]
104+
return C
105+
106+
@staticmethod
107+
def _nicemult(B, A):
108+
C = [
109+
A[0] * B[0], 0.0, 0.0, 0.0,
110+
0.0, A[5] * B[5], 0.0, 0.0,
111+
0.0, 0.0, A[10] * B[10], 0.0,
112+
A[12] * B[0] + B[12], A[13] * B[5] + B[13], A[14] * B[10] + B[14], 1.0,
54113
]
114+
return C
115+
116+
def __str__(self):
117+
s = ""
118+
for i in range(4):
119+
s += " [" + ",".join("%d" % self.m[4*j+i] for j in range(4)) + "],\n"
120+
return "[\n" + s + "]\n"
121+
122+
def __eq__(self, other):
123+
return self.m == other.m
124+
125+
if __name__ == "__main__":
126+
assert Matrix().translate(1,2).translate(3,4) == Matrix().translate(4,6)
127+
assert Matrix().scale(1,2).scale(3,4) == Matrix().scale(3,8)
128+
assert Matrix().scale(2,3).translate(4,5) == Matrix().translate(8,15).scale(2,3)
129+
assert Matrix().scale(2,3).translate(4,5) == Matrix().scale(2,3) * Matrix().translate(4,5)
130+
assert Matrix(nice=False).translate(1,2).translate(3,4) == Matrix().translate(4,6)
131+
assert Matrix(nice=False).scale(1,2).scale(3,4) == Matrix().scale(3,8)
132+
assert Matrix(nice=False).scale(2,3).translate(4,5) == Matrix().translate(8,15).scale(2,3)
133+
assert Matrix(nice=False).scale(2,3).translate(4,5) == Matrix().scale(2,3) * Matrix().translate(4,5)

blitzloop/renderer/gles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ def draw(self, pos, size, tpos, tsize, color):
417417
self.tmatrix.reset()
418418
self.tmatrix.translate(*tpos)
419419
self.tmatrix.scale(*tsize)
420-
gl.glUniformMatrix4fv(self.l_textransform, 1, False, self.tmatrix.m.transpose())
420+
gl.glUniformMatrix4fv(self.l_textransform, 1, False, self.tmatrix.m)
421421
SolidRenderer.draw(self, pos, size, color)
422422

423423
class ImageTexture(object):

0 commit comments

Comments
 (0)