manim icon indicating copy to clipboard operation
manim copied to clipboard

Fix: Issue with OpenGL rendering for Transform of SVGMobjects #4182

Open henrikmidtiby opened this issue 5 months ago • 2 comments

This is a fix for issue https://github.com/ManimCommunity/manim/issues/4182

Overview: What does this pull request change?

In some cases the stroke_width parameter is not saved as a np.ndarray but a float or int instead. In that case the len(...) call will fail in the align_data method in opengl_mobject.py.

In the PR the for loop in align_data is also skipped for data with the key stroke_width or if the self.data[key] is of type int in the interpolate method.

Reviewer Checklist

  • [ ] The PR title is descriptive enough for the changelog, and the PR is labeled correctly
  • [ ] If applicable: newly added non-private functions and classes have a docstring including a short summary and a PARAMETERS section
  • [ ] If applicable: newly added functions and classes are tested

henrikmidtiby avatar Aug 04 '25 14:08 henrikmidtiby

Wouldn't it be better to make sure the stroke_width is actually stored as a numpy array? (I don't have a strong opinion on this though, I'd also be willing to merge this as-is.)

Thanks for your effort!

behackl avatar Aug 07 '25 20:08 behackl

Wouldn't it be better to make sure the stroke_width is actually stored as a numpy array? I think it would be a cleaner solution to make it a numpy array.

In this branch https://github.com/henrikmidtiby/manim/commits/Issue4182MakeArray/ I have tried to make stroke_width an np.array in all locations in opengl_vectorized_mobject.py. In that case it works fine with all the unit tests, but the example given in issue https://github.com/ManimCommunity/manim/issues/4182#issuecomment-3151032237 would now fail with the error shown below.

│ /home/hemi/localbuild/manim/manim/renderer/opengl_renderer.py:340 in render_mobject              │
│                                                                                                  │
│   337 │   │   │   if config["use_projection_stroke_shaders"]:                                    │
│   338 │   │   │   │   render_opengl_vectorized_mobject_stroke(self, mobject)                     │
│   339 │   │                                                                                      │
│ ❱ 340 │   │   shader_wrapper_list = mobject.get_shader_wrapper_list()                            │
│   341 │   │                                                                                      │
│   342 │   │   # Convert ShaderWrappers to Meshes.                                                │
│   343 │   │   for shader_wrapper in shader_wrapper_list:                                         │
│                                                                                                  │
│ /home/hemi/localbuild/manim/manim/mobject/opengl/opengl_vectorized_mobject.py:1548 in            │
│ get_shader_wrapper_list                                                                          │
│                                                                                                  │
│   1545 │   │   for submob in self.family_members_with_points():                                  │
│   1546 │   │   │   if submob.has_fill() and not config["use_projection_fill_shaders"]:           │
│   1547 │   │   │   │   fill_shader_wrappers.append(submob.get_fill_shader_wrapper())             │
│ ❱ 1548 │   │   │   if submob.has_stroke() and not config["use_projection_stroke_shaders"]:       │
│   1549 │   │   │   │   ssw = submob.get_stroke_shader_wrapper()                                  │
│   1550 │   │   │   │   if submob.draw_stroke_behind_fill:                                        │
│   1551 │   │   │   │   │   back_stroke_shader_wrappers.append(ssw)                               │
│                                                                                                  │
│ /home/hemi/localbuild/manim/manim/mobject/opengl/opengl_vectorized_mobject.py:455 in has_stroke  │
│                                                                                                  │
│    452 │   │   return (                                                                          │
│    453 │   │   │   stroke_widths is not None                                                     │
│    454 │   │   │   and stroke_opacities is not None                                              │
│ ❱  455 │   │   │   and any(stroke_widths)                                                        │
│    456 │   │   │   and any(stroke_opacities)                                                     │
│    457 │   │   )                                                                                 │
│    458                                                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: iteration over a 0-d array

This seems to be caused by the SVGMobject, which sets the stroke_width property to a float an I cannot locate where.

henrikmidtiby avatar Aug 08 '25 06:08 henrikmidtiby