This PR adds the ability for the developer to create and manage their own spatial anchors.
Here's a screenshot from the demo:
When you switch into passthrough mode, you can press the trigger on a surface from scene understanding (aka a scene anchor) and place a spatial anchor, which is represented by a colored cone (the color is selected randomly). If you point at an existing spatial anchor, pressing the trigger will remove it. If you close and open the app again, the spatial anchors will be restored with the same colors they had previously.
You can create an anchor by calling create_anchor(transform: Transform3D, custom_data: Dictionary) on the node. It won't be created immediately - it's an asynchronous operation. But when it is, the openxr_fb_spatial_anchor_tracked signal will be emitted, which will give the developer an XRAnchor3D and the OpenXRFbSpatialEntity object (with the custom_data stashed in it). The custom_data can be used to store application-specific data about what the anchor actually is, ie what object the player is actually placing in the world (on the OpenXR side it only has a UUID and a location).
I suspect a very common case will be creating an instance of a particular scene as a child of the XRAnchor3D. So, rather than connecting to the openxr_fb_spatial_anchor_tracked signal and instantiating the scene manually, the developer can optionally set the scene property, which will be automatically instantiated, and have a method called on it with the OpenXRFbSpatialEntity. (This is very similar to how OpenXRFbSceneManager works!) Here they can grab the custom_data and use it to initialize the scene - the demo uses this to setup the anchor with the correct color.
By using the persist_in_local_file and local_file_path, the OpenXRFbSpatialAnchorManager node will save the anchors to a JSON file (along with their custom_data), and then automatically load them from the file when the application starts up again. While it's possible to query OpenXR for all pre-existing anchors, all you get is the UUIDs and positions, you don't get any information about what the anchor is meant to be in the application. That's why we need to also store these in a JSON file along with the custom_data, which is where the developer would put that information.
The openxr_fb_spatial_anchor_tracked signal is also emitted for anchors that are loaded (not just created), which allows the developer to handle new and existing anchors at the same time.
If the developer doesn't want any of the automatic file saving/loading or other automatic features, they can disable those via properties on the node, which gives them the freedom to do something more custom if they want.
UPDATE:The saving/loading from file functionality was removed from the node, and moved into the demo project. Developers will need to implement their own loading/saving, but once they hand the data off to the node, it should take care of everything else.
This is a follow-up to PR https://github.com/GodotVR/godot_openxr_vendors/pull/107 which added support for scene anchors (aka the data from Meta's scene understanding).
This PR adds the ability for the developer to create and manage their own spatial anchors.
Here's a screenshot from the demo:
When you switch into passthrough mode, you can press the trigger on a surface from scene understanding (aka a scene anchor) and place a spatial anchor, which is represented by a colored cone (the color is selected randomly). If you point at an existing spatial anchor, pressing the trigger will remove it. If you close and open the app again, the spatial anchors will be restored with the same colors they had previously.
This is done via a new node called
OpenXRFbSpatialAnchorManager
which works a lot like theOpenXRFbSceneManager
which was added in PR https://github.com/GodotVR/godot_openxr_vendors/pull/107Here's how it works:
create_anchor(transform: Transform3D, custom_data: Dictionary)
on the node. It won't be created immediately - it's an asynchronous operation. But when it is, theopenxr_fb_spatial_anchor_tracked
signal will be emitted, which will give the developer anXRAnchor3D
and theOpenXRFbSpatialEntity
object (with thecustom_data
stashed in it). Thecustom_data
can be used to store application-specific data about what the anchor actually is, ie what object the player is actually placing in the world (on the OpenXR side it only has a UUID and a location).XRAnchor3D
. So, rather than connecting to theopenxr_fb_spatial_anchor_tracked
signal and instantiating the scene manually, the developer can optionally set thescene
property, which will be automatically instantiated, and have a method called on it with theOpenXRFbSpatialEntity
. (This is very similar to howOpenXRFbSceneManager
works!) Here they can grab thecustom_data
and use it to initialize the scene - the demo uses this to setup the anchor with the correct color.By using thepersist_in_local_file
andlocal_file_path
, theOpenXRFbSpatialAnchorManager
node will save the anchors to a JSON file (along with theircustom_data
), and then automatically load them from the file when the application starts up again. While it's possible to query OpenXR for all pre-existing anchors, all you get is the UUIDs and positions, you don't get any information about what the anchor is meant to be in the application. That's why we need to also store these in a JSON file along with thecustom_data
, which is where the developer would put that information.openxr_fb_spatial_anchor_tracked
signal is also emitted for anchors that are loaded (not just created), which allows the developer to handle new and existing anchors at the same time.If the developer doesn't want any of the automatic file saving/loading or other automatic features, they can disable those via properties on the node, which gives them the freedom to do something more custom if they want.UPDATE: The saving/loading from file functionality was removed from the node, and moved into the demo project. Developers will need to implement their own loading/saving, but once they hand the data off to the node, it should take care of everything else.
Here's the properties in the editor: