ManimCommunity / manim

A community-maintained Python framework for creating mathematical animations.
https://www.manim.community
MIT License
26.27k stars 1.8k forks source link

2D Mobjects being rendered above 3D Mobjects even if they have a lower z-coordinate and z_index. #2032

Open Mixnik26 opened 3 years ago

Mixnik26 commented 3 years ago

An example of this issue is with a tetrahedron (Tetrahedron()) and a 2D plane (Square()), where, if you rotate the plane, it would overlay above the tetrahedron even if the tetrahedron has a higher z-coordinate: `

from manim import *

class Scene(ThreeDScene):
    def construct(self):
        tetra = Tetrahedron()
        plane = Square(side_length=5, color=WHITE, fill_opacity=0.4)
        _3D = ThreeDAxes()

        self.add(_3D)
        self.move_camera(phi=65*DEGREES, theta=-45*DEGREES)
        self.play(FadeIn(plane))
        self.play(FadeIn(tetra.shift([0,0,1])))
        self.play(Rotate(plane, 90*DEGREES, about_point=ORIGIN))
        self.wait()

` This will output:

https://user-images.githubusercontent.com/90397670/132694874-f888ebd8-7e18-4adf-8c8b-4372aff57f94.mp4

The Square Mobject overlays itself over the Tetrahedron when the rotation animation plays. z_index() does not affect this outcome, I've attempted to give the Square Mobject a lower z_index multiple times with the same result. The only way I've found to fix this is by defining the plane as a Polyhedron(): `

from manim import *

class Scene(ThreeDScene):
    def construct(self):
        vertices = [
            [-2.5,2.5,0],
            [2.5,2.5,0],
            [2.5,-2.5,0],
            [-2.5,-2.5,0]
        ]
        plane = Polyhedron(vertices, [[0,1,2,3]])
        for i in range(0,4,1):
            plane.graph[i].scale(0)
        plane.set_color(WHITE)
        tetra = Tetrahedron()
        _3D = ThreeDAxes()
        plane.set_z_index(tetra.get_z_index()-1)

        self.add(_3D)
        self.move_camera(phi=65*DEGREES, theta=-45*DEGREES)
        self.play(FadeIn(tetra.shift([0,0,1])))
        self.play(FadeIn(plane))
        self.play(Rotate(plane, 90*DEGREES, about_point=ORIGIN))
        self.wait()

` This outputs what I was looking for:

https://user-images.githubusercontent.com/90397670/132695649-6bf88c5d-bb37-4828-9359-ba7d607c8525.mp4

alembcke commented 3 years ago

@Mixnik26 I added the argument shade_in_3d=True when calling Square and it fixed it for me. It seems doing this for any 2D mobject turns it into a 3D mobject.

from manim import *

class Scene(ThreeDScene):
    def construct(self):
        tetra = Tetrahedron()
        plane = Square(side_length=5, color=WHITE, fill_opacity=0.4, shade_in_3d=True)
       _3D = ThreeDAxes()

        self.add(_3D)
        self.move_camera(phi=65*DEGREES, theta=-45*DEGREES)
        self.play(FadeIn(plane))
        self.play(FadeIn(tetra.shift([0,0,1])))
        self.play(Rotate(plane, 90*DEGREES, about_point=ORIGIN))
        self.wait()

Here is the output of the above code on my machine:

https://user-images.githubusercontent.com/79891353/135622818-4d2f3d9b-9e7f-4cb9-bbe9-375998bd6253.mp4

Is this solution suitable for you?

Viicos commented 2 years ago

shade_in_3d seems to be the way to go when dealing with 2D Mobjects in a 3D scene. However, it could be great if these Mobjects had the attribute effect applied when creating (or animating) them:

Code: ```py class Sample(ThreeDScene): def construct(self): self.set_camera_orientation( phi=70 * DEGREES, theta=30 * DEGREES, zoom=2 ) axes = ThreeDAxes() cylinder = Cylinder( fill_opacity=0.4, resolution=(24, 12) ).set_color(BLUE_E) circle = Circle( radius=cylinder.radius, fill_opacity=0.7, shade_in_3d=True ) self.add(axes, cylinder) self.play(FadeIn(circle)) self.wait() ```

Result:

https://user-images.githubusercontent.com/65306057/142775443-2c42b809-94b1-4f75-8316-bc853aee04eb.mp4