Skip to content

rapid flickering during loading a new scene #284

@coderofsalvation

Description

@coderofsalvation
Image

On Android and Oculus Quest2 (in immersive mode), it happens quite often that after clicking a portal, rapid flickering occurs (basically alternating between the current scene and a completely white image).
I've attached a (vesta) portal to reproduce it, but beware it never happens on desktop, but many times on oculus quest (and sometimes on android).

I can't tell whether its the JML causing it or not, perhaps one of these global vesta-scripts are used by various scenes, and are choking on something?

<FireBoxRoom>
 <Inputs>
  <Attribute description="URL for Image 1" name="image_1" type="text" value="https://picsum.photos/1920/1080/?random"/>
  <Attribute description="URL for Image 2" name="image_2" type="text" value="https://picsum.photos/1280/720/?random"/>
  <Attribute description="URL for Video" name="video_1" type="text" value="https://www.youtube.com/watch?v=jBNxhmtJLP8"/>
  <Attribute description="Autoplay Video?" name="video_autoplay" type="boolean" value="false"/>
  <Attribute description="URL for portal at entrance" name="link_url" type="text" value="https://vesta.janusxr.org"/>
  <Attribute description="Thumbnail for entrance portal" name="link_thumbnail" type="text" value="https://vesta.janusxr.org/files/admin/default_webspace/vesta_link.jpg"/>
 </Inputs>
 <Assets>
  
  <AssetObject id="main" src="https://vesta.janusxr.org/files/admin/default_webspace/TheMinimalistPalace.dae.gz"/>
  <AssetObject id="main_col" src="https://vesta.janusxr.org/files/admin/default_webspace/TheMinimalistPalaceCol.obj.gz"/>
  
  <AssetObject id="pic1" src="https://vesta.janusxr.org/files/admin/default_webspace/pic1.obj"/>
  <AssetObject id="pic2" src="https://vesta.janusxr.org/files/admin/default_webspace/pic2.obj"/>
  
  <AssetImage id="pic1_img" src="https://picsum.photos/1920/1080/?random"/>
  <AssetImage id="pic2_img" src="https://picsum.photos/1280/720/?random"/>
  <AssetImage id="link_img" src="https://vesta.janusxr.org/files/admin/default_webspace/vesta_link.jpg"/>
  
  <AssetObject id="youtube1" src="https://vesta.janusxr.org/files/admin/default_webspace/youtube1.obj"/>
  <AssetVideo auto_play="true" gain="0.3" id="main_video" src="https://www.youtube.com/watch?v=jBNxhmtJLP8"/>
  
  <AssetImage id="irradiance" src="https://vesta.janusxr.org/files/admin/default_webspace/Skybox/HDRcubemap_irradiance64.dds.gz" tex_clamp="true"/>
  <AssetImage id="radiance" src="https://vesta.janusxr.org/files/admin/default_webspace/Skybox/HDRcubemap_radiance256.dds.gz" tex_clamp="true"/>
  <AssetImage id="probe" src="https://vesta.janusxr.org/files/admin/default_webspace/Skybox/TheMinimalistPalaceWebProbe.jpg"/>
  
  <AssetObject id="carpet" src="https://vesta.janusxr.org/files/admin/default_webspace/TheMinimalistPalaceCarpet.obj.gz"/>
  <AssetScript src="https://vesta.janusxr.org/files/admin/default_webspace/script.js"/>
  <AssetScript src="https://vesta.janusxr.org/static/js/live_update.js"/>
  <AssetScript src="https://vesta.janusxr.org/files/admin/scripts/vesta_comment_inject.js"/>
 </Assets>
 <Room cubemap_irradiance_id="irradiance" cubemap_radiance_id="radiance" pbr="true" pos="-2.8 1 0" use_local_asset="room_plane" visible="false" xdir="0 0 -1" zdir="1 0 0">
  <Object collision_id="main_col" envmap_id="probe" id="main" js_id="Scan_id_forJS"/>
  <Object id="pic1" image_id="pic1_img" lighting="false"/>
  <Object id="pic2" image_id="pic2_img" lighting="false"/>
  <Object collision_id="youtube1" id="youtube1" lighting="false" video_id="main_video"/>
  <Link draw_text="false" pos="-2.95 0.8 0" scale="2 3.2 1" thumb_id="link_img" url="https://vesta.janusxr.org" zdir="1 0 0"/>
  
  <Object fwd="0.542248 0 -0.840219" js_id="vesta_thumbnail_camera" pos="5.2 2 0"/>
 </Room>
