mirror of
https://github.com/3b1b/manim.git
synced 2025-08-19 13:01:00 +00:00
commit
47f16986d7
7 changed files with 2042 additions and 10 deletions
1833
active_projects/dandelin.py
Normal file
1833
active_projects/dandelin.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
16
constants.py
16
constants.py
|
@ -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
|
||||
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
\usepackage{mathrsfs}
|
||||
\usepackage{calligra}
|
||||
\usepackage{wasysym}
|
||||
\usepackage{textcomp}
|
||||
%\usepackage[UTF8]{ctex}
|
||||
|
||||
\begin{document}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
\usepackage{ragged2e}
|
||||
\usepackage{physics}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{textcomp}
|
||||
%\usepackage[UTF8]{ctex}
|
||||
\linespread{1}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue