Convert each camera's frustum line segments into thin-cylinder triangle meshes (one merged Mesh per camera). Compared to build_frustum_geometries() (which returns Path3D/LINES), triangle meshes render more reliably in tools like MeshLab and Blender and do not trigger crashes related to the
(extrinsics, intrinsics, image_size, scale=0.1, line_radius=None)
| 144 | |
| 145 | |
| 146 | def build_frustum_mesh_geometries(extrinsics, intrinsics, image_size, scale=0.1, line_radius=None): |
| 147 | """Convert each camera's frustum line segments into thin-cylinder triangle meshes (one merged Mesh per camera). |
| 148 | |
| 149 | Compared to build_frustum_geometries() (which returns Path3D/LINES), triangle meshes render |
| 150 | more reliably in tools like MeshLab and Blender and do not trigger crashes related to the LINES primitive. |
| 151 | |
| 152 | Args: |
| 153 | extrinsics: (N, 3, 4) cam2world |
| 154 | intrinsics: (N, 3, 3) intrinsics |
| 155 | image_size: (W, H) or (N, 2) |
| 156 | scale: frustum size |
| 157 | line_radius: cylinder radius (None = automatically use scale*0.015) |
| 158 | |
| 159 | Returns: |
| 160 | list[trimesh.Trimesh] — one colored Mesh per camera |
| 161 | """ |
| 162 | import trimesh |
| 163 | |
| 164 | N = len(extrinsics) |
| 165 | if line_radius is None: |
| 166 | line_radius = max(scale * 0.015, 0.001) |
| 167 | |
| 168 | geoms = [] |
| 169 | for i in range(N): |
| 170 | if isinstance(image_size, (list, tuple)) and len(image_size) == 2 and not hasattr(image_size[0], '__len__'): |
| 171 | W, H = image_size |
| 172 | else: |
| 173 | W, H = image_size[i] |
| 174 | |
| 175 | segs = camera_frustum_lines(intrinsics[i], extrinsics[i], W, H, scale) |
| 176 | color = _camera_color(i, N) |
| 177 | rgba = np.array([color[0], color[1], color[2], 255], dtype=np.uint8) |
| 178 | |
| 179 | cyls = [] |
| 180 | for seg in segs: |
| 181 | cyl = _segment_to_cylinder(seg[0], seg[1], line_radius, sections=6) |
| 182 | if cyl is None: |
| 183 | continue |
| 184 | cyl.visual.vertex_colors = np.tile(rgba, (len(cyl.vertices), 1)) |
| 185 | cyls.append(cyl) |
| 186 | |
| 187 | if not cyls: |
| 188 | continue |
| 189 | |
| 190 | merged = trimesh.util.concatenate(cyls) |
| 191 | geoms.append(merged) |
| 192 | |
| 193 | return geoms |
| 194 | |
| 195 | |
| 196 | # ============================================================ |
no test coverage detected