From 435a2631c991ec32c323b787da430216eb68e70e Mon Sep 17 00:00:00 2001 From: Kyle Cheng <37385704+kcheng0222@users.noreply.github.com> Date: Sun, 31 May 2020 09:44:39 -0700 Subject: [PATCH 01/28] Fixed typo from "depricated" to "deprecated" --- manimlib/animation/transform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manimlib/animation/transform.py b/manimlib/animation/transform.py index fef38184..b70e7c8d 100644 --- a/manimlib/animation/transform.py +++ b/manimlib/animation/transform.py @@ -291,7 +291,7 @@ class Swap(CyclicReplace): pass # Renaming, more understandable for two entries -# TODO, this may be depricated...worth reimplementing? +# TODO, this may be deprecated...worth reimplementing? class TransformAnimations(Transform): CONFIG = { "rate_func": squish_rate_func(smooth) From 25f672cc55396285a8de52b8c70b3bec07adc0ef Mon Sep 17 00:00:00 2001 From: Sujan Dutta Date: Fri, 17 Jul 2020 10:47:55 +0530 Subject: [PATCH 02/28] Update imports.py corrected the linking word. --- manimlib/imports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manimlib/imports.py b/manimlib/imports.py index 1020f8ce..90aaa3be 100644 --- a/manimlib/imports.py +++ b/manimlib/imports.py @@ -1,5 +1,5 @@ """ -I won't pretend like this is best practice, by in creating animations for a video, +I won't pretend like this is best practice, but in creating animations for a video, it can be very nice to simply have all of the Mobjects, Animations, Scenes, etc. of manim available without having to worry about what namespace they come from. From 2451f024f68557917eafc34ed7b39923d3620c98 Mon Sep 17 00:00:00 2001 From: Ben Spitz Date: Wed, 6 Jan 2021 12:21:49 -0800 Subject: [PATCH 03/28] Fix typo in value_tracker.py "Note meant to be displayed" -> "Not meant to be displayed" --- manimlib/mobject/value_tracker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manimlib/mobject/value_tracker.py b/manimlib/mobject/value_tracker.py index 79cdedce..e35165bb 100644 --- a/manimlib/mobject/value_tracker.py +++ b/manimlib/mobject/value_tracker.py @@ -5,7 +5,7 @@ from manimlib.mobject.mobject import Mobject class ValueTracker(Mobject): """ - Note meant to be displayed. Instead the position encodes some + Not meant to be displayed. Instead the position encodes some number, often one which another animation or continual_animation uses for its update function, and by treating it as a mobject it can still be animated and manipulated just like anything else. From 384304e92b6d681af817f99e9fe26d3f1589c9eb Mon Sep 17 00:00:00 2001 From: techdude Date: Sun, 31 Jan 2021 18:48:48 -0700 Subject: [PATCH 04/28] Add CONFIG parameter to allow disabling smoothing --- manimlib/mobject/functions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manimlib/mobject/functions.py b/manimlib/mobject/functions.py index b081fc41..1662be7d 100644 --- a/manimlib/mobject/functions.py +++ b/manimlib/mobject/functions.py @@ -12,6 +12,7 @@ class ParametricFunction(VMobject): "dt": 1e-8, # TODO, be smarter about figuring these out? "discontinuities": [], + "smoothing": True, } def __init__(self, function=None, **kwargs): @@ -73,7 +74,8 @@ class ParametricFunction(VMobject): if len(points) > 0: self.start_new_path(points[0]) self.add_points_as_corners(points[1:]) - self.make_smooth() + if self.smoothing: + self.make_smooth() return self From fb8280171b0a7cee46aa3212a75f84b6d275c2f1 Mon Sep 17 00:00:00 2001 From: Abhijith Muthyala <64465542+abhi-6988@users.noreply.github.com> Date: Mon, 1 Feb 2021 12:25:11 +0530 Subject: [PATCH 05/28] Replace redundant CONFIG key in NumberLine --- manimlib/mobject/number_line.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manimlib/mobject/number_line.py b/manimlib/mobject/number_line.py index d6e94ece..1e50692e 100644 --- a/manimlib/mobject/number_line.py +++ b/manimlib/mobject/number_line.py @@ -37,7 +37,7 @@ class NumberLine(Line): "num_decimal_places": 0, "height": 0.25, }, - "exclude_zero_from_default_numbers": False, + "numbers_to_exclude": None } def __init__(self, x_range=None, **kwargs): @@ -70,7 +70,7 @@ class NumberLine(Line): if self.include_ticks: self.add_ticks() if self.include_numbers: - self.add_numbers() + self.add_numbers(excluding=self.numbers_to_exclude) def get_tick_range(self): if self.include_tip: From 0e80799b1f1c47cca94e7daeb2bf48f99376caf2 Mon Sep 17 00:00:00 2001 From: ASUTOSH GHANTO <44160439+asutoshgha@users.noreply.github.com> Date: Tue, 2 Feb 2021 09:11:42 +0530 Subject: [PATCH 06/28] Update README.md added content for macOSX --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 64e561f5..8ae69aad 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,15 @@ pip install -r requirements.txt # Try it out python manim.py example_scenes.py OpeningManimExample ``` - +### Mac OSX +1. Install [FFmpeg],[LaTeX],[cairo](if you only want to run on CPU) in commandline using homebrew. + ```sh + brew install ffmpeg mactex cairo + ``` +2. Install manim using this command if you dont want to tinker with code.(virtualenv wrapper is recommended) + ```sh + pip3 install manimlib + ``` ### Directly (Windows) 1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows). 2. Install a LaTeX distribution. [MiKTeX](https://miktex.org/download) is recommended. From fc01239c7a98049a589672f750bf6fc10b43b368 Mon Sep 17 00:00:00 2001 From: ASUTOSH GHANTO <44160439+asutoshgha@users.noreply.github.com> Date: Tue, 2 Feb 2021 11:36:01 +0530 Subject: [PATCH 07/28] Update README.md corrected my mistakes in readme --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8ae69aad..be376cd7 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,19 @@ pip install -r requirements.txt python manim.py example_scenes.py OpeningManimExample ``` ### Mac OSX -1. Install [FFmpeg],[LaTeX],[cairo](if you only want to run on CPU) in commandline using homebrew. +1. Install FFmpeg,LaTeX,cairo in terminal using homebrew. ```sh brew install ffmpeg mactex cairo ``` -2. Install manim using this command if you dont want to tinker with code.(virtualenv wrapper is recommended) + +2. Install latest version of manim using this command if you dont want to tinker with code.(virtualenv wrapper is recommended) ```sh - pip3 install manimlib + git clone https://github.com/3b1b/manim.git + cd manim + pip install -r requirements.txt + python manim.py example_scenes.py OpeningManimExample ``` + ### Directly (Windows) 1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows). 2. Install a LaTeX distribution. [MiKTeX](https://miktex.org/download) is recommended. From 98a25eaefee92f275c24b4809cff456a9678f2ef Mon Sep 17 00:00:00 2001 From: ASUTOSH GHANTO <44160439+asutoshgha@users.noreply.github.com> Date: Tue, 2 Feb 2021 13:24:40 +0530 Subject: [PATCH 08/28] Update README.md asked changes were made --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index be376cd7..a268b420 100644 --- a/README.md +++ b/README.md @@ -31,16 +31,16 @@ python manim.py example_scenes.py OpeningManimExample ### Mac OSX 1. Install FFmpeg,LaTeX,cairo in terminal using homebrew. ```sh - brew install ffmpeg mactex cairo - ``` + brew install ffmpeg mactex cairo + ``` 2. Install latest version of manim using this command if you dont want to tinker with code.(virtualenv wrapper is recommended) ```sh - git clone https://github.com/3b1b/manim.git - cd manim - pip install -r requirements.txt - python manim.py example_scenes.py OpeningManimExample - ``` + git clone https://github.com/3b1b/manim.git + cd manim + pip install -r requirements.txt + python manim.py example_scenes.py OpeningManimExample + ``` ### Directly (Windows) 1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows). From 3ec8bb0d28eebf0b47565e806d65dd26fcab721c Mon Sep 17 00:00:00 2001 From: ASUTOSH GHANTO <44160439+asutoshgha@users.noreply.github.com> Date: Tue, 2 Feb 2021 13:29:56 +0530 Subject: [PATCH 09/28] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a268b420..f1c2e63e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ pip install -r requirements.txt python manim.py example_scenes.py OpeningManimExample ``` ### Mac OSX -1. Install FFmpeg,LaTeX,cairo in terminal using homebrew. +1. Install FFmpeg, LaTeX, Cairo in terminal using homebrew. ```sh brew install ffmpeg mactex cairo ``` From be5762ba9c8a866640b8c8c9ded64d1d346d7de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B9=A4=E7=BF=94=E4=B8=87=E9=87=8C?= <44120331+TonyCrane@users.noreply.github.com> Date: Tue, 2 Feb 2021 16:17:18 +0800 Subject: [PATCH 10/28] Update README.md --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f1c2e63e..7101b55e 100644 --- a/README.md +++ b/README.md @@ -30,17 +30,17 @@ python manim.py example_scenes.py OpeningManimExample ``` ### Mac OSX 1. Install FFmpeg, LaTeX, Cairo in terminal using homebrew. - ```sh - brew install ffmpeg mactex cairo - ``` + ```sh + brew install ffmpeg mactex cairo + ``` -2. Install latest version of manim using this command if you dont want to tinker with code.(virtualenv wrapper is recommended) - ```sh - git clone https://github.com/3b1b/manim.git - cd manim - pip install -r requirements.txt - python manim.py example_scenes.py OpeningManimExample - ``` +2. Install latest version of manim using these command. + ```sh + git clone https://github.com/3b1b/manim.git + cd manim + pip install -r requirements.txt + python manim.py example_scenes.py OpeningManimExample + ``` ### Directly (Windows) 1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows). From 32632367b6fa9a8cbfe818f74a815251e2aecb70 Mon Sep 17 00:00:00 2001 From: Sahil Makhijani Date: Wed, 3 Feb 2021 00:04:30 +0530 Subject: [PATCH 11/28] Changed manim downloads location from default to custom_default config --- manimlib/utils/directories.py | 3 +++ manimlib/utils/file_ops.py | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/manimlib/utils/directories.py b/manimlib/utils/directories.py index e5629140..dfc9aaec 100644 --- a/manimlib/utils/directories.py +++ b/manimlib/utils/directories.py @@ -23,6 +23,9 @@ def get_text_dir(): def get_mobject_data_dir(): return guarantee_existence(os.path.join(get_temp_dir(), "mobject_data")) +def get_downloads_dir(): + return guarantee_existence(os.path.join(get_temp_dir(), "manim_downloads")) + def get_output_dir(): return guarantee_existence(get_directories()["output"]) diff --git a/manimlib/utils/file_ops.py b/manimlib/utils/file_ops.py index 761bf039..75587761 100644 --- a/manimlib/utils/file_ops.py +++ b/manimlib/utils/file_ops.py @@ -3,7 +3,6 @@ import numpy as np import validators import urllib.request -import tempfile def add_extension_if_not_present(file_name, extension): @@ -24,10 +23,9 @@ def find_file(file_name, directories=None, extensions=None): # Check if this is a file online first, and if so, download # it to a temporary directory if validators.url(file_name): + from manimlib.utils.directories import get_downloads_dir stem, name = os.path.split(file_name) - folder = guarantee_existence( - os.path.join(tempfile.gettempdir(), "manim_downloads") - ) + folder = get_downloads_dir() path = os.path.join(folder, name) urllib.request.urlretrieve(file_name, path) return path From 1097f0df96c8d53da737bf0ee2ebd9308c4f0f47 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 2 Feb 2021 15:56:55 -0800 Subject: [PATCH 12/28] Small cleanups --- custom_defaults.yml | 2 +- manimlib/utils/space_ops.py | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/custom_defaults.yml b/custom_defaults.yml index 7b89767c..d34236ae 100644 --- a/custom_defaults.yml +++ b/custom_defaults.yml @@ -21,7 +21,7 @@ tex: template_file: "tex_template.tex" intermediate_filetype: "dvi" text_to_replace: "[tex_expression]" - # # For ctex, use the following configuration + # For ctex, use the following configuration # executable: "xelatex -no-pdf" # template_file: "ctex_template.tex" # intermediate_filetype: "xdv" diff --git a/manimlib/utils/space_ops.py b/manimlib/utils/space_ops.py index 177f9ae6..5b769e49 100644 --- a/manimlib/utils/space_ops.py +++ b/manimlib/utils/space_ops.py @@ -361,16 +361,15 @@ def earclip_triangulation(verts, rings): n = len(verts) # Establish where loop indices should be connected loop_connections = dict() - # for e0, e1 in zip(rings, rings[1:]): - e0 = rings[0] - for e1 in rings[1:]: - # Find closet pair of points with the first - # coming from the current ring, and the second - # coming from the next ring + end0 = rings[0] + for end1 in rings[1:]: + # Find the closet pair of points with the first + # from the current ring, and the second from the + # next ring index_pairs = [ (i, j) - for i in range(0, e0) - for j in range(e0, e1) + for i in range(0, end0) + for j in range(end0, end1) if i not in loop_connections if j not in loop_connections ] @@ -383,14 +382,15 @@ def earclip_triangulation(verts, rings): # it's treated as a single highly-convex ring loop_connections[i] = j loop_connections[j] = i - e0 = e1 + end0 = end1 # Setup linked list after = [] - e0 = 0 - for e1 in rings: - after.extend([*range(e0 + 1, e1), e0]) - e0 = e1 + end0 = 0 + for end1 in rings: + after.extend(range(end0 + 1, end1)) + after.append(end0) + end0 = end1 # Find an ordering of indices walking around the polygon indices = [] From 2fbe0c6ee6535dd73c40279e91d90550b330929a Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 2 Feb 2021 16:19:45 -0800 Subject: [PATCH 13/28] Performance improvement for triangulation --- manimlib/utils/space_ops.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/manimlib/utils/space_ops.py b/manimlib/utils/space_ops.py index 5b769e49..804a3689 100644 --- a/manimlib/utils/space_ops.py +++ b/manimlib/utils/space_ops.py @@ -366,16 +366,22 @@ def earclip_triangulation(verts, rings): # Find the closet pair of points with the first # from the current ring, and the second from the # next ring - index_pairs = [ - (i, j) - for i in range(0, end0) - for j in range(end0, end1) - if i not in loop_connections - if j not in loop_connections + filtered_i, filtered_j = [ + list(filter( + lambda i: i not in loop_connections, + indices + )) + for indices in (range(0, end0), range(end0, end1)) ] - i, j = index_pairs[np.argmin([ - norm_squared(verts[i] - verts[j]) - for i, j in index_pairs + + i = filtered_i[np.argmin([ + # It's slightly faster to use L-infinity norm + max(abs(verts[i] - verts[end0])) + for i in filtered_i + ])] + j = filtered_j[np.argmin([ + max(abs(verts[i] - verts[j])) + for j in filtered_j ])] # Connect the polygon at these points so that From ddcd052036cd6dd3365f5e81a67c52bdc45e3518 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 2 Feb 2021 16:26:25 -0800 Subject: [PATCH 14/28] Performance improvements for triangulation --- manimlib/utils/space_ops.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/manimlib/utils/space_ops.py b/manimlib/utils/space_ops.py index 804a3689..612c15e3 100644 --- a/manimlib/utils/space_ops.py +++ b/manimlib/utils/space_ops.py @@ -1,6 +1,5 @@ import numpy as np import math -import itertools as it from mapbox_earcut import triangulate_float32 as earcut from manimlib.constants import RIGHT @@ -376,11 +375,11 @@ def earclip_triangulation(verts, rings): i = filtered_i[np.argmin([ # It's slightly faster to use L-infinity norm - max(abs(verts[i] - verts[end0])) + norm_squared(verts[i] - verts[end0]) for i in filtered_i ])] j = filtered_j[np.argmin([ - max(abs(verts[i] - verts[j])) + norm_squared(verts[i] - verts[j]) for j in filtered_j ])] From 0c6149c9ddb99ed91f974c9ad503dba680d35eb3 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 2 Feb 2021 16:43:24 -0800 Subject: [PATCH 15/28] Minor cleanup to triangulation --- manimlib/utils/space_ops.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/manimlib/utils/space_ops.py b/manimlib/utils/space_ops.py index 612c15e3..950a5891 100644 --- a/manimlib/utils/space_ops.py +++ b/manimlib/utils/space_ops.py @@ -343,7 +343,7 @@ def is_inside_triangle(p, a, b, c): def norm_squared(v): - return sum(v * v) + return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] # TODO, fails for polygons drawn over themselves @@ -352,7 +352,7 @@ def earclip_triangulation(verts, rings): Returns a list of indices giving a triangulation of a polygon, potentially with holes - - verts is an NxM numpy array of points with M > 2 + - verts is a numpy array of points - rings is a list of indices indicating where the ends of new paths are @@ -362,25 +362,27 @@ def earclip_triangulation(verts, rings): loop_connections = dict() end0 = rings[0] for end1 in rings[1:]: - # Find the closet pair of points with the first - # from the current ring, and the second from the - # next ring - filtered_i, filtered_j = [ - list(filter( - lambda i: i not in loop_connections, - indices - )) - for indices in (range(0, end0), range(end0, end1)) - ] + # Find a close pair of points connecting the current + # ring to the next ring - i = filtered_i[np.argmin([ - # It's slightly faster to use L-infinity norm + # Ignore indices already used for prior connections + i_range = list(filter( + lambda i: i not in loop_connections, + range(0, end0) + )) + j_range = list(range(end0, end1)) + + # Closet point on the first ring to the first point + # of the second ring + i = i_range[np.argmin([ norm_squared(verts[i] - verts[end0]) - for i in filtered_i + for i in i_range ])] - j = filtered_j[np.argmin([ + # Closet point of the second ring to the aforementioned + # point of the first ring + j = j_range[np.argmin([ norm_squared(verts[i] - verts[j]) - for j in filtered_j + for j in j_range ])] # Connect the polygon at these points so that From 3938f81c1b4a5ee81d5bfc6563c17a225f7e5068 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 2 Feb 2021 16:44:04 -0800 Subject: [PATCH 16/28] Performance improvements for Write and DrawBorderWithFill --- manimlib/animation/creation.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/manimlib/animation/creation.py b/manimlib/animation/creation.py index f888bb73..5d29b52e 100644 --- a/manimlib/animation/creation.py +++ b/manimlib/animation/creation.py @@ -70,6 +70,10 @@ class DrawBorderThenFill(Animation): super().__init__(vmobject, **kwargs) def begin(self): + # Trigger triangulation calculation + for submob in self.mobject.get_family(): + submob.get_triangulation() + self.outline = self.get_outline() super().begin() self.mobject.match_style(self.outline) @@ -103,6 +107,7 @@ class DrawBorderThenFill(Animation): submob.set_data(outline.data) submob.unlock_data() submob.lock_matching_data(submob, start) + submob.needs_new_triangulation = False self.sm_to_index[hash(submob)] = 1 if index == 0: From fc6953e102731748aadfdc00a036fc5c59fad9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B9=A4=E7=BF=94=E4=B8=87=E9=87=8C?= <44120331+TonyCrane@users.noreply.github.com> Date: Wed, 3 Feb 2021 17:17:55 +0800 Subject: [PATCH 17/28] remove samples=1 in window.py --- manimlib/window.py | 1 - 1 file changed, 1 deletion(-) diff --git a/manimlib/window.py b/manimlib/window.py index 9a883e22..eeb60ae5 100644 --- a/manimlib/window.py +++ b/manimlib/window.py @@ -12,7 +12,6 @@ class Window(PygletWindow): resizable = True gl_version = (3, 3) vsync = True - samples = 1 cursor = True def __init__(self, scene, **kwargs): From 5a16e3a35851e9a819d931cc5afbb2e1d948c37c Mon Sep 17 00:00:00 2001 From: Samip Poudel <074bct533.samip@pcampus.edu.np> Date: Wed, 3 Feb 2021 17:22:28 +0545 Subject: [PATCH 18/28] Converted 0 to 0.0 in sdf() and angle_between_vectors() --- manimlib/shaders/quadratic_bezier_fill/frag.glsl | 2 +- manimlib/shaders/quadratic_bezier_stroke/geom.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manimlib/shaders/quadratic_bezier_fill/frag.glsl b/manimlib/shaders/quadratic_bezier_fill/frag.glsl index c16c167e..b2a1c82a 100644 --- a/manimlib/shaders/quadratic_bezier_fill/frag.glsl +++ b/manimlib/shaders/quadratic_bezier_fill/frag.glsl @@ -51,7 +51,7 @@ float sdf(){ float sgn = orientation * sign(v2); float Fp = (p.x * p.x - p.y); if(sgn * Fp < 0){ - return 0; + return 0.0; }else{ return min_dist_to_curve(uv_coords, uv_b2, bezier_degree); } diff --git a/manimlib/shaders/quadratic_bezier_stroke/geom.glsl b/manimlib/shaders/quadratic_bezier_stroke/geom.glsl index ffb4e8eb..8baea0f9 100644 --- a/manimlib/shaders/quadratic_bezier_stroke/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_stroke/geom.glsl @@ -66,7 +66,7 @@ void flatten_points(in vec3[3] points, out vec2[3] flat_points){ float angle_between_vectors(vec2 v1, vec2 v2){ float v1_norm = length(v1); float v2_norm = length(v2); - if(v1_norm == 0 || v2_norm == 0) return 0; + if(v1_norm == 0 || v2_norm == 0) return 0.0; float dp = dot(v1, v2) / (v1_norm * v2_norm); float angle = acos(clamp(dp, -1.0, 1.0)); float sn = sign(cross2d(v1, v2)); From c8f4c4972042ae54f2cf4016f9a8ab502f8ee682 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 2 Feb 2021 17:20:48 -0800 Subject: [PATCH 19/28] Yet another triangulation fix --- manimlib/utils/space_ops.py | 73 +++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/manimlib/utils/space_ops.py b/manimlib/utils/space_ops.py index 950a5891..ef09f306 100644 --- a/manimlib/utils/space_ops.py +++ b/manimlib/utils/space_ops.py @@ -1,4 +1,5 @@ import numpy as np +import itertools as it import math from mapbox_earcut import triangulate_float32 as earcut @@ -347,54 +348,64 @@ def norm_squared(v): # TODO, fails for polygons drawn over themselves -def earclip_triangulation(verts, rings): +def earclip_triangulation(verts, ring_ends): """ Returns a list of indices giving a triangulation of a polygon, potentially with holes - verts is a numpy array of points - - rings is a list of indices indicating where + - ring_ends is a list of indices indicating where the ends of new paths are """ - n = len(verts) - # Establish where loop indices should be connected + + # First, connect all the rings so that the polygon + # with holes is instead treated as a (very convex) + # polygon with one edge. Do this by drawing connections + # between rings close to each other + rings = [ + list(range(e0, e1)) + for e0, e1 in zip([0, *ring_ends], ring_ends) + ] + attached_rings = rings[:1] + detached_rings = rings[1:] loop_connections = dict() - end0 = rings[0] - for end1 in rings[1:]: - # Find a close pair of points connecting the current - # ring to the next ring - # Ignore indices already used for prior connections - i_range = list(filter( - lambda i: i not in loop_connections, - range(0, end0) - )) - j_range = list(range(end0, end1)) + while detached_rings: + i_range, j_range = [ + list(filter( + # Ignore indices that are already being + # used to draw some connection + lambda i: i not in loop_connections, + it.chain(*ring_group) + )) + for ring_group in (attached_rings, detached_rings) + ] - # Closet point on the first ring to the first point - # of the second ring - i = i_range[np.argmin([ - norm_squared(verts[i] - verts[end0]) - for i in i_range - ])] - # Closet point of the second ring to the aforementioned - # point of the first ring - j = j_range[np.argmin([ - norm_squared(verts[i] - verts[j]) - for j in j_range - ])] + # Closet point on the atttached rings to the first point + # of the detached rings + i = min(i_range, key=lambda i: norm_squared(verts[i] - verts[j_range[0]])) + # Closet point of the detached rings to the aforementioned + # point of the attached rings + j = min(j_range, key=lambda j: norm_squared(verts[i] - verts[j])) - # Connect the polygon at these points so that - # it's treated as a single highly-convex ring + # Remember to connect the polygon at these points loop_connections[i] = j loop_connections[j] = i - end0 = end1 + + # Move the ring which j belongs to from the + # attached list to the detached list + new_ring = next(filter( + lambda ring: ring[0] <= j < ring[-1], + detached_rings + )) + detached_rings.remove(new_ring) + attached_rings.append(new_ring) # Setup linked list after = [] end0 = 0 - for end1 in rings: + for end1 in ring_ends: after.extend(range(end0 + 1, end1)) after.append(end0) end0 = end1 @@ -402,7 +413,7 @@ def earclip_triangulation(verts, rings): # Find an ordering of indices walking around the polygon indices = [] i = 0 - for x in range(n + len(rings) - 1): + for x in range(len(verts) + len(ring_ends) - 1): # starting = False if i in loop_connections: j = loop_connections[i] From 46294a5fad6dd3a148b5f1d5a19981a57a57edaa Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 13:41:02 -0800 Subject: [PATCH 20/28] Fix aliasing issue on filled VMobject by calling get_unit_normal on reduced control points --- manimlib/shaders/quadratic_bezier_fill/geom.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manimlib/shaders/quadratic_bezier_fill/geom.glsl b/manimlib/shaders/quadratic_bezier_fill/geom.glsl index acd15617..4fd9245f 100644 --- a/manimlib/shaders/quadratic_bezier_fill/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_fill/geom.glsl @@ -121,11 +121,11 @@ void main(){ return; } - vec3 local_unit_normal = get_unit_normal(vec3[3](bp[0], bp[1], bp[2])); - orientation = sign(dot(v_global_unit_normal[0], local_unit_normal)); - vec3 new_bp[3]; bezier_degree = get_reduced_control_points(vec3[3](bp[0], bp[1], bp[2]), new_bp); + vec3 local_unit_normal = get_unit_normal(new_bp); + orientation = sign(dot(v_global_unit_normal[0], local_unit_normal)); + if(bezier_degree >= 1){ emit_pentagon(new_bp, local_unit_normal); } From d981ee47e2acfa2ded1d581efc0d0b23889133df Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 14:17:39 -0800 Subject: [PATCH 21/28] Shouldn't transform between Text and TexText --- example_scenes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_scenes.py b/example_scenes.py index f2a95727..fc44f8f1 100644 --- a/example_scenes.py +++ b/example_scenes.py @@ -25,7 +25,7 @@ class OpeningManimExample(Scene): transform_title = Text("That was a transform") transform_title.to_corner(UL) self.play( - Transform(title, transform_title), + Transform(title[0], transform_title), LaggedStartMap(FadeOut, basel, shift=DOWN), ) self.wait() From 003fafc20f9072d9dc8b248d6e2f7a4d13e9ad43 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 14:17:55 -0800 Subject: [PATCH 22/28] Unlock mobject data after Write --- manimlib/animation/creation.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/manimlib/animation/creation.py b/manimlib/animation/creation.py index 5d29b52e..4f6aba64 100644 --- a/manimlib/animation/creation.py +++ b/manimlib/animation/creation.py @@ -79,6 +79,10 @@ class DrawBorderThenFill(Animation): self.mobject.match_style(self.outline) self.mobject.lock_matching_data(self.mobject, self.outline) + def finish(self): + super().finish() + self.mobject.unlock_data() + def get_outline(self): outline = self.mobject.copy() outline.set_fill(opacity=0) From 0726dccd0a0526a64ded40112daa39a22ce03c79 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 14:18:21 -0800 Subject: [PATCH 23/28] Ensure get_height, etc. all return positive values --- manimlib/mobject/mobject.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manimlib/mobject/mobject.py b/manimlib/mobject/mobject.py index 8f711a6d..e761abed 100644 --- a/manimlib/mobject/mobject.py +++ b/manimlib/mobject/mobject.py @@ -1002,7 +1002,7 @@ class Mobject(object): def length_over_dim(self, dim): bb = self.get_bounding_box() - return (bb[2] - bb[0])[dim] + return abs((bb[2] - bb[0])[dim]) def get_width(self): return self.length_over_dim(0) From 7dffa24acd8547ace19d479bda44438245f7d219 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 14:18:58 -0800 Subject: [PATCH 24/28] Only reorient points for triangulation if the normal vector is not OUT --- manimlib/mobject/types/vectorized_mobject.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/manimlib/mobject/types/vectorized_mobject.py b/manimlib/mobject/types/vectorized_mobject.py index b5b33e29..425af386 100644 --- a/manimlib/mobject/types/vectorized_mobject.py +++ b/manimlib/mobject/types/vectorized_mobject.py @@ -765,9 +765,9 @@ class VMobject(Mobject): self.needs_new_triangulation = False return self.triangulation - # Rotate points such that unit normal vector is OUT - # TODO, 99% of the time this does nothing. Do a check for that? - points = np.dot(points, z_to_vector(normal_vector)) + if not np.isclose(normal_vector, OUT).all(): + # Rotate points such that unit normal vector is OUT + points = np.dot(points, z_to_vector(normal_vector)) indices = np.arange(len(points), dtype=int) b0s = points[0::3] @@ -797,7 +797,9 @@ class VMobject(Mobject): # Triangulate inner_verts = points[inner_vert_indices] - inner_tri_indices = inner_vert_indices[earclip_triangulation(inner_verts, rings)] + inner_tri_indices = inner_vert_indices[ + earclip_triangulation(inner_verts, rings) + ] tri_indices = np.hstack([indices, inner_tri_indices]) self.triangulation = tri_indices From 521e3ef1432d5db239272380c17ed0c8d9c7ceb4 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 14:19:20 -0800 Subject: [PATCH 25/28] Include wait in the embed shortcut commends --- manimlib/scene/scene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manimlib/scene/scene.py b/manimlib/scene/scene.py index d82a4539..1f4e4926 100644 --- a/manimlib/scene/scene.py +++ b/manimlib/scene/scene.py @@ -125,7 +125,7 @@ class Scene(object): # once embeded, and add a few custom shortcuts local_ns = inspect.currentframe().f_back.f_locals local_ns["touch"] = self.interact - for term in ("play", "add", "remove", "clear", "save_state", "restore"): + for term in ("play", "wait", "add", "remove", "clear", "save_state", "restore"): local_ns[term] = getattr(self, term) shell(local_ns=local_ns, stack_depth=2) # End scene when exiting an embed. From 65f4f4bd290b748d16c96112e776a502c93210f0 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 15:58:16 -0800 Subject: [PATCH 26/28] Factor out computing bounding box --- manimlib/mobject/mobject.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/manimlib/mobject/mobject.py b/manimlib/mobject/mobject.py index e761abed..bd7c487e 100644 --- a/manimlib/mobject/mobject.py +++ b/manimlib/mobject/mobject.py @@ -190,10 +190,12 @@ class Mobject(object): return self.get_num_points() > 0 def get_bounding_box(self): - if not self.needs_new_bounding_box: - return self.data["bounding_box"] + if self.needs_new_bounding_box: + self.data["bounding_box"] = self.compute_bounding_box() + self.needs_new_bounding_box = False + return self.data["bounding_box"] - # all_points = self.get_all_points() + def compute_bounding_box(self): all_points = np.vstack([ self.get_points(), *( @@ -203,15 +205,13 @@ class Mobject(object): ) ]) if len(all_points) == 0: - self.data["bounding_box"] = np.zeros((3, self.dim)) + return np.zeros((3, self.dim)) else: # Lower left and upper right corners mins = all_points.min(0) maxs = all_points.max(0) mids = (mins + maxs) / 2 - self.data["bounding_box"] = np.array([mins, mids, maxs]) - self.needs_new_bounding_box = False - return self.data["bounding_box"] + return np.array([mins, mids, maxs]) def refresh_bounding_box(self, recurse_down=False, recurse_up=True): for mob in self.get_family(recurse_down): From f13c41bcbb5d8508d7d3be3b8e1331ba1407ee0f Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 15:58:27 -0800 Subject: [PATCH 27/28] DotCloud improvements --- manimlib/mobject/types/dot_cloud.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/manimlib/mobject/types/dot_cloud.py b/manimlib/mobject/types/dot_cloud.py index d579e8fd..82e2b0ca 100644 --- a/manimlib/mobject/types/dot_cloud.py +++ b/manimlib/mobject/types/dot_cloud.py @@ -1,6 +1,5 @@ import numpy as np import moderngl -import numbers from manimlib.constants import GREY_C from manimlib.mobject.types.point_cloud_mobject import PMobject @@ -16,7 +15,7 @@ class DotCloud(PMobject): CONFIG = { "color": GREY_C, "opacity": 1, - "radii": DEFAULT_DOT_CLOUD_RADIUS, + "radius": DEFAULT_DOT_CLOUD_RADIUS, "shader_folder": "true_dot", "render_primitive": moderngl.POINTS, "shader_dtype": [ @@ -34,7 +33,7 @@ class DotCloud(PMobject): def init_data(self): super().init_data() self.data["radii"] = np.zeros((1, 1)) - self.set_radii(self.radii) + self.set_radius(self.radius) def to_grid(self, n_rows, n_cols, n_layers=1, buff_ratio=None, @@ -58,25 +57,38 @@ class DotCloud(PMobject): radius = self.get_radius() ns = [n_cols, n_rows, n_layers] brs = [h_buff_ratio, v_buff_ratio, d_buff_ratio] + self.set_radius(0) for n, br, dim in zip(ns, brs, range(3)): self.rescale_to_fit(2 * radius * (1 + br) * (n - 1), dim, stretch=True) + self.set_radius(radius) if height is not None: self.set_height(height) self.center() return self def set_radii(self, radii): - if not isinstance(radii, numbers.Number): - radii = resize_preserving_order(radii, len(self.data["radii"])) - self.data["radii"][:] = radii + self.data["radii"][:] = resize_preserving_order(radii, len(self.data["radii"])) + self.refresh_bounding_box() return self def get_radii(self): return self.data["radii"] + def set_radius(self, radius): + self.data["radii"][:] = radius + self.refresh_bounding_box() + return self + def get_radius(self): return self.get_radii().max() + def compute_bounding_box(self): + bb = super().compute_bounding_box() + radius = self.get_radius() + bb[0] += np.full((3,), -radius) + bb[2] += np.full((3,), radius) + return bb + def scale(self, scale_factor, scale_radii=True, **kwargs): super().scale(scale_factor, **kwargs) if scale_radii: From 1727d4b86a125c4ce722a5900a53734162837b51 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 3 Feb 2021 17:52:11 -0800 Subject: [PATCH 28/28] Small hacky tweak to fix more triangulation issues --- manimlib/utils/space_ops.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/manimlib/utils/space_ops.py b/manimlib/utils/space_ops.py index ef09f306..c124cbec 100644 --- a/manimlib/utils/space_ops.py +++ b/manimlib/utils/space_ops.py @@ -382,12 +382,18 @@ def earclip_triangulation(verts, ring_ends): for ring_group in (attached_rings, detached_rings) ] - # Closet point on the atttached rings to the first point + # Closet point on the atttached rings to an estimated midpoint # of the detached rings - i = min(i_range, key=lambda i: norm_squared(verts[i] - verts[j_range[0]])) + tmp_j_vert = midpoint( + verts[j_range[0]], + verts[j_range[len(j_range) // 2]] + ) + i = min(i_range, key=lambda i: norm_squared(verts[i] - tmp_j_vert)) # Closet point of the detached rings to the aforementioned # point of the attached rings j = min(j_range, key=lambda j: norm_squared(verts[i] - verts[j])) + # Recalculate i based on new j + i = min(i_range, key=lambda i: norm_squared(verts[i] - verts[j])) # Remember to connect the polygon at these points loop_connections[i] = j