mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
Merge pull request #1320 from TonyCrane/shaders
Add documentation for shaders version
This commit is contained in:
commit
696e952a3a
46 changed files with 2172 additions and 4 deletions
36
.github/workflows/docs.yml
vendored
Normal file
36
.github/workflows/docs.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
name: docs
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
name: build up document and deploy
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Install sphinx and manim env
|
||||
run: |
|
||||
pip3 install --upgrade pip
|
||||
sudo apt install python3-setuptools
|
||||
pip3 install -r docs/requirements.txt
|
||||
pip3 install -r requirements.txt
|
||||
|
||||
- name: Build document with Sphinx
|
||||
run: |
|
||||
cd docs
|
||||
export PATH="$PATH:/home/runner/.local/bin"
|
||||
export SPHINXBUILD="python3 -m sphinx"
|
||||
make html
|
||||
|
||||
- name: Deploy to GitHub pages
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
with:
|
||||
ACCESS_TOKEN: ${{ secrets.DOC_DEPLOY_TOKEN }}
|
||||
BRANCH: gh-pages
|
||||
FOLDER: docs/build/html
|
29
.github/workflows/docs_test.yml
vendored
Normal file
29
.github/workflows/docs_test.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
name: docs_test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
docs_test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test document for pull requests
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Install sphinx and manim env
|
||||
run: |
|
||||
pip3 install --upgrade pip
|
||||
sudo apt install python3-setuptools
|
||||
pip3 install -r docs/requirements.txt
|
||||
pip3 install -r requirements.txt
|
||||
|
||||
- name: Build document with Sphinx
|
||||
run: |
|
||||
cd docs
|
||||
export PATH="$PATH:/home/runner/.local/bin"
|
||||
export SPHINXBUILD="python3 -m sphinx"
|
||||
make html
|
|
@ -3,6 +3,7 @@
|
|||
[](http://choosealicense.com/licenses/mit/)
|
||||
[](https://www.reddit.com/r/manim/)
|
||||
[](https://discord.gg/mMRrZQW)
|
||||
[](https://3b1b.github.io/manim/)
|
||||
|
||||
Manim is an animation engine for explanatory math videos. It's used to create precise animations programmatically, as seen in the videos at [3Blue1Brown](https://www.3blue1brown.com/).
|
||||
|
||||
|
@ -11,7 +12,8 @@ This repository contains the version of manim used by 3Blue1Brown. There is als
|
|||
## Installation
|
||||
Manim runs on Python 3.8.
|
||||
|
||||
System requirements are [FFmpeg](https://ffmpeg.org/), [OpenGL](https://www.opengl.org//) and [latex](https://www.latex-project.org) (optional, if you want to use LaTeX).
|
||||
System requirements are [FFmpeg](https://ffmpeg.org/), [OpenGL](https://www.opengl.org//), [LaTeX](https://www.latex-project.org) (optional, if you want to use LaTeX)
|
||||
and [cairo](https://www.cairographics.org/) (optional, if you want to use Text).
|
||||
|
||||
For more options, take a look at the [Using manim](#using-manim) sections further below.
|
||||
|
||||
|
@ -24,7 +26,7 @@ If you want to hack on manimlib itself, clone this repository and in that direct
|
|||
pip install -r requirements.txt
|
||||
|
||||
# Try it out
|
||||
python -m manim example_scenes.py OpeningManimExample
|
||||
python manim.py example_scenes.py OpeningManimExample
|
||||
```
|
||||
|
||||
### Directly (Windows)
|
||||
|
@ -74,7 +76,7 @@ Take a look at custom_defaults.yml for further configuration. To add your custo
|
|||
Look through [https://github.com/3b1b/videos](https://github.com/3b1b/videos) to see the code for previous 3b1b videos. Note, however, that developments are often made to the library without considering backwards compatibility with those old projects. To run an old project with a guarantee that it will work, you will have to go back to the commit which completed that project.
|
||||
|
||||
### Documentation
|
||||
Documentation is in progress at [eulertour.com/docs](https://www.eulertour.com/docs/). And there is also an all-in-one documentation and tutorials maintained by **@manim-kindergarten**: [manim.ml](https://manim.ml/) (in Chinese).
|
||||
Documentation is in progress at [3b1b.github.io/manim](https://3b1b.github.io/manim/). And there is also a Chinese version maintained by **@manim-kindergarten**: [manim.ml](https://manim.ml/) (in Chinese).
|
||||
|
||||
### Walkthrough
|
||||
Todd Zimmerman put together a [tutorial](https://talkingphysics.wordpress.com/2019/01/08/getting-started-animating-with-manim-and-python-3-7/) on getting started with manim, which has been updated to run on Python 3.7.
|
||||
|
|
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
37
docs/example.py
Normal file
37
docs/example.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from manimlib.imports import *
|
||||
|
||||
class SquareToCircle(Scene):
|
||||
def construct(self):
|
||||
circle = Circle()
|
||||
circle.set_fill(BLUE, opacity=0.5)
|
||||
circle.set_stroke(BLUE_E, width=4)
|
||||
square = Square()
|
||||
|
||||
self.play(ShowCreation(square))
|
||||
self.wait()
|
||||
self.play(ReplacementTransform(square, circle))
|
||||
self.wait()
|
||||
# Try typing the following lines
|
||||
# self.play(circle.stretch, 4, {"dim": 0})
|
||||
# self.play(Rotate(circle, TAU / 4))
|
||||
# self.play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
||||
# circle.insert_n_curves(10)
|
||||
# self.play(circle.apply_complex_function, lambda z: z**2)
|
||||
|
||||
class SquareToCircleEmbed(Scene):
|
||||
def construct(self):
|
||||
circle = Circle()
|
||||
circle.set_fill(BLUE, opacity=0.5)
|
||||
circle.set_stroke(BLUE_E, width=4)
|
||||
|
||||
self.add(circle)
|
||||
self.wait()
|
||||
self.play(circle.stretch, 4, {"dim": 0})
|
||||
self.wait(1.5)
|
||||
self.play(Rotate(circle, TAU / 4))
|
||||
self.wait(1.5)
|
||||
self.play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
||||
self.wait(1.5)
|
||||
circle.insert_n_curves(10)
|
||||
self.play(circle.apply_complex_function, lambda z: z**2)
|
||||
self.wait(2)
|
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
|
@ -0,0 +1,35 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
4
docs/requirements.txt
Normal file
4
docs/requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
sphinx>=1.8
|
||||
sphinx-copybutton
|
||||
furo==2020.10.5b9
|
||||
jinja2
|
293
docs/source/_static/colors.css
Normal file
293
docs/source/_static/colors.css
Normal file
|
@ -0,0 +1,293 @@
|
|||
p.color-text {
|
||||
font-size: inherit;
|
||||
font-family: var(--font-stack--monospace);
|
||||
margin-top: 25px;
|
||||
color: WHITE;
|
||||
}
|
||||
|
||||
p.color-text-small {
|
||||
font-size: small;
|
||||
font-family: var(--font-stack--monospace);
|
||||
margin-top: 28px;
|
||||
color: WHITE;
|
||||
}
|
||||
|
||||
.colors {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
border: 10px;
|
||||
margin: 0;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.BLUE_A {
|
||||
background: #C7E9F1;
|
||||
color:#C7E9F1;
|
||||
}
|
||||
|
||||
.BLUE_B {
|
||||
background: #9CDCEB;
|
||||
color:#9CDCEB;
|
||||
}
|
||||
|
||||
.BLUE_C {
|
||||
background: #58C4DD;
|
||||
color:#58C4DD;
|
||||
}
|
||||
|
||||
.BLUE_D {
|
||||
background: #29ABCA;
|
||||
color:#29ABCA;
|
||||
}
|
||||
|
||||
.BLUE_E {
|
||||
background: #1C758A;
|
||||
color:#1C758A;
|
||||
}
|
||||
|
||||
.TEAL_A {
|
||||
background: #ACEAD7;
|
||||
color:#ACEAD7 ;
|
||||
}
|
||||
|
||||
.TEAL_B {
|
||||
background: #76DDC0;
|
||||
color: #76DDC0;
|
||||
}
|
||||
|
||||
.TEAL_C {
|
||||
background: #5CD0B3;
|
||||
color: #5CD0B3;
|
||||
}
|
||||
|
||||
.TEAL_D {
|
||||
background: #55C1A7;
|
||||
color: #55C1A7;
|
||||
}
|
||||
|
||||
.TEAL_E {
|
||||
background: #49A88F;
|
||||
color: #49A88F;
|
||||
}
|
||||
|
||||
.GREEN_A {
|
||||
background: #C9E2AE;
|
||||
color: #C9E2AE;
|
||||
}
|
||||
|
||||
.GREEN_B {
|
||||
background: #A6CF8C;
|
||||
color: #A6CF8C;
|
||||
}
|
||||
|
||||
.GREEN_C {
|
||||
background: #83C167;
|
||||
color: #83C167;
|
||||
}
|
||||
|
||||
.GREEN_D {
|
||||
background: #77B05D;
|
||||
color: #77B05D;
|
||||
}
|
||||
|
||||
.GREEN_E {
|
||||
background: #699C52;
|
||||
color: #699C52;
|
||||
}
|
||||
|
||||
.YELLOW_A {
|
||||
background: #FFF1B6;
|
||||
color: #FFF1B6;
|
||||
}
|
||||
|
||||
.YELLOW_B {
|
||||
background: #FFEA94;
|
||||
color:#FFEA94 ;
|
||||
}
|
||||
|
||||
.YELLOW_C {
|
||||
background: #FFFF00;
|
||||
color: #FFFF00;
|
||||
}
|
||||
|
||||
.YELLOW_D {
|
||||
background: #F4D345;
|
||||
color: #F4D345;
|
||||
}
|
||||
|
||||
.YELLOW_E {
|
||||
background: #E8C11C;
|
||||
color: #E8C11C;
|
||||
}
|
||||
|
||||
.GOLD_A {
|
||||
background: #F7C797;
|
||||
color:#F7C797;
|
||||
}
|
||||
|
||||
.GOLD_B {
|
||||
background: #F9B775;
|
||||
color:#F9B775;
|
||||
}
|
||||
|
||||
.GOLD_C {
|
||||
background: #F0AC5F;
|
||||
color:#F0AC5F;
|
||||
}
|
||||
|
||||
.GOLD_D {
|
||||
background: #E1A158;
|
||||
color:#E1A158;
|
||||
}
|
||||
|
||||
.GOLD_E {
|
||||
background: #C78D46;
|
||||
color:#C78D46;
|
||||
}
|
||||
|
||||
.RED_A {
|
||||
background: #F7A1A3;
|
||||
color:#F7A1A3;
|
||||
}
|
||||
|
||||
.RED_B {
|
||||
background: #FF8080;
|
||||
color:#FF8080;
|
||||
}
|
||||
|
||||
.RED_C {
|
||||
background: #FC6255;
|
||||
color:#FC6255;
|
||||
}
|
||||
|
||||
.RED_D {
|
||||
background: #E65A4C;
|
||||
color:#E65A4C;
|
||||
}
|
||||
|
||||
.RED_E {
|
||||
background: #CF5044;
|
||||
color:#CF5044;
|
||||
}
|
||||
|
||||
.MAROON_A {
|
||||
background: #ECABC1;
|
||||
color: #ECABC1;
|
||||
}
|
||||
|
||||
.MAROON_B {
|
||||
background: #EC92AB;
|
||||
color: #EC92AB;
|
||||
}
|
||||
|
||||
.MAROON_C {
|
||||
background: #C55F73;
|
||||
color: #C55F73;
|
||||
}
|
||||
|
||||
.MAROON_D {
|
||||
background: #A24D61;
|
||||
color: #A24D61;
|
||||
}
|
||||
|
||||
.MAROON_E {
|
||||
background: #94424F;
|
||||
color: #94424F;
|
||||
}
|
||||
|
||||
.PURPLE_A {
|
||||
background: #CAA3E8;
|
||||
color: #CAA3E8;
|
||||
}
|
||||
|
||||
.PURPLE_B {
|
||||
background: #B189C6;
|
||||
color: #B189C6;
|
||||
}
|
||||
|
||||
.PURPLE_C {
|
||||
background: #9A72AC;
|
||||
color: #9A72AC;
|
||||
}
|
||||
|
||||
.PURPLE_D {
|
||||
background: #715582;
|
||||
color: #715582;
|
||||
}
|
||||
|
||||
.PURPLE_E {
|
||||
background: #644172;
|
||||
color: #644172;
|
||||
}
|
||||
|
||||
.GREY_A {
|
||||
background: #DDDDDD;
|
||||
color: #DDDDDD;
|
||||
}
|
||||
|
||||
.GREY_B {
|
||||
background: #BBBBBB;
|
||||
color: #BBBBBB;
|
||||
}
|
||||
|
||||
.GREY_C {
|
||||
background: #888888;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.GREY_D {
|
||||
background: #444444;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
.GREY_E {
|
||||
background: #222222;
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
.WHITE {
|
||||
background: #FFFFFF;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.BLACK {
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.GREY_BROWN {
|
||||
background: #736357;
|
||||
color: #736357;
|
||||
}
|
||||
|
||||
.DARK_BROWN {
|
||||
background: #8B4513;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
.LIGHT_BROWN {
|
||||
background: #CD853F;
|
||||
color: #CD853F;
|
||||
}
|
||||
|
||||
.PINK {
|
||||
background: #D147BD;
|
||||
color: #D147BD;
|
||||
}
|
||||
|
||||
.LIGHT_PINK {
|
||||
background: #DC75CD;
|
||||
color: #DC75CD;
|
||||
}
|
||||
|
||||
.GREEN_SCREEN {
|
||||
background: #00FF00;
|
||||
color: #00FF00;
|
||||
}
|
||||
|
||||
.ORANGE {
|
||||
background: #FF862F;
|
||||
color: #FF862F;
|
||||
}
|
62
docs/source/_static/custom.css
Normal file
62
docs/source/_static/custom.css
Normal file
|
@ -0,0 +1,62 @@
|
|||
p {
|
||||
font-size: initial;
|
||||
}
|
||||
|
||||
span.caption-text {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
font-size: initial;
|
||||
}
|
||||
|
||||
.highlight-python.notranslate {
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
.manim-video {
|
||||
width: 99.9%;
|
||||
padding: 8px 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.manim-example {
|
||||
background-color: #333333;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 2px 2px 4px #ddd;
|
||||
}
|
||||
|
||||
.manim-example .manim-video {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.manim-example img {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h5.example-header {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding: 8px 16px;
|
||||
color: white;
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
text-transform: none;
|
||||
margin-top: -0.4em;
|
||||
margin-bottom: -0.2em;
|
||||
}
|
||||
|
||||
.manim-example .highlight {
|
||||
background-color: #fafafa;
|
||||
border: 2px solid #333333;
|
||||
padding: 8px 8px 10px 8px;
|
||||
font-size: large;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.manim-example .highlight pre {
|
||||
background-color: inherit;
|
||||
border-left: none;
|
||||
margin: 0;
|
||||
padding: 0 6px 0 6px;
|
||||
}
|
BIN
docs/source/_static/example_scenes/OpeningManimExample.mp4
Normal file
BIN
docs/source/_static/example_scenes/OpeningManimExample.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/example_scenes/SquareToCircle.mp4
Normal file
BIN
docs/source/_static/example_scenes/SquareToCircle.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/example_scenes/SurfaceExample.mp4
Normal file
BIN
docs/source/_static/example_scenes/SurfaceExample.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/example_scenes/TexTransformExample.mp4
Normal file
BIN
docs/source/_static/example_scenes/TexTransformExample.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/example_scenes/TextExample.mp4
Normal file
BIN
docs/source/_static/example_scenes/TextExample.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/example_scenes/UpdatersExample.mp4
Normal file
BIN
docs/source/_static/example_scenes/UpdatersExample.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/example_scenes/WarpSquare.mp4
Normal file
BIN
docs/source/_static/example_scenes/WarpSquare.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/icon.png
Normal file
BIN
docs/source/_static/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
docs/source/_static/manim_shaders_process_en.png
Normal file
BIN
docs/source/_static/manim_shaders_process_en.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 603 KiB |
BIN
docs/source/_static/manim_shaders_structure.png
Normal file
BIN
docs/source/_static/manim_shaders_structure.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/source/_static/quickstart/SquareToCircle.mp4
Normal file
BIN
docs/source/_static/quickstart/SquareToCircle.mp4
Normal file
Binary file not shown.
BIN
docs/source/_static/quickstart/SquareToCircle.png
Normal file
BIN
docs/source/_static/quickstart/SquareToCircle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
docs/source/_static/quickstart/SquareToCircleEmbed.mp4
Normal file
BIN
docs/source/_static/quickstart/SquareToCircleEmbed.mp4
Normal file
Binary file not shown.
40
docs/source/conf.py
Normal file
40
docs/source/conf.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath("."))
|
||||
sys.path.insert(0, os.path.abspath('../../'))
|
||||
|
||||
|
||||
project = 'manim'
|
||||
copyright = '- This document has been placed in the public domain.'
|
||||
author = 'TonyCrane'
|
||||
|
||||
release = ''
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.githubpages',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx_copybutton',
|
||||
'manim_example_ext'
|
||||
]
|
||||
|
||||
autoclass_content = 'both'
|
||||
mathjax_path = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
|
||||
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
pygments_style = 'default'
|
||||
|
||||
html_static_path = ["_static"]
|
||||
html_css_files = ["custom.css", "colors.css"]
|
||||
html_theme = 'furo' # pip install furo==2020.10.5b9
|
||||
html_favicon = '_static/icon.png'
|
||||
html_logo = '../../logo/transparent_graph.png'
|
||||
html_theme_options = {
|
||||
"sidebar_hide_name": True,
|
||||
}
|
31
docs/source/development/about.rst
Normal file
31
docs/source/development/about.rst
Normal file
|
@ -0,0 +1,31 @@
|
|||
About
|
||||
=====
|
||||
|
||||
About Manim
|
||||
-----------
|
||||
|
||||
Manim is an animation engine for explanatory math videos.
|
||||
You can use it to make math videos (or other fields) like 3Blue1Brown.
|
||||
|
||||
There are mainly two versions here:
|
||||
|
||||
- `3b1b/manim <https://github.com/3b1b/manim>`_ : Maintained by Grant Sanderson of 3Blue1Brown.
|
||||
|
||||
Using OpenGL and its GLSL language to use GPU for rendering. It has higher efficiency,
|
||||
faster rendering speed, and supports real-time rendering and interaction.
|
||||
|
||||
- `ManimCommunity/manim <https://github.com/ManimCommunity/manim>`_ : Maintained by Manim Community Dev Team.
|
||||
|
||||
Using cairo to use CPU for rendering. There is better documentation and
|
||||
a more open contribution community.
|
||||
|
||||
About this documentation
|
||||
------------------------
|
||||
|
||||
This documentation is based on the version in `3b1b/manim <https://github.com/3b1b/manim>`_.
|
||||
Created by `TonyCrane <https://github.com/TonyCrane>`_ ("鹤翔万里" in Chinese) and in production.
|
||||
|
||||
Among them, the ``manim_example_ext`` extension for Sphinx refers to
|
||||
`the documentation of ManimCommunity <https://docs.manim.community/>`_.
|
||||
|
||||
If you want to contribute to manim or this document, please see: :doc:`contributing`
|
4
docs/source/development/changelog.rst
Normal file
4
docs/source/development/changelog.rst
Normal file
|
@ -0,0 +1,4 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
No changes now.
|
59
docs/source/development/contributing.rst
Normal file
59
docs/source/development/contributing.rst
Normal file
|
@ -0,0 +1,59 @@
|
|||
Contributing
|
||||
============
|
||||
|
||||
Accept any contribution you make :)
|
||||
|
||||
- **Contribute to the manim source code**:
|
||||
|
||||
Please fork to your own repository and make changes, submit a pull request, and fill in
|
||||
the motivation for the change following the instructions in the template. We will check
|
||||
your pull request in detail (this usually takes a while, please be patient)
|
||||
|
||||
- **Contribute to the documentation**:
|
||||
|
||||
Also submit a pull request and write down the main changes.
|
||||
|
||||
- **If you find a bug in the code**:
|
||||
|
||||
Please open an issue and fill in the found problem and your environment according
|
||||
to the template. (But please note that if you think this problem is just a problem
|
||||
of yourself, rather than a problem of source code, it is recommended that you ask a
|
||||
question in the `Q&A category <https://github.com/3b1b/manim/discussions/categories/q-a>`_
|
||||
of the discussion page)
|
||||
|
||||
- **You are welcome to share the content you made with manim**:
|
||||
|
||||
Post it in the `show and tell category <https://github.com/3b1b/manim/discussions/categories/show-and-tell>`_
|
||||
of the discussion page.
|
||||
|
||||
- **You are also welcome to share some of your suggestions and ideas**:
|
||||
|
||||
Post them in the `ideas category <https://github.com/3b1b/manim/discussions/categories/ideas>`_
|
||||
of the discussion page.
|
||||
|
||||
How to build this documentation
|
||||
-------------------------------
|
||||
|
||||
- Clone the 3b1b/manim repository
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
git clone https://github.com/3b1b/manim.git
|
||||
# or your own repo
|
||||
# git clone https://github.com/<your user name>/manim.git
|
||||
cd manim
|
||||
|
||||
- Install python package dependencies
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
pip install -r docs/requirements.txt
|
||||
|
||||
- Go to the ``docs/`` folder and build
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cd docs/
|
||||
make html
|
||||
|
||||
- The output document is located in ``docs/build/html/``
|
2
docs/source/documentation/animation/index.rst
Normal file
2
docs/source/documentation/animation/index.rst
Normal file
|
@ -0,0 +1,2 @@
|
|||
Animation (TODO)
|
||||
================
|
2
docs/source/documentation/camera/index.rst
Normal file
2
docs/source/documentation/camera/index.rst
Normal file
|
@ -0,0 +1,2 @@
|
|||
Camera (TODO)
|
||||
=============
|
172
docs/source/documentation/constants.rst
Normal file
172
docs/source/documentation/constants.rst
Normal file
|
@ -0,0 +1,172 @@
|
|||
constants
|
||||
=========
|
||||
|
||||
The ``constants.py`` in the ``manimlib`` folder defines the constants
|
||||
needed when running manim. Some constants are not explained here because
|
||||
they are only used inside manim.
|
||||
|
||||
Frame and pixel shape
|
||||
---------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
ASPECT_RATIO = 16.0 / 9.0
|
||||
FRAME_HEIGHT = 8.0
|
||||
FRAME_WIDTH = FRAME_HEIGHT * ASPECT_RATIO
|
||||
FRAME_Y_RADIUS = FRAME_HEIGHT / 2
|
||||
FRAME_X_RADIUS = FRAME_WIDTH / 2
|
||||
|
||||
DEFAULT_PIXEL_HEIGHT = 1080
|
||||
DEFAULT_PIXEL_WIDTH = 1920
|
||||
DEFAULT_FRAME_RATE = 30
|
||||
|
||||
Buffs
|
||||
-----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
SMALL_BUFF = 0.1
|
||||
MED_SMALL_BUFF = 0.25
|
||||
MED_LARGE_BUFF = 0.5
|
||||
LARGE_BUFF = 1
|
||||
|
||||
DEFAULT_MOBJECT_TO_EDGE_BUFFER = MED_LARGE_BUFF # Distance between object and edge
|
||||
DEFAULT_MOBJECT_TO_MOBJECT_BUFFER = MED_SMALL_BUFF # Distance between objects
|
||||
|
||||
Run times
|
||||
---------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
DEFAULT_POINTWISE_FUNCTION_RUN_TIME = 3.0
|
||||
DEFAULT_WAIT_TIME = 1.0
|
||||
|
||||
Coordinates
|
||||
-----------
|
||||
|
||||
manim uses three-dimensional coordinates and uses the type of ``ndarray``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
ORIGIN = np.array((0., 0., 0.))
|
||||
UP = np.array((0., 1., 0.))
|
||||
DOWN = np.array((0., -1., 0.))
|
||||
RIGHT = np.array((1., 0., 0.))
|
||||
LEFT = np.array((-1., 0., 0.))
|
||||
IN = np.array((0., 0., -1.))
|
||||
OUT = np.array((0., 0., 1.))
|
||||
X_AXIS = np.array((1., 0., 0.))
|
||||
Y_AXIS = np.array((0., 1., 0.))
|
||||
Z_AXIS = np.array((0., 0., 1.))
|
||||
|
||||
# Useful abbreviations for diagonals
|
||||
UL = UP + LEFT
|
||||
UR = UP + RIGHT
|
||||
DL = DOWN + LEFT
|
||||
DR = DOWN + RIGHT
|
||||
|
||||
TOP = FRAME_Y_RADIUS * UP
|
||||
BOTTOM = FRAME_Y_RADIUS * DOWN
|
||||
LEFT_SIDE = FRAME_X_RADIUS * LEFT
|
||||
RIGHT_SIDE = FRAME_X_RADIUS * RIGHT
|
||||
|
||||
Mathematical constant
|
||||
---------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
PI = np.pi
|
||||
TAU = 2 * PI
|
||||
DEGREES = TAU / 360
|
||||
|
||||
Text
|
||||
----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
START_X = 30
|
||||
START_Y = 20
|
||||
NORMAL = "NORMAL"
|
||||
ITALIC = "ITALIC"
|
||||
OBLIQUE = "OBLIQUE"
|
||||
BOLD = "BOLD"
|
||||
|
||||
Stroke width
|
||||
------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
DEFAULT_STROKE_WIDTH = 4
|
||||
|
||||
Colours
|
||||
-------
|
||||
|
||||
Here are the preview of default colours. (Modified from
|
||||
`elteoremadebeethoven <https://elteoremadebeethoven.github.io/manim_3feb_docs.github.io/html/_static/colors/colors.html>`_)
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<h3>BLUE</h3>
|
||||
<div class="colors BLUE_E"><p class="color-text">BLUE_E</p></div>
|
||||
<div class="colors BLUE_D"><p class="color-text">BLUE_D</p></div>
|
||||
<div class="colors BLUE_C"><p class="color-text">BLUE_C</p></div>
|
||||
<div class="colors BLUE_B"><p class="color-text">BLUE_B</p></div>
|
||||
<div class="colors BLUE_A"><p class="color-text">BLUE_A</p></div>
|
||||
<h3 style="margin-top: 6em">TEAL</h3>
|
||||
<div class="colors TEAL_E"><p class="color-text">TEAL_E</p></div>
|
||||
<div class="colors TEAL_D"><p class="color-text">TEAL_D</p></div>
|
||||
<div class="colors TEAL_C"><p class="color-text">TEAL_C</p></div>
|
||||
<div class="colors TEAL_B"><p class="color-text">TEAL_B</p></div>
|
||||
<div class="colors TEAL_A"><p class="color-text">TEAL_A</p></div>
|
||||
<h3 style="margin-top: 6em">GREEN</h3>
|
||||
<div class="colors GREEN_E"><p class="color-text">GREEN_E</p></div>
|
||||
<div class="colors GREEN_D"><p class="color-text">GREEN_D</p></div>
|
||||
<div class="colors GREEN_C"><p class="color-text">GREEN_C</p></div>
|
||||
<div class="colors GREEN_B"><p class="color-text">GREEN_B</p></div>
|
||||
<div class="colors GREEN_A"><p class="color-text">GREEN_A</p></div>
|
||||
<h3 style="margin-top: 6em">YELLOW</h3>
|
||||
<div class="colors YELLOW_E"><p class="color-text">YELLOW_E</p></div>
|
||||
<div class="colors YELLOW_D"><p class="color-text">YELLOW_D</p></div>
|
||||
<div class="colors YELLOW_C"><p class="color-text">YELLOW_C</p></div>
|
||||
<div class="colors YELLOW_B"><p class="color-text">YELLOW_B</p></div>
|
||||
<div class="colors YELLOW_A"><p class="color-text">YELLOW_A</p></div>
|
||||
<h3 style="margin-top: 6em">GOLD</h3>
|
||||
<div class="colors GOLD_E"><p class="color-text">GOLD_E</p></div>
|
||||
<div class="colors GOLD_D"><p class="color-text">GOLD_D</p></div>
|
||||
<div class="colors GOLD_C"><p class="color-text">GOLD_C</p></div>
|
||||
<div class="colors GOLD_B"><p class="color-text">GOLD_B</p></div>
|
||||
<div class="colors GOLD_A"><p class="color-text">GOLD_A</p></div>
|
||||
<h3 style="margin-top: 6em">RED</h3>
|
||||
<div class="colors RED_E"><p class="color-text">RED_E</p></div>
|
||||
<div class="colors RED_D"><p class="color-text">RED_D</p></div>
|
||||
<div class="colors RED_C"><p class="color-text">RED_C</p></div>
|
||||
<div class="colors RED_B"><p class="color-text">RED_B</p></div>
|
||||
<div class="colors RED_A"><p class="color-text">RED_A</p></div>
|
||||
<h3 style="margin-top: 6em">MAROON</h3>
|
||||
<div class="colors MAROON_E"><p class="color-text">MAROON_E</p></div>
|
||||
<div class="colors MAROON_D"><p class="color-text">MAROON_D</p></div>
|
||||
<div class="colors MAROON_C"><p class="color-text">MAROON_C</p></div>
|
||||
<div class="colors MAROON_B"><p class="color-text">MAROON_B</p></div>
|
||||
<div class="colors MAROON_A"><p class="color-text">MAROON_A</p></div>
|
||||
<h3 style="margin-top: 6em">PURPLE</h3>
|
||||
<div class="colors PURPLE_E"><p class="color-text">PURPLE_E</p></div>
|
||||
<div class="colors PURPLE_D"><p class="color-text">PURPLE_D</p></div>
|
||||
<div class="colors PURPLE_C"><p class="color-text">PURPLE_C</p></div>
|
||||
<div class="colors PURPLE_B"><p class="color-text">PURPLE_B</p></div>
|
||||
<div class="colors PURPLE_A"><p class="color-text">PURPLE_A</p></div>
|
||||
<h3 style="margin-top: 6em">GREY</h3>
|
||||
<div class="colors GREY_E"><p class="color-text">GREY_E</p></div>
|
||||
<div class="colors GREY_D"><p class="color-text">GREY_D</p></div>
|
||||
<div class="colors GREY_C"><p class="color-text">GREY_C</p></div>
|
||||
<div class="colors GREY_B"><p class="color-text">GREY_B</p></div>
|
||||
<div class="colors GREY_A"><p class="color-text">GREY_A</p></div>
|
||||
<h3 style="margin-top: 6em">Others</h3>
|
||||
<div class="colors WHITE"><p class="color-text" style="color: BLACK">WHITE</p></div>
|
||||
<div class="colors BLACK"><p class="color-text">BLACK</p></div>
|
||||
<div class="colors GREY_BROWN"><p class="color-text-small">GREY_BROWN</p></div>
|
||||
<div class="colors DARK_BROWN"><p class="color-text-small">DARK_BROWN</p></div>
|
||||
<div class="colors LIGHT_BROWN"><p class="color-text-small">LIGHT_BROWN</p></div>
|
||||
<div class="colors PINK"><p class="color-text">PINK</p></div>
|
||||
<div class="colors LIGHT_PINK"><p class="color-text-small">LIGHT_PINK</p></div>
|
||||
<div class="colors GREEN_SCREEN"><p class="color-text-small">GREEN_SCREEN</p></div>
|
||||
<div class="colors ORANGE"><p class="color-text">ORANGE</p></div>
|
125
docs/source/documentation/custom_default.rst
Normal file
125
docs/source/documentation/custom_default.rst
Normal file
|
@ -0,0 +1,125 @@
|
|||
custom_default
|
||||
==============
|
||||
|
||||
``directories``
|
||||
---------------
|
||||
|
||||
- ``mirror_module_path``
|
||||
(``True`` or ``False``) Whether to create a folder named the name of the
|
||||
running file under the ``output`` path, and save the output (``images/``
|
||||
or ``videos/``) in it.
|
||||
|
||||
- ``output``
|
||||
Output file path, the videos will be saved in the ``videos/`` folder under it,
|
||||
and the pictures will be saved in the ``images/`` folder under it.
|
||||
|
||||
For example, if you set ``output`` to ``"/.../manim/output"`` and
|
||||
``mirror_module_path`` to ``False``, then you exported ``Scene1`` in the code
|
||||
file and saved the last frame, then the final directory structure will be like:
|
||||
|
||||
.. code-block:: text
|
||||
:emphasize-lines: 8, 10
|
||||
|
||||
manim/
|
||||
├── manimlib/
|
||||
│ ├── animation/
|
||||
│ ├── ...
|
||||
│ └── window.py
|
||||
├── output/
|
||||
│ ├── images
|
||||
│ │ └── Scene1.png
|
||||
│ └── videos
|
||||
│ └── Scene1.mp4
|
||||
├── code.py
|
||||
├── custom_default.yml
|
||||
└── manim.py
|
||||
|
||||
But if you set ``mirror_module_path`` to ``True``, the directory structure will be:
|
||||
|
||||
.. code-block:: text
|
||||
:emphasize-lines: 7
|
||||
|
||||
manim/
|
||||
├── manimlib/
|
||||
│ ├── animation/
|
||||
│ ├── ...
|
||||
│ └── window.py
|
||||
├── output/
|
||||
│ └── code/
|
||||
│ ├── images
|
||||
│ │ └── Scene1.png
|
||||
│ └── videos
|
||||
│ └── Scene1.mp4
|
||||
├── code.py
|
||||
├── custom_default.yml
|
||||
└── manim.py
|
||||
|
||||
- ``raster_images``
|
||||
The directory for storing raster images to be used in the code (including
|
||||
``.jpg``, ``.png`` and ``.gif``), which will be read by ``ImageMobject``.
|
||||
|
||||
- ``vector_images``
|
||||
The directory for storing vector images to be used in the code (including
|
||||
``.svg`` and ``.xdv``), which will be read by ``SVGMobject``.
|
||||
|
||||
- ``temporary_storage``
|
||||
The directory for storing temporarily generated cache files, including
|
||||
``Tex`` cache, ``Text`` cache and storage of object points.
|
||||
|
||||
``tex``
|
||||
-------
|
||||
|
||||
- ``executable``
|
||||
The executable program used to compile LaTeX (``latex`` or ``xelatex -no-pdf``
|
||||
is recommended)
|
||||
|
||||
- ``template_file``
|
||||
LaTeX template used, in ``manimlib/tex_templates``
|
||||
|
||||
- ``intermediate_filetype``
|
||||
The type of intermediate vector file generated after compilation (``dvi`` if
|
||||
``latex`` is used, ``xdv`` if ``xelatex`` is used)
|
||||
|
||||
- ``text_to_replace``
|
||||
The text to be replaced in the template (needn't to change)
|
||||
|
||||
``universal_import_line``
|
||||
-------------------------
|
||||
|
||||
Import line that need to execute when entering interactive mode directly.
|
||||
|
||||
``style``
|
||||
---------
|
||||
|
||||
- ``font``
|
||||
Default font of Text
|
||||
|
||||
- ``background_color``
|
||||
Default background color
|
||||
|
||||
``window_position``
|
||||
-------------------
|
||||
|
||||
The relative position of the playback window on the display (two characters,
|
||||
the first character means upper(U) / middle(O) / lower(D), the second character
|
||||
means left(L) / middle(O) / right(R)).
|
||||
|
||||
``camera_qualities``
|
||||
--------------------
|
||||
|
||||
Export quality
|
||||
|
||||
- ``low``
|
||||
Low quality (default is 480p15)
|
||||
|
||||
- ``medium``
|
||||
Medium quality (default is 720p30)
|
||||
|
||||
- ``high``
|
||||
High quality (default is 1080p30)
|
||||
|
||||
- ``ultra_high``
|
||||
Ultra high quality (default is 4K60)
|
||||
|
||||
- ``default_quality``
|
||||
Default quality (one of the above four)
|
2
docs/source/documentation/mobject/index.rst
Normal file
2
docs/source/documentation/mobject/index.rst
Normal file
|
@ -0,0 +1,2 @@
|
|||
Mobject (TODO)
|
||||
==============
|
2
docs/source/documentation/scene/index.rst
Normal file
2
docs/source/documentation/scene/index.rst
Normal file
|
@ -0,0 +1,2 @@
|
|||
Scene (TODO)
|
||||
============
|
2
docs/source/documentation/shaders/index.rst
Normal file
2
docs/source/documentation/shaders/index.rst
Normal file
|
@ -0,0 +1,2 @@
|
|||
Shaders (TODO)
|
||||
==============
|
2
docs/source/documentation/utils/index.rst
Normal file
2
docs/source/documentation/utils/index.rst
Normal file
|
@ -0,0 +1,2 @@
|
|||
Utils (TODO)
|
||||
============
|
104
docs/source/getting_started/config.rst
Normal file
104
docs/source/getting_started/config.rst
Normal file
|
@ -0,0 +1,104 @@
|
|||
CONFIG dictionary
|
||||
=================
|
||||
|
||||
What's CONFIG
|
||||
-------------
|
||||
|
||||
``CONFIG`` dictionary is a feature of manim, which facilitates the inheritance
|
||||
and modification of parameters between parent and child classes.
|
||||
|
||||
| ``CONFIG`` dictionary 's processing is in ``manimlib/utils/config_ops.py``
|
||||
| It can convert the key-value pairs in the ``CONFIG`` dictionary into class attributes and values
|
||||
|
||||
Generally, the first line of the ``.__init__()`` method in some basic class (``Mobject``, ``Animation``,
|
||||
etc.) will call this function ``digest_config(self, kwargs)`` to convert both
|
||||
the ``CONFIG`` dictionary and ``kwargs`` into attributes. Then it can be accessed
|
||||
directly through ``self.``, which simplifies the handling of inheritance between classes.
|
||||
|
||||
**An example**:
|
||||
|
||||
There are many class inheritance relationships in ``manimlib/mobject/geometry.py``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Line 279
|
||||
class Circle(Arc):
|
||||
CONFIG = {
|
||||
"color": RED,
|
||||
"close_new_points": True,
|
||||
"anchors_span_full_range": False
|
||||
}
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Line 304
|
||||
class Dot(Circle):
|
||||
CONFIG = {
|
||||
"radius": DEFAULT_DOT_RADIUS,
|
||||
"stroke_width": 0,
|
||||
"fill_opacity": 1.0,
|
||||
"color": WHITE
|
||||
}
|
||||
|
||||
The ``Circle`` class uses the key-value pair ``"color": RED`` in the ``CONFIG``
|
||||
dictionary to add the attribute ``self.color``.
|
||||
|
||||
At the same time, the ``Dot`` class also contains the key ``color`` in the
|
||||
``CONFIG`` dictionary, but the value is different. At this time, the priority will
|
||||
modify the attribute ``self.color`` to ``WHITE``.
|
||||
|
||||
CONFIG nesting
|
||||
--------------
|
||||
|
||||
The ``CONFIG`` dictionary supports nesting, that is, the value of the key is also
|
||||
a dictionary, for example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Camera(object):
|
||||
CONFIG = {
|
||||
# configs
|
||||
}
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Scene(object):
|
||||
CONFIG = {
|
||||
"window_config": {},
|
||||
"camera_class": Camera,
|
||||
"camera_config": {},
|
||||
"file_writer_config": {},
|
||||
# other configs
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
# some lines
|
||||
self.camera = self.camera_class(**self.camera_config)
|
||||
|
||||
The ``CONFIG`` dictionary of the ``Camera`` class contains many key-value pairs,
|
||||
and this class needs to be instantiated in the ``Scene`` class. For more convenient
|
||||
control, there is a special key-value pair in the Scene class ``"camera_config": {}``,
|
||||
Its value is a dictionary, passed in as ``kwargs`` when initializing the ``Camera`` class
|
||||
to modify the value of the properties of the ``Camera`` class.
|
||||
|
||||
So the nesting of the ``CONFIG`` dictionary **essentially** passes in the value as ``kwargs``.
|
||||
|
||||
Common usage
|
||||
------------
|
||||
|
||||
When writing a class by yourself, you can add attributes or modify the attributes
|
||||
of the parent class through ``CONFIG``.
|
||||
|
||||
The most commonly used is to modify the properties of the camera when writing a ``Scene``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class YourScene(Scene):
|
||||
CONFIG = {
|
||||
"camera_config": {
|
||||
"background_color": WHITE,
|
||||
},
|
||||
}
|
||||
|
||||
For example, the above dictionary will change the background color to white, etc.
|
84
docs/source/getting_started/configuration.rst
Normal file
84
docs/source/getting_started/configuration.rst
Normal file
|
@ -0,0 +1,84 @@
|
|||
CLI flags and configuration
|
||||
===========================
|
||||
|
||||
Command Line Interface
|
||||
----------------------
|
||||
|
||||
To run manim, you need to enter the directory at the same level as ``manim.py``
|
||||
and enter the command in the following format into terminal:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python manim.py <code>.py <Scene> <flags>
|
||||
|
||||
- ``<code>.py`` : The python file you wrote. Needs to be at the same level as ``manim.py``, otherwise you need to use an absolute path or a relative path.
|
||||
- ``<Scene>`` : The scene you want to render here. If it is not written or written incorrectly, it will list all for you to choose. And if there is only one ``Scene`` in the file, this class will be rendered directly.
|
||||
- ``<flags>`` : CLI flags.
|
||||
|
||||
Some useful flags
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
- ``-w`` to write the scene to a file.
|
||||
- ``-o`` to write the scene to a file and open the result.
|
||||
- ``-s`` to skip to the end and just show the final frame.
|
||||
- ``-so`` will save the final frame to an image and show it.
|
||||
- ``-n <number>`` to skip ahead to the ``n``\ ’th animation of a scene.
|
||||
- ``-f`` to make the playback window fullscreen.
|
||||
|
||||
All supported flags
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
========================================================== ====== =================================================================================================================================================================================================
|
||||
flag abbr function
|
||||
========================================================== ====== =================================================================================================================================================================================================
|
||||
``--help`` ``-h`` Show the help message and exit
|
||||
``--write_file`` ``-w`` Render the scene as a movie file
|
||||
``--skip_animations`` ``-s`` Skip to the last frame
|
||||
``--low_quality`` ``-l`` Render at a low quality (for faster rendering)
|
||||
``--medium_quality`` ``-m`` Render at a medium quality
|
||||
``--hd`` Render at a 1080p quality
|
||||
``--uhd`` Render at a 4k quality
|
||||
``--full_screen`` ``-f`` Show window in full screen
|
||||
``--save_pngs`` ``-g`` Save each frame as a png
|
||||
``--save_as_gif`` ``-i`` Save the video as gif
|
||||
``--transparent`` ``-t`` Render to a movie file with an alpha channel
|
||||
``--quiet`` ``-q``
|
||||
``--write_all`` ``-a`` Write all the scenes from a file
|
||||
``--open`` ``-o`` Automatically open the saved file once its done
|
||||
``--finder`` Show the output file in finder
|
||||
``--file_name FILE_NAME`` Name for the movie or image file
|
||||
``--start_at_animation_number START_AT_ANIMATION_NUMBER`` ``-n`` Start rendering not from the first animation, but from another, specified by its index. If you passin two comma separated values, e.g. "3,6", it will end the rendering at the second value.
|
||||
``--resolution RESOLUTION`` ``-r`` Resolution, passed as "WxH", e.g. "1920x1080"
|
||||
``--frame_rate FRAME_RATE`` Frame rate, as an integer
|
||||
``--color COLOR`` ``-c`` Background color
|
||||
``--leave_progress_bars`` Leave progress bars displayed in terminal
|
||||
``--video_dir VIDEO_DIR`` directory to write video
|
||||
========================================================== ====== =================================================================================================================================================================================================
|
||||
|
||||
custom_default
|
||||
--------------
|
||||
|
||||
In order to perform more configuration (about directories, etc.) and permanently
|
||||
change the default value (you don't have to add flags to the command every time),
|
||||
you can modify ``custom_default.yml``. The meaning of each option is in
|
||||
page :doc:`../documentation/custom_default`.
|
||||
|
||||
You can also use different ``custom_default.yml`` for different directories, such as
|
||||
following the directory structure:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
manim/
|
||||
├── manimlib/
|
||||
│ ├── animation/
|
||||
│ ├── ...
|
||||
│ └── window.py
|
||||
├── project/
|
||||
│ ├── code.py
|
||||
│ └── custom_default.yml
|
||||
├── custom_default.yml
|
||||
└── manim.py
|
||||
|
||||
When you enter the ``project/`` folder and run ``python ../manim.py code.py <Scene>``,
|
||||
it will overwrite ``manim/custom_default.yml`` with ``custom_default.yml``
|
||||
in the ``project`` folder.
|
424
docs/source/getting_started/example_scenes.rst
Normal file
424
docs/source/getting_started/example_scenes.rst
Normal file
|
@ -0,0 +1,424 @@
|
|||
Example Scenes
|
||||
==============
|
||||
|
||||
After understanding the previous knowledge, we can understand more scenes.
|
||||
Many example scenes are given in ``example_scenes.py``, let's start with
|
||||
the simplest and one by one.
|
||||
|
||||
SquareToCircle
|
||||
--------------
|
||||
|
||||
.. manim-example:: SquareToCircle
|
||||
:media: ../_static/example_scenes/SquareToCircle.mp4
|
||||
|
||||
from manimlib.imports import *
|
||||
|
||||
class SquareToCircle(Scene):
|
||||
def construct(self):
|
||||
circle = Circle()
|
||||
circle.set_fill(BLUE, opacity=0.5)
|
||||
circle.set_stroke(BLUE_E, width=4)
|
||||
square = Square()
|
||||
|
||||
self.play(ShowCreation(square))
|
||||
self.wait()
|
||||
self.play(ReplacementTransform(square, circle))
|
||||
self.wait()
|
||||
|
||||
This scene is what we wrote in :doc:`quickstart`.
|
||||
No more explanation here
|
||||
|
||||
WarpSquare
|
||||
----------
|
||||
|
||||
.. manim-example:: WarpSquare
|
||||
:media: ../_static/example_scenes/WarpSquare.mp4
|
||||
|
||||
class WarpSquare(Scene):
|
||||
def construct(self):
|
||||
square = Square()
|
||||
self.play(square.apply_complex_function, np.exp)
|
||||
self.wait()
|
||||
|
||||
The new usage in this scene is ``self.play(square.apply_complex_function, np.exp)``,
|
||||
which shows an animation of applying a complex function :math:`f(z)=e^z` to a square.
|
||||
It is equivalent to transforming the original square into the result after
|
||||
applying a function.
|
||||
|
||||
TextExample
|
||||
-----------
|
||||
|
||||
.. manim-example:: TextExample
|
||||
:media: ../_static/example_scenes/TextExample.mp4
|
||||
|
||||
class TextExample(Scene):
|
||||
def construct(self):
|
||||
text = Text("Here is a text", font="Consolas", font_size=90)
|
||||
difference = Text(
|
||||
"""
|
||||
The most important difference between Text and TexText is that\n
|
||||
you can change the font more easily, but can't use the LaTeX grammar
|
||||
""",
|
||||
font="Arial", font_size=24,
|
||||
t2c={"Text": BLUE, "TexText": BLUE, "LaTeX": ORANGE}
|
||||
)
|
||||
VGroup(text, difference).arrange(DOWN, buff=1)
|
||||
self.play(Write(text))
|
||||
self.play(FadeIn(difference, UP))
|
||||
self.wait(3)
|
||||
|
||||
fonts = Text(
|
||||
"And you can also set the font according to different words",
|
||||
font="Arial",
|
||||
t2f={"font": "Consolas", "words": "Consolas"},
|
||||
t2c={"font": BLUE, "words": GREEN}
|
||||
)
|
||||
slant = Text(
|
||||
"And the same as slant and weight",
|
||||
font="Consolas",
|
||||
t2s={"slant": ITALIC},
|
||||
t2w={"weight": BOLD},
|
||||
t2c={"slant": ORANGE, "weight": RED}
|
||||
)
|
||||
VGroup(fonts, slant).arrange(DOWN, buff=0.8)
|
||||
self.play(FadeOut(text), FadeOut(difference, shift=DOWN))
|
||||
self.play(Write(fonts))
|
||||
self.wait()
|
||||
self.play(Write(slant))
|
||||
self.wait()
|
||||
|
||||
The new classes in this scene are ``Text``, ``VGroup``, ``Write``, ``FadeIn`` and ``FadeOut``.
|
||||
|
||||
- ``Text`` can create text, define fonts, etc. The usage ais clearly reflected in the above examples.
|
||||
- ``VGroup`` can put multiple ``VMobject`` together as a whole. In the example, the ``.arrange()`` method is called to arrange the sub-mobjects in sequence downward (``DOWN``), and the spacing is ``buff``.
|
||||
- ``Write`` is an animation that shows similar writing effects.
|
||||
- ``FadeIn`` fades the object in, the second parameter indicates the direction of the fade in.
|
||||
- ``FadeOut`` fades out the object, the second parameter indicates the direction of the fade out.
|
||||
|
||||
TexTransformExample
|
||||
-------------------
|
||||
|
||||
.. manim-example:: TexTransformExample
|
||||
:media: ../_static/example_scenes/TexTransformExample.mp4
|
||||
|
||||
class TexTransformExample(Scene):
|
||||
def construct(self):
|
||||
kw = {
|
||||
"isolate": ["B", "C", "=", "(", ")"]
|
||||
}
|
||||
lines = VGroup(
|
||||
Tex("{{A^2}} + {{B^2}} = {{C^2}}"),
|
||||
Tex("{{A^2}} = {{C^2}} - {{B^2}}"),
|
||||
Tex("{{A^2}} = (C + B)(C - B)", **kw),
|
||||
Tex("A = \\sqrt{(C + B)(C - B)}", **kw)
|
||||
)
|
||||
lines.arrange(DOWN, buff=LARGE_BUFF)
|
||||
for line in lines:
|
||||
line.set_color_by_tex_to_color_map({
|
||||
"A": BLUE,
|
||||
"B": TEAL,
|
||||
"C": GREEN,
|
||||
})
|
||||
|
||||
play_kw = {"run_time": 2}
|
||||
self.add(lines[0])
|
||||
self.play(
|
||||
TransformMatchingTex(
|
||||
lines[0].copy(), lines[1],
|
||||
path_arc=90 * DEGREES,
|
||||
),
|
||||
**play_kw
|
||||
)
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
TransformMatchingTex(lines[1].copy(), lines[2]),
|
||||
**play_kw
|
||||
)
|
||||
self.wait()
|
||||
self.play(FadeOut(lines[2]))
|
||||
self.play(
|
||||
TransformMatchingTex(
|
||||
lines[1].copy(), lines[2],
|
||||
key_map={
|
||||
"C^2": "C",
|
||||
"B^2": "B",
|
||||
}
|
||||
),
|
||||
**play_kw
|
||||
)
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
TransformMatchingTex(
|
||||
lines[2].copy(), lines[3],
|
||||
fade_transform_mismatches=True,
|
||||
),
|
||||
**play_kw
|
||||
)
|
||||
self.wait(3)
|
||||
self.play(FadeOut(lines, RIGHT))
|
||||
|
||||
source = TexText("the morse code")
|
||||
target = TexText("here come dots")
|
||||
|
||||
self.play(Write(source))
|
||||
self.wait()
|
||||
kw = {"run_time": 3, "path_arc": PI / 2}
|
||||
self.play(TransformMatchingShapes(source, target, **kw))
|
||||
self.wait()
|
||||
self.play(TransformMatchingShapes(target, source, **kw))
|
||||
self.wait()
|
||||
|
||||
The new classes in this scene are ``Tex``, ``TexText``, ``TransformMatchingTex``
|
||||
and ``TransformMatchingShapes``.
|
||||
|
||||
- ``Tex`` uses LaTeX to create mathematical formulas.
|
||||
- ``TexText`` uses LaTeX to create text.
|
||||
- ``TransformMatchingTeX`` automatically transforms sub-objects according to the similarities and differences of tex in ``Tex``.
|
||||
- ``TransformMatchingShapes`` automatically transform sub-objects directly based on the similarities and differences of the object point sets.
|
||||
|
||||
UpdatersExample
|
||||
---------------
|
||||
|
||||
.. manim-example:: UpdatersExample
|
||||
:media: ../_static/example_scenes/UpdatersExample.mp4
|
||||
|
||||
class UpdatersExample(Scene):
|
||||
def construct(self):
|
||||
decimal = DecimalNumber(
|
||||
0,
|
||||
show_ellipsis=True,
|
||||
num_decimal_places=3,
|
||||
include_sign=True,
|
||||
)
|
||||
square = Square()
|
||||
square.to_edge(UP)
|
||||
|
||||
always(decimal.next_to, square)
|
||||
f_always(decimal.set_value, square.get_y)
|
||||
|
||||
self.add(square, decimal)
|
||||
self.play(
|
||||
square.to_edge, DOWN,
|
||||
run_time=3,
|
||||
)
|
||||
self.play(square.center)
|
||||
self.wait()
|
||||
|
||||
now = self.time
|
||||
square.add_updater(
|
||||
lambda m: m.set_y(math.sin(self.time - now))
|
||||
)
|
||||
self.wait(10)
|
||||
|
||||
The new classes and usage in this scene are ``DecimalNumber``, ``.to_edge()``,
|
||||
``.center()``, ``always()``, ``f_always()``, ``.set_y()`` and ``.add_updater()``.
|
||||
|
||||
- ``DecimalNumber`` is a variable number, speed it up by breaking it into ``Tex`` characters.
|
||||
- ``.to_edge()`` means to place the object on the edge of the screen.
|
||||
- ``.center()`` means to place the object in the center of the screen.
|
||||
- ``always(f, x)`` means that a certain function (``f(x)``) is executed every frame.
|
||||
- ``f_always(f, g)`` is similar to ``always``, executed ``f(g())`` every frame.
|
||||
- ``.set_y()`` means to set the ordinate of the object on the screen.
|
||||
- ``.add_updater()`` sets an update function for the object. For example: ``mob1.add_updater(lambda mob: mob.next_to(mob2))`` means ``mob1.next_to(mob2)`` is executed every frame.
|
||||
|
||||
SurfaceExample
|
||||
--------------
|
||||
|
||||
.. manim-example:: SurfaceExample
|
||||
:media: ../_static/example_scenes/SurfaceExample.mp4
|
||||
|
||||
class SurfaceExample(Scene):
|
||||
CONFIG = {
|
||||
"camera_class": ThreeDCamera,
|
||||
}
|
||||
|
||||
def construct(self):
|
||||
surface_text = Text("For 3d scenes, try using surfaces")
|
||||
surface_text.fix_in_frame()
|
||||
surface_text.to_edge(UP)
|
||||
self.add(surface_text)
|
||||
self.wait(0.1)
|
||||
|
||||
torus1 = Torus(r1=1, r2=1)
|
||||
torus2 = Torus(r1=3, r2=1)
|
||||
sphere = Sphere(radius=3, resolution=torus1.resolution)
|
||||
# You can texture a surface with up to two images, which will
|
||||
# be interpreted as the side towards the light, and away from
|
||||
# the light. These can be either urls, or paths to a local file
|
||||
# in whatever you've set as the image directory in
|
||||
# the custom_defaults.yml file
|
||||
|
||||
# day_texture = "EarthTextureMap"
|
||||
# night_texture = "NightEarthTextureMap"
|
||||
day_texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Whole_world_-_land_and_oceans.jpg/1280px-Whole_world_-_land_and_oceans.jpg"
|
||||
night_texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/The_earth_at_night.jpg/1280px-The_earth_at_night.jpg"
|
||||
|
||||
surfaces = [
|
||||
TexturedSurface(surface, day_texture, night_texture)
|
||||
for surface in [sphere, torus1, torus2]
|
||||
]
|
||||
|
||||
for mob in surfaces:
|
||||
mob.shift(IN)
|
||||
mob.mesh = SurfaceMesh(mob)
|
||||
mob.mesh.set_stroke(BLUE, 1, opacity=0.5)
|
||||
|
||||
# Set perspective
|
||||
frame = self.camera.frame
|
||||
frame.set_euler_angles(
|
||||
theta=-30 * DEGREES,
|
||||
phi=70 * DEGREES,
|
||||
)
|
||||
|
||||
surface = surfaces[0]
|
||||
|
||||
self.play(
|
||||
FadeIn(surface),
|
||||
ShowCreation(surface.mesh, lag_ratio=0.01, run_time=3),
|
||||
)
|
||||
for mob in surfaces:
|
||||
mob.add(mob.mesh)
|
||||
surface.save_state()
|
||||
self.play(Rotate(surface, PI / 2), run_time=2)
|
||||
for mob in surfaces[1:]:
|
||||
mob.rotate(PI / 2)
|
||||
|
||||
self.play(
|
||||
Transform(surface, surfaces[1]),
|
||||
run_time=3
|
||||
)
|
||||
|
||||
self.play(
|
||||
Transform(surface, surfaces[2]),
|
||||
# Move camera frame during the transition
|
||||
frame.increment_phi, -10 * DEGREES,
|
||||
frame.increment_theta, -20 * DEGREES,
|
||||
run_time=3
|
||||
)
|
||||
# Add ambient rotation
|
||||
frame.add_updater(lambda m, dt: m.increment_theta(-0.1 * dt))
|
||||
|
||||
# Play around with where the light is
|
||||
light_text = Text("You can move around the light source")
|
||||
light_text.move_to(surface_text)
|
||||
light_text.fix_in_frame()
|
||||
|
||||
self.play(FadeTransform(surface_text, light_text))
|
||||
light = self.camera.light_source
|
||||
self.add(light)
|
||||
light.save_state()
|
||||
self.play(light.move_to, 3 * IN, run_time=5)
|
||||
self.play(light.shift, 10 * OUT, run_time=5)
|
||||
|
||||
drag_text = Text("Try moving the mouse while pressing d or s")
|
||||
drag_text.move_to(light_text)
|
||||
drag_text.fix_in_frame()
|
||||
|
||||
self.play(FadeTransform(light_text, drag_text))
|
||||
self.wait()
|
||||
|
||||
This scene shows an example of using a three-dimensional surface, and
|
||||
the related usage has been briefly described in the notes.
|
||||
|
||||
- ``.fix_in_frame()`` makes the object not change with the view angle of the screen, and is always displayed at a fixed position on the screen.
|
||||
|
||||
OpeningManimExample
|
||||
-------------------
|
||||
|
||||
.. manim-example:: OpeningManimExample
|
||||
:media: ../_static/example_scenes/OpeningManimExample.mp4
|
||||
|
||||
class OpeningManimExample(Scene):
|
||||
def construct(self):
|
||||
title = TexText("This is some \\LaTeX")
|
||||
basel = Tex(
|
||||
"\\sum_{n=1}^\\infty "
|
||||
"\\frac{1}{n^2} = \\frac{\\pi^2}{6}"
|
||||
)
|
||||
VGroup(title, basel).arrange(DOWN)
|
||||
self.play(
|
||||
Write(title),
|
||||
FadeIn(basel, UP),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
transform_title = Text("That was a transform")
|
||||
transform_title.to_corner(UL)
|
||||
self.play(
|
||||
Transform(title, transform_title),
|
||||
LaggedStartMap(FadeOut, basel, shift=DOWN),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
fade_comment = Text(
|
||||
"""
|
||||
You probably don't want to overuse
|
||||
Transforms, though, a simple fade often
|
||||
looks nicer.
|
||||
""",
|
||||
font_size=36,
|
||||
color=GREY_B,
|
||||
)
|
||||
fade_comment.next_to(
|
||||
transform_title, DOWN,
|
||||
buff=LARGE_BUFF,
|
||||
aligned_edge=LEFT
|
||||
)
|
||||
self.play(FadeIn(fade_comment, shift=DOWN))
|
||||
self.wait(3)
|
||||
|
||||
grid = NumberPlane((-10, 10), (-5, 5))
|
||||
grid_title = Text(
|
||||
"But manim is for illustrating math, not text",
|
||||
)
|
||||
grid_title.to_edge(UP)
|
||||
grid_title.add_background_rectangle()
|
||||
|
||||
self.add(grid, grid_title) # Make sure title is on top of grid
|
||||
self.play(
|
||||
FadeOut(title, shift=LEFT),
|
||||
FadeOut(fade_comment, shift=LEFT),
|
||||
FadeIn(grid_title),
|
||||
ShowCreation(grid, run_time=3, lag_ratio=0.1),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
matrix = [[1, 1], [0, 1]]
|
||||
linear_transform_title = VGroup(
|
||||
Text("This is what the matrix"),
|
||||
IntegerMatrix(matrix, include_background_rectangle=True),
|
||||
Text("looks like")
|
||||
)
|
||||
linear_transform_title.arrange(RIGHT)
|
||||
linear_transform_title.to_edge(UP)
|
||||
|
||||
self.play(
|
||||
FadeOut(grid_title),
|
||||
FadeIn(linear_transform_title),
|
||||
)
|
||||
self.play(grid.apply_matrix, matrix, run_time=3)
|
||||
self.wait()
|
||||
|
||||
grid_transform_title = Text(
|
||||
"And this is a nonlinear transformation"
|
||||
)
|
||||
grid_transform_title.set_stroke(BLACK, 5, background=True)
|
||||
grid_transform_title.to_edge(UP)
|
||||
grid.prepare_for_nonlinear_transform(100)
|
||||
self.play(
|
||||
ApplyPointwiseFunction(
|
||||
lambda p: p + np.array([np.sin(p[1]), np.sin(p[0]), 0]),
|
||||
grid,
|
||||
run_time=5,
|
||||
),
|
||||
FadeOut(linear_transform_title),
|
||||
FadeIn(grid_transform_title),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
This scene is a comprehensive application of a two-dimensional scene.
|
||||
|
||||
After seeing these scenes, you have already understood part of the
|
||||
usage of manim. For more examples, see `the video code of 3b1b <https://github.com/3b1b/videos>`_.
|
67
docs/source/getting_started/installation.rst
Normal file
67
docs/source/getting_started/installation.rst
Normal file
|
@ -0,0 +1,67 @@
|
|||
Installation
|
||||
============
|
||||
|
||||
Manim runs on Python 3.8.
|
||||
|
||||
System requirements are:
|
||||
|
||||
- `FFmpeg <https://ffmpeg.org/>`__
|
||||
- `OpenGL <https://www.opengl.org//>`__ (included in python package ``PyOpenGL``)
|
||||
- `LaTeX <https://www.latex-project.org>`__ (optional, if you want to use LaTeX)
|
||||
- `cairo <https://www.cairographics.org/>`_ (included in python package ``pycairo``. optional, if you want to use ``Text`` in manim)
|
||||
|
||||
Directly
|
||||
--------
|
||||
|
||||
If you want to hack on manimlib itself, clone this repository and in
|
||||
that directory execute:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
# Install python requirements
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Try it out
|
||||
python -m manim example_scenes.py OpeningManimExample
|
||||
|
||||
If you run the above command and no error message appears,
|
||||
then you have successfully installed all the environments required by manim.
|
||||
|
||||
Directly (Windows)
|
||||
------------------
|
||||
|
||||
1. `Install
|
||||
FFmpeg <https://www.wikihow.com/Install-FFmpeg-on-Windows>`__, and make sure that its path is in the PATH environment variable.
|
||||
2. Install a LaTeX distribution.
|
||||
`TeXLive-full <http://tug.org/texlive/>`__ is recommended.
|
||||
3. Install the remaining Python packages.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
git clone https://github.com/3b1b/manim.git
|
||||
cd manim
|
||||
pip install -r requirements.txt
|
||||
python manim.py example_scenes.py OpeningManimExample
|
||||
|
||||
For Anaconda
|
||||
------------
|
||||
|
||||
- Install FFmpeg and LaTeX as above.
|
||||
- Create a conda environment using
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
git clone https://github.com/3b1b/manim.git
|
||||
cd manim
|
||||
conda env create -f environment.yml
|
||||
|
||||
Using virtualenv and virtualenvwrapper
|
||||
--------------------------------------
|
||||
|
||||
After installing ``virtualenv`` and ``virtualenvwrapper``
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
git clone https://github.com/3b1b/manim.git
|
||||
mkvirtualenv -a manim -r requirements.txt manim
|
||||
python -m manim example_scenes.py OpeningManimExample
|
256
docs/source/getting_started/quickstart.rst
Normal file
256
docs/source/getting_started/quickstart.rst
Normal file
|
@ -0,0 +1,256 @@
|
|||
Quick Start
|
||||
===========
|
||||
|
||||
After installing the manim environment according to the instructions on the
|
||||
:doc:`installation` page, you can try to make a scene yourself from scratch.
|
||||
|
||||
First, create a new ``.py`` file (such as ``start.py``) according to the following
|
||||
directory structure:
|
||||
|
||||
.. code-block:: text
|
||||
:emphasize-lines: 8
|
||||
|
||||
manim/
|
||||
├── manimlib/
|
||||
│ ├── animation/
|
||||
│ ├── ...
|
||||
│ └── window.py
|
||||
├── custom_default.yml
|
||||
├── manim.py
|
||||
└── start.py
|
||||
|
||||
And paste the following code (I will explain the function of each line in detail later):
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
from manimlib.imports import *
|
||||
|
||||
class SquareToCircle(Scene):
|
||||
def construct(self):
|
||||
circle = Circle()
|
||||
circle.set_fill(BLUE, opacity=0.5)
|
||||
circle.set_stroke(BLUE_E, width=4)
|
||||
|
||||
self.add(circle)
|
||||
|
||||
And run this command:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python manim.py start.py SquareToCircle
|
||||
|
||||
A window will pop up on the screen. And then you can :
|
||||
|
||||
- scroll the middle mouse button to move the screen up and down
|
||||
- hold down the :kbd:`z` on the keyboard while scrolling the middle mouse button to zoom the screen
|
||||
- hold down the :kbd:`s` key on the keyboard and move the mouse to pan the screen
|
||||
- hold down the :kbd:`d` key on the keyboard and move the mouse to change the three-dimensional perspective.
|
||||
|
||||
Finally, you can close the window and exit the program by pressing :kbd:`q`.
|
||||
|
||||
Run this command again:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python manim.py start.py SquareToCircle -os
|
||||
|
||||
At this time, no window will pop up. When the program is finished, this rendered
|
||||
image will be automatically opened (saved in the subdirectory ``images/`` of the same
|
||||
level directory of ``start.py`` by default):
|
||||
|
||||
.. image:: ../_static/quickstart/SquareToCircle.png
|
||||
:align: center
|
||||
|
||||
Make an image
|
||||
-------------
|
||||
|
||||
Next, let's take a detailed look at what each row does.
|
||||
|
||||
**Line 1**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from manimlib.imports import *
|
||||
|
||||
This will import all the classes that may be used when using manim.
|
||||
|
||||
**Line 3**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class SquareToCircle(Scene):
|
||||
|
||||
Create a :class:`Scene` subclass ``SquareToCircle``, which will be
|
||||
the scene you write and render.
|
||||
|
||||
**Line 4**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def construct(self):
|
||||
|
||||
Write the ``construct()`` method, the content of which will determine
|
||||
how to create the mobjects in the screen and what operations need to be performed.
|
||||
|
||||
**Line 5**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
circle = Circle()
|
||||
|
||||
Create a circle (an instance of the :class:`Circle` class), called ``circle``
|
||||
|
||||
**Line 6~7**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
circle.set_fill(BLUE, opacity=0.5)
|
||||
circle.set_stroke(BLUE_E, width=4)
|
||||
|
||||
Set the circle style by calling the circle's method.
|
||||
|
||||
- The ``.set_fill()`` method sets the fill color of this circle to blue (``BLUE``, defined in :doc:`../documentation/constants`), and the fill transparency to 0.5.
|
||||
- The ``.set_stroke()`` method sets the stroke color of this circle to dark blue (``BLUE_E``, defined in :doc:`../documentation/constants`), and the stroke width to 4.
|
||||
|
||||
**Line 9**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.add(circle)
|
||||
|
||||
Add this circle to the screen through the ``.add()`` method of :class:`Scene`.
|
||||
|
||||
Add animations
|
||||
--------------
|
||||
|
||||
Let's change some codes and add some animations to make videos instead of just pictures.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
from manimlib.imports import *
|
||||
|
||||
class SquareToCircle(Scene):
|
||||
def construct(self):
|
||||
circle = Circle()
|
||||
circle.set_fill(BLUE, opacity=0.5)
|
||||
circle.set_stroke(BLUE_E, width=4)
|
||||
square = Square()
|
||||
|
||||
self.play(ShowCreation(square))
|
||||
self.wait()
|
||||
self.play(ReplacementTransform(square, circle))
|
||||
self.wait()
|
||||
|
||||
Run this command this time:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python manim.py start.py SquareToCircle
|
||||
|
||||
The pop-up window will play animations of drawing a square and transforming
|
||||
it into a circle. If you want to save this video, run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python manim.py start.py SquareToCircle -ow
|
||||
|
||||
This time there will be no pop-up window, but the video file (saved in the subdirectory
|
||||
``videos/`` of the same level directory of ``start.py`` by default) will be automatically
|
||||
opened after the operation is over:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<video class="manim-video" controls loop autoplay src="../_static/quickstart/SquareToCircle.mp4"></video>
|
||||
|
||||
Let's take a look at the code this time. The first 7 lines are the same as the previous
|
||||
ones, and the 8th line is similar to the 5th line, which creates an instance of the
|
||||
:class:`Square` class and named it ``square``.
|
||||
|
||||
**Line 10**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.play(ShowCreation(square))
|
||||
|
||||
An animation is played through :class:`Scene`'s ``.play()`` method. :class:`ShowCreation`
|
||||
is an animation that shows the process of creating a given mobject.
|
||||
``self.play(ShowCreation(square))`` is to play the animation of creating ``square``.
|
||||
|
||||
**Line 11**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.wait()
|
||||
|
||||
Use :class:`Scene`'s ``.wait()`` method to pause (default 1s), you can pass in
|
||||
parameters to indicate the pause time (for example, ``self.wait(3)`` means pause for 3s).
|
||||
|
||||
**Line 12**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.play(ReplacementTransform(square, circle))
|
||||
|
||||
Play the animation that transforms ``square`` into ``circle``.
|
||||
``ReplacementTransform(A, B)`` means to transform A into B's pattern and replace A with B.
|
||||
|
||||
**Line 13**: Same as line 11, pause for 1s.
|
||||
|
||||
|
||||
Enable interaction
|
||||
------------------
|
||||
|
||||
Interaction is a new feature of the new version. You can add the following line
|
||||
at the end of the code to enable interaction:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.embed()
|
||||
|
||||
Then run ``python manim.py start.py SquareToCircle``.
|
||||
|
||||
After the previous animation is executed, the ipython terminal will be opened on
|
||||
the command line. After that, you can continue to write code in it, and the statement
|
||||
you entered will be executed immediately after pressing :kbd:`Enter`.
|
||||
|
||||
For example: input the following lines (without comment lines) into it respectively
|
||||
(``self.play`` can be abbreviated as ``play`` in this mode):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Stretched 4 times in the vertical direction
|
||||
play(circle.stretch, 4, {"dim": 0})
|
||||
# Rotate the ellipse 90°
|
||||
play(Rotate(circle, TAU / 4))
|
||||
# Move 2 units to the right and shrink to 1/4 of the original
|
||||
play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
||||
# Insert 10 curves into circle for non-linear transformation (no animation will play)
|
||||
circle.insert_n_curves(10)
|
||||
# Apply a complex transformation of f(z)=z^2 to all points on the circle
|
||||
play(circle.apply_complex_function, lambda z: z**2)
|
||||
# Close the window and exit the program
|
||||
exit()
|
||||
|
||||
You will get an animation similar to the following:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<video class="manim-video" controls loop autoplay src="../_static/quickstart/SquareToCircleEmbed.mp4"></video>
|
||||
|
||||
If you want to enter the interactive mode directly, you don't have to write an
|
||||
empty scene containing only ``self.embed()``, you can directly run the following command
|
||||
(this will enter the ipython terminal while the window pops up):
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python manim.py
|
||||
|
||||
You succeeded!
|
||||
--------------
|
||||
|
||||
After reading the above content, you already know how to use manim.
|
||||
Below you can see some examples, in the :doc:`example_scenes` page.
|
||||
But before that, you'd better have a look at the :doc:`configuration` of manim.
|
||||
|
129
docs/source/getting_started/structure.rst
Normal file
129
docs/source/getting_started/structure.rst
Normal file
|
@ -0,0 +1,129 @@
|
|||
Manim's structure
|
||||
=================
|
||||
|
||||
|
||||
Manim's directory structure
|
||||
---------------------------
|
||||
|
||||
The manim directory looks very complicated, with a lot of files,
|
||||
but the structure is clear.
|
||||
|
||||
Below is the directory structure of manim:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
├── manim.py # Manim command entry
|
||||
├── custom_default.yml # Default configuration
|
||||
└── manimlib/ # manim library
|
||||
├── __init__.py # run from here
|
||||
├── config.py # Process CLI flags
|
||||
├── constants.py # Defined some constants
|
||||
├── extract_scene.py # Extract and run the scene
|
||||
├── imports.py # Import all required files in manimlib
|
||||
├── shader_wrapper.py # Shaders' Wrapper for convenient control
|
||||
├── window.py # Playback window
|
||||
├── tex_templates/ # Templates preset for LaTeX
|
||||
│ ├── tex_templates.tex # Tex template (will be compiled with latex, default)
|
||||
│ └── ctex_templates.tex # Tex template that support Chinese (will be compiled with xelatex)
|
||||
├── camera/
|
||||
│ └── camera.py # Including Camera and CameraFrame
|
||||
├── scene/
|
||||
│ ├── scene_file_writer.py # Used to write scene to video file
|
||||
│ ├── scene.py # The basic Scene class
|
||||
│ ├── three_d_scene.py # Three-dimensional scene
|
||||
│ ├── graph_scene.py # GraphScene (with coordinate axis)
|
||||
│ ├── reconfigurable_scene.py
|
||||
│ ├── sample_space_scene.py # Probability related sample space scene
|
||||
│ └── vector_space_scene.py # Vector field scene
|
||||
├── animation/
|
||||
│ ├── animation.py # The basic class of animation
|
||||
│ ├── composition.py # Animation group
|
||||
│ ├── creation.py # Animation related to Create
|
||||
│ ├── fading.py # Fade related animation
|
||||
│ ├── growing.py # Animation related to Grow
|
||||
│ ├── indication.py # Some animations for emphasis
|
||||
│ ├── movement.py # Animation related to movement
|
||||
│ ├── numbers.py # Realize changes to DecimalNumber
|
||||
│ ├── rotation.py # Animation related to rotation
|
||||
│ ├── specialized.py # Some uncommon animations for special projects
|
||||
│ ├── transform_matching_parts.py # Transform which can automatically match parts
|
||||
│ ├── transform.py # Some Transforms
|
||||
│ └── update.py # Realize update from function
|
||||
├── mobject/
|
||||
│ ├── mobject.py # The basic class of all math object
|
||||
│ ├── types/ # 4 types of mobject
|
||||
│ │ ├── dot_cloud.py # Dot cloud (an subclass of PMobject)
|
||||
│ │ ├── image_mobject.py # Insert pictures
|
||||
│ │ ├── point_cloud_mobject.py # PMobject (mobject composed of points)
|
||||
│ │ ├── surface.py # ParametricSurface
|
||||
│ │ └── vectorized_mobject.py # VMobject (vectorized mobject)
|
||||
│ ├── svg/ # mobject related to svg
|
||||
│ │ ├── svg_mobject.py # SVGMobject
|
||||
│ │ ├── brace.py # Brace
|
||||
│ │ ├── drawings.py # Some special mobject of svg image
|
||||
│ │ ├── tex_mobject.py # Tex and TexText implemented by LaTeX
|
||||
│ │ └── text_mobject.py # Text implemented by cairo
|
||||
│ ├── changing.py # Dynamically changing mobject
|
||||
│ ├── coordinate_systems.py # coordinate system
|
||||
│ ├── frame.py # mobject related to frame
|
||||
│ ├── functions.py # ParametricFunction
|
||||
│ ├── geometry.py # geometry mobjects
|
||||
│ ├── matrix.py # matrix
|
||||
│ ├── mobject_update_utils.py # some defined updater
|
||||
│ ├── number_line.py # Number line
|
||||
│ ├── numbers.py # Numbers that can be changed
|
||||
│ ├── probability.py # mobject related to probability
|
||||
│ ├── shape_matchers.py # mobject adapted to the size of other objects
|
||||
│ ├── three_dimensions.py # Three-dimensional objects
|
||||
│ ├── value_tracker.py # ValueTracker which storage number
|
||||
│ └── vector_field.py # VectorField
|
||||
├── once_useful_constructs/ # 3b1b's Common scenes written for some videos
|
||||
│ └── ...
|
||||
├── shaders/ # GLSL scripts for rendering
|
||||
│ ├── simple_vert.glsl # a simple glsl script for position
|
||||
│ ├── insert/ # glsl scripts to be inserted in other glsl scripts
|
||||
│ │ ├── NOTE.md # explain how to insert glsl scripts
|
||||
│ │ └── ... # useful scripts
|
||||
│ ├── image/ # glsl for images
|
||||
│ │ └── ... # containing shaders for vertex and fragment
|
||||
│ ├── quadratic_bezier_fill/ # glsl for the fill of quadratic bezier curve
|
||||
│ │ └── ... # containing shaders for vertex, fragment and geometry
|
||||
│ ├── quadratic_bezier_stroke/ # glsl for the stroke of quadratic bezier curve
|
||||
│ │ └── ... # containing shaders for vertex, fragment and geometry
|
||||
│ ├── surface/ # glsl for surfaces
|
||||
│ │ └── ... # containing shaders for vertex and fragment
|
||||
│ ├── textured_surface/ # glsl for textured_surface
|
||||
│ │ └── ... # containing shaders for vertex and fragment
|
||||
│ └── true_dot/ # glsl for a dot
|
||||
│ └── ... # containing shaders for vertex, fragment and geometry
|
||||
└── utils/ # Some useful utility functions
|
||||
├── bezier.py # For bezier curve
|
||||
├── color.py # For color
|
||||
├── config_ops.py # Process CONFIG
|
||||
├── customization.py # Read from custom_default.yml
|
||||
├── debug.py # Utilities for debugging in program
|
||||
├── family_ops.py # Process family members
|
||||
├── file_ops.py # Process files and directories
|
||||
├── images.py # Read image
|
||||
├── iterables.py # Functions related to list/dictionary processing
|
||||
├── paths.py # Curve path
|
||||
├── rate_functions.py # Some defined rate_functions
|
||||
├── simple_functions.py # Some commonly used functions
|
||||
├── sounds.py # Process sounds
|
||||
├── space_ops.py # Space coordinate calculation
|
||||
├── strings.py # Process strings
|
||||
└── tex_file_writing.py # Use LaTeX to write strings as svg
|
||||
|
||||
Inheritance structure of manim's classes
|
||||
----------------------------------------
|
||||
|
||||
`Here <https://github.com/3b1b/manim/files/5824383/manim_shaders_structure.pdf>`_
|
||||
is a pdf showed inheritance structure of manim's classes, large,
|
||||
but basically all classes have included:
|
||||
|
||||
.. image:: ../_static/manim_shaders_structure.png
|
||||
|
||||
Manim execution process
|
||||
-----------------------
|
||||
|
||||
.. image:: ../_static/manim_shaders_process_en.png
|
33
docs/source/index.rst
Normal file
33
docs/source/index.rst
Normal file
|
@ -0,0 +1,33 @@
|
|||
Manim's documentation
|
||||
=====================
|
||||
|
||||
.. image:: ../../logo/white_with_name.png
|
||||
|
||||
Manim is an animation engine for explanatory math videos. It's used to create precise animations programmatically, as seen in the videos
|
||||
at `3Blue1Brown <https://www.3blue1brown.com/>`_.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Getting Started
|
||||
|
||||
getting_started/installation
|
||||
getting_started/quickstart
|
||||
getting_started/configuration
|
||||
getting_started/example_scenes
|
||||
getting_started/config
|
||||
getting_started/structure
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Documentation
|
||||
|
||||
documentation/constants
|
||||
documentation/custom_default
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Development
|
||||
|
||||
development/changelog
|
||||
development/contributing
|
||||
development/about
|
108
docs/source/manim_example_ext.py
Normal file
108
docs/source/manim_example_ext.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives, Directive
|
||||
|
||||
import jinja2
|
||||
import os
|
||||
|
||||
|
||||
class skip_manim_node(nodes.Admonition, nodes.Element):
|
||||
pass
|
||||
|
||||
|
||||
def visit(self, node, name=""):
|
||||
self.visit_admonition(node, name)
|
||||
|
||||
|
||||
def depart(self, node):
|
||||
self.depart_admonition(node)
|
||||
|
||||
|
||||
class ManimExampleDirective(Directive):
|
||||
has_content = True
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
option_spec = {
|
||||
"hide_code": bool,
|
||||
"media": str,
|
||||
}
|
||||
final_argument_whitespace = True
|
||||
|
||||
def run(self):
|
||||
hide_code = "hide_code" in self.options
|
||||
scene_name = self.arguments[0]
|
||||
media_file_name = self.options["media"]
|
||||
|
||||
source_block = [
|
||||
".. code-block:: python",
|
||||
"",
|
||||
*[" " + line for line in self.content],
|
||||
]
|
||||
source_block = "\n".join(source_block)
|
||||
|
||||
state_machine = self.state_machine
|
||||
document = state_machine.document
|
||||
|
||||
if any(media_file_name.endswith(ext) for ext in [".png", ".jpg", ".gif"]):
|
||||
is_video = False
|
||||
else:
|
||||
is_video = True
|
||||
|
||||
rendered_template = jinja2.Template(TEMPLATE).render(
|
||||
scene_name=scene_name,
|
||||
scene_name_lowercase=scene_name.lower(),
|
||||
hide_code=hide_code,
|
||||
is_video=is_video,
|
||||
media_file_name=media_file_name,
|
||||
source_block=source_block,
|
||||
)
|
||||
state_machine.insert_input(
|
||||
rendered_template.split("\n"), source=document.attributes["source"]
|
||||
)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_node(skip_manim_node, html=(visit, depart))
|
||||
|
||||
setup.app = app
|
||||
setup.config = app.config
|
||||
setup.confdir = app.confdir
|
||||
|
||||
app.add_directive("manim-example", ManimExampleDirective)
|
||||
|
||||
metadata = {"parallel_read_safe": False, "parallel_write_safe": True}
|
||||
return metadata
|
||||
|
||||
|
||||
TEMPLATE = r"""
|
||||
{% if not hide_code %}
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<div class="manim-example">
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if is_video %}
|
||||
.. raw:: html
|
||||
|
||||
<video id="{{ scene_name_lowercase }}" class="manim-video" controls loop autoplay src="{{ media_file_name }}"></video>
|
||||
{% else %}
|
||||
.. image:: {{ media_file_name }}
|
||||
:align: center
|
||||
:name: {{ scene_name_lowercase }}
|
||||
{% endif %}
|
||||
|
||||
{% if not hide_code %}
|
||||
.. raw:: html
|
||||
|
||||
<h5 class="example-header">{{ scene_name }}<a class="headerlink" href="#{{ scene_name_lowercase }}">¶</a></h5>
|
||||
|
||||
{{ source_block }}
|
||||
{% endif %}
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div>
|
||||
"""
|
|
@ -25,4 +25,5 @@ dependencies:
|
|||
- validators
|
||||
- ipython
|
||||
- PyOpenGL
|
||||
- pycairo
|
||||
|
||||
|
|
BIN
logo/transparent_graph.png
Normal file
BIN
logo/transparent_graph.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
BIN
logo/white_with_name.png
Normal file
BIN
logo/white_with_name.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
|
@ -16,4 +16,5 @@ screeninfo
|
|||
pyreadline; sys_platform == 'win32'
|
||||
validators
|
||||
ipython
|
||||
PyOpenGL
|
||||
PyOpenGL
|
||||
pycairo
|
Loading…
Add table
Reference in a new issue