mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 14:03:59 +08:00
Cleanup of ZoomedScene updates
This commit is contained in:
@ -34,12 +34,12 @@ class Camera(object):
|
||||
"frame_shape": (FRAME_HEIGHT, FRAME_WIDTH),
|
||||
"space_center": ORIGIN,
|
||||
"background_color": BLACK,
|
||||
"background_alpha": 0, # Out of rgb_max_val
|
||||
# Points in vectorized mobjects with norm greater
|
||||
# than this value will be rescaled.
|
||||
"max_allowable_norm": FRAME_WIDTH,
|
||||
"image_mode": "RGBA",
|
||||
"n_rgb_coords": 4,
|
||||
"background_alpha": 0, # Out of rgb_max_val
|
||||
"pixel_array_dtype": 'uint8',
|
||||
"use_z_coordinate_for_display_order": False,
|
||||
# z_buff_func is only used if the flag above is set to True.
|
||||
|
@ -10,9 +10,9 @@ from utils.config_ops import digest_config
|
||||
|
||||
class MovingCamera(Camera):
|
||||
"""
|
||||
Stays in line with the height, width and position
|
||||
of a given mobject
|
||||
Stays in line with the height, width and position of it's 'frame', which is a Rectangle
|
||||
"""
|
||||
|
||||
CONFIG = {
|
||||
"fixed_dimension": 0, # width
|
||||
"default_frame_stroke_color": WHITE,
|
||||
@ -21,8 +21,8 @@ class MovingCamera(Camera):
|
||||
|
||||
def __init__(self, frame=None, **kwargs):
|
||||
"""
|
||||
frame is a Mobject, (should be a rectangle) determining
|
||||
which region of space the camera displys
|
||||
frame is a Mobject, (should almost certainly be a rectangle)
|
||||
determining which region of space the camera displys
|
||||
"""
|
||||
digest_config(self, kwargs)
|
||||
if frame is None:
|
||||
|
@ -3,17 +3,9 @@ from __future__ import absolute_import
|
||||
from camera.moving_camera import MovingCamera
|
||||
from utils.iterables import list_difference_update
|
||||
|
||||
# Distinct notions of view frame vs. display frame
|
||||
|
||||
# For now, let's say it is the responsibility of the scene holding
|
||||
# this camera to add all of the relevant image_mobjects_from_cameras,
|
||||
# as well as their display_frames
|
||||
|
||||
|
||||
class MultiCamera(MovingCamera):
|
||||
CONFIG = {
|
||||
# "lock_display_frame_dimensions_to_view_frame": True,
|
||||
# "display_frame_fixed_dimension": 1, # Height
|
||||
"allow_cameras_to_capture_their_own_display": False,
|
||||
}
|
||||
|
||||
@ -31,11 +23,7 @@ class MultiCamera(MovingCamera):
|
||||
self.image_mobjects_from_cameras.append(imfc)
|
||||
|
||||
def update_sub_cameras(self):
|
||||
# if self.lock_display_frame_dimensions_to_view_frame:
|
||||
# for imfc in self.image_mobjects_from_cameras:
|
||||
# aspect_ratio = imfc.view_frame.get_width() / imfc.view_frame.get_height()
|
||||
|
||||
# Reshape sub_camera pixel_arrays
|
||||
""" Reshape sub_camera pixel_arrays """
|
||||
for imfc in self.image_mobjects_from_cameras:
|
||||
frame_height, frame_width = self.frame_shape
|
||||
pixel_height, pixel_width = self.get_pixel_array().shape[:2]
|
||||
@ -55,7 +43,6 @@ class MultiCamera(MovingCamera):
|
||||
return self
|
||||
|
||||
def capture_mobjects(self, mobjects, **kwargs):
|
||||
# Make sure all frames are in mobjects? Or not?
|
||||
self.update_sub_cameras()
|
||||
for imfc in self.image_mobjects_from_cameras:
|
||||
to_add = list(mobjects)
|
||||
|
@ -19,11 +19,7 @@ class AbstractImageMobject(Mobject):
|
||||
Automatically filters out black pixels
|
||||
"""
|
||||
CONFIG = {
|
||||
"filter_color": "black",
|
||||
"invert": False,
|
||||
# "use_cache" : True,
|
||||
"height": 2.0,
|
||||
"image_mode": "RGBA",
|
||||
"pixel_array_dtype": "uint8",
|
||||
}
|
||||
|
||||
@ -31,12 +27,11 @@ class AbstractImageMobject(Mobject):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def set_color(self):
|
||||
# Likely to be implemented in subclasses
|
||||
# Likely to be implemented in subclasses, but no obgligation
|
||||
pass
|
||||
|
||||
def init_points(self):
|
||||
# Corresponding corners of image are fixed to these
|
||||
# Three points
|
||||
# Corresponding corners of image are fixed to these 3 points
|
||||
self.points = np.array([
|
||||
UP + LEFT,
|
||||
UP + RIGHT,
|
||||
@ -52,16 +47,9 @@ class AbstractImageMobject(Mobject):
|
||||
|
||||
|
||||
class ImageMobject(AbstractImageMobject):
|
||||
"""
|
||||
Automatically filters out black pixels
|
||||
"""
|
||||
CONFIG = {
|
||||
"filter_color": "black",
|
||||
"invert": False,
|
||||
# "use_cache" : True,
|
||||
"height": 2.0,
|
||||
"image_mode": "RGBA",
|
||||
"pixel_array_dtype": "uint8",
|
||||
}
|
||||
|
||||
def __init__(self, filename_or_array, **kwargs):
|
||||
@ -118,6 +106,10 @@ class ImageMobject(AbstractImageMobject):
|
||||
mobject1.pixel_array, mobject2.pixel_array, alpha
|
||||
).astype(self.pixel_array_dtype)
|
||||
|
||||
# TODO, add the ability to have the dimensions/orientation of this
|
||||
# mobject more strongly tied to the frame of the camera it contains,
|
||||
# in the case where that's a MovingCamera
|
||||
|
||||
|
||||
class ImageMobjectFromCamera(AbstractImageMobject):
|
||||
CONFIG = {
|
||||
|
@ -1,17 +1,16 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import numpy as np
|
||||
|
||||
from scene.scene import Scene
|
||||
from animation.creation import FadeIn
|
||||
from camera.moving_camera import MovingCamera
|
||||
from camera.multi_camera import MultiCamera
|
||||
from mobject.geometry import Rectangle
|
||||
from mobject.types.image_mobject import ImageMobjectFromCamera
|
||||
|
||||
from constants import *
|
||||
|
||||
|
||||
# Note, any scenes from old videos using ZoomedScene will almost certainly
|
||||
# break, as it was restructured.
|
||||
|
||||
class ZoomedScene(Scene):
|
||||
CONFIG = {
|
||||
"camera_class": MultiCamera,
|
||||
@ -56,9 +55,10 @@ class ZoomedScene(Scene):
|
||||
self.zoomed_display = zoomed_display
|
||||
|
||||
def activate_zooming(self, animate=False, run_times=[2, 1]):
|
||||
self.zoom_activated = True
|
||||
zoomed_camera = self.zoomed_camera
|
||||
zoomed_display = self.zoomed_display
|
||||
|
||||
self.zoom_activated = True
|
||||
self.camera.add_image_mobject_from_camera(zoomed_display)
|
||||
|
||||
to_add = [zoomed_camera.frame, zoomed_display]
|
||||
@ -84,132 +84,7 @@ class ZoomedScene(Scene):
|
||||
zoomed_mobjects = [self.zoomed_camera.frame, self.zoomed_display]
|
||||
moving_zoomed_mobjects = set(moving_mobjects).intersection(zoomed_mobjects)
|
||||
if self.zoom_activated and moving_zoomed_mobjects:
|
||||
# If either of the zoomed_mobjects are moving, then so is
|
||||
# everything
|
||||
return self.mobjects
|
||||
else:
|
||||
return moving_mobjects
|
||||
|
||||
|
||||
|
||||
class OldZoomedScene(Scene):
|
||||
"""
|
||||
Move around self.little_rectangle to determine
|
||||
which part of the screen is zoomed in on.
|
||||
"""
|
||||
CONFIG = {
|
||||
"zoomed_canvas_frame_shape": (3, 3),
|
||||
"zoomed_canvas_center": None,
|
||||
"zoomed_canvas_corner": UP + RIGHT,
|
||||
"zoomed_canvas_corner_buff": DEFAULT_MOBJECT_TO_EDGE_BUFFER,
|
||||
"zoomed_camera_background": None,
|
||||
"little_rectangle_start_position": ORIGIN,
|
||||
"zoom_factor": 6,
|
||||
"square_color": WHITE,
|
||||
"zoom_activated": False,
|
||||
}
|
||||
|
||||
def activate_zooming(self):
|
||||
self.generate_big_rectangle()
|
||||
self.setup_zoomed_canvas()
|
||||
self.setup_zoomed_camera()
|
||||
self.zoom_activated = True
|
||||
|
||||
def animate_activate_zooming(self):
|
||||
self.activate_zooming()
|
||||
self.play(*map(FadeIn, [
|
||||
self.little_rectangle, self.big_rectangle
|
||||
]))
|
||||
|
||||
def disactivate_zooming(self):
|
||||
self.remove(self.big_rectangle, self.little_rectangle)
|
||||
self.zoom_activated = False
|
||||
|
||||
def get_zoomed_camera_mobject(self):
|
||||
return self.little_rectangle
|
||||
|
||||
def get_zoomed_screen(self):
|
||||
return self.big_rectangle
|
||||
|
||||
def generate_big_rectangle(self):
|
||||
height, width = self.zoomed_canvas_frame_shape
|
||||
self.big_rectangle = Rectangle(
|
||||
height=height,
|
||||
width=width,
|
||||
color=self.square_color
|
||||
)
|
||||
if self.zoomed_canvas_center is not None:
|
||||
self.big_rectangle.shift(self.zoomed_canvas_center)
|
||||
elif self.zoomed_canvas_corner is not None:
|
||||
self.big_rectangle.to_corner(
|
||||
self.zoomed_canvas_corner,
|
||||
buff=self.zoomed_canvas_corner_buff
|
||||
)
|
||||
self.add(self.big_rectangle)
|
||||
|
||||
def setup_zoomed_canvas(self):
|
||||
upper_left = self.big_rectangle.get_corner(UP + LEFT)
|
||||
lower_right = self.big_rectangle.get_corner(DOWN + RIGHT)
|
||||
pixel_coords = self.camera.points_to_pixel_coords(
|
||||
np.array([upper_left, lower_right])
|
||||
)
|
||||
self.zoomed_canvas_pixel_indices = pixel_coords
|
||||
(up, left), (down, right) = pixel_coords
|
||||
self.zoomed_canvas_pixel_shape = (
|
||||
right - left,
|
||||
down - up,
|
||||
)
|
||||
|
||||
def setup_zoomed_camera(self):
|
||||
self.little_rectangle = self.big_rectangle.copy()
|
||||
self.little_rectangle.scale(1. / self.zoom_factor)
|
||||
self.little_rectangle.move_to(
|
||||
self.little_rectangle_start_position
|
||||
)
|
||||
self.zoomed_camera = MovingCamera(
|
||||
self.little_rectangle,
|
||||
pixel_shape=self.zoomed_canvas_pixel_shape,
|
||||
background=self.zoomed_camera_background
|
||||
)
|
||||
self.add(self.little_rectangle)
|
||||
# TODO, is there a better way to hanld this?
|
||||
self.zoomed_camera.adjusted_thickness = lambda x: x
|
||||
|
||||
def get_frame(self):
|
||||
frame = Scene.get_frame(self)
|
||||
if self.zoom_activated:
|
||||
(up, left), (down, right) = self.zoomed_canvas_pixel_indices
|
||||
frame[left:right, up:down, :] = self.zoomed_camera.get_image()
|
||||
return frame
|
||||
|
||||
def set_camera_pixel_array(self, pixel_array):
|
||||
self.camera.set_pixel_array(pixel_array)
|
||||
if self.zoom_activated:
|
||||
(up, left), (down, right) = self.zoomed_canvas_pixel_indices
|
||||
self.zoomed_camera.set_pixel_array(
|
||||
pixel_array[left:right, up:down])
|
||||
|
||||
def set_camera_background(self, background):
|
||||
self.set_camera_pixel_array(self, background)
|
||||
# TODO, check this...
|
||||
|
||||
def reset_camera(self):
|
||||
self.camera.reset()
|
||||
if self.zoom_activated:
|
||||
self.zoomed_camera.reset()
|
||||
|
||||
def capture_mobjects_in_camera(self, mobjects, **kwargs):
|
||||
self.camera.capture_mobjects(mobjects, **kwargs)
|
||||
if self.zoom_activated:
|
||||
if self.big_rectangle in mobjects:
|
||||
mobjects = list(mobjects)
|
||||
mobjects.remove(self.big_rectangle)
|
||||
self.zoomed_camera.capture_mobjects(
|
||||
mobjects, **kwargs
|
||||
)
|
||||
|
||||
def get_moving_mobjects(self, *animations):
|
||||
moving_mobjects = Scene.get_moving_mobjects(self, *animations)
|
||||
if self.zoom_activated and self.little_rectangle in moving_mobjects:
|
||||
# When the camera is moving, so is everything,
|
||||
return self.mobjects
|
||||
else:
|
||||
return moving_mobjects
|
||||
return moving_mobjects
|
||||
|
Reference in New Issue
Block a user