feature: Improve device quirks support
This commit is contained in:
parent
79c7846ecd
commit
ad451ac014
6 changed files with 50 additions and 23 deletions
|
@ -39,11 +39,11 @@ From there, you need to follow all the below steps if applicable to your current
|
|||
|
||||
1. First, you need to build the native version of raylib. To do that, go inside the `modules/raylib-python-cffi/raylib-c` directory.
|
||||
2. Then, make the build directories and go into them: `mkdir -p build/out; cd build`
|
||||
3. Configure raylib: `cmake -DCUSTOMIZE_BUILD=ON -DSUPPORT_FILEFORMAT_JPG=ON -DSUPPORT_FILEFORMAT_FLAC=ON -DWITH_PIC=ON -DCMAKE_BUILD_TYPE=Release -DPLATFORM=DRM -DENABLE_WAYLAND_DRM_LEASING=ON -DSUPPORT_CLIPBOARD_IMAGE=ON -DCMAKE_INSTALL_PREFIX:PATH=$PWD/out ..`
|
||||
3. Configure raylib: `cmake -DCUSTOMIZE_BUILD=ON -DSUPPORT_FILEFORMAT_JPG=ON -DSUPPORT_FILEFORMAT_FLAC=ON -DWITH_PIC=ON -DCMAKE_BUILD_TYPE=Release -DPLATFORM=DRM -DENABLE_WAYLAND_DRM_LEASING=ON -DSUPPORT_CLIPBOARD_IMAGE=ON -DBUILD_EXAMPLES=OFF -DSUPPORT_SSH_KEYBOARD_RPI=OFF -DDISABLE_EVDEV_INPUT=ON -DCMAKE_INSTALL_PREFIX:PATH=$PWD/out ..`
|
||||
4. Finally, build and install raylib: `make install -j$(nproc)`
|
||||
5. After that, you need to build the Python bindings. To do that, go to the `modules/raylib-python-cffi` directory. Assuming you did everything correctly, you should be able to go 2 directories back (`../..`) to get there.
|
||||
6. If you're on normal Linux and are not using Nix, do this command to build the package: `PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PWD/raylib-c/build/out/lib64/pkgconfig/" ENABLE_WAYLAND_DRM_LEASING=YES RAYLIB_PLATFORM=DRM python3 setup.py bdist_wheel`
|
||||
7. If you are using Nix/NixOS, do this command to build the package: `PKG_CONFIG_PATH_FOR_TARGET="$PKG_CONFIG_PATH_FOR_TARGET:$PWD/raylib-c/build/out/lib64/pkgconfig/" ENABLE_WAYLAND_DRM_LEASING=YES RAYLIB_PLATFORM=DRM python3 setup.py bdist_wheel; pip install dist/*.whl`
|
||||
7. If you are using Nix/NixOS, do this command to build the package: `PKG_CONFIG_PATH_FOR_TARGET="$PKG_CONFIG_PATH_FOR_TARGET:$PWD/raylib-c/build/out/lib64/pkgconfig/" ENABLE_WAYLAND_DRM_LEASING=YES RAYLIB_PLATFORM=DRM python3 setup.py bdist_wheel`
|
||||
8. Finally, install the package: `pip install dist/*.whl`
|
||||
|
||||
### Building `PyEvdi` (Linux)
|
||||
|
|
|
@ -4,9 +4,10 @@ from dataclasses import dataclass
|
|||
import uuid
|
||||
|
||||
@dataclass
|
||||
class EvdiDisplaySpec:
|
||||
class UnrealXRDisplayMetadata:
|
||||
edid: bytes
|
||||
device_vendor: str
|
||||
device_quirks: dict[str, str | int]
|
||||
max_width: int
|
||||
max_height: int
|
||||
max_refresh_rate: int
|
||||
|
|
|
@ -2,13 +2,13 @@ import subprocess
|
|||
import os
|
||||
|
||||
from libunreal.supported_devices import supported_devices
|
||||
from libunreal.edid import EvdiDisplaySpec
|
||||
from libunreal.edid import UnrealXRDisplayMetadata
|
||||
import pyedid
|
||||
|
||||
def upload_new_device_edid(display_spec: EvdiDisplaySpec, edid: bytes | bytearray):
|
||||
def upload_new_device_edid(display_spec: UnrealXRDisplayMetadata, edid: bytes | bytearray):
|
||||
pass
|
||||
|
||||
def fetch_xr_glass_edid(allow_unsupported_devices) -> EvdiDisplaySpec:
|
||||
def fetch_xr_glass_edid(allow_unsupported_devices) -> UnrealXRDisplayMetadata:
|
||||
# Scan for all VGA devices and their IDs
|
||||
pci_device_comand = subprocess.run(["lspci"], capture_output=True)
|
||||
|
||||
|
@ -72,11 +72,11 @@ def fetch_xr_glass_edid(allow_unsupported_devices) -> EvdiDisplaySpec:
|
|||
|
||||
max_refresh = int(manufacturer_supported_devices[edid.name]["max_refresh"])
|
||||
|
||||
return EvdiDisplaySpec(raw_edid_file, edid.manufacturer_pnp_id, max_width, max_height, max_refresh, card_device, monitor.replace(f"{card_device}-", ""))
|
||||
return UnrealXRDisplayMetadata(raw_edid_file, edid.manufacturer_pnp_id, manufacturer_supported_devices[edid.name], max_width, max_height, max_refresh, card_device, monitor.replace(f"{card_device}-", ""))
|
||||
|
||||
raise ValueError("Could not find supported device. Check if the device is plugged in. If it is plugged in and working correctly, check the README or open an issue.")
|
||||
|
||||
def upload_edid_firmware(display: EvdiDisplaySpec, fw: bytes | bytearray):
|
||||
def upload_edid_firmware(display: UnrealXRDisplayMetadata, fw: bytes | bytearray):
|
||||
if display.linux_drm_connector == "" or display.linux_drm_card == "":
|
||||
raise ValueError("Linux DRM connector and/or Linux DRM card not specified!")
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@ supported_devices: dict[str, dict[str, dict[str, str | int]]] = {
|
|||
"Air": {
|
||||
"max_width": 1920,
|
||||
"max_height": 1080,
|
||||
"max_refresh": 120
|
||||
"max_refresh": 120,
|
||||
"sensor_init_delay": 10,
|
||||
"z_vector_disabled": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
main.py
11
main.py
|
@ -1,9 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
from sys import platform
|
||||
import logging
|
||||
import atexit
|
||||
import json
|
||||
import os
|
||||
|
||||
# Silence pyray init messages
|
||||
raylib_python_logger = logging.getLogger("raylib")
|
||||
raylib_python_logger.setLevel(logging.ERROR)
|
||||
|
||||
from platformdirs import user_data_dir, user_config_dir
|
||||
from loguru import logger
|
||||
import PyEvdi
|
||||
|
@ -16,6 +21,7 @@ import libunreal
|
|||
|
||||
default_configuration: dict[str, str | int] = {
|
||||
"display_angle": 45,
|
||||
"display_pixel_spacing": 45,
|
||||
"display_count": 3,
|
||||
"allow_unsupported_devices": False,
|
||||
"allow_unsupported_vendors": False,
|
||||
|
@ -106,7 +112,7 @@ def main():
|
|||
|
||||
# Get the display EDID
|
||||
logger.info("Attempting to read display EDID file")
|
||||
edid: libunreal.EvdiDisplaySpec | None = None
|
||||
edid: libunreal.UnrealXRDisplayMetadata | None = None
|
||||
|
||||
if configuration["override_default_edid"] or configuration["allow_unsupported_vendors"]:
|
||||
# We need to parse it to get the maximum width, height, and refresh rate for EVDI's calculations
|
||||
|
@ -134,7 +140,7 @@ def main():
|
|||
if max_refresh == 0:
|
||||
raise ValueError("Could not determine maximum refresh rate from EDID file, and the refresh rate overrides aren't set!")
|
||||
|
||||
edid = libunreal.EvdiDisplaySpec(edid_file, parsed_edid_file.name if parsed_edid_file.name else "", max_width, max_height, max_refresh, "", "")
|
||||
edid = libunreal.UnrealXRDisplayMetadata(edid_file, parsed_edid_file.name if parsed_edid_file.name else "", {}, max_width, max_height, max_refresh, "", "")
|
||||
else:
|
||||
edid = libunreal.fetch_xr_glass_edid(configuration["allow_unsupported_devices"])
|
||||
|
||||
|
@ -176,6 +182,7 @@ def main():
|
|||
|
||||
logger.info("Initialized displays. Entering rendering loop")
|
||||
render_loop(edid, cards)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Welcome to UnrealXR!\n")
|
||||
main()
|
||||
|
|
35
render.py
35
render.py
|
@ -1,11 +1,11 @@
|
|||
from time import sleep
|
||||
import time
|
||||
import math
|
||||
|
||||
from loguru import logger
|
||||
import PyEvdi
|
||||
import pyray
|
||||
|
||||
from libunreal import EvdiDisplaySpec, MCUCallbackWrapper, start_mcu_event_listener
|
||||
from libunreal import UnrealXRDisplayMetadata, MCUCallbackWrapper, start_mcu_event_listener
|
||||
|
||||
previous_pitch = 0.0
|
||||
previous_yaw = 0.0
|
||||
|
@ -64,7 +64,7 @@ def text_message(message: str):
|
|||
def stub_brightness_function(brightness: int):
|
||||
pass
|
||||
|
||||
def render_loop(display_metadata: EvdiDisplaySpec, cards: list[PyEvdi.Card]):
|
||||
def render_loop(display_metadata: UnrealXRDisplayMetadata, cards: list[PyEvdi.Card]):
|
||||
logger.info("Starting sensor event listener")
|
||||
|
||||
mcu_callbacks = MCUCallbackWrapper(roll_callback, pitch_callback, yaw_callback, text_message, stub_brightness_function, stub_brightness_function)
|
||||
|
@ -73,7 +73,7 @@ def render_loop(display_metadata: EvdiDisplaySpec, cards: list[PyEvdi.Card]):
|
|||
logger.info("Beginning sensor initialization. Awaiting first sensor update")
|
||||
|
||||
while (not has_gotten_pitch_callback_before) or (not has_gotten_yaw_callback_before) or (not has_gotten_roll_callback_before):
|
||||
sleep(0.01)
|
||||
time.sleep(0.01)
|
||||
|
||||
logger.info("Initialized sensors")
|
||||
|
||||
|
@ -89,15 +89,32 @@ def render_loop(display_metadata: EvdiDisplaySpec, cards: list[PyEvdi.Card]):
|
|||
movement_vector = pyray.Vector3()
|
||||
look_vector = pyray.Vector3()
|
||||
|
||||
logger.error("QUIRK: Waiting 10 seconds before reading sensors due to sensor drift bugs")
|
||||
sleep(10)
|
||||
logger.error("Continuing...")
|
||||
has_z_vector_disabled_quirk = False
|
||||
has_sensor_init_delay_quirk = False
|
||||
sensor_init_start_time = time.time()
|
||||
|
||||
if "z_vector_disabled" in display_metadata.device_quirks:
|
||||
logger.warning("QUIRK: The Z vector has been disabled for your specific device")
|
||||
has_z_vector_disabled_quirk = True
|
||||
|
||||
if "sensor_init_delay" in display_metadata.device_quirks:
|
||||
logger.warning(f"QUIRK: Waiting {str(display_metadata.device_quirks["sensor_init_delay"])} second(s) before reading sensors")
|
||||
logger.warning("|| MOVEMENT WILL NOT BE OPERATIONAL DURING THIS TIME. ||")
|
||||
sensor_init_start_time = time.time()
|
||||
has_sensor_init_delay_quirk = True
|
||||
|
||||
while not pyray.window_should_close():
|
||||
if has_sensor_init_delay_quirk:
|
||||
if time.time() - sensor_init_start_time >= int(display_metadata.device_quirks["sensor_init_delay"]):
|
||||
# Unset the quirk state
|
||||
logger.info("Movement is now enabled.")
|
||||
has_sensor_init_delay_quirk = False
|
||||
else:
|
||||
look_vector.x = (current_yaw-previous_yaw)*6.5
|
||||
look_vector.y = (current_pitch-previous_pitch)*6.5
|
||||
# the Z vector is more trouble than its worth so it just doesn't get accounted for...
|
||||
#look_vector.z = (current_roll-previous_roll)*6.5
|
||||
|
||||
if not has_z_vector_disabled_quirk:
|
||||
look_vector.z = (current_roll-previous_roll)*6.5
|
||||
|
||||
pyray.update_camera_pro(camera, movement_vector, look_vector, 0.0)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue