From 6ff35015abc11a4f3a799e5459712d84fa9005e4 Mon Sep 17 00:00:00 2001 From: "kodiakhq[bot]" <49736102+kodiakhq[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 15:16:54 +0000 Subject: [PATCH] Improve freeglut support in OpenGL visualizer (#4691) Description of changes: - always check for the presence of GLE functions before invoking them --- doc/sphinx/installation.rst | 2 +- src/python/espressomd/visualization.py | 54 +++++++++++++++----------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/doc/sphinx/installation.rst b/doc/sphinx/installation.rst index 2c41ed7982d..23c7de67942 100644 --- a/doc/sphinx/installation.rst +++ b/doc/sphinx/installation.rst @@ -280,7 +280,7 @@ Run the following commands: .. code-block:: bash brew install cmake python cython boost boost-mpi fftw \ - doxygen gsl numpy scipy ipython jupyter + doxygen gsl numpy scipy ipython jupyter freeglut brew install hdf5-mpi brew link --force cython pip install -c requirements.txt PyOpenGL matplotlib diff --git a/src/python/espressomd/visualization.py b/src/python/espressomd/visualization.py index 73aaa9239d1..5e92c273697 100644 --- a/src/python/espressomd/visualization.py +++ b/src/python/espressomd/visualization.py @@ -1936,6 +1936,12 @@ def _rasterize_shape(self): continue return points + def _has_gle_features(self, feature_names): + for feature_name in feature_names: + if not bool(getattr(OpenGL.GLE, feature_name)): + return False + return True + class Cylinder(Shape): """ @@ -2006,6 +2012,8 @@ def __init__(self, shape, particle_type, color, material, self.length = self.shape.get_parameter('length') self.thickness = self.shape.get_parameter('thickness') self.central_angle = self.shape.get_parameter('central_angle') + self.use_gle = self._has_gle_features( + ["gleSpiral", "gleSetNumSides", "gleSetJoinStyle"]) def draw(self): """ @@ -2013,7 +2021,7 @@ def draw(self): Use rasterization of base class, otherwise. """ - if bool(OpenGL.GLE.gleSpiral) and self.central_angle == 0.: + if self.use_gle and self.central_angle == 0.: self._draw_using_gle() else: super().draw() @@ -2072,6 +2080,8 @@ def __init__(self, shape, particle_type, color, material, self.smoothing_radius = np.array( self.shape.get_parameter('smoothing_radius')) self.max_box_l = max(box_l) + self.use_gle = self._has_gle_features( + ["gleSpiral", "gleSetNumSides", "gleSetJoinStyle"]) def draw(self): """ @@ -2086,7 +2096,7 @@ def draw(self): ax, rx, ry = rotation_helper(self.axis) OpenGL.GL.glRotatef(ax, rx, ry, 0.0) - if bool(OpenGL.GLE.gleSpiral): + if self.use_gle: self._draw_using_gle() else: self._draw_using_primitives() @@ -2094,27 +2104,25 @@ def draw(self): OpenGL.GL.glPopMatrix() def _draw_using_gle(self): - # if available, use the GL Extrusion library - if bool(OpenGL.GLE.gleSpiral): - n = max(10, self.quality // 3) - contour = [[0.5 * self.max_box_l, -0.5 * self.length]] - for theta in np.linspace(0, 0.5 * np.pi, n): - contour.append([(1. - np.sin(theta)) * self.smoothing_radius, - -0.5 * self.length + (1. - np.cos(theta)) * self.smoothing_radius]) - for theta in np.linspace(0.5 * np.pi, np.pi, n): - contour.append([(1. - np.sin(theta)) * self.smoothing_radius, - 0.5 * self.length - (1. + np.cos(theta)) * self.smoothing_radius]) - contour.append([0.5 * self.max_box_l, 0.5 * self.length]) - - normals = np.diff(np.array(contour), axis=0) - normals /= np.linalg.norm(normals, ord=2, axis=1, keepdims=True) - normals = np.roll(normals, 1, axis=1) - normals[:, 0] *= -1 - - OpenGL.GLE.gleSetJoinStyle(OpenGL.GLE.TUBE_JN_ANGLE) - OpenGL.GLE.gleSetNumSides(max(90, 3 * self.quality)) - OpenGL.GLE.gleSpiral(contour, normals, [0, 0, 1], self.radius, 0., 0., 0., - [[1, 0, 0], [0, 1, 0]], [[0, 0, 0], [0, 0, 0]], 0., 360) + n = max(10, self.quality // 3) + contour = [[0.5 * self.max_box_l, -0.5 * self.length]] + for theta in np.linspace(0, 0.5 * np.pi, n): + contour.append([(1. - np.sin(theta)) * self.smoothing_radius, + -0.5 * self.length + (1. - np.cos(theta)) * self.smoothing_radius]) + for theta in np.linspace(0.5 * np.pi, np.pi, n): + contour.append([(1. - np.sin(theta)) * self.smoothing_radius, + 0.5 * self.length - (1. + np.cos(theta)) * self.smoothing_radius]) + contour.append([0.5 * self.max_box_l, 0.5 * self.length]) + + normals = np.diff(np.array(contour), axis=0) + normals /= np.linalg.norm(normals, ord=2, axis=1, keepdims=True) + normals = np.roll(normals, 1, axis=1) + normals[:, 0] *= -1 + + OpenGL.GLE.gleSetJoinStyle(OpenGL.GLE.TUBE_JN_ANGLE) + OpenGL.GLE.gleSetNumSides(max(90, 3 * self.quality)) + OpenGL.GLE.gleSpiral(contour, normals, [0, 0, 1], self.radius, 0., 0., 0., + [[1, 0, 0], [0, 1, 0]], [[0, 0, 0], [0, 0, 0]], 0., 360) def _draw_using_primitives(self): clip_plane = get_extra_clip_plane()