mirror of
https://github.com/3b1b/manim.git
synced 2025-11-14 06:37:44 +00:00
Reorganized camera folder
This commit is contained in:
parent
0978984541
commit
087f66aca5
6 changed files with 140 additions and 131 deletions
|
|
@ -25,6 +25,8 @@ from animation.transform import *
|
|||
from animation.update import *
|
||||
|
||||
from camera.camera import *
|
||||
from camera.moving_camera import *
|
||||
from camera.mapping_camera import *
|
||||
|
||||
from continual_animation.continual_animation import *
|
||||
|
||||
|
|
|
|||
129
camera/camera.py
129
camera/camera.py
|
|
@ -11,22 +11,18 @@ from colour import Color
|
|||
|
||||
from constants import *
|
||||
from mobject.image_mobject import ImageMobject
|
||||
from mobject.mobject import Group
|
||||
from mobject.mobject import Mobject
|
||||
from mobject.point_cloud_mobject import PMobject
|
||||
from mobject.vectorized_mobject import VMobject
|
||||
from utils.color import color_to_int_rgba
|
||||
from utils.color import rgb_to_hex
|
||||
from utils.config_ops import DictAsObject
|
||||
from utils.config_ops import digest_config
|
||||
from utils.config_ops import digest_locals
|
||||
from utils.images import get_full_raster_image_path
|
||||
from utils.iterables import batch_by_property
|
||||
from utils.iterables import list_difference_update
|
||||
from utils.iterables import remove_list_redundancies
|
||||
from utils.simple_functions import fdiv
|
||||
|
||||
|
||||
class Camera(object):
|
||||
CONFIG = {
|
||||
"background_image" : None,
|
||||
|
|
@ -613,128 +609,3 @@ class BackgroundColoredVMobjectDisplayer(object):
|
|||
self.reset_canvas()
|
||||
return curr_array
|
||||
|
||||
|
||||
class MovingCamera(Camera):
|
||||
"""
|
||||
Stays in line with the height, width and position
|
||||
of a given mobject
|
||||
"""
|
||||
CONFIG = {
|
||||
"aligned_dimension" : "width" #or height
|
||||
}
|
||||
def __init__(self, mobject, **kwargs):
|
||||
digest_locals(self)
|
||||
Camera.__init__(self, **kwargs)
|
||||
|
||||
def capture_mobjects(self, *args, **kwargs):
|
||||
self.space_center = self.mobject.get_center()
|
||||
self.realign_frame_shape()
|
||||
Camera.capture_mobjects(self, *args, **kwargs)
|
||||
|
||||
def realign_frame_shape(self):
|
||||
height, width = self.frame_shape
|
||||
if self.aligned_dimension == "height":
|
||||
self.frame_shape = (self.mobject.get_height(), width)
|
||||
else:
|
||||
self.frame_shape = (height, self.mobject.get_width())
|
||||
self.resize_frame_shape(0 if self.aligned_dimension == "height" else 1)
|
||||
|
||||
# TODO: Add an attribute to mobjects under which they can specify that they should just
|
||||
# map their centers but remain otherwise undistorted (useful for labels, etc.)
|
||||
class MappingCamera(Camera):
|
||||
CONFIG = {
|
||||
"mapping_func" : lambda p : p,
|
||||
"min_anchor_points" : 50,
|
||||
"allow_object_intrusion" : False
|
||||
}
|
||||
|
||||
def points_to_pixel_coords(self, points):
|
||||
return Camera.points_to_pixel_coords(self, np.apply_along_axis(self.mapping_func, 1, points))
|
||||
|
||||
def capture_mobjects(self, mobjects, **kwargs):
|
||||
mobjects = self.get_mobjects_to_display(mobjects, **kwargs)
|
||||
if self.allow_object_intrusion:
|
||||
mobject_copies = mobjects
|
||||
else:
|
||||
mobject_copies = [mobject.copy() for mobject in mobjects]
|
||||
for mobject in mobject_copies:
|
||||
if isinstance(mobject, VMobject) and \
|
||||
0 < mobject.get_num_anchor_points() < self.min_anchor_points:
|
||||
mobject.insert_n_anchor_points(self.min_anchor_points)
|
||||
Camera.capture_mobjects(
|
||||
self, mobject_copies,
|
||||
include_submobjects = False,
|
||||
excluded_mobjects = None,
|
||||
)
|
||||
|
||||
# Note: This allows layering of multiple cameras onto the same portion of the pixel array,
|
||||
# the later cameras overwriting the former
|
||||
#
|
||||
# TODO: Add optional separator borders between cameras (or perhaps peel this off into a
|
||||
# CameraPlusOverlay class)
|
||||
class MultiCamera(Camera):
|
||||
def __init__(self, *cameras_with_start_positions, **kwargs):
|
||||
self.shifted_cameras = [
|
||||
DictAsObject(
|
||||
{
|
||||
"camera" : camera_with_start_positions[0],
|
||||
"start_x" : camera_with_start_positions[1][1],
|
||||
"start_y" : camera_with_start_positions[1][0],
|
||||
"end_x" : camera_with_start_positions[1][1] + camera_with_start_positions[0].pixel_shape[1],
|
||||
"end_y" : camera_with_start_positions[1][0] + camera_with_start_positions[0].pixel_shape[0],
|
||||
})
|
||||
for camera_with_start_positions in cameras_with_start_positions
|
||||
]
|
||||
Camera.__init__(self, **kwargs)
|
||||
|
||||
def capture_mobjects(self, mobjects, **kwargs):
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.capture_mobjects(mobjects, **kwargs)
|
||||
|
||||
self.pixel_array[
|
||||
shifted_camera.start_y:shifted_camera.end_y,
|
||||
shifted_camera.start_x:shifted_camera.end_x] \
|
||||
= shifted_camera.camera.pixel_array
|
||||
|
||||
def set_background(self, pixel_array, **kwargs):
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.set_background(
|
||||
pixel_array[
|
||||
shifted_camera.start_y:shifted_camera.end_y,
|
||||
shifted_camera.start_x:shifted_camera.end_x],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def set_pixel_array(self, pixel_array, **kwargs):
|
||||
Camera.set_pixel_array(self, pixel_array, **kwargs)
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.set_pixel_array(
|
||||
pixel_array[
|
||||
shifted_camera.start_y:shifted_camera.end_y,
|
||||
shifted_camera.start_x:shifted_camera.end_x],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def init_background(self):
|
||||
Camera.init_background(self)
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.init_background()
|
||||
|
||||
# A MultiCamera which, when called with two full-size cameras, initializes itself
|
||||
# as a splitscreen, also taking care to resize each individual camera within it
|
||||
class SplitScreenCamera(MultiCamera):
|
||||
def __init__(self, left_camera, right_camera, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
self.left_camera = left_camera
|
||||
self.right_camera = right_camera
|
||||
|
||||
half_width = self.pixel_shape[1] / 2
|
||||
for camera in [self.left_camera, self.right_camera]:
|
||||
camera.pixel_shape = (self.pixel_shape[0], half_width) # TODO: Round up on one if width is odd
|
||||
camera.init_background()
|
||||
camera.resize_frame_shape()
|
||||
camera.reset()
|
||||
|
||||
MultiCamera.__init__(self, (left_camera, (0, 0)), (right_camera, (0, half_width)))
|
||||
|
||||
|
||||
|
|
|
|||
104
camera/mapping_camera.py
Normal file
104
camera/mapping_camera.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from camera.camera import Camera
|
||||
from utils.config_ops import DictAsObject
|
||||
from utils.config_ops import digest_config
|
||||
|
||||
# TODO: Add an attribute to mobjects under which they can specify that they should just
|
||||
# map their centers but remain otherwise undistorted (useful for labels, etc.)
|
||||
class MappingCamera(Camera):
|
||||
CONFIG = {
|
||||
"mapping_func" : lambda p : p,
|
||||
"min_anchor_points" : 50,
|
||||
"allow_object_intrusion" : False
|
||||
}
|
||||
|
||||
def points_to_pixel_coords(self, points):
|
||||
return Camera.points_to_pixel_coords(self, np.apply_along_axis(self.mapping_func, 1, points))
|
||||
|
||||
def capture_mobjects(self, mobjects, **kwargs):
|
||||
mobjects = self.get_mobjects_to_display(mobjects, **kwargs)
|
||||
if self.allow_object_intrusion:
|
||||
mobject_copies = mobjects
|
||||
else:
|
||||
mobject_copies = [mobject.copy() for mobject in mobjects]
|
||||
for mobject in mobject_copies:
|
||||
if isinstance(mobject, VMobject) and \
|
||||
0 < mobject.get_num_anchor_points() < self.min_anchor_points:
|
||||
mobject.insert_n_anchor_points(self.min_anchor_points)
|
||||
Camera.capture_mobjects(
|
||||
self, mobject_copies,
|
||||
include_submobjects = False,
|
||||
excluded_mobjects = None,
|
||||
)
|
||||
|
||||
# Note: This allows layering of multiple cameras onto the same portion of the pixel array,
|
||||
# the later cameras overwriting the former
|
||||
#
|
||||
# TODO: Add optional separator borders between cameras (or perhaps peel this off into a
|
||||
# CameraPlusOverlay class)
|
||||
class MultiCamera(Camera):
|
||||
def __init__(self, *cameras_with_start_positions, **kwargs):
|
||||
self.shifted_cameras = [
|
||||
DictAsObject(
|
||||
{
|
||||
"camera" : camera_with_start_positions[0],
|
||||
"start_x" : camera_with_start_positions[1][1],
|
||||
"start_y" : camera_with_start_positions[1][0],
|
||||
"end_x" : camera_with_start_positions[1][1] + camera_with_start_positions[0].pixel_shape[1],
|
||||
"end_y" : camera_with_start_positions[1][0] + camera_with_start_positions[0].pixel_shape[0],
|
||||
})
|
||||
for camera_with_start_positions in cameras_with_start_positions
|
||||
]
|
||||
Camera.__init__(self, **kwargs)
|
||||
|
||||
def capture_mobjects(self, mobjects, **kwargs):
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.capture_mobjects(mobjects, **kwargs)
|
||||
|
||||
self.pixel_array[
|
||||
shifted_camera.start_y:shifted_camera.end_y,
|
||||
shifted_camera.start_x:shifted_camera.end_x] \
|
||||
= shifted_camera.camera.pixel_array
|
||||
|
||||
def set_background(self, pixel_array, **kwargs):
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.set_background(
|
||||
pixel_array[
|
||||
shifted_camera.start_y:shifted_camera.end_y,
|
||||
shifted_camera.start_x:shifted_camera.end_x],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def set_pixel_array(self, pixel_array, **kwargs):
|
||||
Camera.set_pixel_array(self, pixel_array, **kwargs)
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.set_pixel_array(
|
||||
pixel_array[
|
||||
shifted_camera.start_y:shifted_camera.end_y,
|
||||
shifted_camera.start_x:shifted_camera.end_x],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def init_background(self):
|
||||
Camera.init_background(self)
|
||||
for shifted_camera in self.shifted_cameras:
|
||||
shifted_camera.camera.init_background()
|
||||
|
||||
# A MultiCamera which, when called with two full-size cameras, initializes itself
|
||||
# as a splitscreen, also taking care to resize each individual camera within it
|
||||
class SplitScreenCamera(MultiCamera):
|
||||
def __init__(self, left_camera, right_camera, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
self.left_camera = left_camera
|
||||
self.right_camera = right_camera
|
||||
|
||||
half_width = self.pixel_shape[1] / 2
|
||||
for camera in [self.left_camera, self.right_camera]:
|
||||
camera.pixel_shape = (self.pixel_shape[0], half_width) # TODO: Round up on one if width is odd
|
||||
camera.init_background()
|
||||
camera.resize_frame_shape()
|
||||
camera.reset()
|
||||
|
||||
MultiCamera.__init__(self, (left_camera, (0, 0)), (right_camera, (0, half_width)))
|
||||
|
||||
32
camera/moving_camera.py
Normal file
32
camera/moving_camera.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from camera.camera import Camera
|
||||
|
||||
class MovingCamera(Camera):
|
||||
"""
|
||||
Stays in line with the height, width and position
|
||||
of a given mobject
|
||||
"""
|
||||
CONFIG = {
|
||||
"aligned_dimension" : "width" #or height
|
||||
}
|
||||
def __init__(self, frame, **kwargs):
|
||||
"""
|
||||
frame is a Mobject, (should be a rectangle) determining
|
||||
which region of space the camera displys
|
||||
"""
|
||||
self.frame = frame
|
||||
Camera.__init__(self, **kwargs)
|
||||
|
||||
def capture_mobjects(self, *args, **kwargs):
|
||||
self.space_center = self.frame.get_center()
|
||||
self.realign_frame_shape()
|
||||
Camera.capture_mobjects(self, *args, **kwargs)
|
||||
|
||||
def realign_frame_shape(self):
|
||||
height, width = self.frame_shape
|
||||
if self.aligned_dimension == "height":
|
||||
self.frame_shape = (self.frame.get_height(), width)
|
||||
else:
|
||||
self.frame_shape = (height, self.frame.get_width())
|
||||
self.resize_frame_shape(0 if self.aligned_dimension == "height" else 1)
|
||||
|
|
@ -3,7 +3,7 @@ from __future__ import absolute_import
|
|||
from constants import *
|
||||
|
||||
from scene.scene import Scene
|
||||
from camera.camera import MovingCamera
|
||||
from camera.moving_camera import MovingCamera
|
||||
from topics.geometry import ScreenRectangle
|
||||
|
||||
class MovingCameraScene(Scene):
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import numpy as np
|
|||
from scene.scene import Scene
|
||||
from animation.creation import FadeIn
|
||||
from camera.camera import Camera
|
||||
from camera.camera import MovingCamera
|
||||
from camera.moving_camera import MovingCamera
|
||||
from mobject.mobject import Mobject
|
||||
from topics.geometry import Rectangle
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue