q3dviewer 1.0.8__py3-none-any.whl → 1.0.9__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/viewer.py CHANGED
@@ -6,7 +6,7 @@ Distributed under MIT license. See LICENSE for more information.
6
6
 
7
7
  from q3dviewer.glwidget import *
8
8
  import signal
9
- from PySide6.QtWidgets import QMainWindow, QApplication
9
+ from PySide6.QtWidgets import QMainWindow, QApplication, QHBoxLayout
10
10
 
11
11
 
12
12
  def handler(signal, frame):
@@ -15,22 +15,45 @@ def handler(signal, frame):
15
15
 
16
16
 
17
17
  class Viewer(QMainWindow):
18
- def __init__(self, name='Viewer', win_size=[1920, 1080]):
18
+ def __init__(self, name='Viewer', win_size=[1920, 1080],
19
+ gl_widget_class=GLWidget, update_interval=20):
19
20
  signal.signal(signal.SIGINT, handler)
20
21
  super(Viewer, self).__init__()
21
22
  self.setGeometry(0, 0, win_size[0], win_size[1])
23
+ self.gl_widget_class = gl_widget_class
22
24
  self.init_ui()
25
+ self.update_interval = update_interval
26
+ self.add_update_timer()
23
27
  self.setWindowTitle(name)
28
+ self.installEventFilter(self)
24
29
 
25
30
  def init_ui(self):
26
31
  center_widget = QWidget()
27
32
  self.setCentralWidget(center_widget)
28
- self.layout = QHBoxLayout()
29
- center_widget.setLayout(self.layout)
30
- self.glwidget = GLWidget()
31
- self.layout.addWidget(self.glwidget, 1)
33
+ main_layout = QHBoxLayout()
34
+ self.add_control_panel(main_layout)
35
+ center_widget.setLayout(main_layout)
36
+ self.glwidget = self.gl_widget_class()
37
+ main_layout.addWidget(self.glwidget, 1)
38
+ self.default_gl_setting(self.glwidget)
39
+
40
+ def add_control_panel(self, main_layout):
41
+ """
42
+ Override this function to add your own control panel to
43
+ the left side of the main window.
44
+ Don't forget add your own layout to the main_layout.
45
+ """
46
+ pass
47
+
48
+ def default_gl_setting(self, glwidget):
49
+ """
50
+ Override this function to set the default opengl setting of the viewer.
51
+ """
52
+ pass
53
+
54
+ def add_update_timer(self):
32
55
  timer = QtCore.QTimer(self)
33
- timer.setInterval(20) # period, in milliseconds
56
+ timer.setInterval(self.update_interval) # period, in milliseconds
34
57
  timer.timeout.connect(self.update)
35
58
  timer.start()
36
59
 
@@ -1,21 +1,14 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: q3dviewer
3
- Version: 1.0.8
4
- Summary: UNKNOWN
5
- Home-page: UNKNOWN
6
- Author: UNKNOWN
7
- Author-email: UNKNOWN
8
- License: UNKNOWN
9
- Platform: UNKNOWN
10
- Requires-Dist: PyOpenGL
11
- Requires-Dist: laspy
12
- Requires-Dist: meshio
3
+ Version: 1.0.9
4
+ License-File: LICENSE
13
5
  Requires-Dist: numpy
6
+ Requires-Dist: pyside6
7
+ Requires-Dist: PyOpenGL
14
8
  Requires-Dist: pillow
15
- Requires-Dist: pye57
9
+ Requires-Dist: meshio
16
10
  Requires-Dist: pypcd4
17
- Requires-Dist: pyside6
18
-
19
- UNKNOWN
20
-
11
+ Requires-Dist: pye57
12
+ Requires-Dist: laspy
13
+ Requires-Dist: imageio
21
14
 
@@ -0,0 +1,45 @@
1
+ q3dviewer/__init__.py,sha256=rP5XX_x8g7hxIMqNHlU89BN4dt5MSvoYYwip68fCmhc,173
2
+ q3dviewer/base_glwidget.py,sha256=7CJKea2JSP78jsESZJP38yfLhhRINF-VQ9R8sMXwAo0,10697
3
+ q3dviewer/base_item.py,sha256=lzb04oRaS4rRJrAP6C1Bu4ugK237FgupMTB97zjNVFw,1768
4
+ q3dviewer/gau_io.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ q3dviewer/glwidget.py,sha256=im8hjVYEL0Zl7fOIHTQMJdWu7WNOHlvTdIDYjebz9WA,4940
6
+ q3dviewer/viewer.py,sha256=LH1INLFhi6pRjzazzQJ0AWT4hgyXI6GnmqoJFUwUZVE,2517
7
+ q3dviewer/custom_items/__init__.py,sha256=gOiAxdjDaAnFL8YbqSEWWWOwUrJfvzP9JLR34sCB9-4,434
8
+ q3dviewer/custom_items/axis_item.py,sha256=PTBSf5DmQI8ieSinYjY_aC7P8q1nzE-2Vc2GNd1O3Os,2568
9
+ q3dviewer/custom_items/cloud_io_item.py,sha256=gjK3n9WKB7JwxC93ijkweEHA5EezpgNJ8KO-PBaDKCs,2835
10
+ q3dviewer/custom_items/cloud_item.py,sha256=7r6s_j1qEUfLe70t-M68-oIrGRrPOUcZp18ML6jST0s,12542
11
+ q3dviewer/custom_items/frame_item.py,sha256=6BOM3MXi-Akv6KUXDC3QYEAXKxwk0Eo1KQn-F7jkqrQ,7559
12
+ q3dviewer/custom_items/gaussian_item.py,sha256=CZoXMmj2JPFfMqu7v4q4dLUI2cg_WfE1DHWGXjEYn6M,9869
13
+ q3dviewer/custom_items/grid_item.py,sha256=20n4TGm5YEaudhnEOCOk-HtsKwxVxaPr8YV36kO04yU,4802
14
+ q3dviewer/custom_items/image_item.py,sha256=ctNR81fVgxkdl2n3U_TPFL6yn086UhNI_A9fFHgkc-4,5491
15
+ q3dviewer/custom_items/line_item.py,sha256=u0oFN2iHzsRHtnbvyvC_iglEkCwEU2NnTuE536sKUAE,4348
16
+ q3dviewer/custom_items/text_item.py,sha256=nuHMVMQrwy50lNk9hxB94criFxbJJK-SYiK2fSXWUMQ,2158
17
+ q3dviewer/shaders/cloud_frag.glsl,sha256=tbCsDUp9YlPe0hRWlFS724SH6TtMeLO-GVYROzEElZg,609
18
+ q3dviewer/shaders/cloud_vert.glsl,sha256=Vxgw-Zrr0knAK0z4qMXKML6IC4EbffKMwYN2TMXROoI,2117
19
+ q3dviewer/shaders/gau_frag.glsl,sha256=5_UY84tWDts59bxP8x4I-wgnzY8aGeGuo28wX--LW7E,975
20
+ q3dviewer/shaders/gau_prep.glsl,sha256=eCT9nm65uz32w8NaDjeGKhyAZh42Aea-QTwr3yQVr9U,7218
21
+ q3dviewer/shaders/gau_vert.glsl,sha256=NNbVhv_JyqZDK9iXAyBAcIHAtim7G9yWbC9IaUfTL1w,1666
22
+ q3dviewer/shaders/sort_by_key.glsl,sha256=CA2zOcbyDGYAJSJEUvgjUqNshg9NAehf8ipL3Jsv4qE,1097
23
+ q3dviewer/test/test_interpolation.py,sha256=rR_CXsYFLpn0zO0mHf_jL-naluDBMSky--FviOQga0Q,1657
24
+ q3dviewer/test/test_rendering.py,sha256=gbTcu7-cg20DgC5Zoi17C1s5lBGLfAE1rW9biqPjRsA,2164
25
+ q3dviewer/tools/__init__.py,sha256=01wG7BGM6VX0QyFBKsqPmyf2e-vrmV_N3-mo-VQ1VBg,20
26
+ q3dviewer/tools/cinematographer.py,sha256=o_24SSQ4mF062QQ7Gv3i90v7fA79PcHLB03UHXufuEA,13950
27
+ q3dviewer/tools/cloud_viewer.py,sha256=lNvOD0XWDAfgdqc2aJGigcCJsaWUS4qxadjFwf59-OY,3861
28
+ q3dviewer/tools/example_viewer.py,sha256=yeVXT0k4-h1vTLKnGzWADZD3our6XUaYUTy0p5daTkE,959
29
+ q3dviewer/tools/film_maker.py,sha256=MtmmL1-iogSmHXCZc0MLk35_bP-RMBN8twaOtTkv77w,15180
30
+ q3dviewer/tools/gaussian_viewer.py,sha256=vIwWmiFhjNmknrEkBLzt2yiegeH7LP3OeNjnGM6GzaI,1633
31
+ q3dviewer/tools/lidar_calib.py,sha256=M01bGg2mT8LwVcYybolr4UW_UUaR-f-BFciEHtjeK-w,10488
32
+ q3dviewer/tools/lidar_cam_calib.py,sha256=SYNLDvi15MX7Q3aGn771fvu1cES9xeXgP0_WmDq33w4,11200
33
+ q3dviewer/tools/ros_viewer.py,sha256=ARB3I5wohY3maP8dCu0O0hxObd6JFKuK2y7AApVgMWA,2551
34
+ q3dviewer/utils/__init__.py,sha256=irm8Z_bT8l9kzhoMlds2Dal8g4iw4vjmqNPZSs4W6e0,157
35
+ q3dviewer/utils/cloud_io.py,sha256=ttD8FJExdDhXB1Z0Ej9S939i8gcq4JfyqwLXVh8CEFw,11094
36
+ q3dviewer/utils/convert_ros_msg.py,sha256=sAoQfy3qLQKsIArBAVm8H--wlQXOcmkKK3-Ox9UCcrc,1686
37
+ q3dviewer/utils/gl_helper.py,sha256=dRY_kUqyPMr7NTcupUr6_VTvgnj53iE2C0Lk0-oFYsI,1435
38
+ q3dviewer/utils/maths.py,sha256=5TmjWUX1K3UjygXxrUsydjbo7tPzu0gD-yy7qtQUGBU,10588
39
+ q3dviewer/utils/range_slider.py,sha256=jZJQL-uQgnpgLvtYSWpKTrJlLkt3aqNpaRQAePEpNd0,3174
40
+ q3dviewer-1.0.9.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
41
+ q3dviewer-1.0.9.dist-info/METADATA,sha256=zD6g_ySQ3hityOMXY5cKo1wpbaYk0whJEVzQIRReqL4,275
42
+ q3dviewer-1.0.9.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
43
+ q3dviewer-1.0.9.dist-info/entry_points.txt,sha256=aeUdGH7UIgMZEMFUc-0xPZWspY95GoPdZcZuLceq85g,361
44
+ q3dviewer-1.0.9.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
45
+ q3dviewer-1.0.9.dist-info/RECORD,,
@@ -1,8 +1,8 @@
1
1
  [console_scripts]
2
2
  cloud_viewer = q3dviewer.tools.cloud_viewer:main
3
+ film_maker = q3dviewer.tools.film_maker:main
3
4
  gaussian_viewer = q3dviewer.tools.gaussian_viewer:main
4
5
  lidar_calib = q3dviewer.tools.lidar_calib:main
5
6
  lidar_cam_calib = q3dviewer.tools.lidar_cam_calib:main
6
7
  mesh_viewer = q3dviewer.tools.mesh_viewer:main
7
8
  ros_viewer = q3dviewer.tools.ros_viewer:main
8
-
q3dviewer/basic_window.py DELETED
@@ -1,228 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import numpy as np
4
- import pyqtgraph.opengl as gl
5
- from pyqtgraph.Qt import QtCore
6
- from PyQt5.QtWidgets import QWidget, QComboBox, QVBoxLayout, QHBoxLayout, QSizePolicy,\
7
- QSpacerItem, QMainWindow
8
- from OpenGL.GL import *
9
- from PyQt5.QtGui import QKeyEvent, QVector3D
10
- from PyQt5.QtWidgets import QApplication, QWidget
11
- import numpy as np
12
- import signal
13
- import sys
14
- from PyQt5.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, QSpinBox
15
-
16
-
17
- class SettingWindow(QWidget):
18
- def __init__(self):
19
- super().__init__()
20
- self.combo_items = QComboBox()
21
- self.combo_items.currentIndexChanged.connect(self.onComboboxSelection)
22
- main_layout = QVBoxLayout()
23
- self.stretch = QSpacerItem(
24
- 10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)
25
- main_layout.addWidget(self.combo_items)
26
- self.layout = QVBoxLayout()
27
- self.layout.addItem(self.stretch)
28
- main_layout.addLayout(self.layout)
29
- self.setLayout(main_layout)
30
- self.setWindowTitle("Setting Window")
31
- self.setGeometry(200, 200, 300, 200)
32
- self.items = {}
33
-
34
- def addSetting(self, name, item):
35
- self.items.update({name: item})
36
- self.combo_items.addItem("%s(%s)" % (name, item.__class__.__name__))
37
-
38
- def clearSetting(self):
39
- while self.layout.count():
40
- child = self.layout.takeAt(0)
41
- if child.widget():
42
- child.widget().deleteLater()
43
-
44
- def onComboboxSelection(self, index):
45
- self.layout.removeItem(self.stretch)
46
- # remove all setting of previous widget
47
- self.clearSetting()
48
-
49
- key = list(self.items.keys())
50
- try:
51
- item = self.items[key[index]]
52
- item.addSetting(self.layout)
53
- self.layout.addItem(self.stretch)
54
- except AttributeError:
55
- print("%s: No setting." % (item.__class__.__name__))
56
-
57
-
58
- class ViewWidget(gl.GLViewWidget):
59
- def __init__(self):
60
- self.followed_name = 'none'
61
- self.named_items = {}
62
- self.color = '#000000'
63
- self.followable_item_name = ['none']
64
- self.setting_window = SettingWindow()
65
- super(ViewWidget, self).__init__()
66
-
67
- def onFollowableSelection(self, index):
68
- self.followed_name = self.followable_item_name[index]
69
-
70
- def update(self):
71
- if self.followed_name != 'none':
72
- pos = self.named_items[self.followed_name].T[:3, 3]
73
- self.opts['center'] = QVector3D(pos[0], pos[1], pos[2])
74
- super().update()
75
-
76
- def addSetting(self, layout):
77
- label1 = QLabel("Set background color:")
78
- label1.setToolTip("using '#xxxxxx', i.e. #FF4500")
79
- box1 = QLineEdit()
80
- box1.setToolTip("'using '#xxxxxx', i.e. #FF4500")
81
- box1.setText(str(self.color))
82
- box1.textChanged.connect(self.setBKColor)
83
- layout.addWidget(label1)
84
- layout.addWidget(box1)
85
- label2 = QLabel("Set Focus:")
86
- combo2 = QComboBox()
87
- for name in self.followable_item_name:
88
- combo2.addItem(name)
89
- combo2.currentIndexChanged.connect(self.onFollowableSelection)
90
- layout.addWidget(label2)
91
- layout.addWidget(combo2)
92
-
93
- def setBKColor(self, color):
94
- if (type(color) != str):
95
- return
96
- if color.startswith("#"):
97
- try:
98
- self.setBackgroundColor(color)
99
- self.color = color
100
- except ValueError:
101
- return
102
-
103
- def addItem(self, name, item):
104
- self.named_items.update({name: item})
105
- if (item.__class__.__name__ == 'GLAxisItem'):
106
- self.followable_item_name.append(name)
107
- self.setting_window.addSetting(name, item)
108
- super().addItem(item)
109
-
110
- def mouseReleaseEvent(self, ev):
111
- if hasattr(self, 'mousePos'):
112
- delattr(self, 'mousePos')
113
-
114
- def mouseMoveEvent(self, ev):
115
- lpos = ev.localPos()
116
- if not hasattr(self, 'mousePos'):
117
- self.mousePos = lpos
118
- diff = lpos - self.mousePos
119
- self.mousePos = lpos
120
- if ev.buttons() == QtCore.Qt.MouseButton.RightButton:
121
- self.orbit(-diff.x(), diff.y())
122
- elif ev.buttons() == QtCore.Qt.MouseButton.LeftButton:
123
- pitch_abs = np.abs(self.opts['elevation'])
124
- camera_mode = 'view-upright'
125
- if(pitch_abs <= 45.0 or pitch_abs == 90):
126
- camera_mode = 'view'
127
- self.pan(diff.x(), diff.y(), 0, relative=camera_mode)
128
-
129
- def keyPressEvent(self, ev: QKeyEvent):
130
- step = 10
131
- zoom_delta = 20
132
- speed = 2
133
- self.projectionMatrix().data()
134
-
135
- pitch_abs = np.abs(self.opts['elevation'])
136
- camera_mode = 'view-upright'
137
- if(pitch_abs <= 45.0 or pitch_abs == 90):
138
- camera_mode = 'view'
139
-
140
- if ev.key() == QtCore.Qt.Key_M: # setting meun
141
- print("Open setting windows")
142
- self.openSettingWindow()
143
- elif ev.key() == QtCore.Qt.Key_R:
144
- print("Clear viewer")
145
- for item in self.named_items.values():
146
- try:
147
- item.clear()
148
- except:
149
- pass
150
- elif ev.key() == QtCore.Qt.Key_Up:
151
- if ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier:
152
- self.pan(0, +step, 0, relative=camera_mode)
153
- else:
154
- self.orbit(azim=0, elev=-speed)
155
- elif ev.key() == QtCore.Qt.Key_Down:
156
- if ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier:
157
- self.pan(0, -step, 0, relative=camera_mode)
158
- else:
159
- self.orbit(azim=0, elev=speed)
160
- elif ev.key() == QtCore.Qt.Key_Left:
161
- if ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier:
162
- self.pan(+step, 0, 0, relative=camera_mode)
163
- else:
164
- self.orbit(azim=speed, elev=0)
165
-
166
- elif ev.key() == QtCore.Qt.Key_Right:
167
- if ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier:
168
- self.pan(-step, 0, 0, relative=camera_mode)
169
- else:
170
- self.orbit(azim=-speed, elev=0)
171
-
172
- elif ev.key() == QtCore.Qt.Key_Z:
173
- self.opts['distance'] *= 0.999**(+zoom_delta)
174
- elif ev.key() == QtCore.Qt.Key_X:
175
- self.opts['distance'] *= 0.999**(-zoom_delta)
176
- else:
177
- super().keyPressEvent(ev)
178
-
179
- def openSettingWindow(self):
180
- if self.setting_window.isVisible():
181
- self.setting_window.raise_()
182
-
183
- else:
184
- self.setting_window.show()
185
-
186
-
187
- class Viewer(QMainWindow):
188
- def __init__(self, name='Viewer', win_size=[1920, 1080], vw=ViewWidget):
189
- signal.signal(signal.SIGINT, signal.SIG_DFL)
190
- super(Viewer, self).__init__()
191
- self.vw = vw
192
- self.setGeometry(0, 0, win_size[0], win_size[1])
193
- self.initUI()
194
- self.setWindowTitle(name)
195
-
196
- def initUI(self):
197
- centerWidget = QWidget()
198
- self.setCentralWidget(centerWidget)
199
- layout = QVBoxLayout()
200
- centerWidget.setLayout(layout)
201
- self.viewerWidget = self.vw()
202
- layout.addWidget(self.viewerWidget, 1)
203
- timer = QtCore.QTimer(self)
204
- timer.setInterval(20) # period, in milliseconds
205
- timer.timeout.connect(self.update)
206
- self.viewerWidget.setCameraPosition(distance=40)
207
- timer.start()
208
-
209
- def addItems(self, named_items: dict):
210
- for name, item in named_items.items():
211
- self.viewerWidget.addItem(name, item)
212
-
213
- def __getitem__(self, name: str):
214
- if name in self.viewerWidget.named_items:
215
- return self.viewerWidget.named_items[name]
216
- else:
217
- return None
218
-
219
- def update(self):
220
- # force update by timer
221
- self.viewerWidget.update()
222
-
223
- def closeEvent(self, _):
224
- sys.exit(0)
225
-
226
- def show(self):
227
- self.viewerWidget.setting_window.addSetting("main win", self.viewerWidget)
228
- super().show()
q3dviewer/cloud_viewer.py DELETED
@@ -1,74 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import numpy as np
4
- from q3dviewer.custom_items import *
5
- from q3dviewer.basic_window import *
6
- from pypcd4 import PointCloud
7
-
8
- class CloudViewer(Viewer):
9
- def __init__(self):
10
- super(CloudViewer, self).__init__(name="Cloud Viewer")
11
- self.setAcceptDrops(True)
12
-
13
- def dragEnterEvent(self, event):
14
- if event.mimeData().hasUrls():
15
- event.accept()
16
- else:
17
- event.ignore()
18
-
19
- def dropEvent(self, event):
20
- for url in event.mimeData().urls():
21
- file_path = url.toLocalFile()
22
- self.openCloudFile(file_path)
23
-
24
- def openCloudFile(self, file):
25
- cloud_item = self['cloud']
26
- if cloud_item is None:
27
- print("Can't find clouditem.")
28
- return
29
- if file.endswith('.pcd'):
30
- pc = PointCloud.from_path(file).pc_data
31
- if 'rgb' in pc.dtype.names:
32
- color = pc["rgb"].astype(np.uint32)
33
- cloud_item.setColorMode('RGB')
34
- elif 'intensity' in pc.dtype.names:
35
- color = pc["intensity"].astype(np.uint32)
36
- cloud_item.setColorMode('I')
37
- else:
38
- color = pc['z'].astype(np.uint32)
39
- cloud_item.setColorMode('#FFFFFF')
40
- cloud = np.rec.fromarrays(
41
- [np.stack([pc["x"], pc["y"], pc["z"]], axis=1), color],
42
- dtype=cloud_item.data_type)
43
- elif file.endswith('.npy'):
44
- pc = np.load(file)
45
- cloud = np.rec.fromarrays(
46
- [np.stack([pc[:, 0], pc[:, 1], pc[:, 2]], axis=1), pc[:, 3].astype(np.uint32)],
47
- dtype=cloud_item.data_type)
48
- cloud_item.setData(data=cloud)
49
-
50
-
51
- def main():
52
- import argparse
53
- parser = argparse.ArgumentParser()
54
- parser.add_argument("--pcd", help="the pcd path")
55
- args = parser.parse_args()
56
- app = QApplication([])
57
- viewer = CloudViewer()
58
- cloud_item = CloudIOItem(size=1, alpha=0.1)
59
- axis_item = GLAxisItem(size=0.5, width=5)
60
- gird_item = GridItem(size=1000, spacing=20)
61
- # viewer.viewerWidget.setBackgroundColor(255, 255, 255, 255)
62
-
63
- viewer.addItems({'cloud': cloud_item, 'grid': gird_item, 'axis': axis_item})
64
-
65
- if args.pcd:
66
- pcd_fn = args.pcd
67
- viewer.openCloudFile(pcd_fn)
68
-
69
- viewer.show()
70
- app.exec_()
71
-
72
-
73
- if __name__ == '__main__':
74
- main()
@@ -1,173 +0,0 @@
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
6
-
7
-
8
- # Vertex and Fragment shader source code
9
- vertex_shader_source = """
10
- #version 330 core
11
- layout(location = 0) in vec3 position;
12
- layout(location = 1) in vec2 texCoord;
13
-
14
- out vec2 TexCoord;
15
-
16
- uniform mat4 view_matrix;
17
- uniform mat4 project_matrix;
18
-
19
- void main()
20
- {
21
- gl_Position = project_matrix * view_matrix * vec4(position, 1.0);
22
- TexCoord = texCoord;
23
- }
24
- """
25
-
26
- fragment_shader_source = """
27
- #version 330 core
28
- in vec2 TexCoord;
29
- out vec4 color;
30
- uniform sampler2D ourTexture;
31
- void main()
32
- {
33
- color = texture(ourTexture, TexCoord);
34
- }
35
- """
36
-
37
-
38
- def set_uniform_mat4(shader, content, name):
39
- content = content.T
40
- glUniformMatrix4fv(
41
- glGetUniformLocation(shader, name),
42
- 1,
43
- GL_FALSE,
44
- content.astype(np.float32)
45
- )
46
-
47
-
48
- class GLCameraFrameItem(gl.GLGraphicsItem.GLGraphicsItem):
49
- def __init__(self, T=np.eye(4), size=1, width=3, path=None):
50
- gl.GLGraphicsItem.GLGraphicsItem.__init__(self)
51
- self.size = size
52
- self.width = width
53
- self.T = T
54
- self.path = path
55
-
56
- def initializeGL(self):
57
- # Rectangle vertices and texture coordinates
58
- hsize = self.size / 2
59
- self.vertices = np.array([
60
- # positions # texture coords
61
- [-hsize, -hsize, 0.0, 0.0, 0.0], # bottom-left
62
- [hsize, -hsize, 0.0, 1.0, 0.0], # bottom-right
63
- [hsize, hsize, 0.0, 1.0, 1.0], # top-right
64
- [-hsize, hsize, 0.0, 0.0, 1.0], # top-left
65
- [0, 0, -hsize * 0.66, 0.0, 0.0], # top-left
66
- ], dtype=np.float32)
67
-
68
- R = self.T[:3, :3]
69
- t = self.T[:3, 3]
70
- self.vertices[:, :3] = (
71
- R @ self.vertices[:, :3].T + t[:, np.newaxis]).T
72
-
73
- self.focal_p = np.array([0, 0, hsize * 0.66])
74
-
75
- indices = np.array([
76
- 0, 1, 2, # first triangle
77
- 2, 3, 0 # second triangle
78
- ], dtype=np.uint32)
79
-
80
- self.vao = glGenVertexArrays(1)
81
- vbo = glGenBuffers(1)
82
- ebo = glGenBuffers(1)
83
-
84
- glBindVertexArray(self.vao)
85
-
86
- glBindBuffer(GL_ARRAY_BUFFER, vbo)
87
- glBufferData(GL_ARRAY_BUFFER, self.vertices.itemsize *
88
- 5 * 4, self.vertices, GL_STATIC_DRAW)
89
-
90
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
91
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
92
- indices.nbytes, indices, GL_STATIC_DRAW)
93
-
94
- # Vertex positions
95
-
96
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
97
- 20, ctypes.c_void_p(0))
98
- glEnableVertexAttribArray(0)
99
- # Texture coordinates
100
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
101
- 20, ctypes.c_void_p(12))
102
- glEnableVertexAttribArray(1)
103
-
104
- project_matrix = np.array(self._GLGraphicsItem__view.projectionMatrix().data(),
105
- np.float32).reshape([4, 4]).T
106
- # Compile shaders and create shader program
107
- self.program = shaders.compileProgram(
108
- shaders.compileShader(vertex_shader_source, GL_VERTEX_SHADER),
109
- shaders.compileShader(fragment_shader_source, GL_FRAGMENT_SHADER),
110
- )
111
- glUseProgram(self.program)
112
- set_uniform_mat4(self.program, project_matrix, 'project_matrix')
113
- glUseProgram(0)
114
-
115
- self.texture = glGenTextures(1)
116
- glBindTexture(GL_TEXTURE_2D, self.texture)
117
-
118
- # Load image
119
- image = Image.open(self.path)
120
- # image = image.transpose(Image.FLIP_TOP_BOTTOM)
121
- img_data = image.convert("RGBA").tobytes()
122
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width,
123
- image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
124
- glGenerateMipmap(GL_TEXTURE_2D)
125
- glBindTexture(GL_TEXTURE_2D, 0)
126
- glBindVertexArray(0)
127
-
128
- def setTransform(self, T):
129
- self.T = T
130
-
131
- def paint(self):
132
- self.view_matrix = np.array(
133
- self._GLGraphicsItem__view.viewMatrix().data(), np.float32).reshape([4, 4]).T
134
- project_matrix = np.array(self._GLGraphicsItem__view.projectionMatrix(
135
- ).data(), np.float32).reshape([4, 4]).T
136
-
137
- glEnable(GL_DEPTH_TEST)
138
- glEnable(GL_BLEND)
139
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
140
-
141
- glUseProgram(self.program)
142
- set_uniform_mat4(self.program, self.view_matrix, 'view_matrix')
143
- set_uniform_mat4(self.program, project_matrix, 'project_matrix')
144
- glBindVertexArray(self.vao)
145
- glBindTexture(GL_TEXTURE_2D, self.texture)
146
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
147
- glBindTexture(GL_TEXTURE_2D, 0)
148
- glBindVertexArray(0)
149
- glUseProgram(0)
150
-
151
- glLineWidth(self.width)
152
- glBegin(GL_LINES)
153
- glColor4f(1, 1, 1, 1) # z is blue
154
- glVertex3f(*self.vertices[0, :3])
155
- glVertex3f(*self.vertices[1, :3])
156
- glVertex3f(*self.vertices[1, :3])
157
- glVertex3f(*self.vertices[2, :3])
158
- glVertex3f(*self.vertices[2, :3])
159
- glVertex3f(*self.vertices[3, :3])
160
- glVertex3f(*self.vertices[3, :3])
161
- glVertex3f(*self.vertices[0, :3])
162
- glVertex3f(*self.vertices[4, :3])
163
- glVertex3f(*self.vertices[0, :3])
164
- glVertex3f(*self.vertices[4, :3])
165
- glVertex3f(*self.vertices[1, :3])
166
- glVertex3f(*self.vertices[4, :3])
167
- glVertex3f(*self.vertices[2, :3])
168
- glVertex3f(*self.vertices[4, :3])
169
- glVertex3f(*self.vertices[3, :3])
170
- glEnd()
171
-
172
- glDisable(GL_DEPTH_TEST)
173
- glDisable(GL_BLEND)