Rebuild point cloud geometry using octree LOD selection.
(self)
| 251 | self._renderer.scene.add_geometry("pcd", self._pcd, self._mat) |
| 252 | |
| 253 | def update_geometry(self): |
| 254 | """Rebuild point cloud geometry using octree LOD selection.""" |
| 255 | if self._renderer is None or self.camera is None: |
| 256 | return |
| 257 | o3d = _import_open3d() |
| 258 | t0 = time.time() |
| 259 | |
| 260 | if self.octree is not None: |
| 261 | # Use octree LOD: adaptive detail based on camera distance |
| 262 | cam = self.camera |
| 263 | w2c = cam.get_w2c() |
| 264 | fx, fy, cx, cy = cam.fov_intrinsics( |
| 265 | self.render_width, self.render_height |
| 266 | ) |
| 267 | # frame_idx controls temporal visibility in octree |
| 268 | fi = self.frame_idx if self.display_mode != "all" else ( |
| 269 | self.pcm.num_frames - 1 if self.pcm else 0 |
| 270 | ) |
| 271 | xyz, rgb = self.octree.lod_select( |
| 272 | w2c, fx, fy, cx, cy, |
| 273 | self.render_width, self.render_height, |
| 274 | self.near, self.far, |
| 275 | fi, self.lod_target_pixels, |
| 276 | ) |
| 277 | else: |
| 278 | # Fallback: brute force with random downsample |
| 279 | xyz, rgb = self.pcm.get_points( |
| 280 | self.frame_idx, self.display_mode, self.conf_threshold |
| 281 | ) |
| 282 | if len(xyz) > self.max_points: |
| 283 | idx = np.random.choice(len(xyz), self.max_points, replace=False) |
| 284 | idx.sort() |
| 285 | xyz, rgb = xyz[idx], rgb[idx] |
| 286 | |
| 287 | if len(xyz) == 0: |
| 288 | xyz = np.zeros((1, 3), dtype=np.float64) |
| 289 | rgb = np.zeros((1, 3), dtype=np.float64) |
| 290 | |
| 291 | print(f"[geometry] {len(xyz):,} points, ", end="", flush=True) |
| 292 | |
| 293 | self._pcd.points = o3d.utility.Vector3dVector(xyz.astype(np.float64)) |
| 294 | self._pcd.colors = o3d.utility.Vector3dVector( |
| 295 | np.clip(rgb, 0, 1).astype(np.float64) |
| 296 | ) |
| 297 | print(f"built in {time.time()-t0:.1f}s") |
| 298 | |
| 299 | if hasattr(self._renderer.scene, "update_geometry"): |
| 300 | flags = ( |
| 301 | o3d.visualization.rendering.Scene.UPDATE_POINTS_FLAG |
| 302 | | o3d.visualization.rendering.Scene.UPDATE_COLORS_FLAG |
| 303 | ) |
| 304 | self._renderer.scene.update_geometry("pcd", self._pcd, flags) |
| 305 | else: |
| 306 | self._renderer.scene.remove_geometry("pcd") |
| 307 | self._renderer.scene.add_geometry("pcd", self._pcd, self._mat) |
| 308 | |
| 309 | self._dirty_geometry = False |
| 310 |
no test coverage detected