manim icon indicating copy to clipboard operation
manim copied to clipboard

New manim releases break My 3D Dot Groups when using OpenGL (from 0.16 to 0.17)

Open igreat opened this issue 3 years ago • 2 comments

OpenGL renderer gives me a TypeError: object of type 'float' has no len() when I try to render 3D Dots

When trying to generate a group of 3D Dots in OpenGL in the new manim releases, I ended up getting a TypeError. I have no idea about the backend of manim, so I apologize that I can't give a more detailed explanation of the error, so I'll just try to give as much context.

Specifically, this worked when I used manim 0.16, but when I upgraded to 0.17, I got this error. I haven't experimented enough to pinpoint the exact release where this issue starts, but it's surely between 0.16 and 0.17.

Here is the specific piece of code that generates the 3D Dots.

...
dots_all = Group()
for ax in ax_grid:
    dots1 = Group(
        *[
            Dot3D(ax.c2p(*point, 0), radius=0.04, color=colors.PURPLE)
            for point in array1
        ]
    )

    dots2 = Group(
        *[
            Dot3D([ax.c2p(*point, 0)], radius=0.04, color=colors.RED)
            for point in array2
        ]
    )
    dots_all.add(Group(dots1, dots2))
...
self.play(FadeIn(dots_all))
...

Note: this could be an issue of just 3D Dots or Groups of 3D Dots. I haven't experimented enough to pin point the exact issue.

Logs

