Prevent fatal error in WebXR when 'immersize-ar' loses and regains tracking

This commit is contained in:
David Snopek 2021-01-27 14:16:00 -06:00
parent 1ea133b6b5
commit a23fc126eb
3 changed files with 32 additions and 10 deletions

View File

@ -380,6 +380,11 @@ const GodotWebXR = {
gl.deleteTexture(texture); gl.deleteTexture(texture);
} }
GodotWebXR.textures[i] = null; GodotWebXR.textures[i] = null;
const texture_id = GodotWebXR.texture_ids[i];
if (texture_id !== null) {
GL.textures[texture_id] = null;
}
GodotWebXR.texture_ids[i] = null; GodotWebXR.texture_ids[i] = null;
} }
@ -460,7 +465,7 @@ const GodotWebXR = {
godot_webxr_get_external_texture_for_eye__proxy: 'sync', godot_webxr_get_external_texture_for_eye__proxy: 'sync',
godot_webxr_get_external_texture_for_eye__sig: 'ii', godot_webxr_get_external_texture_for_eye__sig: 'ii',
godot_webxr_get_external_texture_for_eye: function (p_eye) { godot_webxr_get_external_texture_for_eye: function (p_eye) {
if (!GodotWebXR.session || !GodotWebXR.pose) { if (!GodotWebXR.session) {
return 0; return 0;
} }
@ -469,6 +474,13 @@ const GodotWebXR = {
return GodotWebXR.texture_ids[view_index]; return GodotWebXR.texture_ids[view_index];
} }
// Check pose separately and after returning the cached texture id,
// because we won't get a pose in some cases if we lose tracking, and
// we don't want to return 0 just because tracking was lost.
if (!GodotWebXR.pose) {
return 0;
}
const glLayer = GodotWebXR.session.renderState.baseLayer; const glLayer = GodotWebXR.session.renderState.baseLayer;
const view = GodotWebXR.pose.views[view_index]; const view = GodotWebXR.pose.views[view_index];
const viewport = glLayer.getViewport(view); const viewport = glLayer.getViewport(view);

View File

@ -78,6 +78,8 @@ void _emwebxr_on_session_failed(char *p_message) {
Ref<XRInterface> interface = xr_server->find_interface("WebXR"); Ref<XRInterface> interface = xr_server->find_interface("WebXR");
ERR_FAIL_COND(interface.is_null()); ERR_FAIL_COND(interface.is_null());
interface->uninitialize();
String message = String(p_message); String message = String(p_message);
interface->emit_signal("session_failed", message); interface->emit_signal("session_failed", message);
} }
@ -224,6 +226,12 @@ bool WebXRInterfaceJS::initialize() {
// make this our primary interface // make this our primary interface
xr_server->set_primary_interface(this); xr_server->set_primary_interface(this);
// Clear render_targetsize to make sure it gets reset to the new size.
// Clearing in uninitialize() doesn't work because a frame can still be
// rendered after it's called, which will fill render_targetsize again.
render_targetsize.width = 0;
render_targetsize.height = 0;
initialized = true; initialized = true;
godot_webxr_initialize( godot_webxr_initialize(
@ -277,22 +285,24 @@ Transform WebXRInterfaceJS::_js_matrix_to_transform(float *p_js_matrix) {
} }
Size2 WebXRInterfaceJS::get_render_targetsize() { Size2 WebXRInterfaceJS::get_render_targetsize() {
Size2 target_size; if (render_targetsize.width != 0 && render_targetsize.height != 0) {
return render_targetsize;
}
int *js_size = godot_webxr_get_render_targetsize(); int *js_size = godot_webxr_get_render_targetsize();
if (!initialized || js_size == nullptr) { if (!initialized || js_size == nullptr) {
// As a default, use half the window size. // As a temporary default (until WebXR is fully initialized), use half the window size.
target_size = DisplayServer::get_singleton()->window_get_size(); Size2 temp = DisplayServer::get_singleton()->window_get_size();
target_size.width /= 2.0; temp.width /= 2.0;
return target_size; return temp;
} }
target_size.width = js_size[0]; render_targetsize.width = js_size[0];
target_size.height = js_size[1]; render_targetsize.height = js_size[1];
free(js_size); free(js_size);
return target_size; return render_targetsize;
}; };
Transform WebXRInterfaceJS::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) { Transform WebXRInterfaceJS::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {

View File

@ -47,7 +47,6 @@ class WebXRInterfaceJS : public WebXRInterface {
private: private:
bool initialized; bool initialized;
// @todo Should these really use enums instead of strings?
String session_mode; String session_mode;
String required_features; String required_features;
String optional_features; String optional_features;
@ -55,6 +54,7 @@ private:
String reference_space_type; String reference_space_type;
bool controllers_state[2]; bool controllers_state[2];
Size2 render_targetsize;
Transform _js_matrix_to_transform(float *p_js_matrix); Transform _js_matrix_to_transform(float *p_js_matrix);
void _update_tracker(int p_controller_id); void _update_tracker(int p_controller_id);