mirror of
https://github.com/3b1b/manim.git
synced 2025-08-21 05:44:04 +00:00
refactoring scenes 2-5, started on scene 6 (faux 3D)
This commit is contained in:
parent
e139d54ba9
commit
b38a8dade6
1 changed files with 410 additions and 186 deletions
|
@ -50,12 +50,9 @@ NUM_VISIBLE_CONES = 5 # ibidem
|
|||
ARC_TIP_LENGTH = 0.2
|
||||
AMBIENT_FULL = 1.0
|
||||
AMBIENT_DIMMED = 0.2
|
||||
|
||||
LIGHT_COLOR = YELLOW
|
||||
DEGREES = TAU/360
|
||||
|
||||
def show_line_length(line):
|
||||
v = line.points[1] - line.points[0]
|
||||
print v[0]**2 + v[1]**2
|
||||
SWITCH_ON_RUN_TIME = 1.5
|
||||
|
||||
|
||||
class AngleUpdater(ContinualAnimation):
|
||||
|
@ -79,9 +76,18 @@ class AngleUpdater(ContinualAnimation):
|
|||
|
||||
|
||||
|
||||
LIGHT_COLOR = YELLOW
|
||||
DEGREES = 360/TAU
|
||||
SWITCH_ON_RUN_TIME = 1.5
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class AmbientLight(VMobject):
|
||||
|
@ -214,7 +220,6 @@ class Spotlight(VMobject):
|
|||
return u
|
||||
|
||||
def move_source_to(self,point):
|
||||
print "moving source"
|
||||
self.source_point = np.array(point)
|
||||
self.recalculate_sectors(point = point, screen = self.screen)
|
||||
self.update_shadow(point = point)
|
||||
|
@ -375,6 +380,28 @@ class UpdateLightIndicator(AnimationGroup):
|
|||
self.mobject = indicator
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class IntroScene(PiCreatureScene):
|
||||
|
||||
CONFIG = {
|
||||
|
@ -388,16 +415,10 @@ class IntroScene(PiCreatureScene):
|
|||
randy = self.get_primary_pi_creature()
|
||||
randy.scale(0.7).to_corner(DOWN+RIGHT)
|
||||
|
||||
self.force_skipping()
|
||||
|
||||
self.build_up_euler_sum()
|
||||
self.build_up_sum_on_number_line()
|
||||
self.show_pi_answer()
|
||||
self.other_pi_formulas()
|
||||
|
||||
self.revert_to_original_skipping_status()
|
||||
|
||||
|
||||
self.refocus_on_euler_sum()
|
||||
|
||||
|
||||
|
@ -595,20 +616,41 @@ class IntroScene(PiCreatureScene):
|
|||
ScaleInPlace(pi_squared,2,rate_func = wiggle)
|
||||
)
|
||||
|
||||
q_circle = Circle(color=WHITE,radius=0.8)
|
||||
q_mark = TexMobject("?")
|
||||
q_mark.next_to(q_circle)
|
||||
|
||||
thought = Group(q_circle, q_mark)
|
||||
q_mark.height *= 2
|
||||
self.pi_creature_thinks(thought,target_mode = "confused",
|
||||
bubble_kwargs = { "height" : 1.5, "width" : 2 })
|
||||
|
||||
self.wait()
|
||||
# Morty thinks of a circle
|
||||
|
||||
# q_circle = Circle(color=WHITE,radius=0.8)
|
||||
# q_mark = TexMobject("?")
|
||||
# q_mark.next_to(q_circle)
|
||||
|
||||
# thought = Group(q_circle, q_mark)
|
||||
# q_mark.height *= 2
|
||||
# self.pi_creature_thinks(thought,target_mode = "confused",
|
||||
# bubble_kwargs = { "height" : 1.5, "width" : 2 })
|
||||
|
||||
# self.wait()
|
||||
|
||||
|
||||
|
||||
class FirstLightHouseScene(PiCreatureScene):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class FirstLighthouseScene(PiCreatureScene):
|
||||
|
||||
def construct(self):
|
||||
self.remove(self.get_primary_pi_creature())
|
||||
|
@ -771,21 +813,43 @@ class FirstLightHouseScene(PiCreatureScene):
|
|||
|
||||
|
||||
|
||||
class SingleLightHouseScene(PiCreatureScene):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class SingleLighthouseScene(PiCreatureScene):
|
||||
|
||||
def construct(self):
|
||||
|
||||
self.create_light_source_and_creature()
|
||||
self.setup_elements()
|
||||
self.setup_trackers() # spotlight and angle msmt change when screen rotates
|
||||
self.rotate_screen()
|
||||
|
||||
|
||||
|
||||
def create_light_source_and_creature(self):
|
||||
def setup_elements(self):
|
||||
|
||||
SCREEN_SIZE = 3.0
|
||||
DISTANCE_FROM_LIGHTHOUSE = 10.0
|
||||
source_point = [-DISTANCE_FROM_LIGHTHOUSE/2,0,0]
|
||||
observer_point = [DISTANCE_FROM_LIGHTHOUSE/2,0,0]
|
||||
|
||||
# Lighthouse
|
||||
|
||||
lighthouse = LightHouse()
|
||||
ambient_light = AmbientLight(
|
||||
opacity_function = inverse_quadratic(AMBIENT_FULL,2,1),
|
||||
|
@ -795,6 +859,9 @@ class SingleLightHouseScene(PiCreatureScene):
|
|||
)
|
||||
lighthouse.scale(2).next_to(source_point, DOWN, buff = 0)
|
||||
ambient_light.move_to(source_point)
|
||||
|
||||
# Pi Creature
|
||||
|
||||
morty = self.get_primary_pi_creature()
|
||||
morty.scale(0.5)
|
||||
morty.move_to(observer_point)
|
||||
|
@ -803,72 +870,95 @@ class SingleLightHouseScene(PiCreatureScene):
|
|||
SwitchOn(ambient_light)
|
||||
)
|
||||
|
||||
# Screen
|
||||
|
||||
screen = Line([0,-1,0],[0,1,0])
|
||||
screen.rotate(-TAU/6)
|
||||
screen.next_to(morty, LEFT, buff = 1)
|
||||
self.screen = Line([0,-1,0],[0,1,0])
|
||||
self.screen.rotate(-TAU/6)
|
||||
self.screen.next_to(morty, LEFT, buff = 1)
|
||||
|
||||
spotlight = Spotlight(
|
||||
# Spotlight
|
||||
|
||||
self.spotlight = Spotlight(
|
||||
opacity_function = inverse_quadratic(1,2,1),
|
||||
num_levels = NUM_LEVELS,
|
||||
radius = 10,
|
||||
brightness = 5,
|
||||
screen = screen
|
||||
screen = self.screen
|
||||
)
|
||||
spotlight.move_source_to(source_point)
|
||||
self.spotlight.move_source_to(source_point)
|
||||
|
||||
|
||||
# Animations
|
||||
|
||||
self.play(
|
||||
ApplyMethod(ambient_light.dimming,AMBIENT_DIMMED),
|
||||
FadeIn(spotlight))
|
||||
self.add(spotlight.shadow)
|
||||
FadeIn(self.spotlight)
|
||||
)
|
||||
self.add(self.spotlight.shadow)
|
||||
|
||||
self.add_foreground_mobject(morty)
|
||||
|
||||
screen_tracker = ScreenTracker(spotlight)
|
||||
# activate ONLY when spotlight is moving!
|
||||
|
||||
|
||||
|
||||
def setup_trackers(self):
|
||||
|
||||
# Make spotlight follow the screen
|
||||
|
||||
screen_tracker = ScreenTracker(self.spotlight)
|
||||
|
||||
self.add(screen_tracker)
|
||||
pointing_screen_at_source = ApplyMethod(spotlight.screen.rotate,TAU/6)
|
||||
pointing_screen_at_source = Rotate(self.screen,TAU/6)
|
||||
self.play(pointing_screen_at_source)
|
||||
|
||||
|
||||
|
||||
# angle msmt (arc)
|
||||
|
||||
arc_angle = spotlight.opening_angle()
|
||||
arc_angle = self.spotlight.opening_angle()
|
||||
# draw arc arrows to show the opening angle
|
||||
angle_arc = Arc(radius = 5, start_angle = spotlight.start_angle(),
|
||||
angle = spotlight.opening_angle(), tip_length = ARC_TIP_LENGTH)
|
||||
angle_arc = Arc(radius = 5, start_angle = self.spotlight.start_angle(),
|
||||
angle = self.spotlight.opening_angle(), tip_length = ARC_TIP_LENGTH)
|
||||
#angle_arc.add_tip(at_start = True, at_end = True)
|
||||
angle_arc.move_arc_center_to(source_point)
|
||||
angle_arc.move_arc_center_to(self.spotlight.source_point)
|
||||
|
||||
self.add(angle_arc)
|
||||
|
||||
# angle msmt (decimal number)
|
||||
|
||||
angle_indicator = DecimalNumber(arc_angle/TAU*360,
|
||||
num_decimal_points = 0,
|
||||
unit = "^\\circ")
|
||||
angle_indicator.next_to(angle_arc,RIGHT)
|
||||
self.add_foreground_mobject(angle_indicator)
|
||||
|
||||
angle_update_func = lambda x: spotlight.opening_angle()/TAU * 360
|
||||
ca3 = ContinualChangingDecimal(angle_indicator,angle_update_func)
|
||||
self.add(ca3)
|
||||
angle_update_func = lambda x: self.spotlight.opening_angle()/TAU * 360
|
||||
ca1 = ContinualChangingDecimal(angle_indicator,angle_update_func)
|
||||
self.add(ca1)
|
||||
|
||||
ca4 = AngleUpdater(angle_arc, spotlight)
|
||||
self.add(ca4)
|
||||
ca2 = AngleUpdater(angle_arc, self.spotlight)
|
||||
self.add(ca2)
|
||||
|
||||
rotating_screen = ApplyMethod(spotlight.screen.rotate,
|
||||
TAU/8, run_time=1.5)
|
||||
#self.wait(2)
|
||||
rotating_screen_2 = ApplyMethod(spotlight.screen.rotate,
|
||||
-TAU/4, run_time=3, rate_func = there_and_back)
|
||||
#self.wait(2)
|
||||
rotating_screen_3 = ApplyMethod(spotlight.screen.rotate,
|
||||
TAU/8, run_time=1.5)
|
||||
|
||||
self.play(rotating_screen)
|
||||
def rotate_screen(self):
|
||||
|
||||
# rotating_screen_1 = Rotate(self.screen,
|
||||
# TAU/8, run_time=1.5)
|
||||
# #self.wait(2)
|
||||
# rotating_screen_2 = Rotate(self.screen,
|
||||
# -TAU/4, run_time=3)
|
||||
# #self.wait(2)
|
||||
# rotating_screen_3 = Rotate(self.screen,
|
||||
# TAU/8, run_time=1.5)
|
||||
|
||||
# self.play(rotating_screen_1)
|
||||
# self.play(rotating_screen_2)
|
||||
# self.play(rotating_screen_3)
|
||||
|
||||
rotating_screen_1 = Rotate(self.screen, TAU/8, rate_func = there_and_back)
|
||||
rotating_screen_2 = Rotate(self.screen, -TAU/8, rate_func = there_and_back)
|
||||
self.play(rotating_screen_1)
|
||||
self.play(rotating_screen_2)
|
||||
self.play(rotating_screen_3)
|
||||
|
||||
|
||||
|
||||
#self.wait()
|
||||
|
@ -880,8 +970,8 @@ class SingleLightHouseScene(PiCreatureScene):
|
|||
|
||||
# # morph into Earth scene
|
||||
|
||||
# globe = Circle(radius = 3)
|
||||
# globe.move_to([2,0,0])
|
||||
# earth = Circle(radius = 3)
|
||||
# earth.move_to([2,0,0])
|
||||
# sun_position = [-100,0,0]
|
||||
# #self.add(screen_tracker)
|
||||
# print "tuet"
|
||||
|
@ -900,248 +990,382 @@ class SingleLightHouseScene(PiCreatureScene):
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class EarthScene(Scene):
|
||||
|
||||
def construct(self):
|
||||
|
||||
DEGREES = TAU/360
|
||||
radius = 2.5
|
||||
center_x = 3
|
||||
theta0 = 80 * DEGREES
|
||||
theta0 = 70 * DEGREES
|
||||
dtheta = 10 * DEGREES
|
||||
theta1 = theta0 + dtheta
|
||||
|
||||
|
||||
# screen
|
||||
|
||||
screen = Line([center_x - radius * np.cos(theta0),radius * np.sin(theta0),0],
|
||||
[center_x - radius * np.cos(theta1),radius * np.sin(theta1),0])
|
||||
screen.set_stroke(color = RED, width = 5)
|
||||
|
||||
globe = Circle(radius = radius, stroke_width = 0)
|
||||
globe.move_to([center_x,0,0])
|
||||
foreground_globe = globe.copy() # above the shadow
|
||||
foreground_globe.radius -= 0.2
|
||||
foreground_globe.set_stroke(color = WHITE, width = 1)
|
||||
self.add_foreground_mobject(foreground_globe)
|
||||
globe.add(screen)
|
||||
# Earth
|
||||
|
||||
earth = Circle(radius = radius, stroke_width = 0)
|
||||
earth.move_to([center_x,0,0])
|
||||
foreground_earth = earth.copy() # above the shadow
|
||||
foreground_earth.radius -= 0.2
|
||||
foreground_earth.set_stroke(color = WHITE, width = 1)
|
||||
self.add_foreground_mobject(foreground_earth)
|
||||
earth.add(screen)
|
||||
|
||||
# Morty
|
||||
|
||||
morty = Mortimer().scale(0.3).next_to(screen, RIGHT, buff = 0.5)
|
||||
self.add_foreground_mobject(morty)
|
||||
|
||||
|
||||
# Light source (far-away Sun)
|
||||
|
||||
sun = Spotlight(
|
||||
opacity_function = lambda r : 0.5,
|
||||
num_levels = NUM_LEVELS,
|
||||
radius = 100,
|
||||
radius = 1100,
|
||||
brightness = 5,
|
||||
screen = screen
|
||||
)
|
||||
|
||||
sun.move_source_to([-90,0,0])
|
||||
self.add(globe,sun,screen)
|
||||
sun.move_source_to([-1000,0,0])
|
||||
|
||||
# Add elements to scene
|
||||
|
||||
self.add(earth,sun,screen)
|
||||
screen_tracker = ScreenTracker(sun)
|
||||
|
||||
self.add(screen_tracker)
|
||||
|
||||
|
||||
# move screen to equator
|
||||
|
||||
self.play(
|
||||
ApplyMethod(globe.rotate,theta0 + dtheta/2),
|
||||
ApplyMethod(morty.move_to,[1.5,0,0])
|
||||
Rotate(earth,theta0 + dtheta/2,run_time = 3),
|
||||
ApplyMethod(morty.move_to,[1.5,0,0], run_time = 3),
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ScreenShapingScene(Scene):
|
||||
|
||||
def construct(self):
|
||||
|
||||
DEGREES = TAU / 360
|
||||
self.setup_elements()
|
||||
self.deform_screen()
|
||||
self.create_brightness_rect()
|
||||
self.slant_screen()
|
||||
self.unslant_screen()
|
||||
self.left_shift_screen_while_showing_light_indicator()
|
||||
self.add_distance_arrow()
|
||||
self.right_shift_screen_while_showing_light_indicator_and_distance_arrow()
|
||||
self.left_shift_again()
|
||||
self.morph_into_faux_3d()
|
||||
|
||||
screen_height = 1.0
|
||||
brightness_rect_height = 1.0
|
||||
|
||||
screen = Line([3,-screen_height/2,0],[3,screen_height/2,0], path_arc = 0, num_arc_anchors = 10)
|
||||
def setup_elements(self):
|
||||
|
||||
source = Spotlight(
|
||||
self.screen_height = 1.0
|
||||
self.brightness_rect_height = 1.0
|
||||
|
||||
# screen
|
||||
self.screen = Line([3,-self.screen_height/2,0],[3,self.screen_height/2,0],
|
||||
path_arc = 0, num_arc_anchors = 10)
|
||||
|
||||
# spotlight
|
||||
self.spotlight = Spotlight(
|
||||
opacity_function = inverse_quadratic(1,5,1),
|
||||
num_levels = NUM_LEVELS,
|
||||
radius = 10,
|
||||
brightness = 5,
|
||||
screen = screen
|
||||
screen = self.screen
|
||||
)
|
||||
|
||||
source.move_source_to([-5,0,0])
|
||||
self.spotlight.move_source_to([-5,0,0])
|
||||
screen_tracker = ScreenTracker(self.spotlight)
|
||||
|
||||
# lighthouse
|
||||
lighthouse = LightHouse()
|
||||
lighthouse.scale(2).next_to(self.spotlight.source_point,DOWN,buff=0)
|
||||
|
||||
# ambient light
|
||||
ambient_light = AmbientLight(
|
||||
opacity_function = inverse_quadratic(AMBIENT_DIMMED,1,1),
|
||||
num_levels = NUM_LEVELS,
|
||||
radius = 10,
|
||||
brightness = 1,
|
||||
)
|
||||
lighthouse.scale(2).next_to(source.source_point,DOWN,buff=0)
|
||||
ambient_light.move_source_to(source.source_point)
|
||||
ambient_light.move_source_to(self.spotlight.source_point)
|
||||
|
||||
self.add(lighthouse, ambient_light,source,screen)
|
||||
|
||||
morty = Mortimer().scale(0.3).next_to(screen, RIGHT, buff = 0.5)
|
||||
self.add_foreground_mobject(morty)
|
||||
|
||||
self.wait()
|
||||
|
||||
screen_tracker = ScreenTracker(source)
|
||||
# Morty
|
||||
self.morty = Mortimer().scale(0.3).next_to(self.screen, RIGHT, buff = 0.5)
|
||||
|
||||
# Add everything to the scene
|
||||
self.add(lighthouse, ambient_light,self.spotlight,self.screen)
|
||||
self.add_foreground_mobject(self.morty)
|
||||
self.add(screen_tracker)
|
||||
|
||||
self.play(
|
||||
ApplyMethod(screen.set_path_arc, 45 * DEGREES),
|
||||
)
|
||||
|
||||
|
||||
|
||||
def deform_screen(self):
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(ApplyMethod(self.screen.set_path_arc, 45 * DEGREES))
|
||||
self.play(ApplyMethod(self.screen.set_path_arc, -90 * DEGREES))
|
||||
self.play(ApplyMethod(self.screen.set_path_arc, 0))
|
||||
|
||||
|
||||
|
||||
|
||||
def create_brightness_rect(self):
|
||||
|
||||
# in preparation for the slanting, create a rectangle that shows the brightness
|
||||
|
||||
# a rect a zero width overlaying the screen
|
||||
# so we can morph it into the brightness rect above
|
||||
brightness_rect0 = Rectangle(width = 0,
|
||||
height = self.screen_height).move_to(self.screen.get_center())
|
||||
self.add_foreground_mobject(brightness_rect0)
|
||||
|
||||
self.brightness_rect = Rectangle(width = self.brightness_rect_height,
|
||||
height = self.brightness_rect_height, fill_color = YELLOW, fill_opacity = 0.5)
|
||||
|
||||
self.brightness_rect.next_to(self.screen, UP, buff = 1)
|
||||
|
||||
self.play(
|
||||
ApplyMethod(screen.set_path_arc, -90 * DEGREES),
|
||||
ReplacementTransform(brightness_rect0,self.brightness_rect)
|
||||
)
|
||||
|
||||
self.play(
|
||||
ApplyMethod(screen.set_path_arc, 0),
|
||||
)
|
||||
|
||||
|
||||
# in preparation for the slanting, create a rectangle that show the brightness
|
||||
|
||||
rect_origin = Rectangle(width = 0, height = screen_height).move_to(screen.get_center())
|
||||
self.add_foreground_mobject(rect_origin)
|
||||
|
||||
brightness_rect = Rectangle(width = brightness_rect_height,
|
||||
height = brightness_rect_height, fill_color = YELLOW, fill_opacity = 0.5)
|
||||
|
||||
brightness_rect.next_to(screen, UP, buff = 1)
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(rect_origin,brightness_rect)
|
||||
)
|
||||
|
||||
original_screen = screen.copy()
|
||||
original_brightness_rect = brightness_rect.copy()
|
||||
self.original_screen = self.screen.copy()
|
||||
self.original_brightness_rect = self.brightness_rect.copy()
|
||||
# for unslanting the screen later
|
||||
|
||||
lower_screen_point, upper_screen_point = screen.get_start_and_end()
|
||||
|
||||
def slant_screen(self):
|
||||
|
||||
lower_screen_point, upper_screen_point = self.screen.get_start_and_end()
|
||||
|
||||
lower_slanted_screen_point = interpolate(
|
||||
lower_screen_point, source.source_point, 0.2
|
||||
lower_screen_point, self.spotlight.source_point, 0.2
|
||||
)
|
||||
upper_slanted_screen_point = interpolate(
|
||||
upper_screen_point, source.source_point, -0.2
|
||||
upper_screen_point, self.spotlight.source_point, -0.2
|
||||
)
|
||||
|
||||
slanted_brightness_rect = brightness_rect.copy()
|
||||
slanted_brightness_rect.width *= 2
|
||||
slanted_brightness_rect.generate_points()
|
||||
slanted_brightness_rect.set_fill(opacity = 0.25)
|
||||
self.slanted_brightness_rect = self.brightness_rect.copy()
|
||||
self.slanted_brightness_rect.width *= 2
|
||||
self.slanted_brightness_rect.generate_points()
|
||||
self.slanted_brightness_rect.set_fill(opacity = 0.25)
|
||||
|
||||
slanted_screen = Line(lower_slanted_screen_point,upper_slanted_screen_point,
|
||||
self.slanted_screen = Line(lower_slanted_screen_point,upper_slanted_screen_point,
|
||||
path_arc = 0, num_arc_anchors = 10)
|
||||
slanted_brightness_rect.move_to(brightness_rect.get_center())
|
||||
self.slanted_brightness_rect.move_to(self.brightness_rect.get_center())
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(screen,slanted_screen),
|
||||
ReplacementTransform(brightness_rect,slanted_brightness_rect),
|
||||
ReplacementTransform(self.screen,self.slanted_screen),
|
||||
ReplacementTransform(self.brightness_rect,self.slanted_brightness_rect),
|
||||
)
|
||||
|
||||
|
||||
|
||||
def unslant_screen(self):
|
||||
|
||||
self.wait()
|
||||
|
||||
|
||||
|
||||
screen = slanted_screen
|
||||
source.screen = screen
|
||||
self.remove(slanted_screen)
|
||||
|
||||
brightness_rect = slanted_brightness_rect
|
||||
self.remove(slanted_brightness_rect)
|
||||
self.remove(self.slanted_screen)
|
||||
self.remove(self.slanted_brightness_rect)
|
||||
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(screen,original_screen),
|
||||
ReplacementTransform(brightness_rect,original_brightness_rect),
|
||||
ReplacementTransform(self.screen,self.original_screen),
|
||||
ReplacementTransform(self.slanted_brightness_rect,self.original_brightness_rect),
|
||||
)
|
||||
|
||||
self.remove(original_brightness_rect)
|
||||
|
||||
#self.remove(self.original_brightness_rect)
|
||||
|
||||
|
||||
def left_shift_screen_while_showing_light_indicator(self):
|
||||
|
||||
# Scene 5: constant screen size, changing opening angle
|
||||
|
||||
# let's use an actual light indicator instead of just rects
|
||||
|
||||
indicator_intensity = 0.25
|
||||
indicator_height = 1.25 * screen_height
|
||||
self.indicator_intensity = 0.25
|
||||
indicator_height = 1.25 * self.screen_height
|
||||
|
||||
# indicator_origin = Ellipse(width = 0, height = screen_height).move_to(screen.get_center())
|
||||
# indicator_origin.set_fill(opacity = 0)
|
||||
# self.add_foreground_mobject(indicator_origin)
|
||||
# indicator0 = Ellipse(width = 0, height = screen_height).move_to(self.screen.get_center())
|
||||
# indicator0.set_fill(opacity = 0)
|
||||
# self.add_foreground_mobject(indicator0)
|
||||
|
||||
indicator = LightIndicator(radius = indicator_height/2,
|
||||
self.indicator = LightIndicator(radius = indicator_height/2,
|
||||
opacity_for_unit_intensity = OPACITY_FOR_UNIT_INTENSITY,
|
||||
color = LIGHT_COLOR,
|
||||
precision = 2)
|
||||
indicator.set_intensity(indicator_intensity)
|
||||
self.indicator.set_intensity(self.indicator_intensity)
|
||||
|
||||
indicator.move_to(slanted_brightness_rect.get_center())
|
||||
|
||||
|
||||
self.indicator.move_to(self.original_brightness_rect.get_center())
|
||||
|
||||
|
||||
self.play(
|
||||
FadeOut(slanted_brightness_rect),
|
||||
FadeIn(indicator)
|
||||
FadeOut(self.original_brightness_rect),
|
||||
FadeIn(self.indicator)
|
||||
)
|
||||
|
||||
self.add_foreground_mobject(indicator.reading)
|
||||
self.add_foreground_mobject(self.indicator.reading)
|
||||
|
||||
new_indicator_intensity = 1.0
|
||||
self.unit_indicator_intensity = 1.0
|
||||
|
||||
# shifted_brightness_rect = brightness_rect.copy()
|
||||
# shifted_brightness_rect.shift([-3,0,0]).set_fill(opacity = 0.8)
|
||||
|
||||
left_shift = (screen.get_center()[0] - source.source_point[0])/2
|
||||
self.left_shift = (self.screen.get_center()[0] - self.spotlight.source_point[0])/2
|
||||
|
||||
self.play(
|
||||
ApplyMethod(screen.shift,[-left_shift,0,0]),
|
||||
ApplyMethod(morty.shift,[-left_shift,0,0]),
|
||||
ApplyMethod(indicator.shift,[-left_shift,0,0]),
|
||||
ApplyMethod(indicator.set_intensity,new_indicator_intensity),
|
||||
ApplyMethod(self.screen.shift,[-self.left_shift,0,0]),
|
||||
ApplyMethod(self.morty.shift,[-self.left_shift,0,0]),
|
||||
#ApplyMethod(self.indicator.shift,[-self.left_shift,0,0]),
|
||||
ApplyMethod(self.indicator.set_intensity,self.unit_indicator_intensity),
|
||||
)
|
||||
|
||||
self.remove(original_screen) # was still hiding behind the shadow
|
||||
self.remove(self.original_screen) # was still hiding behind the shadow
|
||||
|
||||
# add distance indicator
|
||||
|
||||
left_x = source.source_point[0]
|
||||
right_x = screen.get_center()[0]
|
||||
line_y = -2
|
||||
line1 = Arrow([left_x,line_y,0],[right_x,line_y,0])
|
||||
line2 = Arrow([right_x,line_y,0],[left_x,line_y,0])
|
||||
line1.set_fill(color = WHITE)
|
||||
line2.set_fill(color = WHITE)
|
||||
distance_decimal = Integer(1).next_to(line1,DOWN)
|
||||
line = VGroup(line1, line2,distance_decimal)
|
||||
self.add(line)
|
||||
|
||||
|
||||
# move everything away
|
||||
distance_to_source = right_x - left_x
|
||||
new_right_x = left_x + 2*distance_to_source
|
||||
new_line1 = Arrow([left_x,line_y,0],[new_right_x,line_y,0])
|
||||
new_line2 = Arrow([new_right_x,line_y,0],[left_x,line_y,0])
|
||||
new_line1.set_fill(color = WHITE)
|
||||
new_line2.set_fill(color = WHITE)
|
||||
new_distance_decimal = Integer(2).next_to(new_line1,DOWN)
|
||||
new_line = VGroup(new_line1, new_line2, new_distance_decimal)
|
||||
def add_distance_arrow(self):
|
||||
|
||||
# distance arrow (length 1)
|
||||
left_x = self.spotlight.source_point[0]
|
||||
right_x = self.screen.get_center()[0]
|
||||
arrow_y = -2
|
||||
arrow1 = Arrow([left_x,arrow_y,0],[right_x,arrow_y,0])
|
||||
arrow2 = Arrow([right_x,arrow_y,0],[left_x,arrow_y,0])
|
||||
arrow1.set_fill(color = WHITE)
|
||||
arrow2.set_fill(color = WHITE)
|
||||
distance_decimal = Integer(1).next_to(arrow1,DOWN)
|
||||
self.arrow = VGroup(arrow1, arrow2,distance_decimal)
|
||||
self.add(self.arrow)
|
||||
|
||||
|
||||
# distance arrow (length 2)
|
||||
# will be morphed into
|
||||
self.distance_to_source = right_x - left_x
|
||||
new_right_x = left_x + 2 * self.distance_to_source
|
||||
new_arrow1 = Arrow([left_x,arrow_y,0],[new_right_x,arrow_y,0])
|
||||
new_arrow2 = Arrow([new_right_x,arrow_y,0],[left_x,arrow_y,0])
|
||||
new_arrow1.set_fill(color = WHITE)
|
||||
new_arrow2.set_fill(color = WHITE)
|
||||
new_distance_decimal = Integer(2).next_to(new_arrow1,DOWN)
|
||||
self.new_arrow = VGroup(new_arrow1, new_arrow2, new_distance_decimal)
|
||||
# don't add it yet
|
||||
|
||||
|
||||
def right_shift_screen_while_showing_light_indicator_and_distance_arrow(self):
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(line,new_line),
|
||||
ApplyMethod(screen.shift,[distance_to_source,0,0]),
|
||||
ApplyMethod(indicator.shift,[left_shift,0,0]),
|
||||
ApplyMethod(indicator.set_intensity,indicator_intensity),
|
||||
ApplyMethod(morty.shift,[distance_to_source,0,0]),
|
||||
ReplacementTransform(self.arrow,self.new_arrow),
|
||||
ApplyMethod(self.screen.shift,[self.distance_to_source,0,0]),
|
||||
#ApplyMethod(self.indicator.shift,[self.left_shift,0,0]),
|
||||
|
||||
ApplyMethod(self.indicator.set_intensity,self.indicator_intensity),
|
||||
# this should trigger ChangingDecimal, but it doesn't
|
||||
# maybe bc it's an anim within an anim?
|
||||
|
||||
ApplyMethod(self.morty.shift,[self.distance_to_source,0,0]),
|
||||
)
|
||||
|
||||
|
||||
|
||||
def left_shift_again(self):
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(self.new_arrow,self.arrow),
|
||||
ApplyMethod(self.screen.shift,[-self.distance_to_source,0,0]),
|
||||
#ApplyMethod(self.indicator.shift,[-self.left_shift,0,0]),
|
||||
ApplyMethod(self.indicator.set_intensity,self.unit_indicator_intensity),
|
||||
ApplyMethod(self.morty.shift,[-self.distance_to_source,0,0]),
|
||||
)
|
||||
|
||||
def morph_into_faux_3d(self):
|
||||
|
||||
p0_lower, p0_upper = self.screen.get_start_and_end()
|
||||
|
||||
p01 = p0_lower
|
||||
p02 = p0_lower
|
||||
p03 = p0_upper
|
||||
p04 = p0_upper
|
||||
|
||||
screen3d0 = Polygon(p01,p02,p03,p04)
|
||||
screen3d0.set_stroke(width = 1, color = WHITE)
|
||||
|
||||
screen3d0_edge = VMobject()
|
||||
screen3d0_edge.set_anchor_points([p03,p04,p01])
|
||||
|
||||
perspective_v = 0.5 * np.array([1,-1,0])
|
||||
p1 = p01 + 0.5 * perspective_v
|
||||
p2 = p02 - 0.5 * perspective_v
|
||||
p3 = p03 - 0.5 * perspective_v
|
||||
p4 = p04 + 0.5 * perspective_v
|
||||
|
||||
screen3d = Polygon(p1,p2,p3,p4)
|
||||
screen3d.set_fill(color = WHITE, opacity = 0.5)
|
||||
|
||||
screen3d_edge = VMobject()
|
||||
screen3d_edge.set_anchor_points([p3,p4,p1])
|
||||
|
||||
self.spotlight.screen = screen3d0_edge
|
||||
|
||||
self.play(Transform(self.spotlight.screen,screen3d_edge))
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue