q3dviewer 1.2.1__tar.gz → 1.2.2__tar.gz

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.
Files changed (43) hide show
  1. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/PKG-INFO +1 -1
  2. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/mesh_item.py +95 -12
  3. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/cloud_viewer.py +11 -4
  4. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer.egg-info/PKG-INFO +1 -1
  5. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/setup.py +1 -1
  6. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/README.md +0 -0
  7. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/Qt/__init__.py +0 -0
  8. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/__init__.py +0 -0
  9. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/base_glwidget.py +0 -0
  10. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/base_item.py +0 -0
  11. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/__init__.py +0 -0
  12. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/axis_item.py +0 -0
  13. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/cloud_io_item.py +0 -0
  14. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/cloud_item.py +0 -0
  15. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/frame_item.py +0 -0
  16. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/gaussian_item.py +0 -0
  17. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/grid_item.py +0 -0
  18. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/image_item.py +0 -0
  19. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/line_item.py +0 -0
  20. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/text3d_item.py +0 -0
  21. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/custom_items/text_item.py +0 -0
  22. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/glwidget.py +0 -0
  23. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/__init__.py +0 -0
  24. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/example_viewer.py +0 -0
  25. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/film_maker.py +0 -0
  26. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/gaussian_viewer.py +0 -0
  27. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/lidar_calib.py +0 -0
  28. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/lidar_cam_calib.py +0 -0
  29. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/tools/ros_viewer.py +0 -0
  30. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/__init__.py +0 -0
  31. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/cloud_io.py +0 -0
  32. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/convert_ros_msg.py +0 -0
  33. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/gl_helper.py +0 -0
  34. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/helpers.py +0 -0
  35. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/maths.py +0 -0
  36. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/utils/range_slider.py +0 -0
  37. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer/viewer.py +0 -0
  38. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer.egg-info/SOURCES.txt +0 -0
  39. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer.egg-info/dependency_links.txt +0 -0
  40. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer.egg-info/entry_points.txt +0 -0
  41. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer.egg-info/requires.txt +0 -0
  42. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/q3dviewer.egg-info/top_level.txt +0 -0
  43. {q3dviewer-1.2.1 → q3dviewer-1.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: q3dviewer
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: A library designed for quickly deploying a 3D viewer.
5
5
  Home-page: https://github.com/scomup/q3dviewer
6
6
  Author: Liu Yang
@@ -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
- def __init__(self, color='lightblue', wireframe=False, enable_lighting=True):
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
- # self.vbo_colors = None
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
- # self.vbo_colors = glGenBuffers(1)
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
- # if self.flat_rgbs is not None:
278
- # glBindBuffer(GL_ARRAY_BUFFER, self.vbo_colors)
279
- # glBufferData(GL_ARRAY_BUFFER, self.flat_rgbs.nbytes, self.flat_rgbs, GL_STATIC_DRAW)
280
- # glEnableVertexAttribArray(2)
281
- # glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, None)
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):
@@ -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
- mesh_item.set_data(verts=verts, faces=faces)
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: q3dviewer
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: A library designed for quickly deploying a 3D viewer.
5
5
  Home-page: https://github.com/scomup/q3dviewer
6
6
  Author: Liu Yang
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='q3dviewer',
5
- version='1.2.1',
5
+ version='1.2.2',
6
6
  author="Liu Yang",
7
7
  description="A library designed for quickly deploying a 3D viewer.",
8
8
  long_description=open("README.md").read(),
File without changes
File without changes
File without changes