Skip to content

Commit 826f9e4

Browse files
committed
Refactored p5 for better support of multiple renderers
- Each renderer has its own matrix stack now - transforms.py uses the functions provided by the renderer to update matrix and style settings - This was needed as skia had predefined function for rotate, transform, scale etc. and we didn't need to implement it manually
1 parent 3b0e31d commit 826f9e4

File tree

3 files changed

+210
-74
lines changed

3 files changed

+210
-74
lines changed

p5/core/transforms.py

+18-74
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,24 @@ def __exit__(self, exc_type, exc_value, traceback):
3636
pop_matrix()
3737

3838

39-
matrix_stack = []
40-
41-
4239
def push_matrix():
4340
"""Pushes the current transformation matrix onto the matrix stack.
4441
"""
45-
matrix_stack.append(p5.renderer.transform_matrix.copy())
42+
p5.renderer.push_matrix()
4643
return _MatrixContext()
4744

4845

4946
def pop_matrix():
5047
"""Pops the current transformation matrix off the matrix stack.
5148
"""
52-
assert len(matrix_stack) > 0, "No matrix to pop"
53-
p5.renderer.transform_matrix = matrix_stack.pop()
49+
p5.renderer.pop_matrix()
5450

5551

5652
def reset_transforms():
5753
"""Reset all transformations to their default state.
5854
5955
"""
60-
p5.renderer.transform_matrix = np.identity(4)
56+
p5.renderer.reset_transforms()
6157

6258

6359
def translate(x, y, z=0):
@@ -82,9 +78,7 @@ def translate(x, y, z=0):
8278
:rtype: np.ndarray
8379
8480
"""
85-
tmat = matrix.translation_matrix(x, y, z)
86-
p5.renderer.transform_matrix = p5.renderer.transform_matrix.dot(tmat)
87-
return tmat
81+
return p5.renderer.translate(x, y, z)
8882

8983

9084
def rotate(theta, axis=np.array([0, 0, 1])):
@@ -100,10 +94,7 @@ def rotate(theta, axis=np.array([0, 0, 1])):
10094
:rtype: np.ndarray
10195
10296
"""
103-
axis = np.array(axis[:])
104-
tmat = matrix.rotation_matrix(axis, theta)
105-
p5.renderer.transform_matrix = p5.renderer.transform_matrix.dot(tmat)
106-
return tmat
97+
return p5.renderer.rotate(theta)
10798

10899

109100
def rotate_x(theta):
@@ -116,7 +107,7 @@ def rotate_x(theta):
116107
:rtype: np.ndarray
117108
118109
"""
119-
rotate(theta, axis=np.array([1, 0, 0]))
110+
p5.renderer.rotate_x(theta)
120111

121112

122113
def rotate_y(theta):
@@ -129,7 +120,7 @@ def rotate_y(theta):
129120
:rtype: np.ndarray
130121
131122
"""
132-
rotate(theta, axis=np.array([0, 1, 0]))
123+
p5.renderer.rotate_y(theta)
133124

134125

135126
def rotate_z(theta):
@@ -140,9 +131,8 @@ def rotate_z(theta):
140131
141132
:returns: The rotation matrix used to apply the transformation.
142133
:rtype: np.ndarray
143-
144-
"""
145-
rotate(theta, axis=np.array([0, 0, 1]))
134+
"""
135+
p5.renderer.rotate_z(theta)
146136

147137

148138
def scale(sx, sy=None, sz=None):
@@ -160,14 +150,7 @@ def scale(sx, sy=None, sz=None):
160150
:returns: The transformation matrix used to appy the transformation.
161151
:rtype: np.ndarray
162152
"""
163-
if sy is None and sz is None:
164-
sy = sx
165-
sz = sx
166-
elif sz is None:
167-
sz = 1
168-
tmat = matrix.scale_transform(sx, sy, sz)
169-
p5.renderer.transform_matrix = p5.renderer.transform_matrix.dot(tmat)
170-
return tmat
153+
return p5.renderer.scale(sx, sy, sz)
171154

172155

173156
def apply_matrix(transform_matrix):
@@ -176,20 +159,19 @@ def apply_matrix(transform_matrix):
176159
:param transform_matrix: The new transform matrix.
177160
:type transform_matrix: np.ndarray (or a 4×4 list)
178161
"""
179-
tmatrix = np.array(transform_matrix)
180-
p5.renderer.transform_matrix = p5.renderer.transform_matrix.dot(tmatrix)
162+
p5.renderer.apply_matrix()
181163

182164

183165
def reset_matrix():
184166
"""Reset the current transform matrix.
185167
"""
186-
p5.renderer.transform_matrix = np.identity(4)
168+
p5.renderer.reset_matrix()
187169

188170

189171
def print_matrix():
190172
"""Print the transform matrix being used by the sketch.
191173
"""
192-
print(p5.renderer.transform_matrix)
174+
print(p5.renderer.print_matrix())
193175

194176

195177
def shear_x(theta):
@@ -202,10 +184,7 @@ def shear_x(theta):
202184
:rtype: np.ndarray
203185
204186
"""
205-
shear_mat = np.identity(4)
206-
shear_mat[0, 1] = np.tan(theta)
207-
p5.renderer.transform_matrix = p5.renderer.transform_matrix.dot(shear_mat)
208-
return shear_mat
187+
return p5.renderer.shear_x(theta)
209188

210189

211190
def shear_y(theta):
@@ -218,10 +197,7 @@ def shear_y(theta):
218197
:rtype: np.ndarray
219198
220199
"""
221-
shear_mat = np.identity(4)
222-
shear_mat[1, 0] = np.tan(theta)
223-
p5.renderer.transform_matrix = p5.renderer.transform_matrix.dot(shear_mat)
224-
return shear_mat
200+
return p5.renderer.shear_y(theta)
225201

