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)}
camera
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.