Merge pull request #261 from 3b1b/dandelin

Dandelin
This commit is contained in:
Grant Sanderson 2018-07-31 19:40:47 -07:00 committed by GitHub
commit 47f16986d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 2042 additions and 10 deletions

1833
active_projects/dandelin.py Normal file

File diff suppressed because it is too large Load diff

View file

@ -158,6 +158,12 @@ class FadeInAndShiftFromDirection(Transform):
Transform.__init__(self, mobject, target, **kwargs)
class FadeInFrom(FadeInAndShiftFromDirection):
"""
Alternate name for FadeInAndShiftFromDirection
"""
class FadeInFromDown(FadeInAndShiftFromDirection):
"""
Essential a more convenient form of FadeInAndShiftFromDirection

View file

@ -35,18 +35,19 @@ with open("media_dir.txt", 'w') as media_file:
media_file.write(MEDIA_DIR)
#
DEFAULT_PIXEL_HEIGHT = 1080
DEFAULT_PIXEL_WIDTH = 1920
LOW_QUALITY_FRAME_DURATION = 1. / 15
MEDIUM_QUALITY_FRAME_DURATION = 1. / 30
PRODUCTION_QUALITY_FRAME_DURATION = 1. / 60
# There might be other configuration than pixel shape later...
PRODUCTION_QUALITY_CAMERA_CONFIG = {
"pixel_height": DEFAULT_PIXEL_HEIGHT,
"pixel_width": DEFAULT_PIXEL_WIDTH,
"pixel_height": 1440,
"pixel_width": 2560,
}
HIGH_QUALITY_CAMERA_CONFIG = {
"pixel_height": 1080,
"pixel_width": 1920,
}
MEDIUM_QUALITY_CAMERA_CONFIG = {
@ -59,6 +60,9 @@ LOW_QUALITY_CAMERA_CONFIG = {
"pixel_width": 854,
}
DEFAULT_PIXEL_HEIGHT = PRODUCTION_QUALITY_CAMERA_CONFIG["pixel_height"]
DEFAULT_PIXEL_WIDTH = PRODUCTION_QUALITY_CAMERA_CONFIG["pixel_width"]
DEFAULT_POINT_DENSITY_2D = 25
DEFAULT_POINT_DENSITY_1D = 250

View file

@ -14,13 +14,16 @@ from animation.creation import FadeOut
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from scene.scene import Scene
from scene.moving_camera_scene import MovingCameraScene
from for_3b1b_videos.pi_creature_animations import Blink
from for_3b1b_videos.pi_creature import Mortimer
from for_3b1b_videos.pi_creature import Randolph
from mobject.geometry import Line
from mobject.geometry import DashedLine
from mobject.geometry import Rectangle
from mobject.geometry import Square
from mobject.svg.drawings import PatreonLogo
from mobject.svg.drawings import Logo
class OpeningQuote(Scene):
@ -189,14 +192,23 @@ class PatreonEndScreen(PatreonThanks):
fill_opacity=1,
stroke_width=0,
width=FRAME_WIDTH,
height=1.1 * FRAME_Y_RADIUS
height=0.6 * FRAME_HEIGHT,
)
black_rect.to_edge(UP, buff=0)
line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT)
line.move_to(black_rect, DOWN)
line.shift(SMALL_BUFF * SMALL_BUFF * DOWN)
line.move_to(ORIGIN)
self.add(line)
thanks = TextMobject("Funded by the community, with special thanks to:")
thanks.scale(0.9)
thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF)
thanks.set_color(YELLOW)
underline = Line(LEFT, RIGHT)
underline.scale_to_fit_width(thanks.get_width() + MED_SMALL_BUFF)
underline.next_to(thanks, DOWN, SMALL_BUFF)
thanks.add(underline)
self.add(thanks)
patrons = VGroup(*map(TextMobject, self.specific_patrons))
patrons.scale(self.patron_scale_val)
for patron in patrons:
@ -217,15 +229,43 @@ class PatreonEndScreen(PatreonThanks):
columns.next_to(black_rect, DOWN, 3 * LARGE_BUFF)
columns.to_edge(RIGHT)
thanks.align_to(columns, alignment_vect=RIGHT)
self.play(
columns.move_to, 2 * DOWN, DOWN,
columns.to_edge, RIGHT,
Animation(black_rect),
Animation(line),
Animation(thanks),
rate_func=None,
run_time=self.run_time,
)
class LogoGenerationTemplate(MovingCameraScene):
def setup(self):
frame = self.camera_frame
frame.shift(DOWN)
self.logo = Logo()
name = TextMobject("3Blue1Brown")
name.scale(2.5)
name.next_to(logo, DOWN, buff=MED_LARGE_BUFF)
self.name = name
def construct(self):
logo = self.logo
name = self.name
self.play(
Write(name, run_time=3, lag_factor=2.5),
*self.get_logo_animations(logo)
)
self.wait()
def get_logo_animations(self, logo):
return [] # For subclasses
class ExternallyAnimatedScene(Scene):
def construct(self):
raise Exception("Don't actually run this class.")

View file

@ -1,4 +1,5 @@
from __future__ import absolute_import
import itertools as it
from constants import *
@ -19,11 +20,13 @@ from mobject.geometry import Line
from mobject.geometry import Polygon
from mobject.geometry import Rectangle
from mobject.geometry import Square
from mobject.geometry import AnnularSector
from mobject.three_dimensions import Cube
from utils.config_ops import digest_config
from utils.space_ops import angle_of_vector
from utils.space_ops import complex_to_R3
from utils.space_ops import rotate_vector
from utils.bezier import interpolate
class Lightbulb(SVGMobject):
@ -630,7 +633,151 @@ class VectorizedEarth(SVGMobject):
self.add_to_back(circle)
### Cards ###
class Logo(VMobject):
CONFIG = {
"pupil_radius": 1.0,
"outer_radius": 2.0,
"iris_background_blue": "#74C0E3",
"iris_background_brown": "#8C6239",
"blue_spike_colors": [
"#528EA3",
"#3E6576",
"#224C5B",
BLACK,
],
"brown_spike_colors": [
"#754C24",
"#603813",
"#42210b",
BLACK,
],
"n_spike_layers": 4,
"n_spikes": 28,
"spike_angle": TAU / 28,
}
def __init__(self, **kwargs):
VMobject.__init__(self, **kwargs)
self.add_iris_back()
self.add_spikes()
self.add_pupil()
def add_iris_back(self):
blue_iris_back = AnnularSector(
inner_radius=self.pupil_radius,
outer_radius=self.outer_radius,
angle=270 * DEGREES,
start_angle=180 * DEGREES,
fill_color=self.iris_background_blue,
fill_opacity=1,
stroke_width=0,
)
brown_iris_back = AnnularSector(
inner_radius=self.pupil_radius,
outer_radius=self.outer_radius,
angle=90 * DEGREES,
start_angle=90 * DEGREES,
fill_color=self.iris_background_brown,
fill_opacity=1,
stroke_width=0,
)
self.iris_background = VGroup(
blue_iris_back,
brown_iris_back,
)
self.add(self.iris_background)
def add_spikes(self):
layers = VGroup()
radii = np.linspace(
self.outer_radius,
self.pupil_radius,
self.n_spike_layers,
endpoint=False,
)
radii[:2] = radii[1::-1] # Swap first two
radii[-1] = interpolate(
radii[-1], self.pupil_radius, 0.25
)
for radius in radii:
tip_angle = self.spike_angle
half_base = radius * np.tan(tip_angle)
triangle, right_half_triangle = [
Polygon(
radius * UP,
half_base * RIGHT,
vertex3,
fill_opacity=1,
stroke_width=0,
)
for vertex3 in half_base * LEFT, ORIGIN,
]
left_half_triangle = right_half_triangle.copy()
left_half_triangle.flip(UP, about_point=ORIGIN)
n_spikes = self.n_spikes
full_spikes = [
triangle.copy().rotate(
-angle,
about_point=ORIGIN
)
for angle in np.linspace(
0, TAU, n_spikes, endpoint=False
)
]
index = 3 * n_spikes / 4
if radius == radii[0]:
layer = VGroup(*full_spikes)
layer.rotate(
-TAU / n_spikes / 2,
about_point=ORIGIN
)
layer.brown_index = index
else:
half_spikes = [
right_half_triangle.copy(),
left_half_triangle.copy().rotate(
90 * DEGREES, about_point=ORIGIN,
),
right_half_triangle.copy().rotate(
90 * DEGREES, about_point=ORIGIN,
),
left_half_triangle.copy()
]
layer = VGroup(*it.chain(
half_spikes[:1],
full_spikes[1:index],
half_spikes[1:3],
full_spikes[index + 1:],
half_spikes[3:],
))
layer.brown_index = index + 1
layers.add(layer)
# Color spikes
blues = self.blue_spike_colors
browns = self.brown_spike_colors
for layer, blue, brown in zip(layers, blues, browns):
index = layer.brown_index
layer[:index].set_color(blue)
layer[index:].set_color(brown)
self.spike_layers = layers
self.add(layers)
def add_pupil(self):
self.pupil = Circle(
radius=self.pupil_radius,
fill_color=BLACK,
fill_opacity=1,
stroke_width=0,
)
self.add(self.pupil)
# Cards
class DeckOfCards(VGroup):

View file

@ -11,6 +11,7 @@
\usepackage{mathrsfs}
\usepackage{calligra}
\usepackage{wasysym}
\usepackage{textcomp}
%\usepackage[UTF8]{ctex}
\begin{document}

View file

@ -15,6 +15,7 @@
\usepackage{ragged2e}
\usepackage{physics}
\usepackage{xcolor}
\usepackage{textcomp}
%\usepackage[UTF8]{ctex}
\linespread{1}