q3dviewer 1.2.1__py3-none-any.whl → 1.2.2__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/custom_items/mesh_item.py +95 -12
- q3dviewer/shaders/mesh_vert.glsl +44 -8
- q3dviewer/tools/cloud_viewer.py +11 -4
- {q3dviewer-1.2.1.dist-info → q3dviewer-1.2.2.dist-info}/METADATA +1 -1
- {q3dviewer-1.2.1.dist-info → q3dviewer-1.2.2.dist-info}/RECORD +9 -9
- {q3dviewer-1.2.1.dist-info → q3dviewer-1.2.2.dist-info}/LICENSE +0 -0
- {q3dviewer-1.2.1.dist-info → q3dviewer-1.2.2.dist-info}/WHEEL +0 -0
- {q3dviewer-1.2.1.dist-info → q3dviewer-1.2.2.dist-info}/entry_points.txt +0 -0
- {q3dviewer-1.2.1.dist-info → q3dviewer-1.2.2.dist-info}/top_level.txt +0 -0
|
@@ -10,7 +10,7 @@ import numpy as np
|
|
|
10
10
|
from q3dviewer.base_item import BaseItem
|
|
11
11
|
from OpenGL.GL import *
|
|
12
12
|
from OpenGL.GL import shaders
|
|
13
|
-
from q3dviewer.Qt.QtWidgets import QLabel, QCheckBox, QDoubleSpinBox, QSlider, QHBoxLayout, QLineEdit
|
|
13
|
+
from q3dviewer.Qt.QtWidgets import QLabel, QCheckBox, QDoubleSpinBox, QSlider, QHBoxLayout, QLineEdit, QComboBox
|
|
14
14
|
import matplotlib.colors as mcolors
|
|
15
15
|
import os
|
|
16
16
|
from q3dviewer.utils import set_uniform, text_to_rgba
|
|
@@ -18,7 +18,53 @@ from q3dviewer.utils import set_uniform, text_to_rgba
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class MeshItem(BaseItem):
|
|
21
|
-
|
|
21
|
+
"""
|
|
22
|
+
An OpenGL mesh item for rendering triangulated 3D surfaces.
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
color (str or tuple): The flat color to use when `color_mode` is 'FLAT'.
|
|
26
|
+
Accepts any valid matplotlib color (e.g., 'lightblue', 'red', '#FF4500', (1.0, 0.5, 0.0)).
|
|
27
|
+
wireframe (bool): If True, render the mesh in wireframe mode (edges only).
|
|
28
|
+
If False, render filled triangles. Default is False.
|
|
29
|
+
enable_lighting (bool): Whether to enable Phong lighting for the mesh.
|
|
30
|
+
If True, the mesh will be shaded based on light direction and material properties.
|
|
31
|
+
If False, the mesh will use flat shading with object colors only. Default is True.
|
|
32
|
+
color_mode (str): The coloring mode for mesh vertices.
|
|
33
|
+
- 'FLAT': Single flat color for all vertices (uses the `color` attribute).
|
|
34
|
+
- 'I': Color by intensity channel from per-vertex colors (rainbow gradient).
|
|
35
|
+
- 'RGB': Per-vertex RGB color from per-vertex color data.
|
|
36
|
+
alpha (float): The transparency of the mesh, in the range [0, 1],
|
|
37
|
+
where 0 is fully transparent and 1 is fully opaque. Default is 1.0.
|
|
38
|
+
line_width (float): The width of lines when rendering in wireframe mode.
|
|
39
|
+
Range is typically 0.5 to 5.0. Default is 1.0.
|
|
40
|
+
|
|
41
|
+
Material Properties (Phong Lighting):
|
|
42
|
+
ambient_strength (float): Ambient light contribution [0.0-1.0]. Default is 0.1.
|
|
43
|
+
diffuse_strength (float): Diffuse light contribution [0.0-2.0]. Default is 1.2.
|
|
44
|
+
specular_strength (float): Specular highlight contribution [0.0-2.0]. Default is 0.1.
|
|
45
|
+
shininess (float): Specular shininess exponent [1-256]. Higher values = smaller highlights. Default is 32.0.
|
|
46
|
+
|
|
47
|
+
Methods:
|
|
48
|
+
set_data(verts, faces, colors=None): Set mesh geometry and optional per-vertex colors.
|
|
49
|
+
- verts: np.ndarray of shape (N, 3) - vertex positions
|
|
50
|
+
- faces: np.ndarray of shape (M, 3) with uint32 indices - triangle indices
|
|
51
|
+
- colors: np.ndarray of shape (N,) with uint32 IRGB format (optional)
|
|
52
|
+
uint32 format: I (bits 24-31), R (bits 16-23), G (bits 8-15), B (bits 0-7)
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
# Create a simple triangle mesh with per-vertex colors
|
|
56
|
+
verts = np.array([[0,0,0], [1,0,0], [0,1,0]], dtype=np.float32)
|
|
57
|
+
faces = np.array([[0,1,2]], dtype=np.uint32)
|
|
58
|
+
colors = np.array([
|
|
59
|
+
(255 << 24) | (255 << 16) | (0 << 8) | 0, # Red, intensity=255
|
|
60
|
+
(200 << 24) | (0 << 16) | (255 << 8) | 0, # Green, intensity=200
|
|
61
|
+
(150 << 24) | (0 << 16) | (0 << 8) | 255 # Blue, intensity=150
|
|
62
|
+
], dtype=np.uint32)
|
|
63
|
+
|
|
64
|
+
mesh = q3d.MeshItem(color='lightblue', color_mode='RGB', enable_lighting=True)
|
|
65
|
+
mesh.set_data(verts, faces, colors)
|
|
66
|
+
"""
|
|
67
|
+
def __init__(self, color='lightblue', wireframe=False, enable_lighting=True, color_mode='FLAT'):
|
|
22
68
|
super(MeshItem, self).__init__()
|
|
23
69
|
self.color = color
|
|
24
70
|
self.flat_rgb = text_to_rgba(color, flat=True)
|
|
@@ -28,12 +74,18 @@ class MeshItem(BaseItem):
|
|
|
28
74
|
# Mesh data
|
|
29
75
|
self.triangles = None
|
|
30
76
|
self.normals = None
|
|
77
|
+
self.vertex_colors = None # Per-vertex colors (uint32 IRGB format)
|
|
78
|
+
|
|
79
|
+
self.mode_table = {'FLAT': 0, 'I': 1, 'RGB': 2}
|
|
80
|
+
self.color_mode = self.mode_table[color_mode]
|
|
81
|
+
self.vmin = 0
|
|
82
|
+
self.vmax = 255
|
|
31
83
|
|
|
32
84
|
# OpenGL objects
|
|
33
85
|
self.vao = None
|
|
34
86
|
self.vbo_vertices = None
|
|
35
87
|
self.vbo_normals = None
|
|
36
|
-
|
|
88
|
+
self.vbo_colors = None
|
|
37
89
|
self.program = None
|
|
38
90
|
|
|
39
91
|
# Rendering parameters
|
|
@@ -90,6 +142,17 @@ class MeshItem(BaseItem):
|
|
|
90
142
|
layout.addWidget(alpha_box)
|
|
91
143
|
|
|
92
144
|
|
|
145
|
+
# Color mode selection
|
|
146
|
+
label_color = QLabel("Color Mode:")
|
|
147
|
+
layout.addWidget(label_color)
|
|
148
|
+
self.combo_color = QComboBox()
|
|
149
|
+
self.combo_color.addItem("flat color")
|
|
150
|
+
self.combo_color.addItem("intensity")
|
|
151
|
+
self.combo_color.addItem("RGB")
|
|
152
|
+
self.combo_color.setCurrentIndex(self.color_mode)
|
|
153
|
+
self.combo_color.currentIndexChanged.connect(self._on_color_mode)
|
|
154
|
+
layout.addWidget(self.combo_color)
|
|
155
|
+
|
|
93
156
|
label_rgb = QLabel("Color:")
|
|
94
157
|
label_rgb.setToolTip("Use hex color, i.e. #FF4500, or named color, i.e. 'red'")
|
|
95
158
|
layout.addWidget(label_rgb)
|
|
@@ -158,6 +221,11 @@ class MeshItem(BaseItem):
|
|
|
158
221
|
except ValueError:
|
|
159
222
|
pass
|
|
160
223
|
|
|
224
|
+
def _on_color_mode(self, index):
|
|
225
|
+
print(f"Color mode1 : {index}")
|
|
226
|
+
self.color_mode = index
|
|
227
|
+
self.edit_rgb.setVisible(index == self.mode_table['FLAT'])
|
|
228
|
+
self.need_update_setting = True
|
|
161
229
|
|
|
162
230
|
def update_wireframe(self, value):
|
|
163
231
|
self.wireframe = value
|
|
@@ -191,14 +259,26 @@ class MeshItem(BaseItem):
|
|
|
191
259
|
self.alpha = float(value)
|
|
192
260
|
self.need_update_setting = True
|
|
193
261
|
|
|
194
|
-
def set_data(self, verts, faces):
|
|
262
|
+
def set_data(self, verts, faces, colors=None):
|
|
195
263
|
"""
|
|
196
264
|
verts: np.ndarray of shape (N, 3)
|
|
197
265
|
faces: np.ndarray of shape (M, 3) with uint32 indices
|
|
266
|
+
colors: np.ndarray of shape (N,) with uint32 IRGB format (optional)
|
|
267
|
+
uint32 contains: I (bits 24-31), R (bits 16-23), G (bits 8-15), B (bits 0-7)
|
|
198
268
|
"""
|
|
199
269
|
verts = np.asarray(verts, dtype=np.float32)
|
|
200
270
|
faces = np.asarray(faces, dtype=np.uint32)
|
|
201
271
|
triangles = verts[faces.flatten()]
|
|
272
|
+
|
|
273
|
+
if colors is not None:
|
|
274
|
+
colors = np.asarray(colors, dtype=np.uint32)
|
|
275
|
+
if len(colors) == len(verts):
|
|
276
|
+
# Expand per-vertex colors to per-triangle-vertex
|
|
277
|
+
self.vertex_colors = colors[faces.flatten()]
|
|
278
|
+
else:
|
|
279
|
+
self.vertex_colors = None
|
|
280
|
+
else:
|
|
281
|
+
self.vertex_colors = None
|
|
202
282
|
|
|
203
283
|
self.triangles = np.asarray(triangles, dtype=np.float32)
|
|
204
284
|
self.normals = self.calculate_normals()
|
|
@@ -256,7 +336,7 @@ class MeshItem(BaseItem):
|
|
|
256
336
|
self.vao = glGenVertexArrays(1)
|
|
257
337
|
self.vbo_vertices = glGenBuffers(1)
|
|
258
338
|
self.vbo_normals = glGenBuffers(1)
|
|
259
|
-
|
|
339
|
+
self.vbo_colors = glGenBuffers(1)
|
|
260
340
|
|
|
261
341
|
glBindVertexArray(self.vao)
|
|
262
342
|
|
|
@@ -273,13 +353,13 @@ class MeshItem(BaseItem):
|
|
|
273
353
|
glEnableVertexAttribArray(1)
|
|
274
354
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, None)
|
|
275
355
|
|
|
276
|
-
# Color buffer
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
356
|
+
# Color buffer (uint32 IRGB format)
|
|
357
|
+
if self.vertex_colors is not None:
|
|
358
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.vbo_colors)
|
|
359
|
+
glBufferData(GL_ARRAY_BUFFER, self.vertex_colors.nbytes, self.vertex_colors, GL_STATIC_DRAW)
|
|
360
|
+
glEnableVertexAttribArray(2)
|
|
361
|
+
glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, 0, None)
|
|
362
|
+
|
|
283
363
|
glBindVertexArray(0)
|
|
284
364
|
self.need_update_buffer = False
|
|
285
365
|
|
|
@@ -295,6 +375,9 @@ class MeshItem(BaseItem):
|
|
|
295
375
|
set_uniform(self.program, float(self.shininess), 'shininess')
|
|
296
376
|
set_uniform(self.program, float(self.alpha), 'alpha')
|
|
297
377
|
set_uniform(self.program, int(self.flat_rgb), 'flat_rgb')
|
|
378
|
+
set_uniform(self.program, int(self.color_mode), 'color_mode')
|
|
379
|
+
set_uniform(self.program, float(self.vmin), 'vmin')
|
|
380
|
+
set_uniform(self.program, float(self.vmax), 'vmax')
|
|
298
381
|
self.need_update_setting = False
|
|
299
382
|
|
|
300
383
|
def paint(self):
|
q3dviewer/shaders/mesh_vert.glsl
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#version 330 core
|
|
2
2
|
layout (location = 0) in vec3 aPos;
|
|
3
3
|
layout (location = 1) in vec3 aNormal;
|
|
4
|
-
layout (location = 2) in
|
|
4
|
+
layout (location = 2) in uint aColor;
|
|
5
5
|
|
|
6
6
|
out vec3 FragPos;
|
|
7
7
|
out vec3 Normal;
|
|
@@ -10,19 +10,55 @@ out vec3 objectColor;
|
|
|
10
10
|
uniform mat4 view;
|
|
11
11
|
uniform mat4 projection;
|
|
12
12
|
uniform int flat_rgb;
|
|
13
|
+
uniform int color_mode; // 0: FLAT, 1: Intensity, 2: RGB
|
|
14
|
+
uniform float vmin;
|
|
15
|
+
uniform float vmax;
|
|
16
|
+
|
|
17
|
+
vec3 getRainbowColor(uint value_raw) {
|
|
18
|
+
float range = vmax - vmin;
|
|
19
|
+
float value = 1.0 - (float(value_raw) - vmin) / range;
|
|
20
|
+
value = clamp(value, 0.0, 1.0);
|
|
21
|
+
float hue = value * 5.0 + 1.0;
|
|
22
|
+
int i = int(floor(hue));
|
|
23
|
+
float f = hue - float(i);
|
|
24
|
+
if (mod(i, 2) == 0) f = 1.0 - f;
|
|
25
|
+
float n = 1.0 - f;
|
|
26
|
+
|
|
27
|
+
vec3 color;
|
|
28
|
+
if (i <= 1) color = vec3(n, 0.0, 1.0);
|
|
29
|
+
else if (i == 2) color = vec3(0.0, n, 1.0);
|
|
30
|
+
else if (i == 3) color = vec3(0.0, 1.0, n);
|
|
31
|
+
else if (i == 4) color = vec3(n, 1.0, 0.0);
|
|
32
|
+
else color = vec3(1.0, n, 0.0);
|
|
33
|
+
return color;
|
|
34
|
+
}
|
|
13
35
|
|
|
14
36
|
void main()
|
|
15
37
|
{
|
|
16
38
|
FragPos = aPos;
|
|
17
|
-
|
|
18
39
|
Normal = aNormal;
|
|
19
40
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
float( uint(flat_rgb) & uint(0x000000FF))/255
|
|
25
|
-
|
|
41
|
+
vec3 c = vec3(1.0, 1.0, 1.0);
|
|
42
|
+
|
|
43
|
+
if (color_mode == 0) {
|
|
44
|
+
// FLAT: use uniform flat color
|
|
45
|
+
c.z = float( uint(flat_rgb) & uint(0x000000FF))/255.;
|
|
46
|
+
c.y = float((uint(flat_rgb) & uint(0x0000FF00)) >> 8)/255.;
|
|
47
|
+
c.x = float((uint(flat_rgb) & uint(0x00FF0000)) >> 16)/255.;
|
|
48
|
+
}
|
|
49
|
+
else if (color_mode == 1) {
|
|
50
|
+
// Intensity: use intensity channel (bits 24-31) for rainbow color
|
|
51
|
+
uint intensity = aColor >> 24;
|
|
52
|
+
c = getRainbowColor(intensity);
|
|
53
|
+
}
|
|
54
|
+
else if (color_mode == 2) {
|
|
55
|
+
// RGB: use RGB channels (bits 0-23)
|
|
56
|
+
c.z = float(aColor & uint(0x000000FF))/255.;
|
|
57
|
+
c.y = float((aColor & uint(0x0000FF00)) >> 8)/255.;
|
|
58
|
+
c.x = float((aColor & uint(0x00FF0000)) >> 16)/255.;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
objectColor = c;
|
|
26
62
|
|
|
27
63
|
// Final vertex position (apply view/projection)
|
|
28
64
|
gl_Position = projection * view * vec4(aPos, 1.0);
|
q3dviewer/tools/cloud_viewer.py
CHANGED
|
@@ -58,7 +58,12 @@ class FileLoaderThread(QThread):
|
|
|
58
58
|
if url.toLocalFile().lower().endswith(('.stl')):
|
|
59
59
|
from q3dviewer.utils.cloud_io import load_stl
|
|
60
60
|
verts, faces = load_stl(file_path)
|
|
61
|
-
|
|
61
|
+
# create colors, N, array
|
|
62
|
+
color = np.zeros((verts.shape[0],), dtype=np.uint32)
|
|
63
|
+
# random uint32 colors in IRGB format
|
|
64
|
+
color = np.random.randint(0, 0xFFFFFFFF, size=(verts.shape[0],), dtype=np.uint32)
|
|
65
|
+
mesh_item.set_data(verts=verts, faces=faces, colors=color)
|
|
66
|
+
break
|
|
62
67
|
else:
|
|
63
68
|
cloud = cloud_item.load(file_path, append=(i > 0))
|
|
64
69
|
center = np.nanmean(cloud['xyz'].astype(np.float64), axis=0)
|
|
@@ -186,18 +191,20 @@ def main():
|
|
|
186
191
|
viewer = CloudViewer(name='Cloud Viewer')
|
|
187
192
|
cloud_item = q3d.CloudIOItem(size=1, alpha=0.1)
|
|
188
193
|
axis_item = q3d.AxisItem(size=0.5, width=5)
|
|
194
|
+
axis_item.disable_setting()
|
|
189
195
|
grid_item = q3d.GridItem(size=1000, spacing=20)
|
|
190
196
|
marker_item = q3d.Text3DItem() # Changed from CloudItem to Text3DItem
|
|
191
197
|
text_item = q3d.Text2DItem(pos=(20, 40), text="", color='lime', size=16)
|
|
198
|
+
text_item.disable_setting()
|
|
192
199
|
mesh_item = q3d.MeshItem() # Added MeshIOItem for mesh support
|
|
193
200
|
|
|
194
201
|
viewer.add_items(
|
|
195
202
|
{'marker': marker_item,
|
|
196
|
-
'cloud': cloud_item,
|
|
203
|
+
'cloud': cloud_item,
|
|
204
|
+
'mesh': mesh_item,
|
|
197
205
|
'grid': grid_item,
|
|
198
206
|
'axis': axis_item,
|
|
199
|
-
'text': text_item,
|
|
200
|
-
'mesh': mesh_item})
|
|
207
|
+
'text': text_item,})
|
|
201
208
|
|
|
202
209
|
if args.path:
|
|
203
210
|
pcd_fn = args.path
|
|
@@ -13,7 +13,7 @@ q3dviewer/custom_items/gaussian_item.py,sha256=JMubpahkTPh0E8ShL3FLTahv0e35ODzjg
|
|
|
13
13
|
q3dviewer/custom_items/grid_item.py,sha256=LDB_MYACoxld-xvz01_MfAf12vLcRkH7R_WtGHHdSgk,4945
|
|
14
14
|
q3dviewer/custom_items/image_item.py,sha256=k7HNTqdL2ckTbxMx7A7eKaP4aksZ85-pBjNdbpm6PXM,5355
|
|
15
15
|
q3dviewer/custom_items/line_item.py,sha256=rel-lx8AgjDY7qyIecHxHQZzaswRn2ZTiOIjB_0Mrqo,4444
|
|
16
|
-
q3dviewer/custom_items/mesh_item.py,sha256=
|
|
16
|
+
q3dviewer/custom_items/mesh_item.py,sha256=Ds3GyYzvFF5VpjG-_LU9SNZiBoLmztCZrkcalEMjub8,17890
|
|
17
17
|
q3dviewer/custom_items/text3d_item.py,sha256=DYBPXnCmMEzWDE1y523YsWSl91taXAdu0kdnhUcwE4A,5524
|
|
18
18
|
q3dviewer/custom_items/text_item.py,sha256=toeGjBu7RtT8CMUuaDWnmXPnA1UKHhnCzUNeonGczSo,2703
|
|
19
19
|
q3dviewer/shaders/cloud_frag.glsl,sha256=psKVt9qI6BW0bCqOk4lcKqUd6XgYGtdFigyN9OdYSNI,609
|
|
@@ -22,10 +22,10 @@ q3dviewer/shaders/gau_frag.glsl,sha256=vWt5I3Ojrc2PCxRlBJGyJhujbveSicMA54T01Fk29
|
|
|
22
22
|
q3dviewer/shaders/gau_prep.glsl,sha256=0BiWhYCQGeX2iN-e7m3dy1xWXqWrErErRAzHlcmWHF0,7218
|
|
23
23
|
q3dviewer/shaders/gau_vert.glsl,sha256=_rkm51zaWgPDJ-otJL-WX12fDvnPBOTooVfqo21Rexs,1666
|
|
24
24
|
q3dviewer/shaders/mesh_frag.glsl,sha256=i9ljnO2kjLNGaR1TPQIK4-4iJ-JppJ5bCsOHg1730gQ,1997
|
|
25
|
-
q3dviewer/shaders/mesh_vert.glsl,sha256=
|
|
25
|
+
q3dviewer/shaders/mesh_vert.glsl,sha256=tj9pbaWUYoKn1CtYahahPVzXNDTEtaQanq3S3VphmPg,1896
|
|
26
26
|
q3dviewer/shaders/sort_by_key.glsl,sha256=M5RK6uRDp40vVH6XtBIrdJTcYatqXyZwd6kCzEa2DZg,1097
|
|
27
27
|
q3dviewer/tools/__init__.py,sha256=01wG7BGM6VX0QyFBKsqPmyf2e-vrmV_N3-mo-VQ1VBg,20
|
|
28
|
-
q3dviewer/tools/cloud_viewer.py,sha256=
|
|
28
|
+
q3dviewer/tools/cloud_viewer.py,sha256=sZ16uOt5J_3E7H0ZW3NHq0mTkWuoBkRRtwEQgcEv-Io,7794
|
|
29
29
|
q3dviewer/tools/example_viewer.py,sha256=C867mLnCBjawS6LGgRsJ_c6-6wztfL9vOBQt85KbbdU,572
|
|
30
30
|
q3dviewer/tools/film_maker.py,sha256=xLFgRhFWoMQ37qlvcu1lXWaTWXMNRYlRcZFfHW5JtmQ,16676
|
|
31
31
|
q3dviewer/tools/gaussian_viewer.py,sha256=vIwWmiFhjNmknrEkBLzt2yiegeH7LP3OeNjnGM6GzaI,1633
|
|
@@ -39,9 +39,9 @@ q3dviewer/utils/gl_helper.py,sha256=dRY_kUqyPMr7NTcupUr6_VTvgnj53iE2C0Lk0-oFYsI,
|
|
|
39
39
|
q3dviewer/utils/helpers.py,sha256=SqR4YTQZi13FKbkVUYgodXce1JJ_YmrHEIRkUmnIUas,3085
|
|
40
40
|
q3dviewer/utils/maths.py,sha256=zHaPtvVZIuo8xepIXCMeSL9tpx8FahUrq0l4K1oXrBk,8834
|
|
41
41
|
q3dviewer/utils/range_slider.py,sha256=Cs_xrwt6FCDVxGxan7r-ARd5ySwQ50xnCzcmz0dB_X0,4215
|
|
42
|
-
q3dviewer-1.2.
|
|
43
|
-
q3dviewer-1.2.
|
|
44
|
-
q3dviewer-1.2.
|
|
45
|
-
q3dviewer-1.2.
|
|
46
|
-
q3dviewer-1.2.
|
|
47
|
-
q3dviewer-1.2.
|
|
42
|
+
q3dviewer-1.2.2.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
|
|
43
|
+
q3dviewer-1.2.2.dist-info/METADATA,sha256=pZQwcgig77nSIonNFabIUAptK75BfyLqrydzgc7FwNg,8049
|
|
44
|
+
q3dviewer-1.2.2.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
45
|
+
q3dviewer-1.2.2.dist-info/entry_points.txt,sha256=EOjker7XYaBk70ffvNB_knPcfA33Bnlg21ZjEeM1EyI,362
|
|
46
|
+
q3dviewer-1.2.2.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
|
|
47
|
+
q3dviewer-1.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|