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