</FireBoxRoom>

https://vesta.janusxr.org/files/admin/default_webspace/script.js

room.onLoad = function() 
{
	var timetest = room.url.length % 10;
	room.loadNewAsset("Image", {id:"carpet", src:"https://vesta.janusvr.com/files/admin/default_webspace/carpets/carpet" + timetest + ".jpg"})
	room.createObject("Object", {id:"carpet", js_id:"carpet", image_id:"carpet"});
	
	if (room.objects['Scan_id_forJS'])
	{
		room.objects["Scan_id_forJS"].col = Vector(0.5+0.5*Math.random(), 0.5+0.5*Math.random(), 0.5+0.5*Math.random());
	}
}

https://vesta.janusxr.org/static/js/live_update.js

var live_update_started = false;
var userid;
var lighting_fix = false;
var loaded = false;

room.update = function(dt)
{
	if (!isJanusWeb)
	{
		updateTimers();
	}
	if (!loaded)
	{
		loaded = true;
		userid = player.userid;
		updateUserInfo();
	}
}
function get_server_base()
{
	var protocol = 'http';
	var hostname = extractHostname(room.url)
	
    if (room.url.indexOf("://") > -1) {
        protocol = room.url.split('/')[0];
    }
	
	return protocol+'//'+hostname;
}
function extractHostname(url) {
    var hostname;
    /* find & remove protocol (http, ftp, etc.) and get hostname */

    if (url.indexOf("://") > -1) {
        hostname = url.split('/')[2];
    }
    else {
        hostname = url.split('/')[0];
    }

    /* find & remove port number */
    /*  hostname = hostname.split(':')[0]; */
    /* find & remove "?" */
    hostname = hostname.split('?')[0];

    return hostname;
}

function updateUserInfo()
{
	var xhr = new XMLHttpRequest();
	xhr.addEventListener('load', updateUserInfoDone);
	var server_base = get_server_base();
	xhr.open('POST', server_base+'/user_count');
	if (isJanusWeb)
	{
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	}
	var data = 'started='+live_update_started+'&disableParty=false&username='+encodeURIComponent(userid)+'&roomUrl='+encodeURIComponent(player.url);
	live_update_started = true;
	xhr.send(data);
}

function updateUserInfoDone(ev)
{
	setTimeout(function()
	{
		updateUserInfo()
	}, 10000);
}


/* Native client compatibility functions */
var isJanusWeb = (typeof elation != 'undefined');

