mirror of
https://github.com/3b1b/manim.git
synced 2025-08-02 19:46:21 +08:00
Latest shadows animations
This commit is contained in:
@ -5,8 +5,13 @@ from big_ol_pile_of_manim_imports import *
|
||||
def get_shadow(mobject, opacity=0.5):
|
||||
result = mobject.deepcopy()
|
||||
result.apply_function(lambda p: [p[0], p[1], 0])
|
||||
result.set_fill(BLACK, opacity=opacity)
|
||||
result.set_stroke(BLACK, 0)
|
||||
color = interpolate_color(
|
||||
mobject.get_fill_color(), BLACK,
|
||||
mobject.get_fill_opacity()
|
||||
)
|
||||
# color = BLACK
|
||||
result.set_fill(color, opacity=opacity)
|
||||
result.set_stroke(BLACK, 0.5, opacity=opacity)
|
||||
result.set_shade_in_3d(False)
|
||||
return result
|
||||
|
||||
@ -57,11 +62,6 @@ class ShowShadows(ThreeDScene):
|
||||
|
||||
def setup(self):
|
||||
self.add_plane()
|
||||
self.set_camera_orientation(
|
||||
phi=60 * DEGREES,
|
||||
theta=-90 * DEGREES,
|
||||
)
|
||||
# self.begin_ambient_camera_rotation(0.02)
|
||||
self.setup_orientation_trackers()
|
||||
self.setup_object_and_shadow()
|
||||
self.add_shadow_area_label()
|
||||
@ -73,8 +73,9 @@ class ShowShadows(ThreeDScene):
|
||||
height=24.2,
|
||||
stroke_width=0,
|
||||
fill_color=WHITE,
|
||||
fill_opacity=0.5,
|
||||
fill_opacity=0.35,
|
||||
)
|
||||
plane.set_sheen(0.2, DR)
|
||||
grid = NumberPlane(
|
||||
color=LIGHT_GREY,
|
||||
secondary_color=DARK_GREY,
|
||||
@ -103,12 +104,23 @@ class ShowShadows(ThreeDScene):
|
||||
label = VGroup(text, decimal)
|
||||
label.arrange_submobjects(RIGHT)
|
||||
label.scale(1.5)
|
||||
label.move_to(self.area_label_center)
|
||||
label.move_to(self.area_label_center - decimal.get_center())
|
||||
self.shadow_area_label = label
|
||||
self.shadow_area_decimal = decimal
|
||||
|
||||
# def update_decimal(decimal):
|
||||
# # decimal.set_value(get_area(self.shadow))
|
||||
# self.add_fixed_in_frame_mobjects(decimal)
|
||||
|
||||
# decimal.add_updater(update_decimal)
|
||||
continual_update = ContinualChangingDecimal(
|
||||
decimal, lambda a: get_area(self.shadow)
|
||||
decimal,
|
||||
lambda a: get_area(self.shadow),
|
||||
position_update_func=lambda d: self.add_fixed_in_frame_mobjects(d)
|
||||
)
|
||||
|
||||
# self.add_fixed_orientation_mobjects(label)
|
||||
self.add_fixed_in_frame_mobjects(label)
|
||||
self.add(label)
|
||||
self.add(continual_update)
|
||||
|
||||
@ -118,21 +130,40 @@ class ShowShadows(ThreeDScene):
|
||||
label = VGroup(text, decimal)
|
||||
label.arrange_submobjects(RIGHT)
|
||||
label.scale(1.25)
|
||||
label.next_to(self.obj3d, RIGHT, MED_LARGE_BUFF)
|
||||
label.set_fill(YELLOW)
|
||||
label.set_background_stroke(width=3)
|
||||
label.next_to(self.obj3d, RIGHT, LARGE_BUFF)
|
||||
label.shift(MED_LARGE_BUFF * IN)
|
||||
self.surface_area_label = label
|
||||
self.add_fixed_orientation_mobjects(label)
|
||||
|
||||
def construct(self):
|
||||
# Show creation
|
||||
obj3d = self.obj3d.copy()
|
||||
obj3d.clear_updaters()
|
||||
temp_shadow = updating_mobject_from_func(lambda: get_shadow(obj3d))
|
||||
self.add(temp_shadow)
|
||||
self.play(LaggedStart(DrawBorderThenFill, obj3d))
|
||||
self.move_camera(
|
||||
phi=60 * DEGREES,
|
||||
theta=-120 * DEGREES,
|
||||
added_anims=[
|
||||
LaggedStart(DrawBorderThenFill, obj3d)
|
||||
],
|
||||
run_time=2
|
||||
)
|
||||
self.begin_ambient_camera_rotation(0.01)
|
||||
self.remove(obj3d, temp_shadow)
|
||||
|
||||
average_label = self.get_average_label()
|
||||
# Reorient
|
||||
self.add(self.obj3d, self.shadow)
|
||||
for n in range(self.num_reorientations):
|
||||
self.randomly_reorient()
|
||||
self.wait()
|
||||
if n == 3:
|
||||
self.add_fixed_in_frame_mobjects(average_label)
|
||||
self.play(Write(average_label, run_time=2))
|
||||
else:
|
||||
self.wait()
|
||||
|
||||
def randomly_reorient(self, run_time=3):
|
||||
a, b, c = TAU * np.random.random(3)
|
||||
@ -166,11 +197,32 @@ class ShowShadows(ThreeDScene):
|
||||
obj3d.rotate(angle, vect, about_point=center)
|
||||
return obj3d
|
||||
|
||||
def get_average_label(self):
|
||||
rect = SurroundingRectangle(
|
||||
self.shadow_area_decimal,
|
||||
buff=SMALL_BUFF,
|
||||
color=RED,
|
||||
)
|
||||
words = TextMobject(
|
||||
"Average", "=",
|
||||
"$\\frac{\\text{Surface area}}{4}$"
|
||||
)
|
||||
words.scale(1.5)
|
||||
words[0].match_color(rect)
|
||||
words[2].set_color(self.surface_area_label[0].get_fill_color())
|
||||
words.set_background_stroke(width=3)
|
||||
words.next_to(
|
||||
rect, DOWN,
|
||||
index_of_submobject_to_align=0,
|
||||
)
|
||||
# words.shift(MED_LARGE_BUFF * LEFT)
|
||||
return VGroup(rect, words)
|
||||
|
||||
|
||||
class ShowInfinitelyFarLightSource(ShowShadows):
|
||||
CONFIG = {
|
||||
"num_reorientations": 1,
|
||||
"camera_center": [0, 0, 1]
|
||||
"camera_center": [0, 0, 1],
|
||||
}
|
||||
|
||||
def construct(self):
|
||||
@ -193,6 +245,7 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||
|
||||
def move_light_around(self):
|
||||
light = self.light
|
||||
self.add_foreground_mobjects(self.shadow_area_label)
|
||||
self.play(
|
||||
light.move_to, 5 * OUT + DOWN,
|
||||
run_time=3
|
||||
@ -209,9 +262,27 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||
|
||||
def show_vertical_lines(self):
|
||||
lines = self.get_vertical_lines()
|
||||
obj3d = self.obj3d
|
||||
shadow = self.shadow
|
||||
target_obj3d = obj3d.copy()
|
||||
target_obj3d.become(shadow)
|
||||
target_obj3d.match_style(obj3d)
|
||||
target_obj3d.set_shade_in_3d(False)
|
||||
source_obj3d = obj3d.copy()
|
||||
source_obj3d.set_shade_in_3d(False)
|
||||
source_obj3d.fade(1)
|
||||
|
||||
self.play(LaggedStart(ShowCreation, lines))
|
||||
lines.add_updater(lambda m: m.become(self.get_vertical_lines()))
|
||||
self.wait()
|
||||
self.add(source_obj3d, lines)
|
||||
self.play(
|
||||
ReplacementTransform(source_obj3d, target_obj3d),
|
||||
run_time=2
|
||||
)
|
||||
self.add(target_obj3d, lines)
|
||||
self.play(FadeOut(target_obj3d),)
|
||||
self.wait()
|
||||
lines.add_updater(lambda m: m.become(self.get_vertical_lines()))
|
||||
for x in range(5):
|
||||
self.randomly_reorient()
|
||||
|
||||
@ -220,20 +291,21 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||
light_source = self.camera.light_source
|
||||
obj3d = self.obj3d
|
||||
center = obj3d.get_center()
|
||||
right = center + RIGHT
|
||||
up = center + UP
|
||||
|
||||
def update(shadow):
|
||||
lsp = light_source.get_center()
|
||||
proj_center, proj_right, proj_up = [
|
||||
get_xy_plane_projection_point(lsp, point)
|
||||
for point in [center, right, up]
|
||||
]
|
||||
matrix = np.array([
|
||||
proj_right - proj_center,
|
||||
proj_up - proj_center
|
||||
]).T
|
||||
shadow.apply_matrix(matrix)
|
||||
proj_center = get_xy_plane_projection_point(lsp, center)
|
||||
c_to_lsp = lsp - center
|
||||
unit_c_to_lsp = normalize(c_to_lsp)
|
||||
rotation = rotation_matrix(
|
||||
angle=np.arccos(np.dot(unit_c_to_lsp, OUT)),
|
||||
axis=normalize(np.cross(unit_c_to_lsp, OUT))
|
||||
)
|
||||
new_shadow = get_shadow(
|
||||
self.obj3d.copy().apply_matrix(rotation)
|
||||
)
|
||||
shadow.become(new_shadow)
|
||||
shadow.scale(get_norm(lsp) / get_norm(c_to_lsp))
|
||||
shadow.move_to(proj_center)
|
||||
return shadow
|
||||
shadow.add_updater(update)
|
||||
@ -254,8 +326,8 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||
def get_vertical_lines(self):
|
||||
shadow = self.shadow
|
||||
points = get_boundary_points(shadow, 10)
|
||||
half_points = [(p1 + p2) / 2 for p1, p2 in adjacent_pairs(points)]
|
||||
points = np.append(points, half_points, axis=0)
|
||||
# half_points = [(p1 + p2) / 2 for p1, p2 in adjacent_pairs(points)]
|
||||
# points = np.append(points, half_points, axis=0)
|
||||
light_source = self.light.get_center()
|
||||
lines = VGroup(*[
|
||||
DashedLine(light_source, point)
|
||||
@ -271,7 +343,8 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||
|
||||
class CylinderShadows(ShowShadows):
|
||||
CONFIG = {
|
||||
"surface_area": 2 * PI + 2 * PI * 2
|
||||
"surface_area": 2 * PI + 2 * PI * 2,
|
||||
"area_label_center": [0, -2, 0],
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
@ -328,3 +401,11 @@ class PrismShadows(ShowShadows):
|
||||
prism.set_fill(PINK, 0.8)
|
||||
prism.set_stroke(WHITE, 1)
|
||||
return prism
|
||||
|
||||
|
||||
class TheseFourPiAreSquare(PiCreatureScene):
|
||||
def construct(self):
|
||||
pass
|
||||
|
||||
def create_pi_creatures(self):
|
||||
pass
|
||||
|
Reference in New Issue
Block a user