148 lines
4.1 KiB
Python
148 lines
4.1 KiB
Python
import numpy as np
|
|
import math as mt
|
|
import src.transformations as tn
|
|
|
|
class Camera:
|
|
__position: np.ndarray[float]
|
|
__yaw: float
|
|
__pitch: float
|
|
__roll: float
|
|
__right: np.ndarray[float]
|
|
__up: np.ndarray[float]
|
|
__forward: np.ndarray[float]
|
|
is_static: bool
|
|
moving_speed: float
|
|
rotation_speed: float
|
|
h_fov: float
|
|
v_fov: float
|
|
near_plane: float
|
|
far_plane: float
|
|
|
|
def __init__(self, renderer):
|
|
self.__renderer = renderer
|
|
self.__position = np.array([-5, 6, -55, 1.0])
|
|
self.__yaw = 0
|
|
self.__pitch = 0
|
|
self.__roll = 0
|
|
self.__right = np.array([1, 0, 0, 1])
|
|
self.__up = np.array([0, 1, 0, 1])
|
|
self.__forward = np.array([0, 0, 1, 1])
|
|
self.moving_speed = 0.3
|
|
self.rotation_speed = 0.015
|
|
self.is_static = False
|
|
self.near_plane = 0.1
|
|
self.far_plane = 100
|
|
self.set_fov(mt.pi / 3)
|
|
|
|
def projection_matrix(self):
|
|
right = mt.tan(self.h_fov / 2)
|
|
top = mt.tan(self.v_fov / 2)
|
|
|
|
m00 = 1 / right
|
|
m11 = 1 / top
|
|
m22 = (self.far_plane + self.near_plane) / (self.far_plane - self.near_plane)
|
|
m32 = -2 * self.near_plane * self.far_plane / (self.far_plane - self.near_plane)
|
|
|
|
matrix = np.matrix([
|
|
[m00, 0, 0, 0],
|
|
[0, m11, 0, 0],
|
|
[0, 0, m22, 1],
|
|
[0, 0, m32, 0]
|
|
])
|
|
return matrix
|
|
|
|
def screen_matrix(self):
|
|
hw = self.__renderer.window_width / 2
|
|
hh = self.__renderer.window_height / 2
|
|
|
|
matrix = np.matrix([
|
|
[hw, 0, 0, 0],
|
|
[0, -hh, 0, 0],
|
|
[0, 0, 1, 0],
|
|
[hw, hh, 0, 1]
|
|
])
|
|
return matrix
|
|
|
|
def set_fov(self, h_fov: float):
|
|
self.h_fov = h_fov
|
|
self.v_fov = h_fov * (self.__renderer.window_height / self.__renderer.window_width)
|
|
|
|
def set_position(self, x: float = None, y: float = None, z: float = None):
|
|
if x is not None:
|
|
self.__position[0] = x
|
|
if y is not None:
|
|
self.__position[1] = y
|
|
if z is not None:
|
|
self.__position[2] = z
|
|
|
|
def move_left(self):
|
|
self.__position -= self.__right * self.moving_speed
|
|
|
|
def move_right(self):
|
|
self.__position += self.__right * self.moving_speed
|
|
|
|
def move_down(self):
|
|
self.__position -= self.__up * self.moving_speed
|
|
|
|
def move_up(self):
|
|
self.__position += self.__up * self.moving_speed
|
|
|
|
def move_backward(self):
|
|
self.__position -= self.__forward * self.moving_speed
|
|
|
|
def move_forward(self):
|
|
self.__position += self.__forward * self.moving_speed
|
|
|
|
def yaw_down(self):
|
|
self.__yaw -= self.rotation_speed
|
|
|
|
def yaw_up(self):
|
|
self.__yaw += self.rotation_speed
|
|
|
|
def pitch_down(self):
|
|
self.__pitch -= self.rotation_speed
|
|
|
|
def pitch_up(self):
|
|
self.__pitch += self.rotation_speed
|
|
|
|
def roll_down(self):
|
|
self.__roll -= self.rotation_speed
|
|
|
|
def roll_up(self):
|
|
self.__roll += self.rotation_speed
|
|
|
|
def fov_up(self):
|
|
self.set_fov(self.h_fov - 0.05)
|
|
|
|
def fov_down(self):
|
|
self.set_fov(self.h_fov + 0.05)
|
|
|
|
def update_axis(self):
|
|
rotate = tn.rotate_x(self.__pitch) @ tn.rotate_y(self.__yaw) @ tn.rotate_z(self.__roll)
|
|
self.__forward = np.array([0, 0, 1, 1]) @ rotate
|
|
self.__right = np.array([1, 0, 0, 1]) @ rotate
|
|
self.__up = np.array([0, 1, 0, 1]) @ rotate
|
|
|
|
def camera_matrix(self) -> np.matrix:
|
|
self.update_axis()
|
|
return self.translate_matrix() @ self.rotate_matrix()
|
|
|
|
def translate_matrix(self) -> np.matrix:
|
|
x, y, z, w = self.__position
|
|
return np.matrix([
|
|
[1, 0, 0, 0],
|
|
[0, 1, 0, 0],
|
|
[0, 0, 1, 0],
|
|
[-x, -y, -z, 1]
|
|
])
|
|
|
|
def rotate_matrix(self) -> np.matrix:
|
|
rx, ry, rz, w = self.__right
|
|
fx, fy, fz, w = self.__forward
|
|
ux, uy, uz, w = self.__up
|
|
return np.matrix([
|
|
[rx, ux, fx, 0],
|
|
[ry, uy, fy, 0],
|
|
[rz, uz, fz, 0],
|
|
[0, 0, 0, 1]
|
|
]) |