I'm trying to make a colored Mobius strip, but I always end up with a color difference between the beginning and the end of the strip.
Here is a MWE and the image it produces.
from manim import *
BG_COLOR = "#F7F5E7"
config.background_color = BG_COLOR
def mobius_func(u, v):
x = (1 + v / 2 * np.cos(u / 2)) * np.cos(u)
y = (1 + v / 2 * np.cos(u / 2)) * np.sin(u)
z = v / 2 * np.sin(u / 2)
return np.array((x, y, z))
class Logo(ThreeDScene):
def construct(self):
self.set_camera_orientation(
phi=50 * DEGREES, theta=330 * DEGREES, run_time=2, zoom=2.2
)
mobius = Surface(
mobius_func,
u_range=[0, 2 * PI],
v_range=[-1, 1],
resolution=(64, 16),
)
mobius.set_color(RED)
self.add(mobius)
What causes this problem and how can I fix it ?
To render a Möbius strip correctly, you need a rendering engine that supports the hidden surface removal(such as z buffering) and face culling. But Manim does not supports them. So in short, you can't solve that problem.
Your best bet will be to hack Manim like this.(Of course, it's not recommended for a long term project, because it maybe will not work on versions other than 0.17.2.)
import numpy as np
import manim
def new_get_shaded_rgb(
rgb: np.ndarray,
point: np.ndarray,
unit_normal_vect: np.ndarray,
light_source: np.ndarray,
) -> np.ndarray:
to_sun = manim.utils.space_ops.normalize(light_source - point)
factor = 0.5 * np.dot(unit_normal_vect, to_sun) ** 3
factor = abs(factor) # This patch will give the same color for a back or front face.
result = rgb + factor
return result
manim.camera.three_d_camera.get_shaded_rgb = new_get_shaded_rgb