vispy 0.9.5__cp38-cp38-win_amd64.whl → 0.14.0__cp38-cp38-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vispy might be problematic. Click here for more details.
- vispy/app/backends/_glfw.py +2 -2
- vispy/app/backends/_pyglet.py +8 -2
- vispy/app/backends/_qt.py +88 -63
- vispy/app/backends/_wx.py +6 -1
- vispy/app/canvas.py +4 -2
- vispy/app/tests/test_canvas.py +52 -1
- vispy/app/tests/test_context.py +5 -3
- vispy/color/color_array.py +8 -1
- vispy/color/colormap.py +5 -25
- vispy/geometry/meshdata.py +76 -38
- vispy/geometry/rect.py +6 -0
- vispy/geometry/tests/test_meshdata.py +72 -0
- vispy/gloo/buffer.py +12 -0
- vispy/gloo/gl/_constants.py +9 -5
- vispy/gloo/gl/_es2.py +8 -4
- vispy/gloo/gl/_gl2.py +2 -3
- vispy/gloo/gl/_proxy.py +1 -1
- vispy/gloo/gl/_pyopengl2.py +12 -7
- vispy/gloo/gl/tests/test_names.py +3 -0
- vispy/gloo/glir.py +26 -13
- vispy/gloo/program.py +39 -22
- vispy/gloo/tests/test_program.py +9 -2
- vispy/gloo/tests/test_texture.py +19 -2
- vispy/gloo/texture.py +46 -16
- vispy/gloo/wrappers.py +4 -2
- vispy/glsl/build_spatial_filters.py +241 -293
- vispy/glsl/misc/spatial-filters.frag +1299 -254
- vispy/io/_data/spatial-filters.npy +0 -0
- vispy/io/datasets.py +2 -2
- vispy/io/image.py +1 -1
- vispy/io/stl.py +3 -3
- vispy/scene/cameras/base_camera.py +6 -2
- vispy/scene/cameras/panzoom.py +10 -14
- vispy/scene/cameras/perspective.py +6 -0
- vispy/scene/cameras/tests/test_cameras.py +27 -0
- vispy/scene/cameras/tests/test_perspective.py +37 -0
- vispy/scene/cameras/turntable.py +39 -23
- vispy/scene/canvas.py +9 -5
- vispy/scene/events.py +9 -0
- vispy/scene/node.py +19 -2
- vispy/scene/tests/test_canvas.py +30 -1
- vispy/scene/tests/test_visuals.py +113 -0
- vispy/scene/visuals.py +6 -1
- vispy/scene/widgets/viewbox.py +3 -2
- vispy/testing/_runners.py +6 -12
- vispy/testing/_testing.py +3 -4
- vispy/util/check_environment.py +4 -4
- vispy/util/gallery_scraper.py +50 -32
- vispy/util/tests/test_gallery_scraper.py +2 -0
- vispy/util/transforms.py +1 -1
- vispy/util/wrappers.py +1 -1
- vispy/version.py +2 -3
- vispy/visuals/__init__.py +2 -0
- vispy/visuals/_scalable_textures.py +20 -17
- vispy/visuals/collections/array_list.py +3 -3
- vispy/visuals/collections/base_collection.py +1 -1
- vispy/visuals/ellipse.py +1 -1
- vispy/visuals/filters/__init__.py +3 -2
- vispy/visuals/filters/base_filter.py +120 -0
- vispy/visuals/filters/clipping_planes.py +24 -12
- vispy/visuals/filters/markers.py +28 -0
- vispy/visuals/filters/mesh.py +61 -6
- vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
- vispy/visuals/graphs/graph.py +1 -1
- vispy/visuals/image.py +114 -26
- vispy/visuals/image_complex.py +130 -0
- vispy/visuals/instanced_mesh.py +152 -0
- vispy/visuals/isocurve.py +1 -1
- vispy/visuals/line/dash_atlas.py +46 -41
- vispy/visuals/line/line.py +2 -5
- vispy/visuals/markers.py +310 -384
- vispy/visuals/mesh.py +2 -2
- vispy/visuals/shaders/function.py +3 -0
- vispy/visuals/shaders/tests/test_function.py +6 -0
- vispy/visuals/tests/test_axis.py +2 -2
- vispy/visuals/tests/test_image.py +92 -2
- vispy/visuals/tests/test_image_complex.py +36 -0
- vispy/visuals/tests/test_instanced_mesh.py +50 -0
- vispy/visuals/tests/test_markers.py +6 -0
- vispy/visuals/tests/test_mesh.py +17 -0
- vispy/visuals/tests/test_text.py +11 -0
- vispy/visuals/tests/test_volume.py +218 -12
- vispy/visuals/text/_sdf_cpu.cp38-win_amd64.pyd +0 -0
- vispy/visuals/text/_sdf_cpu.pyx +21 -23
- vispy/visuals/text/text.py +9 -3
- vispy/visuals/tube.py +2 -2
- vispy/visuals/visual.py +144 -3
- vispy/visuals/volume.py +300 -131
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/LICENSE.txt +1 -1
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/METADATA +218 -198
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/RECORD +93 -96
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/WHEEL +1 -1
- vispy/glsl/antialias/__init__.py +0 -0
- vispy/glsl/arrowheads/__init__.py +0 -0
- vispy/glsl/arrows/__init__.py +0 -0
- vispy/glsl/collections/__init__.py +0 -0
- vispy/glsl/colormaps/__init__.py +0 -0
- vispy/glsl/lines/__init__.py +0 -0
- vispy/glsl/markers/__init__.py +0 -0
- vispy/glsl/math/__init__.py +0 -0
- vispy/glsl/misc/__init__.py +0 -0
- vispy/glsl/transforms/__init__.py +0 -0
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/top_level.txt +0 -0
vispy/geometry/meshdata.py
CHANGED
|
@@ -19,6 +19,56 @@ def _fix_colors(colors):
|
|
|
19
19
|
return colors
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _compute_face_normals(vertices):
|
|
23
|
+
if vertices.shape[1:] != (3, 3):
|
|
24
|
+
raise ValueError("Expected (N, 3, 3) array of vertices repeated on"
|
|
25
|
+
f" the triangle corners, got {vertices.shape}.")
|
|
26
|
+
edges1 = vertices[:, 1] - vertices[:, 0]
|
|
27
|
+
edges2 = vertices[:, 2] - vertices[:, 0]
|
|
28
|
+
return np.cross(edges1, edges2)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _repeat_face_normals_on_corners(normals):
|
|
32
|
+
if normals.shape[1:] != (3,):
|
|
33
|
+
raise ValueError("Expected (F, 3) array of face normals, got"
|
|
34
|
+
f" {normals.shape}.")
|
|
35
|
+
n_corners_in_face = 3
|
|
36
|
+
new_shape = (normals.shape[0], n_corners_in_face, normals.shape[1])
|
|
37
|
+
return np.repeat(normals, n_corners_in_face, axis=0).reshape(new_shape)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _compute_vertex_normals(face_normals, faces, vertices):
|
|
41
|
+
if face_normals.shape[1:] != (3,):
|
|
42
|
+
raise ValueError("Expected (F, 3) array of face normals, got"
|
|
43
|
+
f" {face_normals.shape}.")
|
|
44
|
+
if faces.shape[1:] != (3,):
|
|
45
|
+
raise ValueError("Expected (F, 3) array of face vertex indices, got"
|
|
46
|
+
f" {faces.shape}.")
|
|
47
|
+
if vertices.shape[1:] != (3,):
|
|
48
|
+
raise ValueError("Expected (N, 3) array of vertices, got"
|
|
49
|
+
f" {vertices.shape}.")
|
|
50
|
+
|
|
51
|
+
vertex_normals = np.zeros_like(vertices)
|
|
52
|
+
n_corners_in_triangle = 3
|
|
53
|
+
face_normals_repeated_on_corners = np.repeat(face_normals,
|
|
54
|
+
n_corners_in_triangle,
|
|
55
|
+
axis=0)
|
|
56
|
+
# NOTE: The next line is equivalent to
|
|
57
|
+
#
|
|
58
|
+
# vertex_normals[self._faces.ravel()] += face_normals_repeated_on_corners
|
|
59
|
+
#
|
|
60
|
+
# except that it accumulates the values from the right hand side at
|
|
61
|
+
# repeated indices on the left hand side, instead of overwritting them,
|
|
62
|
+
# like in the above.
|
|
63
|
+
np.add.at(vertex_normals, faces.ravel(), face_normals_repeated_on_corners)
|
|
64
|
+
|
|
65
|
+
norms = np.sqrt((vertex_normals**2).sum(axis=1))
|
|
66
|
+
nonzero_norms = norms > 0
|
|
67
|
+
vertex_normals[nonzero_norms] /= norms[nonzero_norms][:, None]
|
|
68
|
+
|
|
69
|
+
return vertex_normals
|
|
70
|
+
|
|
71
|
+
|
|
22
72
|
class MeshData(object):
|
|
23
73
|
"""
|
|
24
74
|
Class for storing and operating on 3D mesh data.
|
|
@@ -141,7 +191,7 @@ class MeshData(object):
|
|
|
141
191
|
self._compute_edges(indexed='faces')
|
|
142
192
|
return self._edges_indexed_by_faces
|
|
143
193
|
else:
|
|
144
|
-
raise
|
|
194
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
145
195
|
|
|
146
196
|
def set_faces(self, faces):
|
|
147
197
|
"""Set the faces
|
|
@@ -191,7 +241,7 @@ class MeshData(object):
|
|
|
191
241
|
self._vertices[self.get_faces()]
|
|
192
242
|
return self._vertices_indexed_by_faces
|
|
193
243
|
else:
|
|
194
|
-
raise
|
|
244
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
195
245
|
|
|
196
246
|
def get_bounds(self):
|
|
197
247
|
"""Get the mesh bounds
|
|
@@ -234,7 +284,7 @@ class MeshData(object):
|
|
|
234
284
|
if verts is not None:
|
|
235
285
|
self._vertices_indexed_by_faces = verts
|
|
236
286
|
else:
|
|
237
|
-
raise
|
|
287
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
238
288
|
|
|
239
289
|
if reset_normals:
|
|
240
290
|
self.reset_normals()
|
|
@@ -293,22 +343,19 @@ class MeshData(object):
|
|
|
293
343
|
normals : ndarray
|
|
294
344
|
The normals.
|
|
295
345
|
"""
|
|
346
|
+
if indexed not in (None, 'faces'):
|
|
347
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
348
|
+
|
|
296
349
|
if self._face_normals is None:
|
|
297
|
-
|
|
298
|
-
self._face_normals =
|
|
299
|
-
v[:, 2] - v[:, 0])
|
|
350
|
+
vertices = self.get_vertices(indexed='faces')
|
|
351
|
+
self._face_normals = _compute_face_normals(vertices)
|
|
300
352
|
|
|
301
|
-
if indexed is None:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
norms[:] = self._face_normals[:, np.newaxis, :]
|
|
308
|
-
self._face_normals_indexed_by_faces = norms
|
|
309
|
-
return self._face_normals_indexed_by_faces
|
|
310
|
-
else:
|
|
311
|
-
raise Exception("Invalid indexing mode. Accepts: None, 'faces'")
|
|
353
|
+
if indexed == 'faces' and self._face_normals_indexed_by_faces is None:
|
|
354
|
+
self._face_normals_indexed_by_faces = \
|
|
355
|
+
_repeat_face_normals_on_corners(self._face_normals)
|
|
356
|
+
|
|
357
|
+
return (self._face_normals if indexed is None
|
|
358
|
+
else self._face_normals_indexed_by_faces)
|
|
312
359
|
|
|
313
360
|
def get_vertex_normals(self, indexed=None):
|
|
314
361
|
"""Get vertex normals
|
|
@@ -326,29 +373,20 @@ class MeshData(object):
|
|
|
326
373
|
normals : ndarray
|
|
327
374
|
The normals.
|
|
328
375
|
"""
|
|
376
|
+
if indexed not in (None, 'faces'):
|
|
377
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
378
|
+
|
|
329
379
|
if self._vertex_normals is None:
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
faces = vertFaces[vindex]
|
|
336
|
-
if len(faces) == 0:
|
|
337
|
-
self._vertex_normals[vindex] = (0, 0, 0)
|
|
338
|
-
continue
|
|
339
|
-
norms = faceNorms[faces] # get all face normals
|
|
340
|
-
norm = norms.sum(axis=0) # sum normals
|
|
341
|
-
renorm = (norm**2).sum()**0.5
|
|
342
|
-
if renorm > 0:
|
|
343
|
-
norm /= renorm
|
|
344
|
-
self._vertex_normals[vindex] = norm
|
|
380
|
+
face_normals = self.get_face_normals()
|
|
381
|
+
faces = self.get_faces()
|
|
382
|
+
vertices = self.get_vertices()
|
|
383
|
+
self._vertex_normals = _compute_vertex_normals(face_normals, faces,
|
|
384
|
+
vertices)
|
|
345
385
|
|
|
346
386
|
if indexed is None:
|
|
347
387
|
return self._vertex_normals
|
|
348
388
|
elif indexed == 'faces':
|
|
349
389
|
return self._vertex_normals[self.get_faces()]
|
|
350
|
-
else:
|
|
351
|
-
raise Exception("Invalid indexing mode. Accepts: None, 'faces'")
|
|
352
390
|
|
|
353
391
|
def get_vertex_colors(self, indexed=None):
|
|
354
392
|
"""Get vertex colors
|
|
@@ -373,7 +411,7 @@ class MeshData(object):
|
|
|
373
411
|
self._vertex_colors[self.get_faces()]
|
|
374
412
|
return self._vertex_colors_indexed_by_faces
|
|
375
413
|
else:
|
|
376
|
-
raise
|
|
414
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
377
415
|
|
|
378
416
|
def get_vertex_values(self, indexed=None):
|
|
379
417
|
"""Get vertex colors
|
|
@@ -398,7 +436,7 @@ class MeshData(object):
|
|
|
398
436
|
self._vertex_values[self.get_faces()]
|
|
399
437
|
return self._vertex_values_indexed_by_faces
|
|
400
438
|
else:
|
|
401
|
-
raise
|
|
439
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
402
440
|
|
|
403
441
|
def set_vertex_colors(self, colors, indexed=None):
|
|
404
442
|
"""Set the vertex color array
|
|
@@ -488,7 +526,7 @@ class MeshData(object):
|
|
|
488
526
|
self._face_colors.reshape(Nf, 1, 4)
|
|
489
527
|
return self._face_colors_indexed_by_faces
|
|
490
528
|
else:
|
|
491
|
-
raise
|
|
529
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
492
530
|
|
|
493
531
|
def set_face_colors(self, colors, indexed=None):
|
|
494
532
|
"""Set the face color array
|
|
@@ -611,7 +649,7 @@ class MeshData(object):
|
|
|
611
649
|
raise Exception("MeshData cannot generate edges--no faces in "
|
|
612
650
|
"this data.")
|
|
613
651
|
else:
|
|
614
|
-
raise
|
|
652
|
+
raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
|
|
615
653
|
|
|
616
654
|
def save(self):
|
|
617
655
|
"""Serialize this mesh to a string appropriate for disk storage
|
vispy/geometry/rect.py
CHANGED
|
@@ -113,6 +113,12 @@ class Rect(object):
|
|
|
113
113
|
return (self.pos[0] + self.size[0] * 0.5,
|
|
114
114
|
self.pos[1] + self.size[1] * 0.5)
|
|
115
115
|
|
|
116
|
+
@center.setter
|
|
117
|
+
def center(self, value):
|
|
118
|
+
delta_x = value[0] - self.center[0]
|
|
119
|
+
delta_y = value[1] - self.center[1]
|
|
120
|
+
self.pos = (self.pos[0] + delta_x, self.pos[1] + delta_y)
|
|
121
|
+
|
|
116
122
|
def padded(self, padding):
|
|
117
123
|
"""Return a new Rect padded (smaller) by padding on all sides
|
|
118
124
|
|
|
@@ -31,4 +31,76 @@ def test_meshdata():
|
|
|
31
31
|
assert_array_equal(square_edges, mesh.get_edges())
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
def test_vertex_normals_indexed_none():
|
|
35
|
+
dtype_float = np.float32
|
|
36
|
+
dtype_int = np.int64
|
|
37
|
+
vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]],
|
|
38
|
+
dtype=dtype_float)
|
|
39
|
+
faces = np.array([[0, 2, 1], [0, 3, 2], [0, 1, 3]], dtype=dtype_int)
|
|
40
|
+
mesh = MeshData(vertices=vertices, faces=faces)
|
|
41
|
+
vertex_normals_unnormalized = np.array(
|
|
42
|
+
[[-1, -1, -1], [0, -1, -1], [-1, 0, -1], [-1, -1, 0]],
|
|
43
|
+
dtype=dtype_float)
|
|
44
|
+
norms = np.sqrt((vertex_normals_unnormalized**2).sum(axis=1,
|
|
45
|
+
keepdims=True))
|
|
46
|
+
expected_vertex_normals = vertex_normals_unnormalized / norms
|
|
47
|
+
|
|
48
|
+
computed_vertex_normals = mesh.get_vertex_normals(indexed=None)
|
|
49
|
+
|
|
50
|
+
assert_array_equal(expected_vertex_normals, computed_vertex_normals)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_vertex_normals_indexed_faces():
|
|
54
|
+
dtype_float = np.float32
|
|
55
|
+
dtype_int = np.int64
|
|
56
|
+
vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]],
|
|
57
|
+
dtype=dtype_float)
|
|
58
|
+
faces = np.array([[0, 2, 1], [0, 3, 2], [0, 1, 3]], dtype=dtype_int)
|
|
59
|
+
mesh = MeshData(vertices=vertices, faces=faces)
|
|
60
|
+
vertex_normals_unnormalized = np.array(
|
|
61
|
+
[[-1, -1, -1], [0, -1, -1], [-1, 0, -1], [-1, -1, 0]],
|
|
62
|
+
dtype=dtype_float)
|
|
63
|
+
norms = np.sqrt((vertex_normals_unnormalized**2).sum(axis=1,
|
|
64
|
+
keepdims=True))
|
|
65
|
+
vertex_normals = vertex_normals_unnormalized / norms
|
|
66
|
+
expected_vertex_normals = vertex_normals[faces]
|
|
67
|
+
|
|
68
|
+
computed_vertex_normals = mesh.get_vertex_normals(indexed="faces")
|
|
69
|
+
|
|
70
|
+
assert_array_equal(expected_vertex_normals, computed_vertex_normals)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_face_normals_indexed_none():
|
|
74
|
+
dtype_float = np.float32
|
|
75
|
+
dtype_int = np.int64
|
|
76
|
+
vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]],
|
|
77
|
+
dtype=dtype_float)
|
|
78
|
+
faces = np.array([[0, 2, 1], [0, 3, 2], [0, 1, 3]], dtype=dtype_int)
|
|
79
|
+
mesh = MeshData(vertices=vertices, faces=faces)
|
|
80
|
+
expected_face_normals = np.array([[0, 0, -1], [-1, 0, 0], [0, -1, 0]],
|
|
81
|
+
dtype=dtype_float)
|
|
82
|
+
|
|
83
|
+
computed_face_normals = mesh.get_face_normals(indexed=None)
|
|
84
|
+
|
|
85
|
+
assert_array_equal(expected_face_normals, computed_face_normals)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_face_normals_indexed_faces():
|
|
89
|
+
dtype_float = np.float32
|
|
90
|
+
dtype_int = np.int64
|
|
91
|
+
vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]],
|
|
92
|
+
dtype=dtype_float)
|
|
93
|
+
faces = np.array([[0, 2, 1], [0, 3, 2], [0, 1, 3]], dtype=dtype_int)
|
|
94
|
+
mesh = MeshData(vertices=vertices, faces=faces)
|
|
95
|
+
expected_face_normals = np.array([
|
|
96
|
+
[[0, 0, -1], [0, 0, -1], [0, 0, -1]],
|
|
97
|
+
[[-1, 0, 0], [-1, 0, 0], [-1, 0, 0]],
|
|
98
|
+
[[0, -1, 0], [0, -1, 0], [0, -1, 0]]],
|
|
99
|
+
dtype=dtype_float)
|
|
100
|
+
|
|
101
|
+
computed_face_normals = mesh.get_face_normals(indexed="faces")
|
|
102
|
+
|
|
103
|
+
assert_array_equal(expected_face_normals, computed_face_normals)
|
|
104
|
+
|
|
105
|
+
|
|
34
106
|
run_tests_if_main()
|
vispy/gloo/buffer.py
CHANGED
|
@@ -414,6 +414,10 @@ class VertexBuffer(DataBuffer):
|
|
|
414
414
|
Buffer data (optional)
|
|
415
415
|
"""
|
|
416
416
|
|
|
417
|
+
def __init__(self, data=None, divisor=None):
|
|
418
|
+
super().__init__(data)
|
|
419
|
+
self.divisor = divisor
|
|
420
|
+
|
|
417
421
|
_GLIR_TYPE = 'VertexBuffer'
|
|
418
422
|
|
|
419
423
|
def _prepare_data(self, data, convert=False):
|
|
@@ -449,6 +453,14 @@ class VertexBuffer(DataBuffer):
|
|
|
449
453
|
self._last_dim = c
|
|
450
454
|
return data
|
|
451
455
|
|
|
456
|
+
@property
|
|
457
|
+
def divisor(self):
|
|
458
|
+
return self._divisor
|
|
459
|
+
|
|
460
|
+
@divisor.setter
|
|
461
|
+
def divisor(self, value):
|
|
462
|
+
self._divisor = max(1, int(value)) if value else None
|
|
463
|
+
|
|
452
464
|
|
|
453
465
|
def _last_stack_str():
|
|
454
466
|
"""Print stack trace from call that didn't originate from here"""
|
vispy/gloo/gl/_constants.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""GL definitions converted to Python by codegen/createglapi.py.
|
|
2
2
|
|
|
3
3
|
THIS CODE IS AUTO-GENERATED. DO NOT EDIT.
|
|
4
4
|
|
|
@@ -8,11 +8,13 @@ Constants for OpenGL ES 2.0.
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Enum(int):
|
|
11
|
-
|
|
11
|
+
"""Enum (integer) with a meaningfull repr."""
|
|
12
|
+
|
|
12
13
|
def __new__(cls, name, value):
|
|
13
14
|
base = int.__new__(cls, value)
|
|
14
15
|
base.name = name
|
|
15
16
|
return base
|
|
17
|
+
|
|
16
18
|
def __repr__(self):
|
|
17
19
|
return self.name
|
|
18
20
|
|
|
@@ -149,6 +151,7 @@ GL_LOW_FLOAT = Enum('GL_LOW_FLOAT', 36336)
|
|
|
149
151
|
GL_LOW_INT = Enum('GL_LOW_INT', 36339)
|
|
150
152
|
GL_LUMINANCE = Enum('GL_LUMINANCE', 6409)
|
|
151
153
|
GL_LUMINANCE_ALPHA = Enum('GL_LUMINANCE_ALPHA', 6410)
|
|
154
|
+
GL_MAX = Enum('GL_MAX', 32776)
|
|
152
155
|
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = Enum('GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS', 35661)
|
|
153
156
|
GL_MAX_CUBE_MAP_TEXTURE_SIZE = Enum('GL_MAX_CUBE_MAP_TEXTURE_SIZE', 34076)
|
|
154
157
|
GL_MAX_FRAGMENT_UNIFORM_VECTORS = Enum('GL_MAX_FRAGMENT_UNIFORM_VECTORS', 36349)
|
|
@@ -162,6 +165,7 @@ GL_MAX_VERTEX_UNIFORM_VECTORS = Enum('GL_MAX_VERTEX_UNIFORM_VECTORS', 36347)
|
|
|
162
165
|
GL_MAX_VIEWPORT_DIMS = Enum('GL_MAX_VIEWPORT_DIMS', 3386)
|
|
163
166
|
GL_MEDIUM_FLOAT = Enum('GL_MEDIUM_FLOAT', 36337)
|
|
164
167
|
GL_MEDIUM_INT = Enum('GL_MEDIUM_INT', 36340)
|
|
168
|
+
GL_MIN = Enum('GL_MIN', 32775)
|
|
165
169
|
GL_MIRRORED_REPEAT = Enum('GL_MIRRORED_REPEAT', 33648)
|
|
166
170
|
GL_NEAREST = Enum('GL_NEAREST', 9728)
|
|
167
171
|
GL_NEAREST_MIPMAP_LINEAR = Enum('GL_NEAREST_MIPMAP_LINEAR', 9986)
|
|
@@ -322,7 +326,7 @@ GL_ZERO = Enum('GL_ZERO', 0)
|
|
|
322
326
|
|
|
323
327
|
|
|
324
328
|
ENUM_MAP = {}
|
|
325
|
-
for ob in list(globals().
|
|
326
|
-
if
|
|
329
|
+
for var_name, ob in list(globals().items()):
|
|
330
|
+
if var_name.startswith('GL_'):
|
|
327
331
|
ENUM_MAP[int(ob)] = ob
|
|
328
|
-
del ob
|
|
332
|
+
del ob, var_name
|
vispy/gloo/gl/_es2.py
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""GL definitions converted to Python by codegen/createglapi.py.
|
|
2
|
+
|
|
3
|
+
THIS CODE IS AUTO-GENERATED. DO NOT EDIT.
|
|
4
|
+
|
|
5
|
+
GL ES 2.0 API (via Angle/DirectX on Windows)
|
|
6
|
+
|
|
7
|
+
"""
|
|
3
8
|
|
|
4
9
|
import ctypes
|
|
5
10
|
from .es2 import _lib
|
|
@@ -81,8 +86,7 @@ def glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha):
|
|
|
81
86
|
_lib.glBufferData.argtypes = ctypes.c_uint, ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_uint,
|
|
82
87
|
# void = glBufferData(GLenum target, GLsizeiptr size, GLvoid* data, GLenum usage)
|
|
83
88
|
def glBufferData(target, data, usage):
|
|
84
|
-
"""
|
|
85
|
-
"""
|
|
89
|
+
"""Data can be numpy array or the size of data to allocate."""
|
|
86
90
|
if isinstance(data, int):
|
|
87
91
|
size = data
|
|
88
92
|
data = ctypes.c_voidp(0)
|
vispy/gloo/gl/_gl2.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""GL definitions converted to Python by codegen/createglapi.py.
|
|
2
2
|
|
|
3
3
|
THIS CODE IS AUTO-GENERATED. DO NOT EDIT.
|
|
4
4
|
|
|
@@ -121,8 +121,7 @@ def glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha):
|
|
|
121
121
|
|
|
122
122
|
# void = glBufferData(GLenum target, GLsizeiptr size, GLvoid* data, GLenum usage)
|
|
123
123
|
def glBufferData(target, data, usage):
|
|
124
|
-
"""
|
|
125
|
-
"""
|
|
124
|
+
"""Data can be numpy array or the size of data to allocate."""
|
|
126
125
|
if isinstance(data, int):
|
|
127
126
|
size = data
|
|
128
127
|
data = ctypes.c_voidp(0)
|
vispy/gloo/gl/_proxy.py
CHANGED
vispy/gloo/gl/_pyopengl2.py
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""GL definitions converted to Python by codegen/createglapi.py.
|
|
2
|
+
|
|
3
|
+
THIS CODE IS AUTO-GENERATED. DO NOT EDIT.
|
|
4
|
+
|
|
5
|
+
Proxy API for GL ES 2.0 subset, via the PyOpenGL library.
|
|
6
|
+
|
|
7
|
+
"""
|
|
3
8
|
|
|
4
9
|
import ctypes
|
|
5
10
|
from OpenGL import GL
|
|
@@ -34,24 +39,24 @@ def glCompressedTexImage2D(target, level, internalformat, width, height, border,
|
|
|
34
39
|
size = data.size
|
|
35
40
|
GL.glCompressedTexImage2D(target, level, internalformat, width, height, border, size, data)
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
|
|
38
43
|
def glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data):
|
|
39
44
|
size = data.size
|
|
40
45
|
GL.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, size, data)
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
|
|
43
48
|
def glDeleteBuffer(buffer):
|
|
44
49
|
GL.glDeleteBuffers(1, [buffer])
|
|
45
50
|
|
|
46
|
-
|
|
51
|
+
|
|
47
52
|
def glDeleteFramebuffer(framebuffer):
|
|
48
53
|
FBO.glDeleteFramebuffers(1, [framebuffer])
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
|
|
51
56
|
def glDeleteRenderbuffer(renderbuffer):
|
|
52
57
|
FBO.glDeleteRenderbuffers(1, [renderbuffer])
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
|
|
55
60
|
def glDeleteTexture(texture):
|
|
56
61
|
GL.glDeleteTextures([texture])
|
|
57
62
|
|
|
@@ -234,6 +234,9 @@ GL_VERTEX_ATTRIB_ARRAY_SIZE GL_VERTEX_ATTRIB_ARRAY_STRIDE
|
|
|
234
234
|
GL_VERTEX_ATTRIB_ARRAY_TYPE GL_VERTEX_SHADER GL_VIEWPORT GL_ZERO
|
|
235
235
|
""".replace('\n', ' ')
|
|
236
236
|
|
|
237
|
+
# vispy_ext.h
|
|
238
|
+
constant_names += "GL_MIN GL_MAX"
|
|
239
|
+
|
|
237
240
|
function_names = [n.strip() for n in function_names.split(' ')]
|
|
238
241
|
function_names = set([n for n in function_names if n])
|
|
239
242
|
constant_names = [n.strip() for n in constant_names.split(' ')]
|
vispy/gloo/glir.py
CHANGED
|
@@ -173,11 +173,13 @@ DRAW
|
|
|
173
173
|
|
|
174
174
|
::
|
|
175
175
|
|
|
176
|
-
('DRAW', <program_id>, <mode:str>, <selection:tuple>)
|
|
177
|
-
# Example: Draw 100 lines
|
|
178
|
-
('DRAW', 4, 'lines', (0, 100))
|
|
176
|
+
('DRAW', <program_id>, <mode:str>, <selection:tuple>, <instances:int>)
|
|
177
|
+
# Example: Draw 100 lines with non-instanced rendering
|
|
178
|
+
('DRAW', 4, 'lines', (0, 100), 1)
|
|
179
179
|
# Example: Draw 100 lines using index buffer with id 5
|
|
180
|
-
('DRAW', 4, 'points', (5, 'unsigned_int', 100))
|
|
180
|
+
('DRAW', 4, 'points', (5, 'unsigned_int', 100), 1)
|
|
181
|
+
# Example: Draw a mesh with 10 vertices 20 times using instanced rendering
|
|
182
|
+
('DRAW', 2, 'mesh', (0, 10), 20)
|
|
181
183
|
|
|
182
184
|
Applies to: Program
|
|
183
185
|
|
|
@@ -362,7 +364,7 @@ import sys
|
|
|
362
364
|
import re
|
|
363
365
|
import json
|
|
364
366
|
import weakref
|
|
365
|
-
from
|
|
367
|
+
from packaging.version import Version
|
|
366
368
|
|
|
367
369
|
import numpy as np
|
|
368
370
|
|
|
@@ -371,6 +373,9 @@ from ..util import logger
|
|
|
371
373
|
|
|
372
374
|
# TODO: expose these via an extension space in .gl?
|
|
373
375
|
_internalformats = [
|
|
376
|
+
gl.Enum('GL_DEPTH_COMPONENT', 6402),
|
|
377
|
+
gl.Enum('GL_DEPTH_COMPONENT16', 33189),
|
|
378
|
+
gl.Enum('GL_DEPTH_COMPONENT32_OES', 33191),
|
|
374
379
|
gl.Enum('GL_RED', 6403),
|
|
375
380
|
gl.Enum('GL_R', 8194),
|
|
376
381
|
gl.Enum('GL_R8', 33321),
|
|
@@ -847,7 +852,7 @@ class GlirParser(BaseGlirParser):
|
|
|
847
852
|
if not this_version:
|
|
848
853
|
logger.warning("OpenGL version could not be determined, which "
|
|
849
854
|
"might be a sign that OpenGL is not loaded correctly.")
|
|
850
|
-
elif
|
|
855
|
+
elif Version(this_version) < Version('2.1'):
|
|
851
856
|
if os.getenv('VISPY_IGNORE_OLD_VERSION', '').lower() != 'true':
|
|
852
857
|
logger.warning('OpenGL version 2.1 or higher recommended, '
|
|
853
858
|
'got %s. Some functionality may fail.'
|
|
@@ -1220,7 +1225,7 @@ class GlirProgram(GlirObject):
|
|
|
1220
1225
|
# Regular uniform
|
|
1221
1226
|
func(handle, count, value)
|
|
1222
1227
|
|
|
1223
|
-
def set_attribute(self, name, type_, value):
|
|
1228
|
+
def set_attribute(self, name, type_, value, divisor=None):
|
|
1224
1229
|
"""Set an attribute value. Value is assumed to have been checked."""
|
|
1225
1230
|
if not self._linked:
|
|
1226
1231
|
raise RuntimeError('Cannot set attribute when program has no code')
|
|
@@ -1247,7 +1252,7 @@ class GlirProgram(GlirObject):
|
|
|
1247
1252
|
funcname = self.ATYPEMAP[type_]
|
|
1248
1253
|
func = getattr(gl, funcname)
|
|
1249
1254
|
# Set data
|
|
1250
|
-
self._attributes[name] = 0, handle, func, value[1:]
|
|
1255
|
+
self._attributes[name] = 0, handle, func, value[1:], divisor
|
|
1251
1256
|
else:
|
|
1252
1257
|
# Get meta data
|
|
1253
1258
|
vbo_id, stride, offset = value
|
|
@@ -1261,7 +1266,7 @@ class GlirProgram(GlirObject):
|
|
|
1261
1266
|
# Set data
|
|
1262
1267
|
func = gl.glVertexAttribPointer
|
|
1263
1268
|
args = size, gtype, gl.GL_FALSE, stride, offset
|
|
1264
|
-
self._attributes[name] = vbo.handle, handle, func, args
|
|
1269
|
+
self._attributes[name] = vbo.handle, handle, func, args, divisor
|
|
1265
1270
|
|
|
1266
1271
|
def _pre_draw(self):
|
|
1267
1272
|
self.activate()
|
|
@@ -1270,11 +1275,13 @@ class GlirProgram(GlirObject):
|
|
|
1270
1275
|
gl.glActiveTexture(gl.GL_TEXTURE0 + unit)
|
|
1271
1276
|
gl.glBindTexture(tex_target, tex_handle)
|
|
1272
1277
|
# Activate attributes
|
|
1273
|
-
for vbo_handle, attr_handle, func, args in self._attributes.values():
|
|
1278
|
+
for vbo_handle, attr_handle, func, args, divisor in self._attributes.values():
|
|
1274
1279
|
if vbo_handle:
|
|
1275
1280
|
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_handle)
|
|
1276
1281
|
gl.glEnableVertexAttribArray(attr_handle)
|
|
1277
1282
|
func(attr_handle, *args)
|
|
1283
|
+
if divisor is not None:
|
|
1284
|
+
gl.glVertexAttribDivisor(attr_handle, divisor)
|
|
1278
1285
|
else:
|
|
1279
1286
|
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
|
|
1280
1287
|
gl.glDisableVertexAttribArray(attr_handle)
|
|
@@ -1308,7 +1315,7 @@ class GlirProgram(GlirObject):
|
|
|
1308
1315
|
# apps it would not even make sense.
|
|
1309
1316
|
# self.deactivate()
|
|
1310
1317
|
|
|
1311
|
-
def draw(self, mode, selection):
|
|
1318
|
+
def draw(self, mode, selection, instances=1):
|
|
1312
1319
|
"""Draw program in given mode, with given selection (IndexBuffer or
|
|
1313
1320
|
first, count).
|
|
1314
1321
|
"""
|
|
@@ -1334,14 +1341,20 @@ class GlirProgram(GlirObject):
|
|
|
1334
1341
|
self._pre_draw()
|
|
1335
1342
|
ibuf = self._parser.get_object(id_)
|
|
1336
1343
|
ibuf.activate()
|
|
1337
|
-
|
|
1344
|
+
if instances > 1:
|
|
1345
|
+
gl.glDrawElementsInstanced(mode, count, as_enum(gtype), None, instances)
|
|
1346
|
+
else:
|
|
1347
|
+
gl.glDrawElements(mode, count, as_enum(gtype), None)
|
|
1338
1348
|
ibuf.deactivate()
|
|
1339
1349
|
else:
|
|
1340
1350
|
# Selection based on start and count
|
|
1341
1351
|
first, count = selection
|
|
1342
1352
|
if count:
|
|
1343
1353
|
self._pre_draw()
|
|
1344
|
-
|
|
1354
|
+
if instances > 1:
|
|
1355
|
+
gl.glDrawArraysInstanced(mode, first, count, instances)
|
|
1356
|
+
else:
|
|
1357
|
+
gl.glDrawArrays(mode, first, count)
|
|
1345
1358
|
# Wrap up
|
|
1346
1359
|
gl.check_error('Check after draw')
|
|
1347
1360
|
self._post_draw()
|