function getRandomIntInclusive(min, max) {
	min = Math.ceil(min);
	max = Math.floor(max);
	return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getTimestamp() {
	if (isJanusWeb) {
		return performance.now();
	}
	return new Date().getTime();
}
 
if (typeof setTimeout != 'function') {
	var globalTimers = {},
			globalTimerID = 1;
 
	setTimeout = function(fn, delay) {
		var now = getTimestamp(),
				id = globalTimerID++;
		globalTimers[id] = {fn: fn, delay: delay, time: now, args: Array.prototype.splice.call(arguments, 2), repeat: false};
		return id;
	}
	setInterval = function(fn, delay) {
		var now = getTimestamp(),
				id = globalTimerID++;
		globalTimers[id] = {fn: fn, delay: delay, time: now, args: Array.prototype.splice.call(arguments, 2), repeat: true};
		return id;
	}
	clearTimeout = function(id) {
		delete globalTimers[id];
	}
	updateTimers = function() {
		var now = getTimestamp();
		var keys = Object.keys(globalTimers);
		for (var i = 0; i < keys.length; i++) {
			var id = keys[i],
					timer = globalTimers[id];
			if (timer.time + timer.delay <= now) {
				timer.fn.apply(null, timer.args);
				if (timer.repeat) {
					timer.time = now;
				} else {
					clearTimeout(id);
				}
			}
		}
	}
}
 
function bind(ctx, fn) {
	if (typeof fn == 'function') {
		var fnargs = Array.prototype.splice.call(arguments, 2);
		fnargs.unshift(ctx);
		return (typeof fn.bind == 'function' ?
				Function.prototype.bind.apply(fn, fnargs) :
				function() { fn.apply(ctx, arguments); }
			);
	} else if (typeof ctx == 'function') {
		return ctx;
	}
}

https://vesta.janusxr.org/files/admin/scripts/vesta_comment_inject.js

var isJanusWeb = (typeof elation != 'undefined');
var api_query_url = null;
var comments = [];
var comment_positions = [];
var fetched = false;
var comment_bubble_scale = 0.2;
var comment_scale = 0.5;
var spin_speed = 30;
var move_timer = 0;
var reload_timer = 0;
var resize_timer = 0;
var comments_enabled = true;


// native
var last_gaze_js_id = null;
var gaze_time = 0.0;
var gaze_on = false;

function get_server_base()
{
	var protocol = 'http';
	var hostname = extractHostname(room.url)
	
    if (room.url.indexOf("://") > -1) {
        protocol = room.url.split('/')[0];
    }
	
	return protocol+'//'+hostname;
}
function extractHostname(url) {
    var hostname;
    //find & remove protocol (http, ftp, etc.) and get hostname

    if (url.indexOf("://") > -1) {
        hostname = url.split('/')[2];
    }
    else {
        hostname = url.split('/')[0];
    }

    //find & remove port number
    // hostname = hostname.split(':')[0];
    //find & remove "?"
    hostname = hostname.split('?')[0];

    return hostname;
}
function getComments()
{
	var xhr = new XMLHttpRequest();
	xhr.addEventListener('load', parseComments);
	xhr.open('GET', api_query_url);
	xhr.send();
}
function parseComments(ev)
{
	var xhr = ev.target;
	var response = JSON.parse(xhr.responseText);

	if (response.success && response.data)
	{
		for (var i = 0; i < response.data.length; i++)
		{
			var comment = response.data[i];
			var pos = comment.pos
			if (pos)
			{
				var cid = comment.id;
				var js_id = 'vestacommentinject_'+cid;
				if (room.objects[js_id] == null)
				{
					var startpos = [0,0,0];
					if (room.playerstartposition)
					{
						startpos = room.playerstartposition;
					}
					var dist = distance(Vector(pos.x, pos.y+1.0, pos.z), Vector(startpos[0], startpos[1], startpos[2]))
					var valid = true;
					if (dist > 1.5)
					{
						for (i2 = 0; i2 < comment_positions.length; i2 ++)
						{
							var pos2 = comment_positions[i2];
							dist = distance(Vector(pos.x, pos.y+1.0, pos.z), pos2);
							if (dist <= comment_bubble_scale*2 && valid)
							{
								//console.log('Skip comment '+cid+', too close to another');
								valid = false;
							}
							
						}
						if (valid)
						{
							var image = comment.image;
							var username = comment.username;
							var css = ".textwrapper { padding: 16px 16px 16px 16px; } .wrapper { font-size: 32px; color: white; border-style:solid; border-width:4px; border-color: #343138; background-color: #1d1c1f; color: white; font-family: sans-serif; } h1 { font-size: 38px; display:table-cell; padding-top: 8px} p { font-size: 32px; }";
							var body = '<div class="wrapper"> <div class="textwrapper"> <h1>'+username+'</h1> <p>'+comment.body+'</p> </div> </div>';
							var bubble;
							if (isJanusWeb)
							{
								bubble = room.createObject('Object', { id:'sphere', collision_radius:comment_bubble_scale, collision_trigger:true, js_id:'bubble_'+js_id, image_id: get_server_base()+'/static/images/comment_equi.jpg', pos:Vector(pos.x, pos.y+1.0, pos.z), gazetime:'200', ongazeactivate:'show_comment("'+js_id+'")', ongazeleave:'hide_comment("'+js_id+'")', ongazeprogress:"gazeProgress(this, event)", scale:Vector(comment_bubble_scale,comment_bubble_scale,comment_bubble_scale), locked:true, lighting:false, cull_face:'front', rotate_deg_per_sec:spin_speed });
							}
							else
							{
								bubble = room.createObject('Object', { id:'sphere', collision_id:'sphere', collision_scale:Vector(1), collision_trigger:true, js_id:'bubble_'+js_id, image_id: get_server_base()+'/static/images/comment_equi.jpg', pos:Vector(pos.x, pos.y+1.0, pos.z), gazetime:'200', ongazeactivate:'show_comment("'+js_id+'")', ongazeleave:'hide_comment("'+js_id+'")', ongazeprogress:"gazeProgress(this, event)", scale:Vector(comment_bubble_scale,comment_bubble_scale,comment_bubble_scale), locked:true, lighting:false, cull_face:'front', rotate_deg_per_sec:spin_speed });
							}
							var bubble_outside = room.createObject('Object', { id:'sphere', js_id:'bubble_outside_'+js_id, col:Vector(1,1,1), pos:Vector(pos.x, pos.y+1.0, pos.z), scale:Vector(comment_bubble_scale,comment_bubble_scale,comment_bubble_scale), locked:true, lighting:false, cull_face:'front', rotate_deg_per_sec:spin_speed });
							var comment_obj = null;
							if (image) // use rendered image
							{
								room.loadNewAsset('Image', {id:image, src:image});
								var comment_obj = room.createObject('Image', { js_id:js_id, collision_trigger:true, id:image, css: css, pos:Vector(pos.x, pos.y+1, pos.z), font_size:32, text_col: Vector(1,1,1), back_alpha: 0, back_col: Vector(0.114, 0.110, 0.122), locked:true, lighting: false, visible:false, cull_face:'none', scale:Vector(comment_scale,comment_scale,comment_scale*0.001) });
							}
							else // fallback paragraph. doesn't work in firefox
							{
								var comment_obj = room.createObject('Paragraph', { js_id:js_id, collision_trigger:true, text:body, css: css, pos:Vector(pos.x, pos.y+1, pos.z), font_size:32, text_col: Vector(1,1,1), back_alpha: 0, back_col: Vector(0.114, 0.110, 0.122), locked:true, lighting: false, visible:false, cull_face:'none', scale:Vector(comment_scale,comment_scale,comment_scale) });
							}
							comments.push(js_id);
							comment_positions.push(Vector(pos.x, pos.y+1.0, pos.z));
							//console.log('Injected comment '+cid);
						}
					}
					else
					{
						//console.log('Skip comment '+cid+', too close to start');
					}
				}
			}
		}
		if (comments.length > 15)
		{
			for (var i = 0; i < comments.length-15; i++)
			{
				var js_id = comments[i];
				var js_id1 = 'bubble_'+comments[i];
				var js_id2 = 'bubble_outside_'+comments[i];
				room.removeObject(js_id);
				room.removeObject(js_id1);
				room.removeObject(js_id2);
				//console.log('Removed extra comment '+js_id);
			}
		}
	}
}
function show_comment(js_id)
{
	var bubble = room.objects['bubble_'+js_id];
	var obj = room.objects[js_id];
	if (bubble && obj && comments_enabled)
	{
		bubble.visible = false;
		if (isJanusWeb)
		{			
			bubble.collision_radius = comment_bubble_scale*2;
		}
		else
		{
			bubble.collision_scale = Vector(2);
		}
		obj.visible = true;
	}
}
function hide_comment(js_id)
{
	var bubble = room.objects['bubble_'+js_id];
	var obj = room.objects[js_id];
	if (bubble && obj && comments_enabled)
	{
		bubble.visible = true;
		obj.visible = false;
		var rescale = true;
		if (isJanusWeb)
		{
			if (bubble.colliders.children.length > 0)
			{
				rescale = false;
			}
		}
		if (rescale)
		{
			if (isJanusWeb)
			{
				bubble.collision_radius = comment_bubble_scale;
			}
			else
			{
				bubble.collision_scale = Vector(1);
			}
		}
		bubble.rotate_deg_per_sec = spin_speed;
	}
}
function gazeProgress(object, ev)
{
	var speed = spin_speed - (spin_speed * ev.data);
	object.rotate_deg_per_sec = speed;
}
room.onload = function()
{
	if (!isJanusWeb)
	{
		room.comments_enabled = true;
	}
}
room.enable_comments = function()
{
	for (i in comments)
	{
		var js_id1 = 'bubble_'+comments[i];
		var bubble_out = room.objects['bubble_outside_'+comments[i]];
		var obj = room.objects[js_id1];
		var obj2 = room.objects[comments[i]];
		if (obj && obj2 && bubble_out)
		{
			obj.visible = true;
			obj2.visible = false;
			bubble_out.visible = true;
		}
	}
}
room.update = function(dt)
{
	if (isJanusWeb)
	{
		if (room.comments_enabled !== 'undefined')
		{
			comments_enabled = room.comments_enabled;
		}
	}
	else
	{
		comments_enabled = true;
	}
	if (api_query_url == null)
	{
		api_query_url = get_server_base()+'/api/get_comments?url='+room.url+'&limit=15';
	}
	if (!isJanusWeb)
	{
		var cursor_obj = player.cursor_object;
		if (last_gaze_js_id == 'bubble_'+cursor_obj)
		{
			cursor_obj = 'bubble_'+cursor_obj
		}
		if (cursor_obj != last_gaze_js_id)
		{
			gaze_time = 0;
		}
		var dist = distance(room.objects[player.cursor_object], player.pos);
		if (dist < 0.3)
		{
			gaze_time = 0;
		}
		if (gaze_time >= 200 && cursor_obj.length > 7)
		{
			if (!gaze_on)
			{
				if (room.objects[cursor_obj.substr(7)])
				{
					show_comment(cursor_obj.substr(7));
					gaze_on = true;
				}
			}
		}
		else
		{
			if (gaze_on)
			{
				hide_comment(last_gaze_js_id.substr(7));
				gaze_on = false;
			}
			else
			{
				gaze_time += dt;
			}
		}
		last_gaze_js_id = cursor_obj;
	}
	if (isJanusWeb || true)
	{
		reload_timer -= dt*0.001;
		move_timer -= dt*0.001;
		resize_timer -= dt*0.001;
		
		if (reload_timer <= 0)
		{
			fetched = false;
			reload_timer += 60;
		}
		
		if (comments_enabled)
		{
			if (fetched == false)
			{
				fetched = true;
				getComments();		
			}
			for (i in comments)
			{
				var js_id1 = 'bubble_'+comments[i];
				var bubble_out = room.objects['bubble_outside_'+comments[i]];
				var obj = room.objects[js_id1];
				var obj2 = room.objects[comments[i]];
				if (obj && obj2)
				{
					//var dist = distance(obj.pos, player.pos);
					if (resize_timer <= 0)
					{
						var dist2 = distance(obj.pos, player.head_pos);
						var scale = comment_bubble_scale+dist2*0.01;
						bubble_out.scale = Vector(scale,scale,scale);
					}
					if (true)
					{
						if (obj2.visible)
						{
							//var angle_from = Math.atan2(player.pos.z - obj.pos.z, player.pos.x - obj.pos.x);
							//var fwd = Vector(Math.cos(angle_from),0,Math.sin(angle_from));
							obj2.ydir = Vector(0,1,0);
							obj2.zdir = scalarMultiply(player.view_dir, -1);
							obj2.xdir = cross(obj2.ydir, obj2.zdir);
							obj2.fwd = scalarMultiply(player.view_dir, -1);
							obj2.pos = Vector(obj.pos); //translate(obj.pos, scalarMultiply(obj2.fwd, -1));
							if (isJanusWeb)
							{
								obj2.updateOrientationFromDirvecs();
							}
						}
						else
						{
							if (move_timer <= 0)
							{
								obj2.pos.y = player.pos.y - 200;
								//obj2.visible = false;
							}
						}
					}
					bubble_out.visible = obj.visible;
				}
			}
		}
		else
		{
			for (i in comments)
			{
				var js_id1 = 'bubble_'+comments[i];
				var bubble_out = room.objects['bubble_outside_'+comments[i]];
				var obj = room.objects[js_id1];
				var obj2 = room.objects[comments[i]];
				if (obj && obj2 && bubble_out)
				{
					obj.visible = false;
					obj2.visible = false;
					bubble_out.visible = false;
				}
			}
		}
		if (resize_timer <= 0)
		{
			resize_timer = 0.1;
		}
		if (move_timer <= 0)
		{
			move_timer = 2;
		}
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions