mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Merge pull request #109 from frozar/3D_camera_moving
[3D CAMERA] Center of rotation
This commit is contained in:
commit
921dc1a6d7
2 changed files with 97 additions and 6 deletions
|
@ -24,6 +24,8 @@ from topics.number_line import *
|
|||
from topics.combinatorics import *
|
||||
from topics.three_dimensions import *
|
||||
|
||||
from topics.three_dimensions import *
|
||||
|
||||
# To watch one of these scenes, run the following:
|
||||
# python extract_scene.py file_name <SceneName> -p
|
||||
#
|
||||
|
@ -59,6 +61,67 @@ class WriteStuff(Scene):
|
|||
self.play(Write(TextMobject("Stuff").scale(3)))
|
||||
|
||||
|
||||
class Rotation3d(ThreeDScene):
|
||||
def construct(self):
|
||||
# STEP 1
|
||||
# Build two cube in the 3D scene, one for around the origin,
|
||||
# the other shifted along the vector RIGHT + UP + OUT
|
||||
cube_origin = Cube(fill_opacity = 0.8, stroke_width = 1.,
|
||||
side_length = 1., fill_color = WHITE)
|
||||
|
||||
# RIGHT side: Red
|
||||
# UP side: Green
|
||||
# OUT side: Blue
|
||||
orientations = [IN, OUT, LEFT, RIGHT, UP, DOWN]
|
||||
for face, orient in zip(cube_origin.family_members_with_points(), orientations):
|
||||
if np.array_equal(orient, RIGHT):
|
||||
face.set_style_data(fill_color = RED)
|
||||
elif np.array_equal(orient, UP):
|
||||
face.set_style_data(fill_color = GREEN)
|
||||
elif np.array_equal(orient, OUT):
|
||||
face.set_style_data(fill_color = BLUE)
|
||||
|
||||
cube_shifted = Cube(fill_opacity = 0.8, stroke_width = 1.,
|
||||
side_length = 1., fill_color = BLUE)
|
||||
shift_vec = 2*(RIGHT + UP + OUT)
|
||||
cube_shifted.shift(shift_vec)
|
||||
|
||||
# STEP 2
|
||||
# Add the cubes in the 3D scene
|
||||
self.add(cube_origin)
|
||||
self.add(cube_shifted)
|
||||
|
||||
# STEP 3
|
||||
# Setup the camera position
|
||||
phi, theta, distance = ThreeDCamera().get_spherical_coords()
|
||||
angle_factor = 0.9
|
||||
phi += 2*np.pi/4*angle_factor
|
||||
theta += 3*2*np.pi/8
|
||||
self.set_camera_position(phi, theta, distance)
|
||||
self.wait()
|
||||
|
||||
# STEP 4
|
||||
# Animation
|
||||
# Animation 1: rotation around the Z-axis with the ORIGIN of the space
|
||||
# as center of rotation
|
||||
theta += 2*np.pi
|
||||
self.move_camera(phi, theta, distance,
|
||||
run_time = 5)
|
||||
|
||||
# Animation 2: shift the space in order of to get the center of the shifted cube
|
||||
# as the next center of rotation
|
||||
cube_center = cube_shifted.get_center()
|
||||
self.move_camera(center_x = cube_center[0],
|
||||
center_y = cube_center[1],
|
||||
center_z = cube_center[2],
|
||||
run_time = 2)
|
||||
|
||||
# Animation 3: rotation around the Z-axis with the center of the shifted cube
|
||||
# as center of rotation
|
||||
theta += 2*np.pi
|
||||
self.move_camera(phi, theta, distance,
|
||||
run_time = 5)
|
||||
|
||||
|
||||
class SpinAroundCube(ThreeDScene):
|
||||
# Take a look at ThreeDSCene in three_dimensions.py.
|
||||
|
|
|
@ -36,8 +36,11 @@ class ThreeDCamera(CameraWithPerspective):
|
|||
def __init__(self, *args, **kwargs):
|
||||
Camera.__init__(self, *args, **kwargs)
|
||||
self.unit_sun_vect = self.sun_vect/np.linalg.norm(self.sun_vect)
|
||||
## Lives in the phi-theta-distance space
|
||||
## rotation_mobject lives in the phi-theta-distance space
|
||||
self.rotation_mobject = VectorizedPoint()
|
||||
## moving_center lives in the x-y-z space
|
||||
## It representes the center of rotation
|
||||
self.moving_center = VectorizedPoint(self.space_center)
|
||||
self.set_position(self.phi, self.theta, self.distance)
|
||||
|
||||
def modified_rgb(self, vmobject, rgb):
|
||||
|
@ -128,10 +131,24 @@ class ThreeDCamera(CameraWithPerspective):
|
|||
np.cos(phi)
|
||||
])
|
||||
|
||||
def set_position(self, phi = None, theta = None, distance = None):
|
||||
def get_center_of_rotation(self, x = None, y = None, z = None):
|
||||
curr_x, curr_y, curr_z = self.moving_center.points[0]
|
||||
if x is None:
|
||||
x = curr_x
|
||||
if y is None:
|
||||
y = curr_y
|
||||
if z is None:
|
||||
z = curr_z
|
||||
return np.array([x, y, z])
|
||||
|
||||
def set_position(self, phi = None, theta = None, distance = None,
|
||||
center_x = None, center_y = None, center_z = None):
|
||||
point = self.get_spherical_coords(phi, theta, distance)
|
||||
self.rotation_mobject.move_to(point)
|
||||
self.phi, self.theta, self.distance = point
|
||||
center_of_rotation = self.get_center_of_rotation(center_x, center_y, center_z)
|
||||
self.moving_center.move_to(center_of_rotation)
|
||||
self.space_center = self.moving_center.points[0]
|
||||
|
||||
def get_view_transformation_matrix(self):
|
||||
return (self.default_distance / self.get_distance()) * np.dot(
|
||||
|
@ -142,6 +159,8 @@ class ThreeDCamera(CameraWithPerspective):
|
|||
def points_to_pixel_coords(self, points):
|
||||
matrix = self.get_view_transformation_matrix()
|
||||
new_points = np.dot(points, matrix.T)
|
||||
self.space_center = self.moving_center.points[0]
|
||||
|
||||
return Camera.points_to_pixel_coords(self, new_points)
|
||||
|
||||
class ThreeDScene(Scene):
|
||||
|
@ -150,8 +169,9 @@ class ThreeDScene(Scene):
|
|||
"ambient_camera_rotation" : None,
|
||||
}
|
||||
|
||||
def set_camera_position(self, phi = None, theta = None, distance = None):
|
||||
self.camera.set_position(phi, theta, distance)
|
||||
def set_camera_position(self, phi = None, theta = None, distance = None,
|
||||
center_x = None, center_y = None, center_z = None):
|
||||
self.camera.set_position(phi, theta, distance, center_x, center_y, center_z)
|
||||
|
||||
def begin_ambient_camera_rotation(self, rate = 0.01):
|
||||
self.ambient_camera_rotation = AmbientMovement(
|
||||
|
@ -167,8 +187,9 @@ class ThreeDScene(Scene):
|
|||
self.ambient_camera_rotation = None
|
||||
|
||||
def move_camera(
|
||||
self,
|
||||
self,
|
||||
phi = None, theta = None, distance = None,
|
||||
center_x = None, center_y = None, center_z = None,
|
||||
added_anims = [],
|
||||
**kwargs
|
||||
):
|
||||
|
@ -178,10 +199,17 @@ class ThreeDScene(Scene):
|
|||
target_point,
|
||||
**kwargs
|
||||
)
|
||||
target_center = self.camera.get_center_of_rotation(center_x, center_y, center_z)
|
||||
movement_center = ApplyMethod(
|
||||
self.camera.moving_center.move_to,
|
||||
target_center,
|
||||
**kwargs
|
||||
)
|
||||
is_camera_rotating = self.ambient_camera_rotation in self.continual_animations
|
||||
if is_camera_rotating:
|
||||
self.remove(self.ambient_camera_rotation)
|
||||
self.play(movement, *added_anims)
|
||||
self.play(movement, movement_center, *added_anims)
|
||||
target_point = self.camera.get_spherical_coords(phi, theta, distance)
|
||||
if is_camera_rotating:
|
||||
self.add(self.ambient_camera_rotation)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue