q3dviewer 1.0.3__py3-none-any.whl → 1.0.5__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/__init__.py +5 -0
- q3dviewer/base_glwidget.py +256 -0
- q3dviewer/base_item.py +57 -0
- q3dviewer/custom_items/__init__.py +9 -0
- q3dviewer/custom_items/axis_item.py +148 -0
- q3dviewer/custom_items/cloud_io_item.py +79 -0
- q3dviewer/custom_items/cloud_item.py +314 -0
- q3dviewer/custom_items/frame_item.py +194 -0
- q3dviewer/custom_items/gaussian_item.py +254 -0
- q3dviewer/custom_items/grid_item.py +88 -0
- q3dviewer/custom_items/image_item.py +172 -0
- q3dviewer/custom_items/line_item.py +120 -0
- q3dviewer/custom_items/text_item.py +63 -0
- q3dviewer/gau_io.py +0 -0
- q3dviewer/glwidget.py +131 -0
- q3dviewer/shaders/cloud_frag.glsl +28 -0
- q3dviewer/shaders/cloud_vert.glsl +72 -0
- q3dviewer/shaders/gau_frag.glsl +42 -0
- q3dviewer/shaders/gau_prep.glsl +249 -0
- q3dviewer/shaders/gau_vert.glsl +77 -0
- q3dviewer/shaders/sort_by_key.glsl +56 -0
- q3dviewer/tools/__init__.py +1 -0
- q3dviewer/tools/cloud_viewer.py +123 -0
- q3dviewer/tools/example_viewer.py +47 -0
- q3dviewer/tools/gaussian_viewer.py +60 -0
- q3dviewer/tools/lidar_calib.py +294 -0
- q3dviewer/tools/lidar_cam_calib.py +314 -0
- q3dviewer/tools/ros_viewer.py +85 -0
- q3dviewer/utils/__init__.py +4 -0
- q3dviewer/utils/cloud_io.py +323 -0
- q3dviewer/utils/convert_ros_msg.py +49 -0
- q3dviewer/utils/gl_helper.py +40 -0
- q3dviewer/utils/maths.py +168 -0
- q3dviewer/utils/range_slider.py +86 -0
- q3dviewer/viewer.py +58 -0
- q3dviewer-1.0.5.dist-info/LICENSE +21 -0
- {q3dviewer-1.0.3.dist-info → q3dviewer-1.0.5.dist-info}/METADATA +7 -4
- q3dviewer-1.0.5.dist-info/RECORD +41 -0
- q3dviewer-1.0.5.dist-info/top_level.txt +1 -0
- q3dviewer-1.0.3.dist-info/RECORD +0 -5
- q3dviewer-1.0.3.dist-info/top_level.txt +0 -1
- {q3dviewer-1.0.3.dist-info → q3dviewer-1.0.5.dist-info}/WHEEL +0 -0
- {q3dviewer-1.0.3.dist-info → q3dviewer-1.0.5.dist-info}/entry_points.txt +0 -0
q3dviewer/glwidget.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
3
|
+
Distributed under MIT license. See LICENSE for more information.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from PySide6 import QtCore
|
|
7
|
+
from PySide6.QtWidgets import QWidget, QComboBox, QVBoxLayout, QHBoxLayout, QSizePolicy, QSpacerItem, QLabel, QLineEdit, QCheckBox
|
|
8
|
+
from PySide6.QtGui import QKeyEvent, QVector3D, QRegularExpressionValidator
|
|
9
|
+
from PySide6.QtCore import QRegularExpression
|
|
10
|
+
from OpenGL.GL import *
|
|
11
|
+
import numpy as np
|
|
12
|
+
from q3dviewer.base_glwidget import BaseGLWidget
|
|
13
|
+
|
|
14
|
+
class SettingWindow(QWidget):
|
|
15
|
+
def __init__(self):
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.combo_items = QComboBox()
|
|
18
|
+
self.combo_items.currentIndexChanged.connect(self.on_combo_selection)
|
|
19
|
+
main_layout = QVBoxLayout()
|
|
20
|
+
self.stretch = QSpacerItem(
|
|
21
|
+
10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
22
|
+
main_layout.addWidget(self.combo_items)
|
|
23
|
+
self.layout = QVBoxLayout()
|
|
24
|
+
self.layout.addItem(self.stretch)
|
|
25
|
+
main_layout.addLayout(self.layout)
|
|
26
|
+
self.setLayout(main_layout)
|
|
27
|
+
self.setWindowTitle("Setting Window")
|
|
28
|
+
self.setGeometry(200, 200, 300, 200)
|
|
29
|
+
self.items = {}
|
|
30
|
+
|
|
31
|
+
def add_setting(self, name, item):
|
|
32
|
+
self.items.update({name: item})
|
|
33
|
+
self.combo_items.addItem("%s(%s)" % (name, item.__class__.__name__))
|
|
34
|
+
|
|
35
|
+
def clear_setting(self):
|
|
36
|
+
while self.layout.count():
|
|
37
|
+
child = self.layout.takeAt(0)
|
|
38
|
+
if child.widget():
|
|
39
|
+
child.widget().deleteLater()
|
|
40
|
+
|
|
41
|
+
def on_combo_selection(self, index):
|
|
42
|
+
self.layout.removeItem(self.stretch)
|
|
43
|
+
# remove all setting of previous widget
|
|
44
|
+
self.clear_setting()
|
|
45
|
+
|
|
46
|
+
key = list(self.items.keys())
|
|
47
|
+
item = self.items[key[index]]
|
|
48
|
+
if hasattr(item, "add_setting"):
|
|
49
|
+
item.add_setting(self.layout)
|
|
50
|
+
self.layout.addItem(self.stretch)
|
|
51
|
+
else:
|
|
52
|
+
print("%s: No setting." % (item.__class__.__name__))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class GLWidget(BaseGLWidget):
|
|
56
|
+
def __init__(self):
|
|
57
|
+
self.followed_name = 'none'
|
|
58
|
+
self.named_items = {}
|
|
59
|
+
self.color_str = '#000000'
|
|
60
|
+
self.followable_item_name = ['none']
|
|
61
|
+
self.setting_window = SettingWindow()
|
|
62
|
+
self.enable_show_center = True
|
|
63
|
+
super(GLWidget, self).__init__()
|
|
64
|
+
|
|
65
|
+
def keyPressEvent(self, ev: QKeyEvent):
|
|
66
|
+
if ev.key() == QtCore.Qt.Key_M: # setting meun
|
|
67
|
+
print("Open setting windows")
|
|
68
|
+
self.open_setting_window()
|
|
69
|
+
super().keyPressEvent(ev)
|
|
70
|
+
|
|
71
|
+
def on_followable_selection(self, index):
|
|
72
|
+
self.followed_name = self.followable_item_name[index]
|
|
73
|
+
|
|
74
|
+
def update(self):
|
|
75
|
+
if self.followed_name != 'none':
|
|
76
|
+
pos = self.named_items[self.followed_name].T[:3, 3]
|
|
77
|
+
self.opts['center'] = QVector3D(pos[0], pos[1], pos[2])
|
|
78
|
+
super().update()
|
|
79
|
+
|
|
80
|
+
def add_setting(self, layout):
|
|
81
|
+
label_color = QLabel("Set background color:")
|
|
82
|
+
layout.addWidget(label_color)
|
|
83
|
+
color_edit = QLineEdit()
|
|
84
|
+
color_edit.setToolTip("'using hex color, i.e. #FF4500")
|
|
85
|
+
color_edit.setText(self.color_str)
|
|
86
|
+
color_edit.textChanged.connect(self.set_bg_color)
|
|
87
|
+
regex = QRegularExpression(r"^#[0-9A-Fa-f]{6}$")
|
|
88
|
+
validator = QRegularExpressionValidator(regex)
|
|
89
|
+
color_edit.setValidator(validator)
|
|
90
|
+
layout.addWidget(color_edit)
|
|
91
|
+
|
|
92
|
+
label_focus = QLabel("Set Focus:")
|
|
93
|
+
combo_focus = QComboBox()
|
|
94
|
+
for name in self.followable_item_name:
|
|
95
|
+
combo_focus.addItem(name)
|
|
96
|
+
combo_focus.currentIndexChanged.connect(self.on_followable_selection)
|
|
97
|
+
layout.addWidget(label_focus)
|
|
98
|
+
layout.addWidget(combo_focus)
|
|
99
|
+
|
|
100
|
+
checkbox_show_center = QCheckBox("Show Center Point")
|
|
101
|
+
checkbox_show_center.setChecked(self.enable_show_center)
|
|
102
|
+
checkbox_show_center.stateChanged.connect(self.change_show_center)
|
|
103
|
+
layout.addWidget(checkbox_show_center)
|
|
104
|
+
|
|
105
|
+
def set_bg_color(self, color_str):
|
|
106
|
+
try:
|
|
107
|
+
color_flat = int(color_str[1:], 16)
|
|
108
|
+
red = (color_flat >> 16) & 0xFF
|
|
109
|
+
green = (color_flat >> 8) & 0xFF
|
|
110
|
+
blue = color_flat & 0xFF
|
|
111
|
+
self.color_str = color_str
|
|
112
|
+
self.set_color([red, green, blue, 0])
|
|
113
|
+
except ValueError:
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
def add_item_with_name(self, name, item):
|
|
117
|
+
self.named_items.update({name: item})
|
|
118
|
+
if (item.__class__.__name__ == 'AxisItem'):
|
|
119
|
+
self.followable_item_name.append(name)
|
|
120
|
+
self.setting_window.add_setting(name, item)
|
|
121
|
+
super().add_item(item)
|
|
122
|
+
|
|
123
|
+
def open_setting_window(self):
|
|
124
|
+
if self.setting_window.isVisible():
|
|
125
|
+
self.setting_window.raise_()
|
|
126
|
+
|
|
127
|
+
else:
|
|
128
|
+
self.setting_window.show()
|
|
129
|
+
|
|
130
|
+
def change_show_center(self, state):
|
|
131
|
+
self.enable_show_center = state
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
3
|
+
Distributed under MIT license. See LICENSE for more information.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#version 330 core
|
|
7
|
+
|
|
8
|
+
uniform int point_type;
|
|
9
|
+
|
|
10
|
+
in vec4 color;
|
|
11
|
+
|
|
12
|
+
out vec4 finalColor;
|
|
13
|
+
|
|
14
|
+
void main()
|
|
15
|
+
{
|
|
16
|
+
// only do this when point_type is sphere
|
|
17
|
+
if (point_type == 2)
|
|
18
|
+
{
|
|
19
|
+
vec2 coord = gl_PointCoord * 2.0 - vec2(1.0); // Map [0,1] to [-1,1]
|
|
20
|
+
float distance = dot(coord, coord); // Squared distance
|
|
21
|
+
|
|
22
|
+
// Discard fragments outside the circle (radius = 1.0)
|
|
23
|
+
if (distance > 1.0)
|
|
24
|
+
discard;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
finalColor = color;
|
|
28
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
3
|
+
Distributed under MIT license. See LICENSE for more information.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#version 330 core
|
|
7
|
+
|
|
8
|
+
layout (location = 0) in vec3 position;
|
|
9
|
+
layout (location = 1) in uint value;
|
|
10
|
+
|
|
11
|
+
uniform mat4 view_matrix;
|
|
12
|
+
uniform mat4 projection_matrix;
|
|
13
|
+
uniform float alpha = 1;
|
|
14
|
+
uniform int color_mode = 0;
|
|
15
|
+
uniform int flat_rgb = 0;
|
|
16
|
+
uniform float vmin = 0;
|
|
17
|
+
uniform float vmax = 255;
|
|
18
|
+
uniform float focal = 1000;
|
|
19
|
+
uniform int point_type = 0; // 0 pixel, 1 flat square, 2 sphere
|
|
20
|
+
uniform float point_size = 0.01; // World size for each point (meter)
|
|
21
|
+
out vec4 color;
|
|
22
|
+
|
|
23
|
+
vec3 getRainbowColor(uint value_raw) {
|
|
24
|
+
float range = vmax - vmin;
|
|
25
|
+
float value = 1.0 - (float(value_raw) - vmin) / range;
|
|
26
|
+
value = clamp(value, 0.0, 1.0);
|
|
27
|
+
float hue = value * 5.0 + 1.0;
|
|
28
|
+
int i = int(floor(hue));
|
|
29
|
+
float f = hue - float(i);
|
|
30
|
+
if (mod(i, 2) == 0) f = 1.0 - f;
|
|
31
|
+
float n = 1.0 - f;
|
|
32
|
+
|
|
33
|
+
vec3 color;
|
|
34
|
+
if (i <= 1) color = vec3(n, 0.0, 1.0);
|
|
35
|
+
else if (i == 2) color = vec3(0.0, n, 1.0);
|
|
36
|
+
else if (i == 3) color = vec3(0.0, 1.0, n);
|
|
37
|
+
else if (i == 4) color = vec3(n, 1.0, 0.0);
|
|
38
|
+
else color = vec3(1.0, n, 0.0);
|
|
39
|
+
return color;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
void main()
|
|
43
|
+
{
|
|
44
|
+
vec4 pw = vec4(position, 1.0);
|
|
45
|
+
vec4 pc = view_matrix * pw;
|
|
46
|
+
gl_Position = projection_matrix * pc;
|
|
47
|
+
|
|
48
|
+
// Calculate point size in pixels based on distance
|
|
49
|
+
if (point_type == 0)
|
|
50
|
+
gl_PointSize = int(point_size);
|
|
51
|
+
else
|
|
52
|
+
gl_PointSize = point_size / gl_Position.w * focal;
|
|
53
|
+
vec3 c = vec3(1.0, 1.0, 1.0);
|
|
54
|
+
if (color_mode == 1)
|
|
55
|
+
{
|
|
56
|
+
uint intensity = value >> 24;
|
|
57
|
+
c = getRainbowColor(intensity);
|
|
58
|
+
}
|
|
59
|
+
else if(color_mode == 2)
|
|
60
|
+
{
|
|
61
|
+
c.z = float(value & uint(0x000000FF))/255.;
|
|
62
|
+
c.y = float((value & uint(0x0000FF00)) >> 8)/255.;
|
|
63
|
+
c.x = float((value & uint(0x00FF0000)) >> 16)/255.;
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
{
|
|
67
|
+
c.z = float( uint(flat_rgb) & uint(0x000000FF))/255.;
|
|
68
|
+
c.y = float((uint(flat_rgb) & uint(0x0000FF00)) >> 8)/255.;
|
|
69
|
+
c.x = float((uint(flat_rgb) & uint(0x00FF0000)) >> 16)/255.;
|
|
70
|
+
}
|
|
71
|
+
color = vec4(c, alpha);
|
|
72
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
this file is modified from GaussianSplattingViewer licensed under the MIT License.
|
|
3
|
+
see https://github.com/limacv/GaussianSplattingViewer/blob/main/shaders/gau_frag.glsl
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#version 430 core
|
|
7
|
+
|
|
8
|
+
in vec3 color;
|
|
9
|
+
in float alpha;
|
|
10
|
+
in vec3 cinv2d;
|
|
11
|
+
in vec2 d_pix; // u - pix
|
|
12
|
+
|
|
13
|
+
uniform int render_mod = 1;
|
|
14
|
+
|
|
15
|
+
out vec4 final_color;
|
|
16
|
+
|
|
17
|
+
void main()
|
|
18
|
+
{
|
|
19
|
+
if (alpha < 0.001)
|
|
20
|
+
discard;
|
|
21
|
+
float maha_dist = cinv2d.x * d_pix.x * d_pix.x + cinv2d.z * d_pix.y * d_pix.y + 2 * cinv2d.y * d_pix.x * d_pix.y;
|
|
22
|
+
if (maha_dist < 0.f)
|
|
23
|
+
discard;
|
|
24
|
+
|
|
25
|
+
float g = exp(- 0.5 * maha_dist);
|
|
26
|
+
float alpha_prime = min(0.99f, alpha * g);
|
|
27
|
+
if (alpha_prime < 1.f / 255.f)
|
|
28
|
+
discard;
|
|
29
|
+
final_color = vec4(color, alpha_prime);
|
|
30
|
+
|
|
31
|
+
if (render_mod == 1)
|
|
32
|
+
{
|
|
33
|
+
final_color.a = final_color.a > 0.3 ? 1 : 0;
|
|
34
|
+
final_color.rgb = final_color.rgb * g;
|
|
35
|
+
}
|
|
36
|
+
else if (render_mod == 2)
|
|
37
|
+
{
|
|
38
|
+
final_color.a = final_color.a > 0.3 ? 1 - final_color.a: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/*
|
|
2
|
+
We proprocess gaussian using compute shader.
|
|
3
|
+
this file is modified from GaussianSplattingViewer licensed under the MIT License.
|
|
4
|
+
see https://github.com/limacv/GaussianSplattingViewer/blob/main/shaders/gau_vert.glsl
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#version 430 core
|
|
8
|
+
|
|
9
|
+
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
//https://en.wikipedia.org/wiki/Table_of_spherical_harmonics
|
|
13
|
+
#define SH_C0_0 0.28209479177387814 // Y0,0: 1/2*sqrt(1/pi) plus
|
|
14
|
+
#define SH_C1_0 -0.4886025119029199 // Y1,-1: sqrt(3/(4*pi)) minus
|
|
15
|
+
#define SH_C1_1 0.4886025119029199 // Y1,0: sqrt(3/(4*pi)) plus
|
|
16
|
+
#define SH_C1_2 -0.4886025119029199 // Y1,1: sqrt(3/(4*pi)) minus
|
|
17
|
+
#define SH_C2_0 1.0925484305920792 // Y2,-2: 1/2 * sqrt(15/pi) plus
|
|
18
|
+
#define SH_C2_1 -1.0925484305920792 // Y2,-1: 1/2 * sqrt(15/pi) minus
|
|
19
|
+
#define SH_C2_2 0.31539156525252005 // Y2,0: 1/4*sqrt(5/pi) plus
|
|
20
|
+
#define SH_C2_3 -1.0925484305920792 // Y2,1: 1/2*sqrt(15/pi) minus
|
|
21
|
+
#define SH_C2_4 0.5462742152960396 // Y2,2: 1/4*sqrt(15/pi) plus
|
|
22
|
+
#define SH_C3_0 -0.5900435899266435 // Y3,-3: 1/4*sqrt(35/(2*pi)) minus
|
|
23
|
+
#define SH_C3_1 2.890611442640554 // Y3,-2: 1/2*sqrt(105/pi) plus
|
|
24
|
+
#define SH_C3_2 -0.4570457994644658 // Y3,-1: 1/4*sqrt(21/(2*pi)) minus
|
|
25
|
+
#define SH_C3_3 0.3731763325901154 // Y3,0: 1/4*sqrt(7/pi) plus
|
|
26
|
+
#define SH_C3_4 -0.4570457994644658 // Y3,1: 1/4*sqrt(21/(2*pi)) minus
|
|
27
|
+
#define SH_C3_5 1.445305721320277 // Y3,2: 1/4*sqrt(105/pi) plus
|
|
28
|
+
#define SH_C3_6 -0.5900435899266435 // Y3,3: 1/4*sqrt(35/(2*pi)) minus
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
#define OFFSET_DATA_POS 0
|
|
32
|
+
#define OFFSET_DATA_ROT 3
|
|
33
|
+
#define OFFSET_DATA_SCALE 7
|
|
34
|
+
#define OFFSET_DATA_ALPHA 10
|
|
35
|
+
#define OFFSET_DATA_SH 11
|
|
36
|
+
|
|
37
|
+
#define OFFSET_PREP_U 0
|
|
38
|
+
#define OFFSET_PREP_COVINV 3
|
|
39
|
+
#define OFFSET_PREP_COLOR 6
|
|
40
|
+
#define OFFSET_PREP_AREA 9
|
|
41
|
+
#define OFFSET_PREP_ALPHA 11
|
|
42
|
+
#define DIM_PREP 12
|
|
43
|
+
|
|
44
|
+
// 12 float
|
|
45
|
+
|
|
46
|
+
layout (std430, binding=0) buffer GaussianData {
|
|
47
|
+
float gs_data[];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
layout (std430, binding=2) buffer GaussianDepth {
|
|
51
|
+
float depth[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
layout (std430, binding=3) buffer GaussianPrep {
|
|
55
|
+
float gs_prep[];
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
uniform mat4 view_matrix;
|
|
59
|
+
uniform mat4 projection_matrix;
|
|
60
|
+
uniform vec2 focal;
|
|
61
|
+
uniform int sh_dim;
|
|
62
|
+
uniform int gs_num;
|
|
63
|
+
|
|
64
|
+
mat3 computeCov3D(vec3 scale, vec4 q)
|
|
65
|
+
{
|
|
66
|
+
mat3 S = mat3(0.f);
|
|
67
|
+
S[0][0] = scale.x;
|
|
68
|
+
S[1][1] = scale.y;
|
|
69
|
+
S[2][2] = scale.z;
|
|
70
|
+
float w = q.x;
|
|
71
|
+
float x = q.y;
|
|
72
|
+
float y = q.z;
|
|
73
|
+
float z = q.w;
|
|
74
|
+
|
|
75
|
+
// In GLSL (OpenGL Shading Language), matrices are generally represented in column-major order
|
|
76
|
+
mat3 R = mat3(
|
|
77
|
+
1.f - 2.f * (y * y + z * z), 2.f * (x * y + w * z), 2.f * (x * z - w * y),
|
|
78
|
+
2.f * (x * y - w * z), 1.f - 2.f * (x * x + z * z), 2.f * (y * z + w * x),
|
|
79
|
+
2.f * (x * z + w * y), 2.f * (y * z - w * x), 1.f - 2.f * (x * x + y * y)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
mat3 M = R * S;
|
|
83
|
+
mat3 Sigma = M * transpose(M);
|
|
84
|
+
return Sigma;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
vec3 computeCov2D(vec4 pc, float focal_x, float focal_y, mat3 cov3D, mat4 viewmatrix)
|
|
88
|
+
{
|
|
89
|
+
float z2 = pc.z * pc.z;
|
|
90
|
+
mat3 J = mat3(
|
|
91
|
+
focal_x/pc.z, 0.0f, 0,
|
|
92
|
+
0.0f, focal_y / pc.z, 0,
|
|
93
|
+
-(focal_x*pc.x)/z2,-(focal_y * pc.y) / z2, 0);
|
|
94
|
+
mat3 W = mat3(viewmatrix);
|
|
95
|
+
mat3 T = J * W;
|
|
96
|
+
|
|
97
|
+
mat3 cov = T * cov3D * transpose(T);
|
|
98
|
+
|
|
99
|
+
cov[0][0] += 0.3f;
|
|
100
|
+
cov[1][1] += 0.3f;
|
|
101
|
+
return vec3(cov[0][0], cov[0][1], cov[1][1]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
vec3 get_vec3(int offset)
|
|
105
|
+
{
|
|
106
|
+
return vec3(gs_data[offset], gs_data[offset + 1], gs_data[offset + 2]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
vec4 get_vec4(int offset)
|
|
110
|
+
{
|
|
111
|
+
return vec4(gs_data[offset], gs_data[offset + 1], gs_data[offset + 2], gs_data[offset + 3]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
void set_prep_vec3(int offset, vec3 d)
|
|
115
|
+
{
|
|
116
|
+
gs_prep[offset] = d.x;
|
|
117
|
+
gs_prep[offset + 1] = d.y;
|
|
118
|
+
gs_prep[offset + 2] = d.z;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
void set_prep_vec2(int offset, vec2 d)
|
|
122
|
+
{
|
|
123
|
+
gs_prep[offset] = d.x;
|
|
124
|
+
gs_prep[offset + 1] = d.y;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
void set_prep_vec1(int offset, float d)
|
|
128
|
+
{
|
|
129
|
+
gs_prep[offset] = d.x;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
vec3 computeColor(int sh_offset, vec3 ray_dir)
|
|
133
|
+
{
|
|
134
|
+
vec3 c = SH_C0_0 * get_vec3(sh_offset);
|
|
135
|
+
|
|
136
|
+
if (sh_dim > 3) // 1 * 3
|
|
137
|
+
{
|
|
138
|
+
float x = ray_dir.x;
|
|
139
|
+
float y = ray_dir.y;
|
|
140
|
+
float z = ray_dir.z;
|
|
141
|
+
c = c +
|
|
142
|
+
SH_C1_0 * y * get_vec3(sh_offset + 1 * 3) +
|
|
143
|
+
SH_C1_1 * z * get_vec3(sh_offset + 2 * 3) +
|
|
144
|
+
SH_C1_2 * x * get_vec3(sh_offset + 3 * 3);
|
|
145
|
+
|
|
146
|
+
if (sh_dim > 12) // (1 + 3) * 3
|
|
147
|
+
{
|
|
148
|
+
float xx = x * x, yy = y * y, zz = z * z;
|
|
149
|
+
float xy = x * y, yz = y * z, xz = x * z;
|
|
150
|
+
c = c +
|
|
151
|
+
SH_C2_0 * xy * get_vec3(sh_offset + 4 * 3) +
|
|
152
|
+
SH_C2_1 * yz * get_vec3(sh_offset + 5 * 3) +
|
|
153
|
+
SH_C2_2 * (2.0f * zz - xx - yy) * get_vec3(sh_offset + 6 * 3) +
|
|
154
|
+
SH_C2_3 * xz * get_vec3(sh_offset + 7 * 3) +
|
|
155
|
+
SH_C2_4 * (xx - yy) * get_vec3(sh_offset + 8 * 3);
|
|
156
|
+
|
|
157
|
+
if (sh_dim > 27) // (1 + 3 + 5) * 3
|
|
158
|
+
{
|
|
159
|
+
c = c +
|
|
160
|
+
SH_C3_0 * y * (3.0f * xx - yy) * get_vec3(sh_offset + 9 * 3) +
|
|
161
|
+
SH_C3_1 * xy * z * get_vec3(sh_offset + 10 * 3) +
|
|
162
|
+
SH_C3_2 * y * (4.0f * zz - xx - yy) * get_vec3(sh_offset + 11 * 3) +
|
|
163
|
+
SH_C3_3 * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * get_vec3(sh_offset + 12 * 3) +
|
|
164
|
+
SH_C3_4 * x * (4.0f * zz - xx - yy) * get_vec3(sh_offset + 13 * 3) +
|
|
165
|
+
SH_C3_5 * z * (xx - yy) * get_vec3(sh_offset + 14 * 3) +
|
|
166
|
+
SH_C3_6 * x * (xx - 3.0f * yy) * get_vec3(sh_offset + 15 * 3);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
c += 0.5f;
|
|
171
|
+
|
|
172
|
+
return c;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
void main()
|
|
176
|
+
{
|
|
177
|
+
int gs_id = int(gl_GlobalInvocationID.x);
|
|
178
|
+
|
|
179
|
+
if (gs_id > gs_num)
|
|
180
|
+
return;
|
|
181
|
+
|
|
182
|
+
int dim_gs = 3 + 4 + 3 + 1 + sh_dim;
|
|
183
|
+
int base_gs = gs_id * dim_gs;
|
|
184
|
+
int base_prep = DIM_PREP * gs_id;
|
|
185
|
+
vec4 pw = vec4(get_vec3(base_gs + OFFSET_DATA_POS), 1.f);
|
|
186
|
+
vec4 pc = view_matrix * pw;
|
|
187
|
+
vec4 u = projection_matrix * pc;
|
|
188
|
+
|
|
189
|
+
// set depth for sorter.
|
|
190
|
+
depth[gs_id] = pc.z;
|
|
191
|
+
|
|
192
|
+
u = u / u.w;
|
|
193
|
+
|
|
194
|
+
if (any(greaterThan(abs(u.xy), vec2(1.3))))
|
|
195
|
+
{
|
|
196
|
+
set_prep_vec3(base_prep + OFFSET_PREP_U, vec3(-100));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// check the depth
|
|
201
|
+
if (abs(u.z) > 1.f)
|
|
202
|
+
{
|
|
203
|
+
set_prep_vec3(base_prep + OFFSET_PREP_U, vec3(-100));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
vec4 rot = get_vec4(base_gs + OFFSET_DATA_ROT);
|
|
209
|
+
vec3 scale = get_vec3(base_gs + OFFSET_DATA_SCALE);
|
|
210
|
+
|
|
211
|
+
mat3 cov3d = computeCov3D(scale, rot);
|
|
212
|
+
vec3 cov2d = computeCov2D(pc,
|
|
213
|
+
focal.x,
|
|
214
|
+
focal.y,
|
|
215
|
+
cov3d,
|
|
216
|
+
view_matrix);
|
|
217
|
+
|
|
218
|
+
// Invert covariance (EWA algorithm)
|
|
219
|
+
float det = (cov2d.x * cov2d.z - cov2d.y * cov2d.y);
|
|
220
|
+
|
|
221
|
+
if (det == 0.0f)
|
|
222
|
+
{
|
|
223
|
+
set_prep_vec3(DIM_PREP * gs_id + OFFSET_PREP_U, vec3(-100., -100., -100.));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
float det_inv = 1.f / det;
|
|
228
|
+
vec3 cinv2d = vec3(cov2d.z * det_inv, -cov2d.y * det_inv, cov2d.x * det_inv);
|
|
229
|
+
|
|
230
|
+
vec2 area = 3.f * sqrt(vec2(cov2d.x, cov2d.z)); // drawing area, 3 sigma of x and y
|
|
231
|
+
|
|
232
|
+
// Covert SH to color
|
|
233
|
+
vec3 cam_pos = inverse(view_matrix)[3].xyz;
|
|
234
|
+
int sh_offset = base_gs + OFFSET_DATA_SH;
|
|
235
|
+
vec3 ray_dir = pw.xyz - cam_pos;
|
|
236
|
+
|
|
237
|
+
ray_dir = normalize(ray_dir);
|
|
238
|
+
vec3 color = computeColor(sh_offset, ray_dir);
|
|
239
|
+
float alpha = gs_data[base_gs + OFFSET_DATA_ALPHA];
|
|
240
|
+
|
|
241
|
+
vec3 covinv = vec3(cov2d.z * det_inv, -cov2d.y * det_inv, cov2d.x * det_inv);
|
|
242
|
+
|
|
243
|
+
set_prep_vec3(base_prep + OFFSET_PREP_U, u.xyz); //set u
|
|
244
|
+
set_prep_vec3(base_prep + OFFSET_PREP_COVINV, covinv); //set cov_int
|
|
245
|
+
set_prep_vec3(base_prep + OFFSET_PREP_COLOR, color); //set color
|
|
246
|
+
set_prep_vec2(base_prep + OFFSET_PREP_AREA, area); //set area
|
|
247
|
+
set_prep_vec1(base_prep + OFFSET_PREP_ALPHA, alpha); //set area
|
|
248
|
+
|
|
249
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
3
|
+
Distributed under MIT license. See LICENSE for more information.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
//draw 2d gaussian using proprocess data.
|
|
7
|
+
|
|
8
|
+
#version 430 core
|
|
9
|
+
|
|
10
|
+
#define OFFSET_PREP_U 0
|
|
11
|
+
#define OFFSET_PREP_COVINV 3
|
|
12
|
+
#define OFFSET_PREP_COLOR 6
|
|
13
|
+
#define OFFSET_PREP_AREA 9
|
|
14
|
+
#define OFFSET_PREP_ALPHA 11
|
|
15
|
+
#define DIM_PREP 12
|
|
16
|
+
|
|
17
|
+
layout(location = 0) in vec2 vert;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
layout (std430, binding=0) buffer GaussianData {
|
|
21
|
+
float gs_data[];
|
|
22
|
+
};
|
|
23
|
+
layout (std430, binding=1) buffer GaussianOrder {
|
|
24
|
+
int gs_index[];
|
|
25
|
+
};
|
|
26
|
+
layout (std430, binding=3) buffer GaussianPrep {
|
|
27
|
+
float gs_prep[];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
uniform vec2 win_size;
|
|
31
|
+
|
|
32
|
+
out vec3 color;
|
|
33
|
+
out float alpha;
|
|
34
|
+
out vec3 cinv2d;
|
|
35
|
+
out vec2 d_pix; // local coordinate in quad, unit in pixel
|
|
36
|
+
|
|
37
|
+
vec3 get_prep_vec3(int offset)
|
|
38
|
+
{
|
|
39
|
+
return vec3(gs_prep[offset], gs_prep[offset + 1], gs_prep[offset + 2]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
vec2 get_prep_vec2(int offset)
|
|
43
|
+
{
|
|
44
|
+
return vec2(gs_prep[offset], gs_prep[offset + 1]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
float get_prep_vec1(int offset)
|
|
48
|
+
{
|
|
49
|
+
return float(gs_prep[offset]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void main()
|
|
53
|
+
{
|
|
54
|
+
int gs_id = gs_index[gl_InstanceID];
|
|
55
|
+
int base_prep = gs_id * DIM_PREP;
|
|
56
|
+
gl_Position = vec4(-100);
|
|
57
|
+
|
|
58
|
+
vec3 u = get_prep_vec3(base_prep + OFFSET_PREP_U);
|
|
59
|
+
|
|
60
|
+
if (u == vec3(-100))
|
|
61
|
+
{
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
vec2 area = get_prep_vec2(base_prep + OFFSET_PREP_AREA);
|
|
66
|
+
|
|
67
|
+
vec2 area_ndc = area / win_size * 2; // in ndc space
|
|
68
|
+
vec2 pix = u.xy + vert * area_ndc;
|
|
69
|
+
gl_Position = vec4(pix, u.z , 1.0f);
|
|
70
|
+
|
|
71
|
+
//color = computeColor(sh_offset, ray_dir);
|
|
72
|
+
color = get_prep_vec3(base_prep + OFFSET_PREP_COLOR);
|
|
73
|
+
alpha = get_prep_vec1(base_prep + OFFSET_PREP_ALPHA);
|
|
74
|
+
cinv2d = get_prep_vec3(base_prep + OFFSET_PREP_COVINV);
|
|
75
|
+
d_pix = vert * area;
|
|
76
|
+
|
|
77
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
3
|
+
Distributed under MIT license. See LICENSE for more information.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
opengl compute shader.
|
|
8
|
+
sort guassian by depth using bitonic sorter
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#version 430 core
|
|
12
|
+
|
|
13
|
+
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
uniform int level;
|
|
17
|
+
uniform int stage;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
layout(std430, binding = 1) buffer index_buffer {
|
|
21
|
+
uint index[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
layout(std430, binding = 2) buffer key_buffer {
|
|
25
|
+
float data[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// bitonic sort
|
|
30
|
+
// https://en.wikipedia.org/wiki/Bitonic_sorter
|
|
31
|
+
|
|
32
|
+
void main() {
|
|
33
|
+
uint a = (gl_GlobalInvocationID.x / stage) * (stage * 2) + gl_GlobalInvocationID.x % stage;
|
|
34
|
+
uint b = a ^ stage;
|
|
35
|
+
uint idx_a = index[a];
|
|
36
|
+
uint idx_b = index[b];
|
|
37
|
+
float data_a = data[idx_a];
|
|
38
|
+
float data_b = data[idx_b];
|
|
39
|
+
|
|
40
|
+
if ((a & level) == 0)
|
|
41
|
+
{
|
|
42
|
+
if (data_a > data_b)
|
|
43
|
+
{
|
|
44
|
+
index[a] = idx_b;
|
|
45
|
+
index[b] = idx_a;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
{
|
|
50
|
+
if(data_a < data_b)
|
|
51
|
+
{
|
|
52
|
+
index[a] = idx_b;
|
|
53
|
+
index[b] = idx_a;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# tools/__init__.py
|