2017-04-23 12:10:41 +00:00
/*************************************************************************/
2020-04-08 14:47:36 +00:00
/* xr_interface.cpp */
2017-04-23 12:10:41 +00:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2017-04-23 12:10:41 +00:00
/*************************************************************************/
2022-01-03 20:27:34 +00:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2017-04-23 12:10:41 +00:00
/* */
/* 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. */
/*************************************************************************/
2018-01-04 23:50:27 +00:00
2020-04-08 14:47:36 +00:00
# include "xr_interface.h"
2022-02-11 11:33:54 +00:00
# include "servers/rendering/renderer_compositor.h"
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
void XRInterface : : _bind_methods ( ) {
2021-06-27 11:51:30 +00:00
ADD_SIGNAL ( MethodInfo ( " play_area_changed " , PropertyInfo ( Variant : : INT , " mode " ) ) ) ;
2020-04-08 14:47:36 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_name " ) , & XRInterface : : get_name ) ;
ClassDB : : bind_method ( D_METHOD ( " get_capabilities " ) , & XRInterface : : get_capabilities ) ;
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
ClassDB : : bind_method ( D_METHOD ( " is_primary " ) , & XRInterface : : is_primary ) ;
2021-08-23 05:23:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_primary " , " primary " ) , & XRInterface : : set_primary ) ;
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
ClassDB : : bind_method ( D_METHOD ( " is_initialized " ) , & XRInterface : : is_initialized ) ;
ClassDB : : bind_method ( D_METHOD ( " initialize " ) , & XRInterface : : initialize ) ;
ClassDB : : bind_method ( D_METHOD ( " uninitialize " ) , & XRInterface : : uninitialize ) ;
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_tracking_status " ) , & XRInterface : : get_tracking_status ) ;
2017-09-29 11:36:27 +00:00
2021-08-23 05:23:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_render_target_size " ) , & XRInterface : : get_render_target_size ) ;
2021-05-07 13:19:04 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_view_count " ) , & XRInterface : : get_view_count ) ;
2017-09-29 11:36:27 +00:00
2021-08-29 06:05:11 +00:00
ClassDB : : bind_method ( D_METHOD ( " trigger_haptic_pulse " , " action_name " , " tracker_name " , " frequency " , " amplitude " , " duration_sec " , " delay_sec " ) , & XRInterface : : trigger_haptic_pulse ) ;
2017-09-29 11:36:27 +00:00
ADD_GROUP ( " Interface " , " interface_ " ) ;
2021-08-23 05:23:16 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " interface_is_primary " ) , " set_primary " , " is_primary " ) ;
2017-09-29 11:36:27 +00:00
2021-06-27 11:51:30 +00:00
// methods and properties specific to VR...
ClassDB : : bind_method ( D_METHOD ( " supports_play_area_mode " , " mode " ) , & XRInterface : : supports_play_area_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_play_area_mode " ) , & XRInterface : : get_play_area_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_play_area_mode " , " mode " ) , & XRInterface : : set_play_area_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_play_area " ) , & XRInterface : : get_play_area ) ;
ADD_GROUP ( " XR " , " xr_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " xr_play_area_mode " , PROPERTY_HINT_ENUM , " Unknown,3DOF,Sitting,Roomscale,Stage " ) , " set_play_area_mode " , " get_play_area_mode " ) ;
2017-04-23 12:10:41 +00:00
2021-06-27 11:51:30 +00:00
// methods and properties specific to AR....
2020-04-08 14:47:36 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_anchor_detection_is_enabled " ) , & XRInterface : : get_anchor_detection_is_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_anchor_detection_is_enabled " , " enable " ) , & XRInterface : : set_anchor_detection_is_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " get_camera_feed_id " ) , & XRInterface : : get_camera_feed_id ) ;
2017-04-23 12:10:41 +00:00
2017-09-29 11:36:27 +00:00
ADD_GROUP ( " AR " , " ar_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " ar_is_anchor_detection_enabled " ) , " set_anchor_detection_is_enabled " , " get_anchor_detection_is_enabled " ) ;
2020-04-08 14:47:36 +00:00
BIND_ENUM_CONSTANT ( XR_NONE ) ;
BIND_ENUM_CONSTANT ( XR_MONO ) ;
BIND_ENUM_CONSTANT ( XR_STEREO ) ;
2021-08-29 06:05:11 +00:00
BIND_ENUM_CONSTANT ( XR_QUAD ) ;
BIND_ENUM_CONSTANT ( XR_VR ) ;
2020-04-08 14:47:36 +00:00
BIND_ENUM_CONSTANT ( XR_AR ) ;
BIND_ENUM_CONSTANT ( XR_EXTERNAL ) ;
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
BIND_ENUM_CONSTANT ( XR_NORMAL_TRACKING ) ;
BIND_ENUM_CONSTANT ( XR_EXCESSIVE_MOTION ) ;
BIND_ENUM_CONSTANT ( XR_INSUFFICIENT_FEATURES ) ;
BIND_ENUM_CONSTANT ( XR_UNKNOWN_TRACKING ) ;
BIND_ENUM_CONSTANT ( XR_NOT_TRACKING ) ;
2021-06-27 11:51:30 +00:00
BIND_ENUM_CONSTANT ( XR_PLAY_AREA_UNKNOWN ) ;
BIND_ENUM_CONSTANT ( XR_PLAY_AREA_3DOF ) ;
BIND_ENUM_CONSTANT ( XR_PLAY_AREA_SITTING ) ;
BIND_ENUM_CONSTANT ( XR_PLAY_AREA_ROOMSCALE ) ;
BIND_ENUM_CONSTANT ( XR_PLAY_AREA_STAGE ) ;
} ;
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
bool XRInterface : : is_primary ( ) {
XRServer * xr_server = XRServer : : get_singleton ( ) ;
ERR_FAIL_NULL_V ( xr_server , false ) ;
2017-04-23 12:10:41 +00:00
2020-04-08 14:47:36 +00:00
return xr_server - > get_primary_interface ( ) = = this ;
2021-08-23 05:23:16 +00:00
}
2017-04-23 12:10:41 +00:00
2021-08-23 05:23:16 +00:00
void XRInterface : : set_primary ( bool p_primary ) {
2020-04-08 14:47:36 +00:00
XRServer * xr_server = XRServer : : get_singleton ( ) ;
ERR_FAIL_NULL ( xr_server ) ;
2017-04-23 12:10:41 +00:00
2021-08-23 05:23:16 +00:00
if ( p_primary ) {
2017-04-23 12:10:41 +00:00
ERR_FAIL_COND ( ! is_initialized ( ) ) ;
2020-04-08 14:47:36 +00:00
xr_server - > set_primary_interface ( this ) ;
2021-08-23 05:23:16 +00:00
} else if ( xr_server - > get_primary_interface ( ) = = this ) {
xr_server - > set_primary_interface ( nullptr ) ;
}
}
2017-09-29 11:36:27 +00:00
2021-08-23 05:23:16 +00:00
XRInterface : : XRInterface ( ) { }
2017-09-29 11:36:27 +00:00
2022-02-11 11:33:54 +00:00
XRInterface : : ~ XRInterface ( ) {
if ( vrs . vrs_texture . is_valid ( ) ) {
RS : : get_singleton ( ) - > free ( vrs . vrs_texture ) ;
vrs . vrs_texture = RID ( ) ;
}
}
2019-03-30 13:03:49 +00:00
2021-06-27 11:51:30 +00:00
// query if this interface supports this play area mode
bool XRInterface : : supports_play_area_mode ( XRInterface : : PlayAreaMode p_mode ) {
return p_mode = = XR_PLAY_AREA_UNKNOWN ;
}
// get the current play area mode
XRInterface : : PlayAreaMode XRInterface : : get_play_area_mode ( ) const {
return XR_PLAY_AREA_UNKNOWN ;
}
// change the play area mode, note that this should return false if the mode is not available
bool XRInterface : : set_play_area_mode ( XRInterface : : PlayAreaMode p_mode ) {
return p_mode = = XR_PLAY_AREA_UNKNOWN ;
}
// if available, returns an array of vectors denoting the play area the player can move around in
PackedVector3Array XRInterface : : get_play_area ( ) const {
// Return an empty array by default.
// Note implementation is responsible for applying our reference frame and world scale to the raw data.
// `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes.
return PackedVector3Array ( ) ;
} ;
2017-09-29 11:36:27 +00:00
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
2020-04-08 14:47:36 +00:00
bool XRInterface : : get_anchor_detection_is_enabled ( ) const {
2017-09-29 11:36:27 +00:00
return false ;
2021-08-23 05:23:16 +00:00
}
2017-09-29 11:36:27 +00:00
2020-05-19 09:24:58 +00:00
void XRInterface : : set_anchor_detection_is_enabled ( bool p_enable ) {
}
2017-08-20 14:17:24 +00:00
2020-04-08 14:47:36 +00:00
int XRInterface : : get_camera_feed_id ( ) {
2017-08-20 14:17:24 +00:00
return 0 ;
2021-08-23 05:23:16 +00:00
}
2022-02-11 11:33:54 +00:00
RID XRInterface : : get_vrs_texture ( ) {
// Default logic will return a standard VRS image based on our target size and default projections.
// Note that this only gets called if VRS is supported on the hardware.
Size2 texel_size = Size2 ( 16.0 , 16.0 ) ; // For now we assume we always use 16x16 texels, seems to be the standard.
int view_count = get_view_count ( ) ;
Size2 target_size = get_render_target_size ( ) ;
real_t aspect = target_size . x / target_size . y ; // is this y/x ?
Size2 vrs_size = Size2 ( round ( 0.5 + target_size . x / texel_size . x ) , round ( 0.5 + target_size . y / texel_size . y ) ) ;
real_t radius = vrs_size . length ( ) * 0.5 ;
Size2 vrs_sizei = vrs_size ;
if ( vrs . size ! = vrs_sizei ) {
const uint8_t densities [ ] = {
0 , // 1x1
1 , // 1x2
// 4, // 2x1
5 , // 2x2
6 , // 2x4
// 9, // 4x2
10 , // 4x4
} ;
// out with the old
if ( vrs . vrs_texture . is_valid ( ) ) {
RS : : get_singleton ( ) - > free ( vrs . vrs_texture ) ;
vrs . vrs_texture = RID ( ) ;
}
// in with the new
Vector < Ref < Image > > images ;
vrs . size = vrs_sizei ;
for ( int i = 0 ; i < view_count & & i < 2 ; i + + ) {
PackedByteArray data ;
data . resize ( vrs_sizei . x * vrs_sizei . y ) ;
uint8_t * data_ptr = data . ptrw ( ) ;
// Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
CameraMatrix cm = get_projection_for_view ( i , aspect , 0.1 , 1000.0 ) ;
Vector3 center = cm . xform ( Vector3 ( 0.0 , 0.0 , 999.0 ) ) ;
Vector2i view_center ;
view_center . x = int ( vrs_size . x * ( center . x + 1.0 ) * 0.5 ) ;
view_center . y = int ( vrs_size . y * ( center . y + 1.0 ) * 0.5 ) ;
int d = 0 ;
for ( int y = 0 ; y < vrs_sizei . y ; y + + ) {
for ( int x = 0 ; x < vrs_sizei . x ; x + + ) {
Vector2 offset = Vector2 ( x - view_center . x , y - view_center . y ) ;
offset . y * = aspect ;
real_t distance = offset . length ( ) ;
int idx = round ( 5.0 * distance / radius ) ;
if ( idx > 4 ) {
idx = 4 ;
}
uint8_t density = densities [ idx ] ;
data_ptr [ d + + ] = density ;
}
}
Ref < Image > image ;
image . instantiate ( ) ;
image - > create_from_data ( vrs_sizei . x , vrs_sizei . y , false , Image : : FORMAT_R8 , data ) ;
images . push_back ( image ) ;
}
if ( images . size ( ) = = 1 ) {
vrs . vrs_texture = RS : : get_singleton ( ) - > texture_2d_create ( images [ 0 ] ) ;
} else {
vrs . vrs_texture = RS : : get_singleton ( ) - > texture_2d_layered_create ( images , RS : : TEXTURE_LAYERED_2D_ARRAY ) ;
}
}
return vrs . vrs_texture ;
}
2021-08-23 05:23:16 +00:00
/** these are optional, so we want dummies **/
2021-08-29 06:05:11 +00:00
PackedStringArray XRInterface : : get_suggested_tracker_names ( ) const {
PackedStringArray arr ;
return arr ;
}
PackedStringArray XRInterface : : get_suggested_pose_names ( const StringName & p_tracker_name ) const {
PackedStringArray arr ;
return arr ;
}
2021-08-23 05:23:16 +00:00
XRInterface : : TrackingStatus XRInterface : : get_tracking_status ( ) const {
return XR_UNKNOWN_TRACKING ;
}
2021-08-29 06:05:11 +00:00
void XRInterface : : trigger_haptic_pulse ( const String & p_action_name , const StringName & p_tracker_name , double p_frequency , double p_amplitude , double p_duration_sec , double p_delay_sec ) {
}