Skip to content

ThreeDScene displaying elements in wrong position in the 3D space #4517

@SebastienFeser

Description

@SebastienFeser

Description of bug / unexpected behavior

The ThreeDScene is displaying the elements in the wrong position in the 3D space when creating and tranforming the various elements.

Expected behavior

The elements must be placed on their right spot in the 3D space when created. Not in front (look at the gif)

How to reproduce the issue

Code for reproducing the problem
from manim import *
import numpy as np

# Configuration for custom dimensions
#config.pixel_width = 640
#config.pixel_height = 308

class PartialDerivative2(ThreeDScene):
    def construct(self):
        # Camera configuration
        self.camera.background_color = WHITE

        # Initial camera position
        self.set_camera_orientation(phi=70 * DEGREES, theta=-45 * DEGREES)

        # Create 3D axes
        axes = ThreeDAxes(
            x_range=[-5, 5, 1],
            y_range=[-5, 5, 1],
            z_range=[-5, 5, 1],
            x_length=8,
            y_length=8,
            z_length=6,
            axis_config={"color": GRAY, "include_tip": True, "tip_width": 0.15, "tip_height": 0.15}
        )

        # Axis labels
        x_label = axes.get_x_axis_label(Tex("$x$", color=BLACK).scale(0.6))
        y_label = axes.get_y_axis_label(Tex("$y$", color=BLACK).scale(0.6))
        z_label = axes.get_z_axis_label(Tex("$z$", color=BLACK).scale(0.6))

        # Create surface with color gradient
        # Function: z = -(1/3)*(x² + 2*y²) + 1.5
        surface = Surface(
            lambda u, v: axes.c2p(u, v, -(1/3) * (u**2 + 2*v**2) + 1.5),
            u_range=[-3.5, 3.5],
            v_range=[-2.5, 2.5],
            resolution=(40, 40),
            fill_opacity=0.85,
            checkerboard_colors=[BLUE_D, BLUE_E],
            stroke_color=BLUE
        )
        surface.set_sheen_direction(UP)
        surface.set_color_by_gradient(BLUE, PURPLE)

        # Reference point (x0, y0)
        x0 = 1.5
        y0 = 0.8
        z0 = -(1/3) * (x0**2 + 2*y0**2) + 1.5

        # Vertical plane at y = y0 (plane parallel to xz plane)
        plane_width = 7
        plane_height = 6

        # ValueTracker for the full plane
        plane_tracker = ValueTracker(-4)

        # Create full plane (from bottom to top) with always_redraw
        plane_full = always_redraw(
            lambda: Surface(
                lambda u, v: axes.c2p(u, y0, v),
                u_range=[-3.5, 3.5],
                v_range=[-4, plane_tracker.get_value()],
                resolution=(20, 20),
                fill_color=GRAY,
                fill_opacity=0.4
            )
        )

        # Create clipped plane (only up to the surface)
        def clipped_plane_func(u, v):
            x = u
            z_surface = -(1/3) * (x**2 + 2*y0**2) + 1.5
            z = min(v, z_surface)  # Limit z to the surface height
            return axes.c2p(x, y0, z)

        # Static clipped plane (will be created later)
        plane_clipped = Surface(
            lambda u, v: clipped_plane_func(u, v),
            u_range=[-3.5, 3.5],
            v_range=[-4, 3],
            resolution=(50, 50),
            fill_color=GRAY,
            fill_opacity=0.4,
            stroke_width=0.5,
            stroke_color=GRAY
        )

        # Dashed lines
        # Line from (x0, y0, 0) to projection on x axis
        dashed_line_x = DashedLine(
            start=axes.c2p(x0, y0, 0),
            end=axes.c2p(x0, 0, 0),
            color=BLACK,
            stroke_width=2,
            dash_length=0.1
        )

        # Line from (x0, y0, 0) to projection on y axis
        dashed_line_y = DashedLine(
            start=axes.c2p(x0, y0, 0),
            end=axes.c2p(0, y0, 0),
            color=BLACK,
            stroke_width=2,
            dash_length=0.1
        )

        # Vertical line from (x0, y0, 0) to (x0, y0, z0)
        dashed_line_z = DashedLine(
            start=axes.c2p(x0, y0, 0),
            end=axes.c2p(x0, y0, z0),
            color=BLACK,
            stroke_width=2,
            dash_length=0.1
        )

        # Labels for x0 and y0 on the axes
        x0_label = Tex("$x_0$", color=BLACK).scale(0.5)
        x0_label.rotate(PI/2, axis=RIGHT)
        x0_label.rotate(-PI/4, axis=OUT)
        x0_label.move_to(axes.c2p(x0, -0.5, 0))

        y0_label = Tex("$y_0$", color=BLACK).scale(0.5)
        y0_label.rotate(PI/2, axis=RIGHT)
        y0_label.rotate(-PI/4, axis=OUT)
        y0_label.move_to(axes.c2p(-0.5, y0, 0))

        # Label (x0, y0) at base point
        point_label = Tex("$(x_0, y_0)$", color=BLACK).scale(0.5)
        point_label.rotate(PI/2, axis=RIGHT)
        point_label.rotate(-PI/4, axis=OUT)
        point_label.move_to(axes.c2p(x0, y0, -0.8))

        # Animation: Scene construction
        self.play(Create(axes), run_time=1.5,)
        self.add_fixed_in_frame_mobjects(x_label, y_label, z_label)

        self.wait(0.5)

        # Display the surface
        self.play(Create(surface), run_time=2)
        self.wait(0.5)

        # Display the dashed lines
        self.play(
            Create(dashed_line_x),
            Create(dashed_line_y),
            run_time=1
        )
        self.wait(0.3)

        # Display labels x0, y0
        self.add(x0_label, y0_label)
        self.wait(0.3)

        # Display the label (x0, y0)
        self.add(point_label)
        self.wait(0.5)

        # Display the vertical dashed line
        self.play(Create(dashed_line_z), run_time=0.8)
        self.wait(0.5)

        # Display the full plane
        self.add(plane_full)
        self.play(plane_tracker.animate.set_value(3), run_time=1.5)

        # Replace with a static plane
        self.remove(plane_full)
        plane_full_static = Surface(
            lambda u, v: axes.c2p(u, y0, v),
            u_range=[-3.5, 3.5],
            v_range=[-4, 3],
            resolution=(20, 20),
            fill_color=GRAY,
            fill_opacity=0.4
        )
        self.add(plane_full_static)

        self.wait(1)

        # Transition: clip the plane
        self.play(
            Transform(plane_full_static, plane_clipped),
            run_time=1.5
        )
        self.wait(2)

        # Rotate camera for better view
        self.begin_ambient_camera_rotation(rate=0.1)
        self.wait(3)
        self.stop_ambient_camera_rotation()

        self.wait(2)

Additional media files

Images/GIFs

Image

Logs

Terminal output
PASTE HERE OR PROVIDE LINK TO https://pastebin.com/ OR SIMILAR

System specifications

System Details - Manim version v19.1 - OS (with version, e.g., Windows 10 v2004 or macOS 10.15 (Catalina)): Windows 11 - RAM: 32GB - Python version (`python/py/python3 --version`): 3.12 - Installed modules (provide output from `pip list`): ``` PASTE HERE ```
LaTeX details
  • LaTeX distribution (e.g. TeX Live 2020):
  • Installed LaTeX packages:

Additional comments

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    🆕 New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions