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):
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