Latest shadows animations

This commit is contained in:
Grant Sanderson 2018-10-09 12:21:58 -07:00
parent 426af6f7fc
commit a192f56d4d

View file

@ -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