From 86ff7f8550703d8636828d7d204e1c8aeeb94432 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Mon, 23 Aug 2021 15:23:16 +1000 Subject: Adding GDExtension support to XRInterface --- servers/xr/xr_interface.cpp | 70 ++++------ servers/xr/xr_interface.h | 27 ++-- servers/xr/xr_interface_extension.cpp | 241 ++++++++++++++++++++++++++++++++++ servers/xr/xr_interface_extension.h | 105 +++++++++++++++ 4 files changed, 381 insertions(+), 62 deletions(-) create mode 100644 servers/xr/xr_interface_extension.cpp create mode 100644 servers/xr/xr_interface_extension.h (limited to 'servers/xr') diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 09e8e12f8b..fc1d82a964 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -36,21 +36,19 @@ void XRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_capabilities"), &XRInterface::get_capabilities); ClassDB::bind_method(D_METHOD("is_primary"), &XRInterface::is_primary); - ClassDB::bind_method(D_METHOD("set_is_primary", "enable"), &XRInterface::set_is_primary); + ClassDB::bind_method(D_METHOD("set_primary", "primary"), &XRInterface::set_primary); ClassDB::bind_method(D_METHOD("is_initialized"), &XRInterface::is_initialized); - ClassDB::bind_method(D_METHOD("set_is_initialized", "initialized"), &XRInterface::set_is_initialized); ClassDB::bind_method(D_METHOD("initialize"), &XRInterface::initialize); ClassDB::bind_method(D_METHOD("uninitialize"), &XRInterface::uninitialize); ClassDB::bind_method(D_METHOD("get_tracking_status"), &XRInterface::get_tracking_status); - ClassDB::bind_method(D_METHOD("get_render_targetsize"), &XRInterface::get_render_targetsize); + ClassDB::bind_method(D_METHOD("get_render_target_size"), &XRInterface::get_render_target_size); ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count); ADD_GROUP("Interface", "interface_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_is_primary", "is_primary"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_initialized"), "set_is_initialized", "is_initialized"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_primary", "is_primary"); // we don't have any properties specific to VR yet.... @@ -77,70 +75,48 @@ void XRInterface::_bind_methods() { BIND_ENUM_CONSTANT(XR_INSUFFICIENT_FEATURES); BIND_ENUM_CONSTANT(XR_UNKNOWN_TRACKING); BIND_ENUM_CONSTANT(XR_NOT_TRACKING); -}; - -StringName XRInterface::get_name() const { - return "Unknown"; -}; +} bool XRInterface::is_primary() { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, false); return xr_server->get_primary_interface() == this; -}; +} -void XRInterface::set_is_primary(bool p_is_primary) { +void XRInterface::set_primary(bool p_primary) { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - if (p_is_primary) { + if (p_primary) { ERR_FAIL_COND(!is_initialized()); xr_server->set_primary_interface(this); - } else { - xr_server->clear_primary_interface_if(this); - }; -}; - -void XRInterface::set_is_initialized(bool p_initialized) { - if (p_initialized) { - if (!is_initialized()) { - initialize(); - }; - } else { - if (is_initialized()) { - uninitialize(); - }; - }; -}; - -XRInterface::Tracking_status XRInterface::get_tracking_status() const { - return tracking_state; -}; - -XRInterface::XRInterface() { - tracking_state = XR_UNKNOWN_TRACKING; -}; + } else if (xr_server->get_primary_interface() == this) { + xr_server->set_primary_interface(nullptr); + } +} -XRInterface::~XRInterface() {} +XRInterface::XRInterface() {} -// optional render to external texture which enhances performance on those platforms that require us to submit our end result into special textures. -unsigned int XRInterface::get_external_texture_for_eye(XRInterface::Eyes p_eye) { - return 0; -}; +XRInterface::~XRInterface() {} /** these will only be implemented on AR interfaces, so we want dummies for VR **/ bool XRInterface::get_anchor_detection_is_enabled() const { return false; -}; +} void XRInterface::set_anchor_detection_is_enabled(bool p_enable) { - // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc. } int XRInterface::get_camera_feed_id() { - // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc. - return 0; -}; +} + +/** these are optional, so we want dummies **/ +XRInterface::TrackingStatus XRInterface::get_tracking_status() const { + return XR_UNKNOWN_TRACKING; +} + +void XRInterface::notification(int p_what) { +} diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 6b248c9554..4f5d4bad10 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -68,7 +68,7 @@ public: EYE_RIGHT }; - enum Tracking_status { /* tracking status currently based on AR but we can start doing more with this for VR as well */ + enum TrackingStatus { /* tracking status currently based on AR but we can start doing more with this for VR as well */ XR_NORMAL_TRACKING, XR_EXCESSIVE_MOTION, XR_INSUFFICIENT_FEATURES, @@ -76,26 +76,25 @@ public: XR_NOT_TRACKING }; +private: protected: _THREAD_SAFE_CLASS_ - Tracking_status tracking_state; static void _bind_methods(); public: /** general interface information **/ - virtual StringName get_name() const; - virtual int get_capabilities() const = 0; + virtual StringName get_name() const = 0; + virtual uint32_t get_capabilities() const = 0; bool is_primary(); - void set_is_primary(bool p_is_primary); + void set_primary(bool p_is_primary); virtual bool is_initialized() const = 0; /* returns true if we've initialized this interface */ - void set_is_initialized(bool p_initialized); /* helper function, will call initialize or uninitialize */ virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */ virtual void uninitialize() = 0; /* deinitialize this interface */ - Tracking_status get_tracking_status() const; /* get the status of our current tracking */ + virtual TrackingStatus get_tracking_status() const; /* get the status of our current tracking */ /** specific to VR **/ // nothing yet @@ -107,27 +106,25 @@ public: /** rendering and internal **/ - virtual Size2 get_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */ + virtual Size2 get_render_target_size() = 0; /* returns the recommended render target size per eye for this device */ virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */ virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */ virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each view projection matrix */ + // note, external color/depth/vrs texture support will be added here soon. + virtual Vector commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */ virtual void process() = 0; - virtual void notification(int p_what) = 0; + virtual void notification(int p_what); XRInterface(); ~XRInterface(); - - // deprecated - virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye); /* if applicable return external texture to render to */ - virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */ }; VARIANT_ENUM_CAST(XRInterface::Capabilities); VARIANT_ENUM_CAST(XRInterface::Eyes); -VARIANT_ENUM_CAST(XRInterface::Tracking_status); +VARIANT_ENUM_CAST(XRInterface::TrackingStatus); -#endif +#endif // !XR_INTERFACE_H diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp new file mode 100644 index 0000000000..e1519d1463 --- /dev/null +++ b/servers/xr/xr_interface_extension.cpp @@ -0,0 +1,241 @@ +/*************************************************************************/ +/* xr_interface_extension.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "xr_interface_extension.h" +#include "servers/rendering/renderer_compositor.h" + +void XRInterfaceExtension::_bind_methods() { + GDVIRTUAL_BIND(_get_name); + GDVIRTUAL_BIND(_get_capabilities); + + GDVIRTUAL_BIND(_is_initialized); + GDVIRTUAL_BIND(_initialize); + GDVIRTUAL_BIND(_uninitialize); + + GDVIRTUAL_BIND(_get_tracking_status); + + ClassDB::bind_method(D_METHOD("add_blit", "render_target", "rect", "use_layer", "layer", "apply_lens_distortion", "eye_center", "k1", "k2", "upscale", "aspect_ratio"), &XRInterfaceExtension::add_blit); + + GDVIRTUAL_BIND(_get_render_target_size); + GDVIRTUAL_BIND(_get_view_count); + GDVIRTUAL_BIND(_get_camera_transform); + GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform"); + GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far"); + + GDVIRTUAL_BIND(_commit_views); + + GDVIRTUAL_BIND(_process); + GDVIRTUAL_BIND(_notification, "what"); + + // we don't have any properties specific to VR yet.... + + // but we do have properties specific to AR.... + GDVIRTUAL_BIND(_get_anchor_detection_is_enabled); + GDVIRTUAL_BIND(_set_anchor_detection_is_enabled, "enabled"); + GDVIRTUAL_BIND(_get_camera_feed_id); +} + +StringName XRInterfaceExtension::get_name() const { + StringName name; + + if (GDVIRTUAL_CALL(_get_name, name)) { + return name; + } + + return "Unknown"; +} + +uint32_t XRInterfaceExtension::get_capabilities() const { + uint32_t capabilities; + + if (GDVIRTUAL_CALL(_get_capabilities, capabilities)) { + return capabilities; + } + + return 0; +} + +bool XRInterfaceExtension::is_initialized() const { + bool initialised = false; + + if (GDVIRTUAL_CALL(_is_initialized, initialised)) { + return initialised; + } + + return false; +} + +bool XRInterfaceExtension::initialize() { + bool initialised = false; + + if (GDVIRTUAL_CALL(_initialize, initialised)) { + return initialised; + } + + return false; +} + +void XRInterfaceExtension::uninitialize() { + GDVIRTUAL_CALL(_uninitialize); +} + +XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const { + uint32_t status; + + if (GDVIRTUAL_CALL(_get_tracking_status, status)) { + return TrackingStatus(status); + } + + return XR_UNKNOWN_TRACKING; +} + +/** these will only be implemented on AR interfaces, so we want dummies for VR **/ +bool XRInterfaceExtension::get_anchor_detection_is_enabled() const { + bool enabled; + + if (GDVIRTUAL_CALL(_get_anchor_detection_is_enabled, enabled)) { + return enabled; + } + + return false; +} + +void XRInterfaceExtension::set_anchor_detection_is_enabled(bool p_enable) { + // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc. + GDVIRTUAL_CALL(_set_anchor_detection_is_enabled, p_enable); +} + +int XRInterfaceExtension::get_camera_feed_id() { + int feed_id; + + if (GDVIRTUAL_CALL(_get_camera_feed_id, feed_id)) { + return feed_id; + } + + return 0; +} + +Size2 XRInterfaceExtension::get_render_target_size() { + Size2 size; + + if (GDVIRTUAL_CALL(_get_render_target_size, size)) { + return size; + } + + return Size2(0, 0); +} + +uint32_t XRInterfaceExtension::get_view_count() { + uint32_t view_count; + + if (GDVIRTUAL_CALL(_get_view_count, view_count)) { + return view_count; + } + + return 1; +} + +Transform3D XRInterfaceExtension::get_camera_transform() { + Transform3D transform; + + if (GDVIRTUAL_CALL(_get_camera_transform, transform)) { + return transform; + } + + return Transform3D(); +} + +Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) { + Transform3D transform; + + if (GDVIRTUAL_CALL(_get_transform_for_view, p_view, p_cam_transform, transform)) { + return transform; + } + + return Transform3D(); +} + +CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) { + CameraMatrix cm; + PackedFloat64Array arr; + + if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) { + ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats"); + real_t *m = (real_t *)cm.matrix; + for (int i = 0; i < 16; i++) { + m[i] = arr[i]; + } + return cm; + } + + return CameraMatrix(); +} + +void XRInterfaceExtension::add_blit(RID p_render_target, Rect2i p_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, float p_k1, float p_k2, float p_upscale, float p_aspect_ratio) { + BlitToScreen blit; + + ERR_FAIL_COND_MSG(!can_add_blits, "add_blit can only be called from an XR plugin from within _commit_views!"); + + blit.render_target = p_render_target; + blit.rect = p_rect; + + blit.multi_view.use_layer = p_use_layer; + blit.multi_view.layer = p_layer; + + blit.lens_distortion.apply = p_apply_lens_distortion; + blit.lens_distortion.eye_center = p_eye_center; + blit.lens_distortion.k1 = p_k1; + blit.lens_distortion.k2 = p_k2; + blit.lens_distortion.upscale = p_upscale; + blit.lens_distortion.aspect_ratio = p_aspect_ratio; + + blits.push_back(blit); +} + +Vector XRInterfaceExtension::commit_views(RID p_render_target, const Rect2 &p_screen_rect) { + // This is just so our XR plugin can add blits... + blits.clear(); + can_add_blits = true; + + if (GDVIRTUAL_CALL(_commit_views, p_render_target, p_screen_rect)) { + return blits; + } + + can_add_blits = false; + return blits; +} + +void XRInterfaceExtension::process() { + GDVIRTUAL_CALL(_process); +} + +void XRInterfaceExtension::notification(int p_what) { + GDVIRTUAL_CALL(_notification, p_what); +} diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h new file mode 100644 index 0000000000..ab4d90bfe6 --- /dev/null +++ b/servers/xr/xr_interface_extension.h @@ -0,0 +1,105 @@ +/*************************************************************************/ +/* xr_interface_extension.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef XR_INTERFACE_EXTENSION_H +#define XR_INTERFACE_EXTENSION_H + +#include "servers/xr/xr_interface.h" + +class XRInterfaceExtension : public XRInterface { + GDCLASS(XRInterfaceExtension, XRInterface); + +public: +private: + bool can_add_blits = false; + Vector blits; + +protected: + _THREAD_SAFE_CLASS_ + + static void _bind_methods(); + +public: + /** general interface information **/ + virtual StringName get_name() const override; + virtual uint32_t get_capabilities() const override; + + GDVIRTUAL0RC(StringName, _get_name); + GDVIRTUAL0RC(uint32_t, _get_capabilities); + + virtual bool is_initialized() const override; + virtual bool initialize() override; + virtual void uninitialize() override; + + GDVIRTUAL0RC(bool, _is_initialized); + GDVIRTUAL0R(bool, _initialize); + GDVIRTUAL0(_uninitialize); + + virtual TrackingStatus get_tracking_status() const override; + GDVIRTUAL0RC(uint32_t, _get_tracking_status); + + /** specific to VR **/ + // nothing yet + + /** specific to AR **/ + virtual bool get_anchor_detection_is_enabled() const override; + virtual void set_anchor_detection_is_enabled(bool p_enable) override; + virtual int get_camera_feed_id() override; + + GDVIRTUAL0RC(bool, _get_anchor_detection_is_enabled); + GDVIRTUAL1(_set_anchor_detection_is_enabled, bool); + GDVIRTUAL0RC(int, _get_camera_feed_id); + + /** rendering and internal **/ + + virtual Size2 get_render_target_size() override; + virtual uint32_t get_view_count() override; + virtual Transform3D get_camera_transform() override; + virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; + virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override; + + GDVIRTUAL0R(Size2, _get_render_target_size); + GDVIRTUAL0R(uint32_t, _get_view_count); + GDVIRTUAL0R(Transform3D, _get_camera_transform); + GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &); + GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, real_t, real_t, real_t); + + void add_blit(RID p_render_target, Rect2i p_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), float p_k1 = 0.0, float p_k2 = 0.0, float p_upscale = 1.0, float p_aspect_ratio = 1.0); + virtual Vector commit_views(RID p_render_target, const Rect2 &p_screen_rect) override; + GDVIRTUAL2(_commit_views, RID, const Rect2 &); + + virtual void process() override; + virtual void notification(int p_what) override; + + GDVIRTUAL0(_process); + GDVIRTUAL1(_notification, int); +}; + +#endif // !XR_INTERFACE_EXTENSION_H -- cgit v1.2.3