q3dviewer 1.0.0__py3-none-any.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.
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import numpy as np
4
+ import pyqtgraph.opengl as gl
5
+ from OpenGL.GL import *
6
+ from OpenGL.GLU import *
7
+ from OpenGL.GLUT import *
8
+ import numpy as np
9
+ import os
10
+ from PyQt5.QtWidgets import QComboBox, QLabel
11
+ from OpenGL.GL import shaders
12
+
13
+
14
+ def div_round_up(x, y):
15
+ return int((x + y - 1) / y)
16
+
17
+
18
+ def set_uniform_mat4(shader, content, name):
19
+ content = content.T
20
+ glUniformMatrix4fv(
21
+ glGetUniformLocation(shader, name),
22
+ 1,
23
+ GL_FALSE,
24
+ content.astype(np.float32)
25
+ )
26
+
27
+
28
+ def set_uniform_1int(shader, content, name):
29
+ glUniform1i(
30
+ glGetUniformLocation(shader, name),
31
+ content
32
+ )
33
+
34
+
35
+ def set_uniform_v2(shader, contents, name):
36
+ glUniform2f(
37
+ glGetUniformLocation(shader, name),
38
+ *contents
39
+ )
40
+
41
+
42
+ def set_uniform_v3(shader, contents, name):
43
+ glUniform3f(
44
+ glGetUniformLocation(shader, name),
45
+ *contents
46
+ )
47
+
48
+
49
+ class GaussianItem(gl.GLGraphicsItem.GLGraphicsItem):
50
+ def __init__(self, **kwds):
51
+ super().__init__()
52
+ self.need_update_gs = False
53
+ self.sh_dim = 0
54
+ self.gs_data = np.empty([0])
55
+ self.prev_Rz = np.array([np.inf, np.inf, np.inf])
56
+ self.path = os.path.dirname(__file__)
57
+ try:
58
+ import torch
59
+ if not torch.cuda.is_available():
60
+ raise ImportError
61
+ self.cuda_pw = None
62
+ self.sort = self.torch_sort
63
+ except ImportError:
64
+ self.sort = self.opengl_sort
65
+
66
+ def addSetting(self, layout):
67
+ label1 = QLabel("set render mode:")
68
+ layout.addWidget(label1)
69
+ combo = QComboBox()
70
+ combo.addItem("render normal guassian")
71
+ combo.addItem("render ball")
72
+ combo.addItem("render inverse guassian")
73
+ combo.currentIndexChanged.connect(self.on_combobox_selection)
74
+ layout.addWidget(combo)
75
+
76
+ def on_combobox_selection(self, index):
77
+ glUseProgram(self.program)
78
+ set_uniform_1int(self.program, index, "render_mod")
79
+ glUseProgram(0)
80
+
81
+ def initializeGL(self):
82
+ fragment_shader = open(self.path + '/../shaders/gau_frag.glsl', 'r').read()
83
+ vertex_shader = open(self.path + '/../shaders/gau_vert.glsl', 'r').read()
84
+ sort_shader = open(self.path + '/../shaders/sort_by_key.glsl', 'r').read()
85
+ prep_shader = open(self.path + '/../shaders/gau_prep.glsl', 'r').read()
86
+
87
+ self.sort_program = shaders.compileProgram(
88
+ shaders.compileShader(sort_shader, GL_COMPUTE_SHADER))
89
+
90
+ self.prep_program = shaders.compileProgram(
91
+ shaders.compileShader(prep_shader, GL_COMPUTE_SHADER))
92
+
93
+ self.program = shaders.compileProgram(
94
+ shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
95
+ shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER),
96
+ )
97
+ positions = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], dtype=np.float32)
98
+
99
+ self.vao = glGenVertexArrays(1)
100
+
101
+ # trade a gaussian as a square (4 2d points)
102
+ square_vert = np.array([-1, 1, 1, 1, 1, -1, -1, -1], dtype=np.float32)
103
+ indices = np.array([0, 1, 2, 0, 2, 3], dtype=np.uint32)
104
+
105
+ # set the vertices for square
106
+ vbo = glGenBuffers(1)
107
+ glBindVertexArray(self.vao)
108
+ glBindBuffer(GL_ARRAY_BUFFER, vbo)
109
+ glBufferData(GL_ARRAY_BUFFER, square_vert.nbytes, square_vert, GL_STATIC_DRAW)
110
+ pos = glGetAttribLocation(self.program, 'vert')
111
+ glVertexAttribPointer(pos, 2, GL_FLOAT, False, 0, None)
112
+ glEnableVertexAttribArray(pos)
113
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
114
+
115
+ # the vert's indices for drawing square
116
+ self.ebo = glGenBuffers(1)
117
+ glBindVertexArray(self.vao)
118
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo)
119
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
120
+ indices.nbytes, indices, GL_STATIC_DRAW)
121
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
122
+ glBindVertexArray(0)
123
+
124
+ # add SSBO for gaussian data
125
+ self.ssbo_gs = glGenBuffers(1)
126
+ self.ssbo_gi = glGenBuffers(1)
127
+ self.ssbo_dp = glGenBuffers(1)
128
+ self.ssbo_pp = glGenBuffers(1)
129
+
130
+ width = self._GLGraphicsItem__view.deviceWidth()
131
+ height = self._GLGraphicsItem__view.deviceHeight()
132
+
133
+ # set constant parameter for gaussian shader
134
+ project_matrix = np.array(self._GLGraphicsItem__view.projectionMatrix().data(), np.float32).reshape([4, 4]).T
135
+ focal_x = project_matrix[0, 0] * width / 2
136
+ focal_y = project_matrix[1, 1] * height / 2
137
+ glUseProgram(self.prep_program)
138
+ set_uniform_mat4(self.prep_program, project_matrix, 'projection_matrix')
139
+ set_uniform_v2(self.prep_program, [focal_x, focal_y], 'focal')
140
+ glUseProgram(0)
141
+
142
+ glUseProgram(self.program)
143
+ set_uniform_v2(self.program, [width, height], 'win_size')
144
+ set_uniform_1int(self.program, 0, "render_mod")
145
+ glUseProgram(0)
146
+
147
+ # opengl settings
148
+ glDisable(GL_CULL_FACE)
149
+ glEnable(GL_BLEND)
150
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
151
+
152
+ def update_gs(self):
153
+ if (self.need_update_gs):
154
+ # compute sorting size
155
+ self.num_sort = int(2**np.ceil(np.log2(self.gs_data.shape[0])))
156
+
157
+ # set input gaussian data
158
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, self.ssbo_gs)
159
+ glBufferData(GL_SHADER_STORAGE_BUFFER, self.gs_data.nbytes, self.gs_data.reshape(-1), GL_STATIC_DRAW)
160
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, self.ssbo_gs)
161
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0)
162
+
163
+ # set depth for sorting
164
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, self.ssbo_dp)
165
+ glBufferData(GL_SHADER_STORAGE_BUFFER, self.num_sort * 4, None, GL_STATIC_DRAW)
166
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, self.ssbo_dp)
167
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0)
168
+
169
+ # set index for sorting (the index need be initialized)
170
+ gi = np.arange(self.num_sort, dtype=np.uint32)
171
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, self.ssbo_gi)
172
+ glBufferData(GL_SHADER_STORAGE_BUFFER, self.num_sort * 4, gi, GL_STATIC_DRAW)
173
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, self.ssbo_gi)
174
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0)
175
+
176
+ # set preprocess buffer
177
+ # the dim of preprocess data is 12 u(3), covinv(3), color(3), area(2), alpha(1)
178
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, self.ssbo_pp)
179
+ glBufferData(GL_SHADER_STORAGE_BUFFER, self.gs_data.shape[0] * 4 * 12,
180
+ None, GL_STATIC_DRAW)
181
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, self.ssbo_pp)
182
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0)
183
+
184
+ glUseProgram(self.prep_program)
185
+ set_uniform_1int(self.prep_program, self.sh_dim, "sh_dim")
186
+ set_uniform_1int(self.prep_program, self.gs_data.shape[0], "gs_num")
187
+ glUseProgram(0)
188
+ self.need_update_gs = False
189
+
190
+ def paint(self):
191
+ # get current view matrix
192
+ self.view_matrix = np.array(self._GLGraphicsItem__view.viewMatrix().data(), np.float32).reshape([4, 4]).T
193
+
194
+ # if gaussian data is update, renew vao, ssbo, etc...
195
+ self.update_gs()
196
+
197
+ if (self.gs_data.shape[0] == 0):
198
+ return
199
+
200
+ # preprocess and sort gaussian by compute shader.
201
+ self.preprocess_gs()
202
+ self.try_sort()
203
+
204
+ # draw by vert shader
205
+ glUseProgram(self.program)
206
+ # bind vao and ebo
207
+ glBindVertexArray(self.vao)
208
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo)
209
+ # draw instances
210
+ glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None, self.gs_data.shape[0])
211
+ # upbind vao and ebo
212
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
213
+ glBindVertexArray(0)
214
+ glUseProgram(0)
215
+
216
+ def try_sort(self):
217
+ # don't sort if the depths are not change.
218
+ Rz = self.view_matrix[2, :3]
219
+ if (np.linalg.norm(self.prev_Rz - Rz) > 0.1):
220
+ # import torch
221
+ # torch.cuda.synchronize()
222
+ # start = time.time()
223
+ self.sort()
224
+ self.prev_Rz = Rz
225
+ # torch.cuda.synchronize()
226
+ # end = time.time()
227
+ # time_diff = end - start
228
+ # print(time_diff)
229
+
230
+ def opengl_sort(self):
231
+ glUseProgram(self.sort_program)
232
+ # can we move this loop to gpu?
233
+ for level in 2**np.arange(1, int(np.ceil(np.log2(self.num_sort))+1)): # level = level*2
234
+ for stage in level/2**np.arange(1, np.log2(level)+1): # stage =stage / 2
235
+ set_uniform_1int(self.sort_program, int(level), "level")
236
+ set_uniform_1int(self.sort_program, int(stage), "stage")
237
+ glDispatchCompute(div_round_up(self.num_sort//2, 256), 1, 1)
238
+ glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)
239
+ # glFinish()
240
+ glUseProgram(0)
241
+
242
+ def torch_sort(self):
243
+ import torch
244
+ if self.cuda_pw is None:
245
+ self.cuda_pw = torch.tensor(self.gs_data[:, :3]).cuda()
246
+ Rz = torch.tensor(self.view_matrix[2, :3]).cuda()
247
+ depth = Rz @ self.cuda_pw.T
248
+ index = torch.argsort(depth).type(torch.int32).cpu().numpy()
249
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, self.ssbo_gi)
250
+ glBufferData(GL_SHADER_STORAGE_BUFFER, index.nbytes, index, GL_STATIC_DRAW)
251
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, self.ssbo_gi)
252
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0)
253
+ return index
254
+
255
+ def preprocess_gs(self):
256
+ glUseProgram(self.prep_program)
257
+ set_uniform_mat4(self.prep_program, self.view_matrix, 'view_matrix')
258
+ glDispatchCompute(div_round_up(self.gs_data.shape[0], 256), 1, 1)
259
+ glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)
260
+ glUseProgram(0)
261
+
262
+ def setData(self, **kwds):
263
+ if 'gs_data' in kwds:
264
+ gs_data = kwds.pop('gs_data')
265
+ self.gs_data = np.ascontiguousarray(gs_data, dtype=np.float32)
266
+ self.sh_dim = self.gs_data.shape[-1] - (3 + 4 + 3 + 1)
267
+ self.need_update_gs = True
@@ -0,0 +1,37 @@
1
+ import pyqtgraph.opengl as gl
2
+ from OpenGL.GL import *
3
+ from PyQt5.QtWidgets import QLabel, QDoubleSpinBox
4
+
5
+
6
+ class GridItem(gl.GLGridItem):
7
+ def __init__(self, size, spacing, color=(255, 255, 255, 76.5)):
8
+ super(GridItem, self).__init__(color=color)
9
+ self.setSize0(size)
10
+ self.setSpacing0(spacing)
11
+
12
+ def addSetting(self, layout):
13
+ label1 = QLabel("Set size:")
14
+ layout.addWidget(label1)
15
+ box1 = QDoubleSpinBox()
16
+ box1.setSingleStep(1.0)
17
+ layout.addWidget(box1)
18
+ box1.setValue(self.size0)
19
+ box1.valueChanged.connect(self.setSize0)
20
+ box1.setRange(0, 100000)
21
+
22
+ label2 = QLabel("Set spacing:")
23
+ layout.addWidget(label2)
24
+ box2 = QDoubleSpinBox()
25
+ layout.addWidget(box2)
26
+ box2.setSingleStep(0.1)
27
+ box2.setValue(self.spacing0)
28
+ box2.valueChanged.connect(self.setSpacing0)
29
+ box2.setRange(0, 1000)
30
+
31
+ def setSize0(self, size):
32
+ self.size0 = size
33
+ self.setSize(self.size0, self.size0)
34
+
35
+ def setSpacing0(self, spacing):
36
+ self.spacing0 = spacing
37
+ self.setSpacing(self.spacing0, self.spacing0)
@@ -0,0 +1,169 @@
1
+ import pyqtgraph.opengl as gl
2
+ from OpenGL.GL import *
3
+ import numpy as np
4
+ from OpenGL.GL import shaders
5
+ from PIL import Image as PIL_Image
6
+ from PyQt5.QtWidgets import QLabel, QSpinBox
7
+
8
+
9
+ # Vertex and Fragment shader source code
10
+ vertex_shader_source = """
11
+ #version 330 core
12
+ layout(location = 0) in vec3 position;
13
+ layout(location = 1) in vec2 texCoord;
14
+
15
+ out vec2 TexCoord;
16
+
17
+ uniform mat4 view_matrix;
18
+ uniform mat4 project_matrix;
19
+
20
+ void main()
21
+ {
22
+ gl_Position = vec4(position, 1.0);
23
+ TexCoord = texCoord;
24
+ }
25
+ """
26
+
27
+ fragment_shader_source = """
28
+ #version 330 core
29
+ in vec2 TexCoord;
30
+ out vec4 color;
31
+ uniform sampler2D ourTexture;
32
+ void main()
33
+ {
34
+ color = texture(ourTexture, TexCoord);
35
+ }
36
+ """
37
+
38
+
39
+ def set_uniform_mat4(shader, content, name):
40
+ content = content.T
41
+ glUniformMatrix4fv(
42
+ glGetUniformLocation(shader, name),
43
+ 1,
44
+ GL_FALSE,
45
+ content.astype(np.float32)
46
+ )
47
+
48
+
49
+ class ImageItem(gl.GLGraphicsItem.GLGraphicsItem):
50
+ def __init__(self, pos=np.array([0, 0]), size=np.array([1280/2, 720/2])):
51
+ gl.GLGraphicsItem.GLGraphicsItem.__init__(self)
52
+ self.pos = pos # bottom-left
53
+ self.size = size
54
+ self.image = np.zeros((self.size[0], self.size[1], 4), dtype=np.uint8)
55
+ self.alpha = 255
56
+
57
+ def initializeGL(self):
58
+ # Rectangle vertices and texture coordinates
59
+ width = self._GLGraphicsItem__view.deviceWidth()
60
+ height = self._GLGraphicsItem__view.deviceHeight()
61
+ x0, y0 = self.pos
62
+ x1, y1 = self.pos + self.size
63
+ x0 = x0 / width * 2 - 1
64
+ y0 = y0 / height * 2 - 1
65
+ x1 = x1 / width * 2 - 1
66
+ y1 = y1 / height * 2 - 1
67
+
68
+ self.vertices = np.array([
69
+ # positions # texture coords
70
+ [x0, y0, 0.0, 0.0, 0.0], # bottom-left
71
+ [x1, y0, 0.0, 1.0, 0.0], # bottom-right
72
+ [x1, y1, 0.0, 1.0, 1.0], # top-right
73
+ [x0, y1, 0.0, 0.0, 1.0], # top-left
74
+ ], dtype=np.float32)
75
+
76
+ indices = np.array([
77
+ 0, 1, 2, # first triangle
78
+ 2, 3, 0 # second triangle
79
+ ], dtype=np.uint32)
80
+
81
+ self.vao = glGenVertexArrays(1)
82
+ vbo = glGenBuffers(1)
83
+ ebo = glGenBuffers(1)
84
+
85
+ glBindVertexArray(self.vao)
86
+
87
+ glBindBuffer(GL_ARRAY_BUFFER, vbo)
88
+ glBufferData(GL_ARRAY_BUFFER, self.vertices.itemsize *
89
+ 5 * 4, self.vertices, GL_STATIC_DRAW)
90
+
91
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
92
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
93
+ indices.nbytes, indices, GL_STATIC_DRAW)
94
+
95
+ # Vertex positions
96
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
97
+ 20, ctypes.c_void_p(0))
98
+ glEnableVertexAttribArray(0)
99
+
100
+ # Texture coordinates
101
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
102
+ 20, ctypes.c_void_p(12))
103
+ glEnableVertexAttribArray(1)
104
+
105
+ # Compile shaders and create shader program
106
+ self.program = shaders.compileProgram(
107
+ shaders.compileShader(vertex_shader_source, GL_VERTEX_SHADER),
108
+ shaders.compileShader(fragment_shader_source, GL_FRAGMENT_SHADER),
109
+ )
110
+
111
+ self.texture = glGenTextures(1)
112
+ glBindTexture(GL_TEXTURE_2D, self.texture)
113
+ glBindVertexArray(0)
114
+
115
+ def setData(self, data):
116
+ if isinstance(data, np.ndarray):
117
+ pass
118
+ elif isinstance(data, PIL_Image.Image):
119
+ data = np.array(data)
120
+ else:
121
+ print("not support image type")
122
+ raise NotImplementedError
123
+
124
+ if data.ndim == 2: # Grayscale image
125
+ data = np.stack((data,) * 3 + (np.ones_like(data) * 255,), axis=-1)
126
+ elif data.shape[-1] == 3: # RGB image
127
+ alpha_channel = np.ones((data.shape[0], data.shape[1], 1), dtype=data.dtype) * self.alpha
128
+ data = np.concatenate((data, alpha_channel), axis=-1)
129
+ self.image = data
130
+
131
+ def paint(self):
132
+ if self.image is not None:
133
+ img_data = self.image
134
+ img_data = np.flipud(img_data) # Flip the image vertically
135
+ img_data = img_data.tobytes()
136
+ glBindTexture(GL_TEXTURE_2D, self.texture)
137
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.image.shape[1],
138
+ self.image.shape[0], 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
139
+ glGenerateMipmap(GL_TEXTURE_2D)
140
+ glBindTexture(GL_TEXTURE_2D, 0)
141
+ self.image = None
142
+
143
+ glEnable(GL_DEPTH_TEST)
144
+ glEnable(GL_BLEND)
145
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
146
+
147
+ glUseProgram(self.program)
148
+ glBindVertexArray(self.vao)
149
+ glBindTexture(GL_TEXTURE_2D, self.texture)
150
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
151
+ glBindTexture(GL_TEXTURE_2D, 0)
152
+ glBindVertexArray(0)
153
+ glUseProgram(0)
154
+
155
+ glDisable(GL_DEPTH_TEST)
156
+ glDisable(GL_BLEND)
157
+
158
+ def addSetting(self, layout):
159
+ label1 = QLabel("Set Alpha:")
160
+ layout.addWidget(label1)
161
+ box1 = QSpinBox()
162
+ box1.setSingleStep(1)
163
+ box1.setRange(0, 255)
164
+ box1.setValue(self.alpha)
165
+ box1.valueChanged.connect(self.setAlpha)
166
+ layout.addWidget(box1)
167
+
168
+ def setAlpha(self, alpha):
169
+ self.alpha = alpha
@@ -0,0 +1,53 @@
1
+ from pyqtgraph.Qt import QtCore
2
+ import pyqtgraph.opengl as gl
3
+ from OpenGL.GL import *
4
+ from PyQt5 import QtGui, QtCore
5
+
6
+
7
+ class GL2DTextItem(gl.GLGraphicsItem.GLGraphicsItem):
8
+ """Draws text over opengl 3D."""
9
+
10
+ def __init__(self, **kwds):
11
+ """All keyword arguments are passed to setData()"""
12
+ gl.GLGraphicsItem.GLGraphicsItem.__init__(self)
13
+ glopts = kwds.pop('glOptions', 'additive')
14
+ self.setGLOptions(glopts)
15
+ self.pos = (100, 100)
16
+ self.color = QtCore.Qt.GlobalColor.white
17
+ self.text = ''
18
+ self.font = QtGui.QFont('Helvetica', 16)
19
+ self.setData(**kwds)
20
+
21
+ def setData(self, **kwds):
22
+ args = ['pos', 'color', 'text', 'size', 'font']
23
+ for k in kwds.keys():
24
+ if k not in args:
25
+ raise ValueError('Invalid keyword argument: %s (allowed arguments are %s)' % (k, str(args)))
26
+ for arg in args:
27
+ if arg in kwds:
28
+ value = kwds[arg]
29
+ if arg == 'pos':
30
+ self.pos = value
31
+ elif arg == 'color':
32
+ value = value
33
+ elif arg == 'font':
34
+ if isinstance(value, QtGui.QFont) is False:
35
+ raise TypeError('"font" must be QFont.')
36
+ elif arg == 'size':
37
+ self.font.setPointSize(value)
38
+ setattr(self, arg, value)
39
+ self.update()
40
+
41
+ def paint(self):
42
+ if len(self.text) < 1:
43
+ return
44
+ self.setupGLState()
45
+
46
+ text_pos = QtCore.QPointF(*self.pos)
47
+ painter = QtGui.QPainter(self.view())
48
+ painter.setPen(self.color)
49
+ painter.setFont(self.font)
50
+ painter.setRenderHints(QtGui.QPainter.RenderHint.Antialiasing | QtGui.QPainter.RenderHint.TextAntialiasing)
51
+ painter.drawText(text_pos, self.text)
52
+ painter.end()
53
+
@@ -0,0 +1,78 @@
1
+ import pyqtgraph.opengl as gl
2
+ from OpenGL.GL import *
3
+ import numpy as np
4
+ import threading
5
+
6
+
7
+ class TrajectoryItem(gl.GLGridItem):
8
+ def __init__(self, width=1, color=(0, 1, 0, 1)):
9
+ super(TrajectoryItem, self).__init__()
10
+ self.width = width
11
+ self.buff = np.empty((0, 3), np.float32)
12
+ self.wait_add_data = None
13
+ self.mutex = threading.Lock()
14
+ self.CAPACITY = 100000
15
+ self.valid_buff_top = 0
16
+ self.color = color
17
+
18
+ def addSetting(self, layout):
19
+ pass
20
+
21
+ def setData(self, data, append=True):
22
+ self.mutex.acquire()
23
+ data = data.astype(np.float32).reshape(-1, 3)
24
+ if (append is False):
25
+ self.wait_add_data = data
26
+ self.add_buff_loc = 0
27
+ else:
28
+ if (self.wait_add_data is None):
29
+ self.wait_add_data = data
30
+ else:
31
+ self.wait_add_data = np.concatenate([self.wait_add_data, data])
32
+ self.add_buff_loc = self.valid_buff_top
33
+ self.mutex.release()
34
+
35
+ def updateRenderBuffer(self):
36
+ if (self.wait_add_data is None):
37
+ return
38
+ self.mutex.acquire()
39
+
40
+ new_buff_top = self.add_buff_loc + self.wait_add_data.shape[0]
41
+ if new_buff_top > self.buff.shape[0]:
42
+ buff_capacity = self.buff.shape[0]
43
+ while (new_buff_top > buff_capacity):
44
+ buff_capacity += self.CAPACITY
45
+ self.buff = np.empty((buff_capacity, 3), np.float32)
46
+ self.buff[self.add_buff_loc:new_buff_top] = self.wait_add_data
47
+ glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
48
+ glBufferData(GL_ARRAY_BUFFER, self.buff.nbytes,
49
+ self.buff, GL_DYNAMIC_DRAW)
50
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
51
+ else:
52
+ self.buff[self.add_buff_loc:new_buff_top] = self.wait_add_data
53
+ glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
54
+ glBufferSubData(GL_ARRAY_BUFFER, self.add_buff_loc * 12,
55
+ self.wait_add_data.shape[0] * 12, self.wait_add_data)
56
+ self.valid_buff_top = new_buff_top
57
+ self.wait_add_data = None
58
+ self.mutex.release()
59
+
60
+ def initializeGL(self):
61
+ self.vbo = glGenBuffers(1)
62
+
63
+ def paint(self):
64
+ self.setupGLState()
65
+ self.updateRenderBuffer()
66
+ glEnable(GL_BLEND)
67
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
68
+ glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
69
+ glEnableClientState(GL_VERTEX_ARRAY)
70
+ glVertexPointer(3, GL_FLOAT, 0, None)
71
+ glLineWidth(self.width)
72
+ glColor4f(*self.color) # z is blue
73
+
74
+ glDrawArrays(GL_LINE_STRIP, 0, self.valid_buff_top)
75
+ glDisableClientState(GL_VERTEX_ARRAY)
76
+
77
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
78
+ glUseProgram(0)