q3dviewer 1.0.1__py3-none-any.whl → 1.0.3__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.
- {q3dviewer-1.0.1.dist-info → q3dviewer-1.0.3.dist-info}/METADATA +1 -1
- q3dviewer-1.0.3.dist-info/RECORD +5 -0
- q3dviewer-1.0.3.dist-info/top_level.txt +1 -0
- q3dviewer/__init__.py +0 -4
- q3dviewer/basic_viewer.py +0 -56
- q3dviewer/custom_items/__init__.py +0 -9
- q3dviewer/custom_items/axis_item.py +0 -73
- q3dviewer/custom_items/camera_frame_item.py +0 -173
- q3dviewer/custom_items/cloud_io_item.py +0 -83
- q3dviewer/custom_items/cloud_item.py +0 -297
- q3dviewer/custom_items/gaussian_item.py +0 -267
- q3dviewer/custom_items/grid_item.py +0 -37
- q3dviewer/custom_items/image_item.py +0 -169
- q3dviewer/custom_items/text_item.py +0 -53
- q3dviewer/custom_items/trajectory_item.py +0 -78
- q3dviewer/gau_io.py +0 -168
- q3dviewer/tools/__init__.py +0 -6
- q3dviewer/tools/cloud_viewer.py +0 -75
- q3dviewer/tools/example_viewer.py +0 -38
- q3dviewer/tools/gaussian_viewer.py +0 -55
- q3dviewer/tools/lidar_calib.py +0 -274
- q3dviewer/tools/lidar_cam_calib.py +0 -299
- q3dviewer/tools/mesh_viewer.py +0 -57
- q3dviewer/tools/ros_viewer.py +0 -102
- q3dviewer/utils.py +0 -146
- q3dviewer/viewer_widget.py +0 -183
- q3dviewer-1.0.1.dist-info/RECORD +0 -28
- q3dviewer-1.0.1.dist-info/top_level.txt +0 -1
- {q3dviewer-1.0.1.dist-info → q3dviewer-1.0.3.dist-info}/WHEEL +0 -0
- {q3dviewer-1.0.1.dist-info → q3dviewer-1.0.3.dist-info}/entry_points.txt +0 -0
|
@@ -1,297 +0,0 @@
|
|
|
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 threading
|
|
10
|
-
from PyQt5.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, QSpinBox
|
|
11
|
-
from PyQt5.QtGui import QValidator
|
|
12
|
-
from OpenGL.GL import shaders
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
vertex_shader = """
|
|
16
|
-
#version 330 core
|
|
17
|
-
|
|
18
|
-
layout (location = 0) in vec3 position;
|
|
19
|
-
layout (location = 1) in uint value;
|
|
20
|
-
|
|
21
|
-
uniform mat4 view_matrix;
|
|
22
|
-
uniform mat4 projection_matrix;
|
|
23
|
-
uniform float alpha;
|
|
24
|
-
uniform int color_mode;
|
|
25
|
-
uniform float vmin = 0;
|
|
26
|
-
uniform float vmax = 255;
|
|
27
|
-
out vec4 color;
|
|
28
|
-
|
|
29
|
-
vec3 getRainbowColor(uint value_raw) {
|
|
30
|
-
// Normalize value to [0, 1]
|
|
31
|
-
float range = vmax - vmin;
|
|
32
|
-
float value = 1.0 - (float(value_raw) - vmin) / range;
|
|
33
|
-
value = clamp(value, 0.0, 1.0);
|
|
34
|
-
// Convert value to hue in the range [0, 1]
|
|
35
|
-
float hue = value * 5.0 + 1.0;
|
|
36
|
-
int i = int(floor(hue));
|
|
37
|
-
float f = hue - float(i);
|
|
38
|
-
if (mod(i, 2) == 0) f = 1.0 - f; // if i is even
|
|
39
|
-
float n = 1.0 - f;
|
|
40
|
-
|
|
41
|
-
// Determine RGB components based on hue value
|
|
42
|
-
vec3 color;
|
|
43
|
-
if (i <= 1) color = vec3(n, 0.0, 1.0);
|
|
44
|
-
else if (i == 2) color = vec3(0.0, n, 1.0);
|
|
45
|
-
else if (i == 3) color = vec3(0.0, 1.0, n);
|
|
46
|
-
else if (i == 4) color = vec3(n, 1.0, 0.0);
|
|
47
|
-
else if (i >= 5) color = vec3(1.0, n, 0.0);
|
|
48
|
-
|
|
49
|
-
return color;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
void main()
|
|
53
|
-
{
|
|
54
|
-
vec4 pw = vec4(position, 1.0);
|
|
55
|
-
vec4 pc = view_matrix * pw;
|
|
56
|
-
gl_Position = projection_matrix * pc;
|
|
57
|
-
vec3 c = vec3(1.0, 1.0, 1.0);
|
|
58
|
-
if (color_mode == -1)
|
|
59
|
-
{
|
|
60
|
-
c = getRainbowColor(value);
|
|
61
|
-
}
|
|
62
|
-
else if(color_mode == -2)
|
|
63
|
-
{
|
|
64
|
-
c.z = float(value & uint(0x000000FF))/255.;
|
|
65
|
-
c.y = float((value & uint(0x0000FF00)) >> 8)/255.;
|
|
66
|
-
c.x = float((value & uint(0x00FF0000)) >> 16)/255.;
|
|
67
|
-
}
|
|
68
|
-
else if(color_mode == -3)
|
|
69
|
-
{
|
|
70
|
-
uint intensity = value >> 24;
|
|
71
|
-
c = getRainbowColor(intensity);
|
|
72
|
-
}
|
|
73
|
-
else
|
|
74
|
-
{
|
|
75
|
-
c.z = float( uint(color_mode) & uint(0x000000FF))/255.;
|
|
76
|
-
c.y = float((uint(color_mode) & uint(0x0000FF00)) >> 8)/255.;
|
|
77
|
-
c.x = float((uint(color_mode) & uint(0x00FF0000)) >> 16)/255.;
|
|
78
|
-
}
|
|
79
|
-
color = vec4(c, alpha);
|
|
80
|
-
}
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
fragment_shader = """
|
|
84
|
-
#version 330 core
|
|
85
|
-
|
|
86
|
-
in vec4 color;
|
|
87
|
-
|
|
88
|
-
out vec4 finalColor;
|
|
89
|
-
|
|
90
|
-
void main()
|
|
91
|
-
{
|
|
92
|
-
finalColor = color;
|
|
93
|
-
}
|
|
94
|
-
"""
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def set_uniform_mat4(shader, content, name):
|
|
98
|
-
content = content.T
|
|
99
|
-
glUniformMatrix4fv(
|
|
100
|
-
glGetUniformLocation(shader, name),
|
|
101
|
-
1,
|
|
102
|
-
GL_FALSE,
|
|
103
|
-
content.astype(np.float32)
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
# draw points with color (x, y, z, color)
|
|
108
|
-
class CloudItem(gl.GLGraphicsItem.GLGraphicsItem):
|
|
109
|
-
def __init__(self, size, alpha, color_mode='I'):
|
|
110
|
-
super().__init__()
|
|
111
|
-
self.valid_buff_top = 0
|
|
112
|
-
self.add_buff_loc = 0
|
|
113
|
-
self.alpha = alpha
|
|
114
|
-
self.size = size
|
|
115
|
-
self.mutex = threading.Lock()
|
|
116
|
-
self.data_type = [('xyz', '<f4', (3,)), ('color', '<u4')]
|
|
117
|
-
self.color_mode = color_mode
|
|
118
|
-
self.setColorMode(color_mode)
|
|
119
|
-
self.CAPACITY = 10000000 # 10MB * 3 (x,y,z, color) * 4
|
|
120
|
-
self.vmax = 255
|
|
121
|
-
self.buff = np.empty((0), self.data_type)
|
|
122
|
-
self.wait_add_data = None
|
|
123
|
-
self.need_update_setting = True
|
|
124
|
-
|
|
125
|
-
def addSetting(self, layout):
|
|
126
|
-
label1 = QLabel("Set Size:")
|
|
127
|
-
layout.addWidget(label1)
|
|
128
|
-
box1 = QSpinBox()
|
|
129
|
-
box1.setSingleStep(1)
|
|
130
|
-
layout.addWidget(box1)
|
|
131
|
-
box1.setValue(self.size)
|
|
132
|
-
box1.valueChanged.connect(self.setSize)
|
|
133
|
-
box1.setRange(0, 100)
|
|
134
|
-
|
|
135
|
-
label2 = QLabel("Set Alpha:")
|
|
136
|
-
layout.addWidget(label2)
|
|
137
|
-
box2 = QDoubleSpinBox()
|
|
138
|
-
layout.addWidget(box2)
|
|
139
|
-
box2.setSingleStep(0.01)
|
|
140
|
-
box2.setValue(self.alpha)
|
|
141
|
-
box2.valueChanged.connect(self.setAlpha)
|
|
142
|
-
box2.setRange(0, 1)
|
|
143
|
-
|
|
144
|
-
label3 = QLabel("Set ColorMode:")
|
|
145
|
-
label3.setToolTip(
|
|
146
|
-
"'I': intensity mode; 'IRGB': IRGB mode; 'RGB': rgb mode; '#xxxxxx'; matplotlib color, i.e. #FF4500;")
|
|
147
|
-
layout.addWidget(label3)
|
|
148
|
-
box3 = QLineEdit()
|
|
149
|
-
box3.setToolTip(
|
|
150
|
-
"'I': intensity mode; 'IRGB': IRGB mode; 'RGB': rgb mode; '#xxxxxx'; matplotlib color, i.e. #FF4500;")
|
|
151
|
-
|
|
152
|
-
box3.setText(str(self.color_mode))
|
|
153
|
-
box3.textChanged.connect(self.setColorMode)
|
|
154
|
-
layout.addWidget(box3)
|
|
155
|
-
|
|
156
|
-
def setAlpha(self, alpha):
|
|
157
|
-
self.alpha = alpha
|
|
158
|
-
self.need_update_setting = True
|
|
159
|
-
|
|
160
|
-
def setVmax(self, vmax):
|
|
161
|
-
self.vmax = vmax
|
|
162
|
-
self.need_update_setting = True
|
|
163
|
-
|
|
164
|
-
def setColorMode(self, color_mode):
|
|
165
|
-
"""
|
|
166
|
-
intensity mode: -1;
|
|
167
|
-
rgb mode: -2;
|
|
168
|
-
matplotlib color: i.e. '#FF4500';
|
|
169
|
-
"""
|
|
170
|
-
if (type(color_mode) == str):
|
|
171
|
-
if color_mode.startswith("#"):
|
|
172
|
-
try:
|
|
173
|
-
self.color_mode_int = int(color_mode[1:], 16)
|
|
174
|
-
except ValueError:
|
|
175
|
-
return
|
|
176
|
-
elif color_mode == 'RGB':
|
|
177
|
-
self.color_mode_int = -2
|
|
178
|
-
elif color_mode == 'IRGB':
|
|
179
|
-
self.color_mode_int = -3
|
|
180
|
-
elif color_mode == 'I':
|
|
181
|
-
self.color_mode_int = -1
|
|
182
|
-
else:
|
|
183
|
-
return
|
|
184
|
-
self.color_mode = color_mode
|
|
185
|
-
self.need_update_setting = True
|
|
186
|
-
|
|
187
|
-
def setSize(self, size):
|
|
188
|
-
self.size = size
|
|
189
|
-
|
|
190
|
-
def clear(self):
|
|
191
|
-
data = np.empty((0), self.data_type)
|
|
192
|
-
self.setData(data)
|
|
193
|
-
|
|
194
|
-
def setData(self, data, append=False):
|
|
195
|
-
if data.dtype is np.dtype('float32') or data.dtype is np.dtype('float64'):
|
|
196
|
-
xyz = data[:, :3]
|
|
197
|
-
if (data.shape[1] == 4):
|
|
198
|
-
color = data[:, 3].view(np.uint32)
|
|
199
|
-
else:
|
|
200
|
-
color = np.zeros(data.shape[0], dtype=np.uint32)
|
|
201
|
-
data = np.rec.fromarrays(
|
|
202
|
-
[xyz, color],
|
|
203
|
-
dtype=self.data_type)
|
|
204
|
-
self.mutex.acquire()
|
|
205
|
-
if (append is False):
|
|
206
|
-
self.wait_add_data = data
|
|
207
|
-
self.add_buff_loc = 0
|
|
208
|
-
else:
|
|
209
|
-
if (self.wait_add_data is None):
|
|
210
|
-
self.wait_add_data = data
|
|
211
|
-
else:
|
|
212
|
-
self.wait_add_data = np.concatenate([self.wait_add_data, data])
|
|
213
|
-
self.add_buff_loc = self.valid_buff_top
|
|
214
|
-
self.mutex.release()
|
|
215
|
-
|
|
216
|
-
def updateSetting(self):
|
|
217
|
-
if (self.need_update_setting is False):
|
|
218
|
-
return
|
|
219
|
-
glUseProgram(self.program)
|
|
220
|
-
glUniform1i(glGetUniformLocation(
|
|
221
|
-
self.program, "color_mode"), self.color_mode_int)
|
|
222
|
-
glUniform1f(glGetUniformLocation(self.program, "vmax"), self.vmax)
|
|
223
|
-
glUniform1f(glGetUniformLocation(self.program, "alpha"), self.alpha)
|
|
224
|
-
glUseProgram(0)
|
|
225
|
-
self.need_update_setting = False
|
|
226
|
-
|
|
227
|
-
def updateRenderBuffer(self):
|
|
228
|
-
# is not new data dont update buff
|
|
229
|
-
if (self.wait_add_data is None):
|
|
230
|
-
return
|
|
231
|
-
self.mutex.acquire()
|
|
232
|
-
|
|
233
|
-
new_buff_top = self.add_buff_loc + self.wait_add_data.shape[0]
|
|
234
|
-
if new_buff_top > self.buff.shape[0]:
|
|
235
|
-
# if need to update buff capacity, create new cpu buff and new vbo
|
|
236
|
-
buff_capacity = self.buff.shape[0]
|
|
237
|
-
while (new_buff_top > buff_capacity):
|
|
238
|
-
buff_capacity += self.CAPACITY
|
|
239
|
-
print("Update capacity to %d" % buff_capacity)
|
|
240
|
-
new_buff = np.empty((buff_capacity), self.data_type)
|
|
241
|
-
new_buff[:self.add_buff_loc] = self.buff[:self.add_buff_loc]
|
|
242
|
-
new_buff[self.add_buff_loc:new_buff_top] = self.wait_add_data
|
|
243
|
-
self.buff = new_buff
|
|
244
|
-
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
|
|
245
|
-
glBufferData(GL_ARRAY_BUFFER, self.buff.nbytes,
|
|
246
|
-
self.buff, GL_DYNAMIC_DRAW)
|
|
247
|
-
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
|
248
|
-
else:
|
|
249
|
-
self.buff[self.add_buff_loc:new_buff_top] = self.wait_add_data
|
|
250
|
-
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
|
|
251
|
-
glBufferSubData(GL_ARRAY_BUFFER, self.add_buff_loc * 16,
|
|
252
|
-
self.wait_add_data.shape[0] * 16, self.wait_add_data)
|
|
253
|
-
self.valid_buff_top = new_buff_top
|
|
254
|
-
self.wait_add_data = None
|
|
255
|
-
self.mutex.release()
|
|
256
|
-
|
|
257
|
-
def initializeGL(self):
|
|
258
|
-
self.program = shaders.compileProgram(
|
|
259
|
-
shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
|
|
260
|
-
shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER),
|
|
261
|
-
)
|
|
262
|
-
# Bind attribute locations
|
|
263
|
-
# set constant parameter for cloud shader
|
|
264
|
-
self.setAlpha(self.alpha)
|
|
265
|
-
self.setColorMode(self.color_mode)
|
|
266
|
-
self.setVmax(self.vmax)
|
|
267
|
-
self.vbo = glGenBuffers(1)
|
|
268
|
-
|
|
269
|
-
def paint(self):
|
|
270
|
-
self.setupGLState()
|
|
271
|
-
self.updateRenderBuffer()
|
|
272
|
-
self.updateSetting()
|
|
273
|
-
glEnable(GL_BLEND)
|
|
274
|
-
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
|
275
|
-
glUseProgram(self.program)
|
|
276
|
-
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
|
|
277
|
-
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 16, ctypes.c_void_p(0))
|
|
278
|
-
glVertexAttribPointer(
|
|
279
|
-
1, 1, GL_FLOAT, GL_UNSIGNED_INT, 16, ctypes.c_void_p(12))
|
|
280
|
-
glEnableVertexAttribArray(0)
|
|
281
|
-
glEnableVertexAttribArray(1)
|
|
282
|
-
|
|
283
|
-
view_matrix = np.array(
|
|
284
|
-
self._GLGraphicsItem__view.viewMatrix().data(), np.float32).reshape([4, 4]).T
|
|
285
|
-
set_uniform_mat4(self.program, view_matrix, 'view_matrix')
|
|
286
|
-
project_matrix = np.array(self._GLGraphicsItem__view.projectionMatrix(
|
|
287
|
-
).data(), np.float32).reshape([4, 4]).T
|
|
288
|
-
set_uniform_mat4(self.program, project_matrix, 'projection_matrix')
|
|
289
|
-
|
|
290
|
-
glPointSize(self.size)
|
|
291
|
-
glDrawArrays(GL_POINTS, 0, self.valid_buff_top)
|
|
292
|
-
|
|
293
|
-
# unbind VBO
|
|
294
|
-
glDisableVertexAttribArray(0)
|
|
295
|
-
glDisableVertexAttribArray(1)
|
|
296
|
-
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
|
297
|
-
glUseProgram(0)
|
|
@@ -1,267 +0,0 @@
|
|
|
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
|
|
@@ -1,37 +0,0 @@
|
|
|
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)
|