mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Able to move camera around for 3d scenes
This commit is contained in:
parent
d34d9abd31
commit
d2b789c033
1 changed files with 94 additions and 2 deletions
|
@ -1,10 +1,12 @@
|
||||||
|
|
||||||
from helpers import *
|
from helpers import *
|
||||||
|
|
||||||
from mobject.vectorized_mobject import VGroup, VMobject
|
from mobject.vectorized_mobject import VGroup, VMobject, VectorizedPoint
|
||||||
from topics.geometry import Square
|
from topics.geometry import Square, Line
|
||||||
from scene import Scene
|
from scene import Scene
|
||||||
from camera import Camera
|
from camera import Camera
|
||||||
|
from animation.continual_animation import AmbientRotation
|
||||||
|
from animation.transform import ApplyMethod
|
||||||
|
|
||||||
class CameraWithPerspective(Camera):
|
class CameraWithPerspective(Camera):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
@ -26,10 +28,15 @@ class ThreeDCamera(CameraWithPerspective):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"sun_vect" : 5*UP+LEFT,
|
"sun_vect" : 5*UP+LEFT,
|
||||||
"shading_factor" : 0.5,
|
"shading_factor" : 0.5,
|
||||||
|
"distance" : 5,
|
||||||
|
"phi" : 0, #Angle off z axis
|
||||||
|
"theta" : 0, #Rotation about z axis
|
||||||
}
|
}
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
Camera.__init__(self, *args, **kwargs)
|
Camera.__init__(self, *args, **kwargs)
|
||||||
self.unit_sun_vect = self.sun_vect/np.linalg.norm(self.sun_vect)
|
self.unit_sun_vect = self.sun_vect/np.linalg.norm(self.sun_vect)
|
||||||
|
self.position_mobject = VectorizedPoint()
|
||||||
|
self.set_position(self.phi, self.theta, self.distance)
|
||||||
|
|
||||||
def get_color(self, method):
|
def get_color(self, method):
|
||||||
color = method()
|
color = method()
|
||||||
|
@ -87,16 +94,101 @@ class ThreeDCamera(CameraWithPerspective):
|
||||||
self, sorted(vmobjects, cmp = z_cmp)
|
self, sorted(vmobjects, cmp = z_cmp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_position(self):
|
||||||
|
return self.position_mobject.points[0]
|
||||||
|
|
||||||
|
def get_phi(self):
|
||||||
|
x, y, z = self.get_position()
|
||||||
|
return angle_of_vector([z, np.sqrt(x**2 + y**2)])
|
||||||
|
|
||||||
|
def get_theta(self):
|
||||||
|
x, y, z = self.get_position()
|
||||||
|
return angle_of_vector([x, y])
|
||||||
|
|
||||||
|
def get_distance(self):
|
||||||
|
return np.linalg.norm(self.get_position())
|
||||||
|
|
||||||
|
def spherical_coords_to_point(self, phi, theta, distance):
|
||||||
|
phi = phi or self.get_phi()
|
||||||
|
theta = theta or self.get_theta()
|
||||||
|
distance = distance or self.get_distance()
|
||||||
|
return distance*np.array([
|
||||||
|
np.sin(phi)*np.cos(theta),
|
||||||
|
np.sin(phi)*np.sin(theta),
|
||||||
|
np.cos(phi)
|
||||||
|
])
|
||||||
|
|
||||||
|
def set_position(self, phi = None, theta = None, distance = None):
|
||||||
|
point = self.spherical_coords_to_point(phi, theta, distance)
|
||||||
|
self.position_mobject.move_to(point)
|
||||||
|
self.phi = self.get_phi()
|
||||||
|
self.theta = self.get_theta()
|
||||||
|
self.distance = self.get_distance()
|
||||||
|
|
||||||
|
def get_view_transformation_matrix(self):
|
||||||
|
return np.dot(
|
||||||
|
rotation_matrix(self.get_phi(), LEFT),
|
||||||
|
rotation_about_z(self.get_theta()),
|
||||||
|
)
|
||||||
|
|
||||||
|
def points_to_pixel_coords(self, points):
|
||||||
|
matrix = self.get_view_transformation_matrix()
|
||||||
|
new_points = np.dot(points, matrix.T)
|
||||||
|
return Camera.points_to_pixel_coords(self, new_points)
|
||||||
|
|
||||||
class ThreeDScene(Scene):
|
class ThreeDScene(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"camera_class" : ThreeDCamera,
|
"camera_class" : ThreeDCamera,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def set_camera_position(self, phi = None, theta = None, distance = None):
|
||||||
|
self.camera.set_position(phi, theta, distance)
|
||||||
|
|
||||||
|
def begin_ambient_camera_rotation(self, rate = -0.02*np.pi):
|
||||||
|
self.ambient_camera_rotation = AmbientRotation(
|
||||||
|
self.camera.position_mobject,
|
||||||
|
axis = OUT,
|
||||||
|
rate = rate
|
||||||
|
)
|
||||||
|
self.add(self.ambient_camera_rotation)
|
||||||
|
|
||||||
|
def move_camera(
|
||||||
|
self,
|
||||||
|
phi = None, theta = None, distance = None,
|
||||||
|
added_anims = [],
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
target_point = self.camera.spherical_coords_to_point(phi, theta, distance)
|
||||||
|
print phi, theta, distance
|
||||||
|
movement = ApplyMethod(
|
||||||
|
self.camera.position_mobject.move_to,
|
||||||
|
target_point,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
if hasattr(self, "ambient_camera_rotation"):
|
||||||
|
self.remove(self.ambient_camera_rotation)
|
||||||
|
self.play(movement, *added_anims)
|
||||||
|
if hasattr(self, "ambient_camera_rotation"):
|
||||||
|
self.add(self.ambient_camera_rotation)
|
||||||
|
|
||||||
|
def separate_moving_and_static_mobjects(self, *animations):
|
||||||
|
moving, static = Scene.separate_moving_and_static_mobjects(self, *animations)
|
||||||
|
if self.camera.position_mobject in moving:
|
||||||
|
return moving + static, []
|
||||||
|
return moving, static
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
|
|
||||||
def is_3d(mobject):
|
def is_3d(mobject):
|
||||||
return hasattr(mobject, "part_of_3d_mobject")
|
return hasattr(mobject, "part_of_3d_mobject")
|
||||||
|
|
||||||
|
def make_3d(mobject):
|
||||||
|
for submob in mobject.submobject_family():
|
||||||
|
submob.part_of_3d_mobject = True
|
||||||
|
|
||||||
class ThreeDMobject(VMobject):
|
class ThreeDMobject(VMobject):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
VMobject.__init__(self, *args, **kwargs)
|
VMobject.__init__(self, *args, **kwargs)
|
||||||
|
|
Loading…
Add table
Reference in a new issue