mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Latest shadows animations
This commit is contained in:
parent
426af6f7fc
commit
a192f56d4d
1 changed files with 110 additions and 29 deletions
|
@ -5,8 +5,13 @@ from big_ol_pile_of_manim_imports import *
|
||||||
def get_shadow(mobject, opacity=0.5):
|
def get_shadow(mobject, opacity=0.5):
|
||||||
result = mobject.deepcopy()
|
result = mobject.deepcopy()
|
||||||
result.apply_function(lambda p: [p[0], p[1], 0])
|
result.apply_function(lambda p: [p[0], p[1], 0])
|
||||||
result.set_fill(BLACK, opacity=opacity)
|
color = interpolate_color(
|
||||||
result.set_stroke(BLACK, 0)
|
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)
|
result.set_shade_in_3d(False)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -57,11 +62,6 @@ class ShowShadows(ThreeDScene):
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.add_plane()
|
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_orientation_trackers()
|
||||||
self.setup_object_and_shadow()
|
self.setup_object_and_shadow()
|
||||||
self.add_shadow_area_label()
|
self.add_shadow_area_label()
|
||||||
|
@ -73,8 +73,9 @@ class ShowShadows(ThreeDScene):
|
||||||
height=24.2,
|
height=24.2,
|
||||||
stroke_width=0,
|
stroke_width=0,
|
||||||
fill_color=WHITE,
|
fill_color=WHITE,
|
||||||
fill_opacity=0.5,
|
fill_opacity=0.35,
|
||||||
)
|
)
|
||||||
|
plane.set_sheen(0.2, DR)
|
||||||
grid = NumberPlane(
|
grid = NumberPlane(
|
||||||
color=LIGHT_GREY,
|
color=LIGHT_GREY,
|
||||||
secondary_color=DARK_GREY,
|
secondary_color=DARK_GREY,
|
||||||
|
@ -103,12 +104,23 @@ class ShowShadows(ThreeDScene):
|
||||||
label = VGroup(text, decimal)
|
label = VGroup(text, decimal)
|
||||||
label.arrange_submobjects(RIGHT)
|
label.arrange_submobjects(RIGHT)
|
||||||
label.scale(1.5)
|
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_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(
|
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(label)
|
||||||
self.add(continual_update)
|
self.add(continual_update)
|
||||||
|
|
||||||
|
@ -118,21 +130,40 @@ class ShowShadows(ThreeDScene):
|
||||||
label = VGroup(text, decimal)
|
label = VGroup(text, decimal)
|
||||||
label.arrange_submobjects(RIGHT)
|
label.arrange_submobjects(RIGHT)
|
||||||
label.scale(1.25)
|
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.surface_area_label = label
|
||||||
self.add_fixed_orientation_mobjects(label)
|
self.add_fixed_orientation_mobjects(label)
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
# Show creation
|
||||||
obj3d = self.obj3d.copy()
|
obj3d = self.obj3d.copy()
|
||||||
obj3d.clear_updaters()
|
obj3d.clear_updaters()
|
||||||
temp_shadow = updating_mobject_from_func(lambda: get_shadow(obj3d))
|
temp_shadow = updating_mobject_from_func(lambda: get_shadow(obj3d))
|
||||||
self.add(temp_shadow)
|
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)
|
self.remove(obj3d, temp_shadow)
|
||||||
|
|
||||||
|
average_label = self.get_average_label()
|
||||||
|
# Reorient
|
||||||
self.add(self.obj3d, self.shadow)
|
self.add(self.obj3d, self.shadow)
|
||||||
for n in range(self.num_reorientations):
|
for n in range(self.num_reorientations):
|
||||||
self.randomly_reorient()
|
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):
|
def randomly_reorient(self, run_time=3):
|
||||||
a, b, c = TAU * np.random.random(3)
|
a, b, c = TAU * np.random.random(3)
|
||||||
|
@ -166,11 +197,32 @@ class ShowShadows(ThreeDScene):
|
||||||
obj3d.rotate(angle, vect, about_point=center)
|
obj3d.rotate(angle, vect, about_point=center)
|
||||||
return obj3d
|
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):
|
class ShowInfinitelyFarLightSource(ShowShadows):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_reorientations": 1,
|
"num_reorientations": 1,
|
||||||
"camera_center": [0, 0, 1]
|
"camera_center": [0, 0, 1],
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -193,6 +245,7 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||||
|
|
||||||
def move_light_around(self):
|
def move_light_around(self):
|
||||||
light = self.light
|
light = self.light
|
||||||
|
self.add_foreground_mobjects(self.shadow_area_label)
|
||||||
self.play(
|
self.play(
|
||||||
light.move_to, 5 * OUT + DOWN,
|
light.move_to, 5 * OUT + DOWN,
|
||||||
run_time=3
|
run_time=3
|
||||||
|
@ -209,9 +262,27 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||||
|
|
||||||
def show_vertical_lines(self):
|
def show_vertical_lines(self):
|
||||||
lines = self.get_vertical_lines()
|
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))
|
self.play(LaggedStart(ShowCreation, lines))
|
||||||
lines.add_updater(lambda m: m.become(self.get_vertical_lines()))
|
|
||||||
self.wait()
|
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):
|
for x in range(5):
|
||||||
self.randomly_reorient()
|
self.randomly_reorient()
|
||||||
|
|
||||||
|
@ -220,20 +291,21 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||||
light_source = self.camera.light_source
|
light_source = self.camera.light_source
|
||||||
obj3d = self.obj3d
|
obj3d = self.obj3d
|
||||||
center = obj3d.get_center()
|
center = obj3d.get_center()
|
||||||
right = center + RIGHT
|
|
||||||
up = center + UP
|
|
||||||
|
|
||||||
def update(shadow):
|
def update(shadow):
|
||||||
lsp = light_source.get_center()
|
lsp = light_source.get_center()
|
||||||
proj_center, proj_right, proj_up = [
|
proj_center = get_xy_plane_projection_point(lsp, center)
|
||||||
get_xy_plane_projection_point(lsp, point)
|
c_to_lsp = lsp - center
|
||||||
for point in [center, right, up]
|
unit_c_to_lsp = normalize(c_to_lsp)
|
||||||
]
|
rotation = rotation_matrix(
|
||||||
matrix = np.array([
|
angle=np.arccos(np.dot(unit_c_to_lsp, OUT)),
|
||||||
proj_right - proj_center,
|
axis=normalize(np.cross(unit_c_to_lsp, OUT))
|
||||||
proj_up - proj_center
|
)
|
||||||
]).T
|
new_shadow = get_shadow(
|
||||||
shadow.apply_matrix(matrix)
|
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)
|
shadow.move_to(proj_center)
|
||||||
return shadow
|
return shadow
|
||||||
shadow.add_updater(update)
|
shadow.add_updater(update)
|
||||||
|
@ -254,8 +326,8 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||||
def get_vertical_lines(self):
|
def get_vertical_lines(self):
|
||||||
shadow = self.shadow
|
shadow = self.shadow
|
||||||
points = get_boundary_points(shadow, 10)
|
points = get_boundary_points(shadow, 10)
|
||||||
half_points = [(p1 + p2) / 2 for p1, p2 in adjacent_pairs(points)]
|
# half_points = [(p1 + p2) / 2 for p1, p2 in adjacent_pairs(points)]
|
||||||
points = np.append(points, half_points, axis=0)
|
# points = np.append(points, half_points, axis=0)
|
||||||
light_source = self.light.get_center()
|
light_source = self.light.get_center()
|
||||||
lines = VGroup(*[
|
lines = VGroup(*[
|
||||||
DashedLine(light_source, point)
|
DashedLine(light_source, point)
|
||||||
|
@ -271,7 +343,8 @@ class ShowInfinitelyFarLightSource(ShowShadows):
|
||||||
|
|
||||||
class CylinderShadows(ShowShadows):
|
class CylinderShadows(ShowShadows):
|
||||||
CONFIG = {
|
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):
|
def get_object(self):
|
||||||
|
@ -328,3 +401,11 @@ class PrismShadows(ShowShadows):
|
||||||
prism.set_fill(PINK, 0.8)
|
prism.set_fill(PINK, 0.8)
|
||||||
prism.set_stroke(WHITE, 1)
|
prism.set_stroke(WHITE, 1)
|
||||||
return prism
|
return prism
|
||||||
|
|
||||||
|
|
||||||
|
class TheseFourPiAreSquare(PiCreatureScene):
|
||||||
|
def construct(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_pi_creatures(self):
|
||||||
|
pass
|
||||||
|
|
Loading…
Add table
Reference in a new issue