226202

227203
def camera(*args, **kwargs):
@@ -275,29 +251,7 @@ def camera(*args, **kwargs):
275251
:type up_vector: tuple
276252
277253
"""
278-
def real_camera(position=(0, 0, p5.sketch.size[1] / math.tan(math.pi / 6)),
279-
target_position=(0, 0, 0), up_vector=(0, 1, 0)):
280-
p5.renderer.lookat_matrix = matrix.look_at(
281-
np.array(position),
282-
np.array(target_position),
283-
np.array(up_vector))
284-
p5.renderer.camera_pos = np.array(position)
285-
286-
if len(args) == 9: # If using non-tuple arguments
287-
kwargs['position'] = args[:3]
288-
kwargs['target_position'] = args[3:6]
289-
kwargs['up_vector'] = args[6:]
290-
elif len(args) <= 3: # If using tuple arguments
291-
if len(args) >= 1:
292-
kwargs['position'] = args[0]
293-
if len(args) >= 2:
294-
kwargs['target_position'] = args[1]
295-
if len(args) >= 3:
296-
kwargs['up_vector'] = args[2]
297-
else:
298-
raise ValueError("Unexpected number of arguments passed to camera()")
299-
300-
real_camera(**kwargs)
254+
p5.renderer.camera(*args, **kwargs)
301255

302256

303257
def perspective(fovy, aspect, near, far):
@@ -316,12 +270,7 @@ def perspective(fovy, aspect, near, far):
316270
:param far: frustum far plane length
317271
:type far: float
318272
"""
319-
p5.renderer.projection_matrix = matrix.perspective_matrix(
320-
fovy,
321-
aspect,
322-
near,
323-
far
324-
)
273+
p5.renderer.perspective(fovy, aspect, near, far)
325274

326275

327276
def ortho(left, right, bottom, top, near, far):
@@ -348,12 +297,7 @@ def ortho(left, right, bottom, top, near, far):
348297
:param far: camera frustum far plane
349298
:type far: float
350299
"""
351-
p5.renderer.projection_matrix = np.array([
352-
[2 / (right - left), 0, 0, -(right + left) / (right - left)],
353-
[0, 2 / (top - bottom), 0, -(top + bottom) / (top - bottom)],
354-
[0, 0, -2 / (far - near), -(far + near) / (far - near)],
355-
[0, 0, 0, 1],
356-
])
300+
p5.renderer.ortho(left, right, bottom, top, near, far)
357301

358302

359303
def frustum():

p5/sketch/Vispy2DRenderer/renderer2d.py

+66
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(self):
6060
self.line_prog = None
6161
self.modelview_matrix = np.identity(4)
6262
self.style_stack = []
63+
self.matrix_stack = []
6364
self.style = Style2D()
6465

6566
def reset_view(self):
@@ -393,3 +394,68 @@ def arc(self, *args):
393394
def shape(self, vertices, contours, shape_type, *args):
394395
"""Render a Pshape"""
395396
self.render_shape(PShape(vertices=vertices, contours=contours, shape_type=shape_type))
397+
398+
def push_matrix(self):
399+
"""Pushes the current transformation matrix onto the matrix stack.
400+
"""
401+
self.matrix_stack.append(self.transform_matrix.copy())
402+
403+
def pop_matrix(self):
404+
"""Pops the current transformation matrix off the matrix stack.
405+
"""
406+
assert len(self.matrix_stack) > 0, "No matrix to pop"
407+
self.transform_matrix = self.matrix_stack.pop()
408+
409+
def reset_transforms(self):
410+
"""Reset all transformations to their default state.
411+
412+
"""
413+
self.transform_matrix = np.identity(4)
414+
415+
def translate(self, x, y, z=0):
416+
tmat = matrix.translation_matrix(x, y, z)
417+
self.transform_matrix = self.transform_matrix.dot(tmat)
418+
return tmat
419+
420+
def rotate(self, theta, axis=np.array([0, 0, 1])):
421+
axis = np.array(axis[:])
422+
tmat = matrix.rotation_matrix(axis, theta)
423+
self.transform_matrix = self.transform_matrix.dot(tmat)
424+
return tmat
425+
426+
def scale(self, sx, sy=None, sz=None):
427+
if sy is None and sz is None:
428+
sy = sx
429+
sz = sx
430+
elif sz is None:
431+
sz = 1
432+
tmat = matrix.scale_transform(sx, sy, sz)
433+
self.transform_matrix = self.transform_matrix.dot(tmat)
434+
return tmat
435+
436+
437+
def apply_matrix(self, transform_matrix):
438+
tmatrix = np.array(transform_matrix)
439+
self.transform_matrix = self.transform_matrix.dot(tmatrix)
440+
441+
442+
def reset_matrix(self):
443+
self.transform_matrix = np.identity(4)
444+
445+
446+
def print_matrix(self):
447+
print(self.transform_matrix)
448+
449+
450+
def shear_x(self, theta):
451+
shear_mat = np.identity(4)
452+
shear_mat[0, 1] = np.tan(theta)
453+
self.transform_matrix = self.transform_matrix.dot(shear_mat)
454+
return shear_mat
455+
456+
457+
def shear_y(self, theta):
458+
shear_mat = np.identity(4)
459+
shear_mat[1, 0] = np.tan(theta)
460+
self.transform_matrix = self.transform_matrix.dot(shear_mat)
461+
return shear_mat

0 commit comments

Comments
 (0)