Terminal output
/Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/cli/render/commands.py:97 in render                                     │
│                                                                              │
│    94 │   │   │   │   for SceneClass in scene_classes_from_file(file):       │
│    95 │   │   │   │   │   with tempconfig({}):                               │
│    96 │   │   │   │   │   │   scene = SceneClass(renderer)                   │
│ ❱  97 │   │   │   │   │   │   rerun = scene.render()                         │
│    98 │   │   │   │   │   if rerun or config["write_all"]:                   │
│    99 │   │   │   │   │   │   renderer.num_plays = 0                         │
│   100 │   │   │   │   │   │   continue                                       │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/scene/scene.py:223 in render                                            │
│                                                                              │
│    220 │   │   """                                                           │
│    221 │   │   self.setup()                                                  │
│    222 │   │   try:                                                          │
│ ❱  223 │   │   │   self.construct()                                          │
│    224 │   │   except EndSceneEarlyException:                                │
│    225 │   │   │   pass                                                      │
│    226 │   │   except RerunSceneException as e:                              │
│                                                                              │
│ /Users/great/Documents/manim                                         │
│ animations/manifold-hypothesis/separating_spirals3d_training.py:98 in        │
│ construct                                                                    │
│                                                                              │
│    95 │   │   │   │   │   else:                                              │
│    96 │   │   │   │   │   │   dots[1][int(i.item())].move_to(ax.c2p(*h_out)) │
│    97 │   │                                                                  │
│ ❱  98 │   │   self.play(FadeIn(dots_all))                                    │
│    99 │   │                                                                  │
│   100 │   │   # self.begin_ambient_camera_rotation(-0.1)                     │
│   101                                                                        │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/scene/scene.py:1033 in play                                             │
│                                                                              │
│   1030 │   │   │   return                                                    │
│   1031 │   │                                                                 │
│   1032 │   │   start_time = self.renderer.time                               │
│ ❱ 1033 │   │   self.renderer.play(self, *args, **kwargs)                     │
│   1034 │   │   run_time = self.renderer.time - start_time                    │
│   1035 │   │   if subcaption:                                                │
│   1036 │   │   │   if subcaption_duration is None:                           │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/utils/caching.py:65 in wrapper                                          │
│                                                                              │
│   62 │   │   │   "List of the first few animation hashes of the scene: %(h)s │
│   63 │   │   │   {"h": str(self.animations_hashes[:5])},                     │
│   64 │   │   )                                                               │
│ ❱ 65 │   │   func(self, scene, *args, **kwargs)                              │
│   66 │                                                                       │
│   67 │   return wrapper                                                      │
│   68                                                                         │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/renderer/opengl_renderer.py:424 in play                                 │
│                                                                              │
│   421 │   │   self.file_writer.begin_animation(not self.skip_animations)     │
│   422 │   │                                                                  │
│   423 │   │   scene.compile_animation_data(*args, **kwargs)                  │
│ ❱ 424 │   │   scene.begin_animations()                                       │
│   425 │   │   if scene.is_current_animation_frozen_frame():                  │
│   426 │   │   │   self.update_frame(scene)                                   │
│   427                                                                        │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/scene/scene.py:1163 in begin_animations                                 │
│                                                                              │
│   1160 │   │   """Start the animations of the scene."""                      │
│   1161 │   │   for animation in self.animations:                             │
│   1162 │   │   │   animation._setup_scene(self)                              │
│ ❱ 1163 │   │   │   animation.begin()                                         │
│   1164 │   │                                                                 │
│   1165 │   │   if config.renderer == RendererType.CAIRO:                     │
│   1166 │   │   │   # Paint all non-moving objects onto the screen, so they d │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/animation/transform.py:201 in begin                                     │
│                                                                              │
│   198 │   │   # Note, this potentially changes the structure                 │
│   199 │   │   # of both mobject and target_mobject                           │
│   200 │   │   if config.renderer == RendererType.OPENGL:                     │
│ ❱ 201 │   │   │   self.mobject.align_data_and_family(self.target_copy)       │
│   202 │   │   else:                                                          │
│   203 │   │   │   self.mobject.align_data(self.target_copy)                  │
│   204 │   │   super().begin()                                                │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/mobject/opengl/opengl_mobject.py:2306 in align_data_and_family          │
│                                                                              │
│   2303 │                                                                     │
│   2304 │   def align_data_and_family(self, mobject):                         │
│   2305 │   │   self.align_family(mobject)                                    │
│ ❱ 2306 │   │   self.align_data(mobject)                                      │
│   2307 │                                                                     │
│   2308 │   def align_data(self, mobject):                                    │
│   2309 │   │   # In case any data arrays get resized when aligned to shader  │
│                                                                              │
│ /Users/great/opt/miniconda3/envs/manim/lib/python3.9/site-packages/m │
│ anim/mobject/opengl/opengl_mobject.py:2320 in align_data                     │
│                                                                              │
│   2317 │   │   │   │   │   continue                                          │
│   2318 │   │   │   │   arr1 = mob1.data[key]                                 │
│   2319 │   │   │   │   arr2 = mob2.data[key]                                 │
│ ❱ 2320 │   │   │   │   if len(arr2) > len(arr1):                             │
│   2321 │   │   │   │   │   mob1.data[key] = resize_preserving_order(arr1, le │
│   2322 │   │   │   │   elif len(arr1) > len(arr2):                           │
│   2323 │   │   │   │   │   mob2.data[key] = resize_preserving_order(arr2, le │
╰──────────────────────────────────────────────────────────────────────────────╯
TypeError: object of type 'float' has no len()

igreat avatar Dec 19 '22 07:12 igreat

Just wanted to add to this thread: I am having the same issue but using a 3D sphere:

class MyScene(ThreeDScene):

    def construct(self):
        sph = Sphere(
            center=(3, 0, 0),
            radius=1,
            resolution=(20, 20),
            u_range=[0.001, PI - 0.001],
            v_range=[0, TAU]
        )
        self.add(sph)
        self.play(Create(sph))
        self.play(Rotate(sph, 2 * PI))  # fails here

This produces essentially the same error as above.

brianbreitsch avatar Oct 19 '24 03:10 brianbreitsch

This also fails with Manim Community v0.18.0.post0 when animating a Surface mobject:

from manim import *
from manim.mobject.opengl.opengl_three_dimensions import OpenGLSurface

config.renderer = RendererType.OPENGL
config.quality  = "low_quality"

class Draw3DEllipsoid(ThreeDScene):
    def construct(self):

        # Axes setup
        axes = ThreeDAxes()
        self.set_camera_orientation(phi=75 * DEGREES, theta=45 * DEGREES)

        # Parametric equation of the ellipsoid
        def ellipsoid(u, v):
            
            # Ellipsoid parameters
            a, b, c = 2, 1, 1.5  # Semi-principal axes lengths

            x = a * np.cos(u) * np.sin(v)
            y = b * np.sin(u) * np.sin(v)
            z = c * np.cos(v)
            return np.array([x, y, z])

        # Create the ellipsoid surface
        ellipsoid_surface = Surface(
            func=ellipsoid,
            u_range=[0, 2 * PI],  # Full rotation
            v_range=[0, PI],      # From top to bottom
            resolution=(20, 20),
        )
        ellipsoid_surface.shift(UR)                     # <--- This works 

        # Add elements to the scene
        self.add(axes, ellipsoid_surface)
        self.begin_ambient_camera_rotation(rate=0.2)
        self.play(ellipsoid_surface.animate.shift(DOWN))  # <--- This fails
        self.wait(5)

if __name__ == "__main__":
    scene = Draw3DEllipsoid()
    scene.render(preview=True)

Generated error

Manim Community v0.18.0.post0

Traceback (most recent call last):
  File "/home/waelti/tmp/manim/ellispoid.py", line 42, in <module>
    scene.render(preview=True)
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/scene/scene.py", line 223, in render
    self.construct()
  File "/home/waelti/tmp/manim/ellispoid.py", line 37, in construct
    self.play(ellipsoid_surface.animate.shift(DOWN))  # <--- This fails
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/scene/scene.py", line 1080, in play
    self.renderer.play(self, *args, **kwargs)
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/utils/caching.py", line 65, in wrapper
    func(self, scene, *args, **kwargs)
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/renderer/opengl_renderer.py", line 424, in play
    scene.begin_animations()
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/scene/scene.py", line 1208, in begin_animations
    animation.begin()
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/animation/transform.py", line 201, in begin
    self.mobject.align_data_and_family(self.target_copy)
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/mobject/opengl/opengl_mobject.py", line 2312, in align_data_and_family
    self.align_data(mobject)
  File "/home/waelti/.local/lib/python3.8/site-packages/manim/mobject/opengl/opengl_mobject.py", line 2326, in align_data
    if len(arr2) > len(arr1):
TypeError: object of type 'float' has no len()

LucasWaelti avatar Dec 01 '24 10:12 LucasWaelti