Able to move camera around for 3d scenes

This commit is contained in:
Grant Sanderson 2017-08-24 19:05:30 -07:00
parent d34d9abd31
commit d2b789c033

View file

@ -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)