Starting the Loop
Now we’re at the beginning of the main loop. First, we handle the movement, then update the FPS counter, and reset the camera image.
In this module we are dealing with the following code snippet of the Engine Loop:
mainmethod1def main(self): 2 3 ... 4 5 self.window.handle_movement() 6 self.fps_counter.update() 7 self.camera_model.reset_camera_image() 8 9 ...
- handle_movement()
The
handle_movementmethod manages the camera’s movement in response to keyboard inputs.handle_movementmethoddef handle_movement(self): camera_speed = 100 current_time = time.time() if current_time - self.last_update_time >= self.update_interval: self.last_update_time = current_time key = cv.waitKey(30) & 0xFF if key == ord('d'): self.move_camera('forward', camera_speed) if key == ord('a'): self.move_camera('backward', camera_speed) if key == ord('w'): self.move_camera('left', camera_speed) if key == ord('s'): self.move_camera('right', camera_speed) if key == ord('q'): self.move_camera('down', camera_speed) if key == ord('e'): self.move_camera('up', camera_speed)
- move_camera()
The
move_cameramethod calculates the direction vectors based on the camera’s current yaw and pitch and updates the camera’s position accordingly.Note
This way, the camera movement using W, A, S, and D is not influenced by the direction you’re looking at.
move_cameramethoddef move_camera(self, direction, speed): # Calculate vectors yaw = np.deg2rad(self.camera_system_rotation_yaw / 10.0) pitch = np.deg2rad(self.camera_system_rotation_pitch / 10.0) forward_x = np.cos(pitch) * np.cos(yaw) forward_y = np.cos(pitch) * np.sin(yaw) forward_z = np.sin(pitch) right_x = np.sin(yaw) right_y = -np.cos(yaw) right_z = 0 up_x = 0 up_y = 0 up_z = 1 if direction == 'forward': self.camera_system_translation_x += int(forward_x * speed) self.camera_system_translation_y += int(forward_y * speed) self.camera_system_translation_z += int(forward_z * speed) elif direction == 'backward': self.camera_system_translation_x -= int(forward_x * speed) self.camera_system_translation_y -= int(forward_y * speed) self.camera_system_translation_z -= int(forward_z * speed) elif direction == 'left': self.camera_system_translation_x -= int(right_x * speed) self.camera_system_translation_y -= int(right_y * speed) elif direction == 'right': self.camera_system_translation_x += int(right_x * speed) self.camera_system_translation_y += int(right_y * speed) elif direction == 'up': self.camera_system_translation_z += int(up_z * speed) elif direction == 'down': self.camera_system_translation_z -= int(up_z * speed) self.camera_system_translation_x = np.clip(self.camera_system_translation_x, 0, 20000) self.camera_system_translation_y = np.clip(self.camera_system_translation_y, 0, 20000) self.camera_system_translation_z = np.clip(self.camera_system_translation_z, 0, 20000) cv.setTrackbarPos("X", self.camera_window_name, self.camera_system_translation_x) cv.setTrackbarPos("Y", self.camera_window_name, self.camera_system_translation_y) cv.setTrackbarPos("Z", self.camera_window_name, self.camera_system_translation_z)
- mouse_event_handler()
The
mouse_event_handlermethod handles the mouse interactions with the window, allowing users to rotate the camera view by dragging or clicking inside the window by right-click.Note
With the left click, you can drag your view like on Google Maps. With the right click, your mouse movement will control the camera, and a double right-click will exit this mode.
mouse_event_handlermethoddef mouse_event_handler(self, event, x, y, flags, param): if event == cv.EVENT_LBUTTONDOWN: self.mouse_is_pressed = True self.last_mouse_position = (x, y) elif event == cv.EVENT_LBUTTONUP: self.mouse_is_pressed = False elif event == cv.EVENT_RBUTTONDOWN: self.right_button_mode = True elif event == cv.EVENT_RBUTTONDBLCLK: self.right_button_mode = False self.last_mouse_position = (x, y) elif event == cv.EVENT_MOUSEMOVE: if self.mouse_is_pressed or self.right_button_mode: dx = x - self.last_mouse_position[0] dy = y - self.last_mouse_position[1] self.camera_system_rotation_yaw += dx self.camera_system_rotation_roll += dy if self.camera_system_rotation_yaw > 3600: self.camera_system_rotation_yaw -= 3599 if self.camera_system_rotation_roll > 3600: self.camera_system_rotation_roll -= 3599 if self.camera_system_rotation_yaw < 0: self.camera_system_rotation_yaw += 3599 if self.camera_system_rotation_roll < 0: self.camera_system_rotation_roll += 3599 cv.setTrackbarPos("Yaw", self.camera_window_name, self.camera_system_rotation_yaw) cv.setTrackbarPos("Roll", self.camera_window_name, self.camera_system_rotation_roll) self.last_mouse_position = (x, y)
- fps_counter.update()
The method updates the current FPS value. It calculates the time difference between the last update and the current one to determine the FPS:
delta_time: Time difference between the current and the last frame.
fps: Calculated as 1.0 / delta_time, representing the frames per second.
fps_counter.updatemethoddef update(self) -> None: timestamp = time.time() delta_time = timestamp - self.last_timestamp self.last_timestamp = timestamp try: self.fps = 1.0 / delta_time except: self.fps = 0 self.fps_history.append(self.fps) if len(self.fps_history) > self.filter_window_size: self.fps_history.pop(0)
Lastly, in this module, we resets the camera image to a blank (white) image.
- reset_camera_image()
reset_camera_imagemethoddef reset_camera_image(self) -> None: self.camera_image.fill(255)