robolib.camera
camera.py - raylib camera wrapper Import level: 2
1""" 2camera.py - raylib camera wrapper 3Import level: 2 4""" 5from __future__ import annotations 6import math 7 8import raylib as rl 9import numpy as np 10 11from robolib.utils import Point3D, vec3_from, make_arr 12from robolib.traits import Serializable 13 14WORLD_CAMERA_SPEED = 0.3 15WORLD_CAMERA_SENSITIVITY = 0.3 16WORLD_CAMERA_ZOOM_SPEED = 1 17TOPDOWN_CAMERA_SPEED = 1 18TOPDOWN_CAMERA_ZOOM_SPEED = 1 19TOPDOWN_LOG_CONSTANT = math.log(2, 1.2) # convert from base 2 to base 1.2 for smooth and height-aware scrolling 20 21class Camera(Serializable): 22 """Raylib camera rapper. Parameters: [position, target, up, fovy, projection]""" 23 def __init__(self, position: Point3D, target: Point3D, up: Point3D, fovy: float, projection: int): 24 self.camera = rl.ffi.new("Camera3D *", [vec3_from(position), vec3_from(target), 25 vec3_from(up), fovy, projection]) 26 self._key2move = {rl.KEY_W: make_arr(1, 0, 0), rl.KEY_S: make_arr(-1, 0, 0), 27 rl.KEY_D: make_arr(0, 1, 0), rl.KEY_A: make_arr(0, -1, 0)} 28 29 def to_dict(self) -> dict: 30 """returns the dict representation of a raylib camera""" 31 return { 32 "position": (self.camera.position.x, self.camera.position.y, self.camera.position.z), 33 "target": (self.camera.target.x, self.camera.target.y, self.camera.target.z), 34 "up": (self.camera.up.x, self.camera.up.y, self.camera.up.z), 35 "fovy": self.camera.fovy, 36 "projection": ["perspective", "orthographic"][self.camera.projection] 37 } 38 39 @staticmethod 40 def from_dict(state: dict) -> Camera: 41 """Creates a raylib camera from a dict representation.""" 42 projection = {"perspective": rl.CAMERA_PERSPECTIVE, "orthographic": rl.CAMERA_ORTHOGRAPHIC}[state["projection"]] 43 return Camera(position=np.float32(state["position"]), target=np.float32(state["target"]), 44 up=np.float32(state["up"]), fovy=state["fovy"], projection=projection) 45 46 def set_position(self, position: Point3D, target: Point3D, up: Point3D): 47 """sets the camera position given a position and 2 vectors: target and up""" 48 self.camera[0].position = vec3_from(position) 49 self.camera[0].target = vec3_from(target) 50 self.camera[0].up = vec3_from(up) 51 52 def manual_movement(self): 53 """Moves the simulator's active camera manually. Only valid for world camera and topdown camera.""" 54 if self.camera[0].projection not in (rl.CAMERA_PERSPECTIVE, rl.CAMERA_ORTHOGRAPHIC): 55 return 56 57 if self.camera[0].projection == rl.CAMERA_PERSPECTIVE: # world camera 58 movement = (sum(v * rl.IsKeyDown(k) * WORLD_CAMERA_SPEED for k, v in self._key2move.items())).view(Point3D) 59 60 rotation = (0, 0, 0) # (pitch, yaw, roll) 61 if rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT): # only when clicked 62 mouse = rl.GetMouseDelta() 63 rotation = (mouse.x * WORLD_CAMERA_SENSITIVITY, mouse.y * WORLD_CAMERA_SENSITIVITY, 0) 64 65 zoom = -rl.GetMouseWheelMove() * WORLD_CAMERA_ZOOM_SPEED 66 67 rl.UpdateCameraPro(self.camera, vec3_from(movement), rotation, zoom) 68 else: # topdown camera 69 speed = math.log2(1 + self.camera[0].fovy) / TOPDOWN_LOG_CONSTANT # height-aware topdown movemenmt speed 70 delta = sum(v * rl.IsKeyDown(k) * speed for k, v in self._key2move.items()) 71 72 self.camera[0].position.x += delta[1] # left/right 73 self.camera[0].target.x += delta[1] # left/right 74 self.camera[0].position.z -= delta[0] # up/down 75 self.camera[0].target.z -= delta[0] # up/down 76 self.camera[0].fovy = max(1.0, self.camera[0].fovy - rl.GetMouseWheelMove() * TOPDOWN_CAMERA_ZOOM_SPEED)
WORLD_CAMERA_SPEED =
0.3
WORLD_CAMERA_SENSITIVITY =
0.3
WORLD_CAMERA_ZOOM_SPEED =
1
TOPDOWN_CAMERA_SPEED =
1
TOPDOWN_CAMERA_ZOOM_SPEED =
1
TOPDOWN_LOG_CONSTANT =
3.8017840169239308
22class Camera(Serializable): 23 """Raylib camera rapper. Parameters: [position, target, up, fovy, projection]""" 24 def __init__(self, position: Point3D, target: Point3D, up: Point3D, fovy: float, projection: int): 25 self.camera = rl.ffi.new("Camera3D *", [vec3_from(position), vec3_from(target), 26 vec3_from(up), fovy, projection]) 27 self._key2move = {rl.KEY_W: make_arr(1, 0, 0), rl.KEY_S: make_arr(-1, 0, 0), 28 rl.KEY_D: make_arr(0, 1, 0), rl.KEY_A: make_arr(0, -1, 0)} 29 30 def to_dict(self) -> dict: 31 """returns the dict representation of a raylib camera""" 32 return { 33 "position": (self.camera.position.x, self.camera.position.y, self.camera.position.z), 34 "target": (self.camera.target.x, self.camera.target.y, self.camera.target.z), 35 "up": (self.camera.up.x, self.camera.up.y, self.camera.up.z), 36 "fovy": self.camera.fovy, 37 "projection": ["perspective", "orthographic"][self.camera.projection] 38 } 39 40 @staticmethod 41 def from_dict(state: dict) -> Camera: 42 """Creates a raylib camera from a dict representation.""" 43 projection = {"perspective": rl.CAMERA_PERSPECTIVE, "orthographic": rl.CAMERA_ORTHOGRAPHIC}[state["projection"]] 44 return Camera(position=np.float32(state["position"]), target=np.float32(state["target"]), 45 up=np.float32(state["up"]), fovy=state["fovy"], projection=projection) 46 47 def set_position(self, position: Point3D, target: Point3D, up: Point3D): 48 """sets the camera position given a position and 2 vectors: target and up""" 49 self.camera[0].position = vec3_from(position) 50 self.camera[0].target = vec3_from(target) 51 self.camera[0].up = vec3_from(up) 52 53 def manual_movement(self): 54 """Moves the simulator's active camera manually. Only valid for world camera and topdown camera.""" 55 if self.camera[0].projection not in (rl.CAMERA_PERSPECTIVE, rl.CAMERA_ORTHOGRAPHIC): 56 return 57 58 if self.camera[0].projection == rl.CAMERA_PERSPECTIVE: # world camera 59 movement = (sum(v * rl.IsKeyDown(k) * WORLD_CAMERA_SPEED for k, v in self._key2move.items())).view(Point3D) 60 61 rotation = (0, 0, 0) # (pitch, yaw, roll) 62 if rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT): # only when clicked 63 mouse = rl.GetMouseDelta() 64 rotation = (mouse.x * WORLD_CAMERA_SENSITIVITY, mouse.y * WORLD_CAMERA_SENSITIVITY, 0) 65 66 zoom = -rl.GetMouseWheelMove() * WORLD_CAMERA_ZOOM_SPEED 67 68 rl.UpdateCameraPro(self.camera, vec3_from(movement), rotation, zoom) 69 else: # topdown camera 70 speed = math.log2(1 + self.camera[0].fovy) / TOPDOWN_LOG_CONSTANT # height-aware topdown movemenmt speed 71 delta = sum(v * rl.IsKeyDown(k) * speed for k, v in self._key2move.items()) 72 73 self.camera[0].position.x += delta[1] # left/right 74 self.camera[0].target.x += delta[1] # left/right 75 self.camera[0].position.z -= delta[0] # up/down 76 self.camera[0].target.z -= delta[0] # up/down 77 self.camera[0].fovy = max(1.0, self.camera[0].fovy - rl.GetMouseWheelMove() * TOPDOWN_CAMERA_ZOOM_SPEED)
Raylib camera rapper. Parameters: [position, target, up, fovy, projection]
Camera( position: numpy.ndarray, target: numpy.ndarray, up: numpy.ndarray, fovy: float, projection: int)
24 def __init__(self, position: Point3D, target: Point3D, up: Point3D, fovy: float, projection: int): 25 self.camera = rl.ffi.new("Camera3D *", [vec3_from(position), vec3_from(target), 26 vec3_from(up), fovy, projection]) 27 self._key2move = {rl.KEY_W: make_arr(1, 0, 0), rl.KEY_S: make_arr(-1, 0, 0), 28 rl.KEY_D: make_arr(0, 1, 0), rl.KEY_A: make_arr(0, -1, 0)}
def
to_dict(self) -> dict:
30 def to_dict(self) -> dict: 31 """returns the dict representation of a raylib camera""" 32 return { 33 "position": (self.camera.position.x, self.camera.position.y, self.camera.position.z), 34 "target": (self.camera.target.x, self.camera.target.y, self.camera.target.z), 35 "up": (self.camera.up.x, self.camera.up.y, self.camera.up.z), 36 "fovy": self.camera.fovy, 37 "projection": ["perspective", "orthographic"][self.camera.projection] 38 }
returns the dict representation of a raylib camera
40 @staticmethod 41 def from_dict(state: dict) -> Camera: 42 """Creates a raylib camera from a dict representation.""" 43 projection = {"perspective": rl.CAMERA_PERSPECTIVE, "orthographic": rl.CAMERA_ORTHOGRAPHIC}[state["projection"]] 44 return Camera(position=np.float32(state["position"]), target=np.float32(state["target"]), 45 up=np.float32(state["up"]), fovy=state["fovy"], projection=projection)
Creates a raylib camera from a dict representation.
def
set_position( self, position: numpy.ndarray, target: numpy.ndarray, up: numpy.ndarray):
47 def set_position(self, position: Point3D, target: Point3D, up: Point3D): 48 """sets the camera position given a position and 2 vectors: target and up""" 49 self.camera[0].position = vec3_from(position) 50 self.camera[0].target = vec3_from(target) 51 self.camera[0].up = vec3_from(up)
sets the camera position given a position and 2 vectors: target and up
def
manual_movement(self):
53 def manual_movement(self): 54 """Moves the simulator's active camera manually. Only valid for world camera and topdown camera.""" 55 if self.camera[0].projection not in (rl.CAMERA_PERSPECTIVE, rl.CAMERA_ORTHOGRAPHIC): 56 return 57 58 if self.camera[0].projection == rl.CAMERA_PERSPECTIVE: # world camera 59 movement = (sum(v * rl.IsKeyDown(k) * WORLD_CAMERA_SPEED for k, v in self._key2move.items())).view(Point3D) 60 61 rotation = (0, 0, 0) # (pitch, yaw, roll) 62 if rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT): # only when clicked 63 mouse = rl.GetMouseDelta() 64 rotation = (mouse.x * WORLD_CAMERA_SENSITIVITY, mouse.y * WORLD_CAMERA_SENSITIVITY, 0) 65 66 zoom = -rl.GetMouseWheelMove() * WORLD_CAMERA_ZOOM_SPEED 67 68 rl.UpdateCameraPro(self.camera, vec3_from(movement), rotation, zoom) 69 else: # topdown camera 70 speed = math.log2(1 + self.camera[0].fovy) / TOPDOWN_LOG_CONSTANT # height-aware topdown movemenmt speed 71 delta = sum(v * rl.IsKeyDown(k) * speed for k, v in self._key2move.items()) 72 73 self.camera[0].position.x += delta[1] # left/right 74 self.camera[0].target.x += delta[1] # left/right 75 self.camera[0].position.z -= delta[0] # up/down 76 self.camera[0].target.z -= delta[0] # up/down 77 self.camera[0].fovy = max(1.0, self.camera[0].fovy - rl.GetMouseWheelMove() * TOPDOWN_CAMERA_ZOOM_SPEED)
Moves the simulator's active camera manually. Only valid for world camera and topdown camera.