{"id":21173650,"url":"https://github.com/letoram/safespaces","last_synced_at":"2025-04-09T16:20:01.650Z","repository":{"id":37550188,"uuid":"127219312","full_name":"letoram/safespaces","owner":"letoram","description":"3D/VR Desktop built for Arcan","archived":false,"fork":false,"pushed_at":"2023-03-07T23:48:47.000Z","size":10992,"stargazers_count":281,"open_issues_count":10,"forks_count":19,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-04-09T16:19:55.694Z","etag":null,"topics":["arcan","desktop-environment","graphics","linux","lua","openhmd","virtual-reality","vr"],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/letoram.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-29T01:28:14.000Z","updated_at":"2025-03-23T07:55:03.000Z","dependencies_parsed_at":"2024-11-20T16:48:41.093Z","dependency_job_id":"3f6f4b05-e170-4f75-aa4b-f9f79ff3e3c2","html_url":"https://github.com/letoram/safespaces","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letoram%2Fsafespaces","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letoram%2Fsafespaces/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letoram%2Fsafespaces/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letoram%2Fsafespaces/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/letoram","download_url":"https://codeload.github.com/letoram/safespaces/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065281,"owners_count":21041872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arcan","desktop-environment","graphics","linux","lua","openhmd","virtual-reality","vr"],"created_at":"2024-11-20T16:48:33.019Z","updated_at":"2025-04-09T16:20:01.630Z","avatar_url":"https://github.com/letoram.png","language":"Lua","readme":"# Safespaces\nThis is the development / prototyping environment for 'Safespaces', a 3D/VR\ndesktop environment for the Arcan display server.\n\nNote that this is a highly experimental young project. Prolonged use is quite\nlikely unhealthy in a number of ways, eye strain guaranteed while debugging.\nTread carefully and try with non-VR device profiles first. Keep a vomit-bucket\nnearby.\n\n# Contact\nThe project and related development is discussed in the #arcan IRC channel on\nthe freenode IRC network. Some of the development here is also done within the\nrelated project [durden](http://durden.arcan-fe.com) as part of the 'VRviewer'\ntool. Most of the codebase here is actually shared with that tool.\n\n# Getting Started\nYou need a working build / installation of [Arcan](https://github.com/letoram/arcan)\nso follow those instructions first. then read the following sections carefully.\n\n## VR Bridge (device support)\nArcan does not enable VR device support by default, so you need to build the\n'arcan_vr' tool that is in the main arcan source repository as 'src/tools/vrbridge'.\nYou should also be able to run that tool from the command-line to test the rotation\ntracking and control of your head mounted display (HMD).\n\nThis usually requires some kind of adjustments to permissions, as it requires\ndirect access to USB device control. When you have that tool working, you will\nwant to tell arcan to use it for VR support:\n\n    arcan_db add_appl_kv arcan ext_vr /path/to/arcan_vr\n\nIf you don't, it will still try to find the arcan\\_vr binary in the regular bin\nfolders (for system- technical reasons it does not rely on PATH but rather hard\npriority of usr/local/bin then usr/bin before giving up).\n\nThis tool act as our device control interface, so if there are more sensor devices\nyou want to add, this is where it can be done. The idea is that each vr-bridge\ninstance exposes a skeletal model (joints, eyes, ...) that you populate with\nwhatever devices you happen to have. These are advertised to the active scripts\n(safespaces here) which then react accordingly by mapping to models, cameras,\ngesture classifiers and other abstract objects.\n\n## Device Profile\nThere is great variety in how HMD devices work, behave, and what extra controls\nyou might need. On top of the VR Bridge that gives us access to the devices\nthemselves, we then need the integration with the visual aspects of the desktop.\n\nYou can find the current profiles (or add your own) in the devices/ folder, and\nthey are normal .lua scripts that gets loaded immediately on startup. An example\nlooks like this:\n\n    return {\n        display = 'MyScreenName',\n        oversample_w = 1.0,\n        oversample_h = 1.0,\n        distortion_model = \"basic\",\n        display_rotate = 'cw90',\n        override_projection = false,\n        width = 2560,\n        height = 1440,\n        map_hint = MAP_FLIP,\n        hmdarg = \"ohmd_index=0\",\n        bindings = [\n            [\"F1\"] = \"mouse=selected\"\n        ]\n    }\n\nThe values herein takes precedence over whatever the VR bridge might have set,\nso you can have your custom overrides here. The 'bindings' complement input\nconfiguration with special ones you might want for a certain device only.\n\nThe key options are as follows:\n\ndisplay = 'pattern' : This checks for a display EDID matching the lua pattern\npresented by the string rather than going for the first one available. If this\nis set, setup won't progress until the correct display has been found.\n\ndisplay\\_id = 'number' : If present, this ignores the display-pattern above\nand just picks whatever that happens to appear as a specific display number,\nwhere 0 will always be the first, and so on.\n\ndisplay\\_rotate = cw90 | ccw90 | 180 | cw90ccw90 : This specifies the base\norientation of the display.\n\ndistortion\\_model = basic, none : Using the universal distortion shader from the\nOpenHMD project or disable barrel distortion altogether.\n\noverride\\_projection = false | true : If set to true, this will use a normal\nperspective projection matrix, ignoring whatever was provided by the vr device\n\nno\\_combiner = false | true : This removes / disables the combiner surface,\neffectively making the rendering monoscopic only via the preview window.\n\nheadless = false | true : This will ignore mapping the head/rotation tracking\nto the output cameras, causing them to be locked in place.\n\nThere are some special built-in profiles:\n\n* 'desktop'    : 3D desktop only, no vr devices or stereoscopic rendering\n* 'client'     : Used as a client in another desktop system\n\nClient is intended to be used with arcan builds that act as a client inside\nanother desktop system and not as a display server itself, that would be 'lwa'\n(where arcan+safespaces is used as a client to a normal arcan desktop), 'sdl'\nor 'sdl2'.\n\n## Configuration\n\nWM, Input, Device Profiles, Default 'space' - all of it is set in the\nconfig.lua file. Look at it. Especially the 'Input Controls' section with\nits meta keys and its bindings as it will tell you how to shutdown, which\nis quite important.\n\nIn fact, to save you from not being able to shutdown properly before knowing\nthe keybinding, we have made it so that when the initial terminal surface is\ndestroyed, by exiting from within the shell or through a keybinding, safespaces\nwill exit. When you feel comfortable, see the section on 'spaces' below for\ninstructions on how to remove that feature.\n\nThe binding format is simply:\n\n    [\"modifiers_SYMBOL\"] = \"api/path\"\n\nand the API paths are how everything in safespaces is controlled. Everything\nis organised like a filesystem, and the API.md file describes how these\nfilesystem paths are generated.\n\n## Spaces\n\nThe next thing to consider is a 'space'. These are simply collections of\npaths that gets started synchronously in one batch, and is basically your\ncurrent environment/scene preset.\n\nThe default space gives you a skybox and a terminal in the middle. *This\nterminal is configured so that if you destroy or exit it, safespaces itself\nwill shut down*. This is a safety measure to save you if the keybindings\nare broken or you do not know how to exit.\n\nTo remove that feature, edit the default space and remove the:\n\n    layers/current/terminal/models/selected/events/on_destroy=shutdown\n\nline.\n\n## Starting\n\nNow that the basic concept sare introduced and you should know where to go\nfor modifying your controls, device and setting up your first space.\n\n    arcan ./safespaces\n\nOr\n\n    arcan /path/to/safespaces-git/safespaces\n\nDepending on where it is located. Some values in your config.lua can be\noverridden on the commandline, particularly the space and the device.\nYou can do this by adding them last on the list of arguments, like this:\n\n    arcan ./safespaces space=myspace device=vive\n\n# Clients\n\nNow you might just want to run more things than terminal. To do that,\nyou will want to understand 'connection points'. These are basically things\nin the vr environment that listens for external connections under some name.\n\nThe terminal emulator happens to set one up for you, so anything started\nfrom the terminal emulator will be spawned as a new rectangle child to the\nterminal itself.\n\nUnderneath the surface, a client built using the arcan client APIs look\nfor the environment:\n\n    ARCAN_CONNPATH=name\n\nThis is used heavily here to let the desktop understand what is going on\nbased on where a client connects to. As an example, the default space has\na 'show on activation' connection point:\n\n    ARCAN_CONNPATH=moviescreen afsrv_terminal\n\nWould activate this hidden screen and spawn a terminal there. There are some\nclients that come with arcan and there are some opt-in tools you can build\nyourself.\n\n## Built-in\n\nWith an arcan build comes support for three clients that are interesting\nhere, terminal, libretro-loader and video decoder (built on VLC). These\nare prefixed with afsrv\\_ (terminal, game, decode). To run a\n[libretro](https://www.libretro.com) core for instance:\n\n    ARCAN_ARG=core=/path/to/core.so:resource=/path/to/gamedata afsrv_game\n\nor indeed direct it to the moviescreen connection point as shown before.\n\n    ARCAN_CONNPATH=moviescreen ARCAN_ARG=file=myfile.mkv afsrv_decode\n\nshould give you some movieplayback.\n\n## Supportive\n\nIn the arcan source repository, there is 'aloadimage', which is a simple\nimage loader that also has support for stereoscopic sources:\n\n    aloadimage --vr l:left_eye.png r:right_eye.png\n\nThe source for this tool can be found in src/tools/aloadimage, and should\nwork as a template for writing your own arcan/safespaces compliant VR\nclients.\n\n## Troubleshooting\n\nChances are that safespaces will only give you a black screen or return to the\ncommand-line. This comes from how complex and varying the lower layer graphics\nsystem actually works, combined with the 'display but not a normal display'\nproperties of the HMD itself. Some tips for getting further:\n\n1. Start with the device=test profile and a normal monitor (no HMD connected)\n\nAssuming no X server or worse yet, display manager, is running and that you\nonly work from the TTY. Make sure to pipe the arcan output to a log file as\nthe normal stdout text has to be disabled for graphics to work, and the log\nmight contain valuable clues.\n\n    arcan safespaces device=test \u0026\u003e log\n\nIf you have an NVIDIA card and not AMD or Intel, chances are their driver is\nstill such a steaming pile that it is not worth pursuing further until they\nclean up their act. We are fine with them requiring EGLStreams and binary blobs\nand custom scanout paths, but if they do, at the very least these layers should\nwork reliably and robustly, which is far from the truth currently. As a user,\nask the developers of their unix driver for help debugging / troubleshooting.\n\nThis makes sure that the 3D pipeline, normal display scanout, etc. is working\ncorrectly. You can also test your keys and keybindings here so it is a useful\nfeature to know about. If this stage is not working, the problem can be with\nyour kernel, graphics driver, permissions and so on. In order to switch the\n\n2. Use the device=desktop profile and a normal monitor (no HMD connected)\n\nThis just makes sure that the 3D pipeline also works when it is uniquely\nmapped to a display and not composited like with the test profile. If this does\nnot work, the troubleshooting is the same as with 1. A debug build of arcan\nitself (cmake with -DCMAKE\\_BUILD\\_TYPE=Debug will produce a more verbose log,\nas will starting with multiple -g arguments on the command line.\n\n3. Try the device=basic profile with your hmd and normal monitor connected.\n\nThis will give you a stereoscopic view on your normal monitor, but it will\ntry to get the orientation from the HMD. Try rotating the HMD, and look on\nyour monitor, does the tracking work?\n\nIf not, the problem is either that arcan\\_vr is not running correctly, your\nHMD is not supported or your user do not have permission to access the\ndevice. Try running arcan\\_vr separately, do you get proper rotation output\nthere? If it does, then it is probably the case that arcan did not find the\narcan\\_vr binary correctly, see if a process with that name is running.\nIf you do not get proper results from arcan\\_vr, the problem likely lies\nwith OpenHMD.\n\nCheck the status with their git repository, check if you have built arcan\\_vr\nstatically with an in-source OpenHMD or through the shared version as our\nversion is slightly patched.\n\n4. Finally use the device profile for your actual HMD.\n\nThere are a few reasons why, after everything, this stage still refuses to\nwork. The reason being that there is a big difference between what display is\nfound \"first\" and if that is your HMD or not. The kernel driver typically\nblocks VR headsets from taking this spot, but this is through a hardcoded list\nin the driver itself. So for some configurations you might have success with no\nscreen plugged in, only your HMD. In others, plugging in your HMD after you\nhave started safespaces might help.\n\nPart of the reason why this might be a problem is that some displays behave in\none way when plugged in 'as normal', then act as a 'hotplug' when the VR bridge\nsends a wakeup command. Then safespaces need to pair the display being plugged\nwith displays that 'appear', which might not actually be the HMD in question\nwhen you have more complicated setups.\n\n## X, Wayland\n\nTo support running legacy applications using the X or Wayland protocols,\nthere are two paths. One is [Xarcan](https://github.com/letoram/xarcan)\nwhich is a modified X server. You start it, attach a window manager and\nuse it as a 'contained in a surface' kind of mode.\n\nFor Wayland, there is another tool in the arcan source repository, in the\nsrc/tools/waybridge folder, which implements the server side of the Wayland\nprotocol. Normally, it should simply be runnable via:\n\n    arcan-wayland -exec my_wayland_client\n\nYou can also run X clients 'rootless' via Xwayland. You do that like this:\n\n    arcan-wayland -xwl -exec my_x_client\n\n## Roadmap\n\nThere is a long road ahead of us to make sure that Safespaces is the definitive\ndesktop for productive work in the VR/AR/MR space. Here follows a checklist\nof some of those steps:\n\nMilestone 1:\n\n- [ ] Devices\n  - [x] Simulated (3D-SBS)\n  - [x] Simple (Monoscopic 3D)\n  - [x] Single HMD\n  - [ ] Distortion Model\n    - [p] Shader Based\n    - [ ] Mesh Based\n    - [ ] Validation\n  - [x] Mouse\n  - [x] Keyboard\n  - [ ] Front-Camera composition\n\n- [ ] Models\n  - [x] Primitives\n    - [ ] Cube\n      - [x] Basic mesh\n      - [x] 1 map per face\n      - [ ] cubemapping\n    - [x] Sphere\n      - [x] Basic mesh\n      - [x] Hemisphere\n    - [x] Cylinder\n      - [x] Basic mesh\n      - [x] half-cylinder\n    - [x] Rectangle\n    - [ ] Border/Background\n    - [ ] GlTF2 (.bin)\n      - [ ] Simple/Textured Mesh\n      - [ ] Skinning/Morphing/Animation\n      - [ ] Physically Based Rendering\n    - [x] Stereoscopic Mapping\n      - [x] Side-by-Side\n      - [x] Over-and-Under\n      - [x] Swap L/R Eye\n      - [ ] Split (left- right sources)\n - [x] Events\n      - [x] On Destroy\n\n- [x] Layouters\n  - Tiling / Auto\n    - [x] Circular Layers\n    - [x] Swap left / right\n    - [x] Cycle left / right\n    - [x] Transforms (spin, nudge, scale)\n    - [x] Curved Planes\n    - [x] Billboarding\n    - [x] Fixed \"infinite\" Layers\n    - [x] Vertical hierarchies\n    - [x] Connection- activated models\n\n - Static / Manual\n    - [ ] Curved Plane\n    - [ ] Drag 'constraint' solver (collision avoidance)\n    - [ ] Draw to Spawn\n\n- [ ] Clients\n  - [x] Built-ins (terminal/external connections)\n  - [ ] Launch targets\n  - [x] Xarcan\n  - [x] Wayland-simple (toplevel/fullscreen only)\n  - [ ] Wayland-composited (xdg-popups, subsurfaces, xwayland)\n\n- [ ] Tools\n  - [ ] Basic 'listview' popup\n  - [x] Console\n  - [ ] Button-grid / Streamdeck\n  - [x] Socket- control IPC\n\nMilestone 2:\n\n- [ ] Advanced Layouters\n  - [ ] Room Scale\n  - [ ] Portals / Space Switching\n\n- [ ] Improved Rendering\n  - [ ] Equi-Angular Cubemaps\n  - [ ] Stencil-masked Composition\n  - [ ] Surface- projected mouse cursor\n\n- [ ] Devices\n  - [ ] Gloves\n  - [ ] Eye Tracker\n  - [ ] Video Capture Analysis\n  - [ ] Positional Tracking / Tools\n  - [ ] Dedicated Handover/Leasing\n  - [ ] Reprojection\n  - [ ] Mouse\n  - [ ] Gesture Detection\n  - [ ] Sensitivity Controls\n  - [ ] Keyboard\n    - [ ] Repeat rate controls\n    - [ ] Runtime keymap switching\n  - [ ] Multiple- HMDs\n    - [ ] Passive\n    - [ ] Active\n\n- [ ] Clients\n  - [ ] Full Wayland-XDG\n    - [ ] Custom cursors\n    - [ ] Multiple toplevels\n    - [ ] Popups\n    - [ ] Positioners\n  - [ ] Full LWA (3D and subsegments)\n    - [ ] Native Nested 3D Clients\n    - [ ] Adoption (Crash Recovery, WM swapping)\n    - [ ] Clipboard support\n\n- [ ] Convenience\n  - [ ] Streaming / Recording\n\nMilestone 3:\n\n- [ ] Devices\n  - [ ] Haptics\n  - [ ] Multiple, Concurrent HMDs\n  - [ ] Advanced Gesture Detection\n  - [ ] Kinematics Predictive Sensor Fusion\n\n- [ ] Networking\n  - [ ] Share Space\n  - [ ] Dynamic Resource Streaming\n  - [ ] Avatar Synthesis\n  - [ ] Filtered sensor state to avatar mapping\n  - [ ] Voice Chat\n\n- [ ] Clients\n  - [ ] Alternate Representations\n  - [ ] Dynamic LoD\n\n- [ ] Rendering\n  - [ ] Culling\n  - [ ] Physics / Collision Response\n  - [ ] Multi-Channel Signed Distance Fields\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fletoram%2Fsafespaces","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fletoram%2Fsafespaces","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fletoram%2Fsafespaces/lists"}