How to implement a level of details visualizer for 3D meshes?
- Dominant language
- C++
- Stars
- 14k
- Forks
- 2.6k
- Avg merge
- 5d 18h
- Merged PRs (30d)
- 6
Description
### Checklist
- [X] I have searched for [similar issues](https://github.com/isl-org/Open3D/issues).
- [X] For Python issues, I have tested with the [latest development wheel](http://www.open3d.org/docs/latest/getting_started.html#development-version-pip).
- [X] I have checked the [release documentation](http://www.open3d.org/docs/release/) and the [latest documentation](http://www.open3d.org/docs/latest/) (for `master` branch).
### My Question
I have trouble implementing a visualizer to visualize the level of detailed meshes. Below is my code:
```python
from typing import List
import tqdm
import numpy as np
import open3d as o3d
def create_lod_meshes(mesh, simplify_ratio: int = 4, num_lod_levels: int = 4) -> List:
# num_vertices = len(mesh.vertices)
num_triangles = len(mesh.triangles)
LOD_meshes = [mesh] # pylint: disable=C0103
pbar = tqdm.trange(num_lod_levels - 1, desc="Creating LOD meshes")
for i in range(num_lod_levels - 1):
target_number_of_triangles = num_triangles // ((i + 1) * simplify_ratio)
simplified_mesh = mesh.simplify_quadric_decimation(
target_number_of_triangles=target_number_of_triangles
)
LOD_meshes.append(simplified_mesh)
pbar.update(1)
return LOD_meshes
def calculate_camera_distance(mesh, view_control):
camera = view_control.convert_to_pinhole_camera_parameters()
view_matrix = camera.extrinsic
# Get the camera's position from the view matrix.
camera_position = np.linalg.inv(view_matrix)[:3, 3]
# Calculate the distance from the camera to the center of the mesh's bounding box.
mesh_center = np.mean(np.asarray(mesh.vertices), axis=0)
camera_distance = np.linalg.norm(camera_position - mesh_center)
return camera_distance
def determine_lod_level(camera_distance):
# Define LOD distance thresholds (you can adjust these ad needed)
# lod_thresholds = [10.0, 20.0, 30.0] # Example thresholds in units
lod_thresholds = [1.25, 2.50, 5.0] # Example thresholds in units
# Default LOD level (highest detail)
lod_level = 0
# Determine the LOD level based on camera distance.
for i, threshold in enumerate(lod_thresholds, 1):
print(f'i: {i}')
if camera_distance > threshold:
lod_level = i
else:
break
return lod_level
def visualize(mesh_path: str = ''):
mesh_path = 'mesh.obj' # For simplification, just replace the path with the path of your 3D object.
mesh_in = o3d.io.read_triangle_mesh(mesh_path)
mesh_in.compute_vertex_normals()
LOD_meshes = create_lod_meshes(mesh=mesh_in)
# Maintain a transformation matrix for the current LOD mesh
# current_transform = np.eye(4)
# Create a visualizer.
vis = o3d.visualization.Visualizer()
vis.create_window()
# Add the initial LOD mesh to the visualizer.
current_lod_mesh = LOD_meshes[-1]
vis.add_geometry(current_lod_mesh)
# camera = vis.get_view_control().convert_to_pinhole_camera_parameters()
# current_transform = camera.extrinsic
while True:
# Calculate camera distance
camera_distance = calculate_camera_distance(mesh_in, vis.get_view_control())
print(f'camera_distance: {camera_distance}')
# Determine LOD level based on camera distance.
lod_level = determine_lod_level(camera_distance)
print(f'lod_level: {lod_level}')
# Update the displayed LOD mesh.
if current_lod_mesh != LOD_meshes[lod_level]:
vis.remove_geometry(current_lod_mesh)
# # Apply the last transformation to the new LOD mesh.
# LOD_meshes[lod_level].transform(current_transform)
current_lod_mesh = LOD_meshes[lod_level]
vis.add_geometry(current_lod_mesh)
print(f"Vertices: {len(current_lod_mesh.vertices)} Triangles: {len(current_lod_mesh.triangles)}")
# vis.remove_geometry(vis.get_geometries()[0]) # Remove the current LOD mesh
# vis.add_geometry(LOD_meshes[lod_level])
# vis.update_geometry(LOD_meshes[lod_level])
vis.poll_events()
vis.update_renderer()
# Update the current_transform to match the transformation of the current LOD mesh.
# current_transform = current_lod_mesh.get_transform()
# camera = vis.get_view_control().convert_to_pinhole_camera_parameters()
# current_transform = camera.extrinsic
# Close the visualizer window on exit.
vis.destroy_window()
if __name__ == "__main__":
visualize()
```
When the visualizer loads the updated mesh, the geometry will be set to the original position. How can I keep it in the same position as the last mesh?
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.