Browse Source

Merge remote-tracking branch 'upstream/master'

pull/675/head
Will Calderbank 6 years ago
parent
commit
1be47d55f4
3 changed files with 184 additions and 109 deletions
  1. +6
    -0
      doc/events.md
  2. +63
    -14
      src/js/libpannellum.js
  3. +115
    -95
      src/js/pannellum.js

+ 6
- 0
doc/events.md View File

@@ -27,6 +27,12 @@ If a scene transition fade interval is specified, this event is fired when the
fading is completed after changing scenes.


## `animatefinished`

Fired when any movements / animations finish, i.e. when the renderer stops
rendering new frames. Passes final pitch, yaw, and HFOV values to handler.


## `error`

Fired when an error occured. The error message string is passed to the


+ 63
- 14
src/js/libpannellum.js View File

@@ -294,18 +294,20 @@ function Renderer(container) {
}
// Make sure image isn't too big
var width = 0, maxWidth = 0;
var maxWidth = 0;
if (imageType == 'equirectangular') {
width = Math.max(image.width, image.height);
maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);
if (Math.max(image.width / 2, image.height) > maxWidth) {
console.log('Error: The image is too big; it\'s ' + image.width + 'px wide, '+
'but this device\'s maximum supported size is ' + (maxWidth * 2) + 'px.');
throw {type: 'webgl size error', width: image.width, maxWidth: maxWidth * 2};
}
} else if (imageType == 'cubemap') {
width = cubeImgWidth;
maxWidth = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
}
if (width > maxWidth) {
console.log('Error: The image is too big; it\'s ' + width + 'px wide, '+
'but this device\'s maximum supported size is ' + maxWidth + 'px.');
throw {type: 'webgl size error', width: width, maxWidth: maxWidth};
if (cubeImgWidth > gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)) {
console.log('Error: The image is too big; it\'s ' + width + 'px wide, '+
'but this device\'s maximum supported size is ' + maxWidth + 'px.');
throw {type: 'webgl size error', width: width, maxWidth: maxWidth};
}
}

// Store horizon pitch and roll if applicable
@@ -414,8 +416,44 @@ function Renderer(container) {
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[0]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[2]);
} else {
// Upload image to the texture
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
if (image.width <= maxWidth) {
gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 0);
// Upload image to the texture
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
} else {
// Image needs to be split into two parts due to texture size limits
gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 1);

// Draw image on canvas
var cropCanvas = document.createElement('canvas');
cropCanvas.width = image.width;
cropCanvas.height = image.height;
var cropContext = cropCanvas.getContext('2d');
cropContext.drawImage(image, 0, 0);

// Upload first half of image to the texture
var cropImage = cropContext.getImageData(0, 0, image.width / 2, image.height);
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage);

// Create and bind texture for second half of image
program.texture2 = gl.createTexture();
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(glBindType, program.texture2);
gl.uniform1i(gl.getUniformLocation(program, 'u_image1'), 1);

// Upload second half of image to the texture
cropImage = cropContext.getImageData(image.width / 2, 0, image.width / 2, image.height);
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage);

// Set parameters for rendering any size
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

// Reactive first texture unit
gl.activeTexture(gl.TEXTURE0);
}
}

// Set parameters for rendering any size
@@ -1320,7 +1358,9 @@ var fragEquiCubeBase = [
'const float PI = 3.14159265358979323846264;',

// Texture
'uniform sampler2D u_image;',
'uniform sampler2D u_image0;',
'uniform sampler2D u_image1;',
'uniform bool u_splitImage;',
'uniform samplerCube u_imageCube;',

// Coordinates passed in from vertex shader
@@ -1365,8 +1405,17 @@ var fragEquirectangular = fragEquiCubeBase + [
// Map from [-1,1] to [0,1] and flip y-axis
'if(coord.x < -u_h || coord.x > u_h || coord.y < -u_v + u_vo || coord.y > u_v + u_vo)',
'gl_FragColor = u_backgroundColor;',
'else',
'gl_FragColor = texture2D(u_image, vec2((coord.x + u_h) / (u_h * 2.0), (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'else {',
'if(u_splitImage) {',
// Image was split into two textures to work around texture size limits
'if(coord.x < 0.0)',
'gl_FragColor = texture2D(u_image0, vec2((coord.x + u_h) / u_h, (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'else',
'gl_FragColor = texture2D(u_image1, vec2((coord.x + u_h) / u_h - 1.0, (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'} else {',
'gl_FragColor = texture2D(u_image0, vec2((coord.x + u_h) / (u_h * 2.0), (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'}',
'}',
'}'
].join('\n');



+ 115
- 95
src/js/pannellum.js View File

@@ -1,17 +1,17 @@
/*
* Pannellum - An HTML5 based Panorama Viewer
* Copyright (c) 2011-2018 Matthew Petroff
*
*
* 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
@@ -67,6 +67,7 @@ var config,
externalEventListeners = {},
specifiedPhotoSphereExcludes = [],
update = false, // Should we update when still to render dynamic content
eps = 1e-6,
hotspotsCreated = false;

var defaultConfig = {
@@ -304,7 +305,7 @@ function init() {
origPitch = config.pitch;

var i, p;
if (config.type == 'cubemap') {
panoImage = [];
for (i = 0; i < 6; i++) {
@@ -342,21 +343,21 @@ function init() {
if (config.type == 'cubemap') {
// Quick loading counter for synchronous loading
var itemsToLoad = 6;
var onLoad = function() {
itemsToLoad--;
if (itemsToLoad === 0) {
onImageLoad();
}
};
var onError = function(e) {
var a = document.createElement('a');
a.href = e.target.src;
a.textContent = a.href;
anError(config.strings.fileAccessError.replace('%s', a.outerHTML));
};
for (i = 0; i < panoImage.length; i++) {
p = config.cubeMap[i];
if (p == "null") { // support partial cubemap image with explicitly empty faces
@@ -378,16 +379,16 @@ function init() {
if (config.basePath) {
p = config.basePath;
}
if (config.dynamic !== true) {
// Still image
p = absoluteURL(config.panorama) ? config.panorama : p + config.panorama;
panoImage.onload = function() {
window.URL.revokeObjectURL(this.src); // Clean up
onImageLoad();
};
var xhr = new XMLHttpRequest();
xhr.onloadend = function() {
if (xhr.status != 200) {
@@ -439,7 +440,7 @@ function init() {
xhr.send();
}
}
if (config.draggable)
uiContainer.classList.add('pnlm-grab');
uiContainer.classList.remove('pnlm-grabbing');
@@ -533,7 +534,7 @@ function parseGPanoXMP(image) {
var start = img.indexOf('<x:xmpmeta');
if (start > -1 && config.ignoreGPanoXMP !== true) {
var xmpData = img.substring(start, img.indexOf('</x:xmpmeta>') + 12);
// Extract the requested tag from the XMP data
var getTag = function(tag) {
var result;
@@ -549,7 +550,7 @@ function parseGPanoXMP(image) {
}
return null;
};
// Relevant XMP data
var xmp = {
fullWidth: getTag('GPano:FullPanoWidthPixels'),
@@ -561,11 +562,11 @@ function parseGPanoXMP(image) {
horizonPitch: getTag('GPano:PosePitchDegrees'),
horizonRoll: getTag('GPano:PoseRollDegrees')
};
if (xmp.fullWidth !== null && xmp.croppedWidth !== null &&
xmp.fullHeight !== null && xmp.croppedHeight !== null &&
xmp.topPixels !== null) {
// Set up viewer using GPano XMP data
if (specifiedPhotoSphereExcludes.indexOf('haov') < 0)
config.haov = xmp.croppedWidth / xmp.fullWidth * 360;
@@ -586,11 +587,11 @@ function parseGPanoXMP(image) {
if (specifiedPhotoSphereExcludes.indexOf('horizonRoll') < 0)
config.horizonRoll = xmp.horizonRoll;
}
// TODO: add support for initial view settings
}
}
// Load panorama
panoImage.src = window.URL.createObjectURL(image);
});
@@ -658,8 +659,9 @@ function aboutMessage(event) {
function mousePosition(event) {
var bounds = container.getBoundingClientRect();
var pos = {};
pos.x = event.clientX - bounds.left;
pos.y = event.clientY - bounds.top;
// pageX / pageY needed for iOS
pos.x = (event.clientX || event.pageX) - bounds.left;
pos.y = (event.clientY || event.pageY) - bounds.top;
return pos;
}

@@ -674,12 +676,12 @@ function onDocumentMouseDown(event) {
event.preventDefault();
// But not all of it
container.focus();
// Only do something if the panorama is loaded
if (!loaded || !config.draggable) {
return;
}
// Calculate mouse position relative to top left of viewer container
var pos = mousePosition(event);

@@ -689,7 +691,7 @@ function onDocumentMouseDown(event) {
console.log('Pitch: ' + coords[0] + ', Yaw: ' + coords[1] + ', Center Pitch: ' +
config.pitch + ', Center Yaw: ' + config.yaw + ', HFOV: ' + config.hfov);
}
// Turn off auto-rotation if enabled
stopAnimation();

@@ -700,16 +702,16 @@ function onDocumentMouseDown(event) {

isUserInteracting = true;
latestInteraction = Date.now();
onPointerDownPointerX = pos.x;
onPointerDownPointerY = pos.y;
onPointerDownYaw = config.yaw;
onPointerDownPitch = config.pitch;
uiContainer.classList.add('pnlm-grabbing');
uiContainer.classList.remove('pnlm-grab');
fireEvent('mousedown', event);
animateInit();
}
@@ -771,9 +773,9 @@ function onDocumentMouseMove(event) {
var yaw = ((Math.atan(onPointerDownPointerX / canvasWidth * 2 - 1) - Math.atan(pos.x / canvasWidth * 2 - 1)) * 180 / Math.PI * config.hfov / 90) + onPointerDownYaw;
speed.yaw = (yaw - config.yaw) % 360 * 0.2;
config.yaw = yaw;
var vfov = 2 * Math.atan(Math.tan(config.hfov/360*Math.PI) * canvasHeight / canvasWidth) * 180 / Math.PI;
var pitch = ((Math.atan(pos.y / canvasHeight * 2 - 1) - Math.atan(onPointerDownPointerY / canvasHeight * 2 - 1)) * 180 / Math.PI * vfov / 90) + onPointerDownPitch;
speed.pitch = (pitch - config.pitch) * 0.2;
config.pitch = pitch;
@@ -826,7 +828,7 @@ function onDocumentTouchStart(event) {

onPointerDownPointerX = pos0.x;
onPointerDownPointerY = pos0.y;
if (event.targetTouches.length == 2) {
// Down pointer is the center of the two fingers
var pos1 = mousePosition(event.targetTouches[1]);
@@ -837,7 +839,7 @@ function onDocumentTouchStart(event) {
}
isUserInteracting = true;
latestInteraction = Date.now();
onPointerDownYaw = config.yaw;
onPointerDownPitch = config.pitch;

@@ -865,7 +867,7 @@ function onDocumentTouchMove(event) {
var pos0 = mousePosition(event.targetTouches[0]);
var clientX = pos0.x;
var clientY = pos0.y;
if (event.targetTouches.length == 2 && onPointerDownPointerDist != -1) {
var pos1 = mousePosition(event.targetTouches[1]);
clientX += (pos1.x - pos0.x) * 0.5;
@@ -1023,7 +1025,7 @@ function onDocumentKeyPress(event) {
if (config.capturedKeyNumbers.indexOf(keynumber) < 0)
return;
event.preventDefault();
// If escape key is pressed
if (keynumber == 27) {
// If in fullscreen mode
@@ -1054,12 +1056,12 @@ function clearKeys() {
function onDocumentKeyUp(event) {
// Record key pressed
var keynumber = event.which || event.keycode;
// Override default action for keys that are used
if (config.capturedKeyNumbers.indexOf(keynumber) < 0)
return;
event.preventDefault();
// Change key
changeKey(keynumber, false);
}
@@ -1077,53 +1079,53 @@ function changeKey(keynumber, value) {
case 109: case 189: case 17: case 173:
if (keysDown[0] != value) { keyChanged = true; }
keysDown[0] = value; break;
// If plus key is released
case 107: case 187: case 16: case 61:
if (keysDown[1] != value) { keyChanged = true; }
keysDown[1] = value; break;
// If up arrow is released
case 38:
if (keysDown[2] != value) { keyChanged = true; }
keysDown[2] = value; break;
// If "w" is released
case 87:
if (keysDown[6] != value) { keyChanged = true; }
keysDown[6] = value; break;
// If down arrow is released
case 40:
if (keysDown[3] != value) { keyChanged = true; }
keysDown[3] = value; break;
// If "s" is released
case 83:
if (keysDown[7] != value) { keyChanged = true; }
keysDown[7] = value; break;
// If left arrow is released
case 37:
if (keysDown[4] != value) { keyChanged = true; }
keysDown[4] = value; break;
// If "a" is released
case 65:
if (keysDown[8] != value) { keyChanged = true; }
keysDown[8] = value; break;
// If right arrow is released
case 39:
if (keysDown[5] != value) { keyChanged = true; }
keysDown[5] = value; break;
// If "d" is released
case 68:
if (keysDown[9] != value) { keyChanged = true; }
keysDown[9] = value;
}
if (keyChanged && value) {
if (typeof performance !== 'undefined' && performance.now()) {
prevTime = performance.now();
@@ -1150,7 +1152,7 @@ function keyRepeat() {
var prevPitch = config.pitch;
var prevYaw = config.yaw;
var prevZoom = config.hfov;
var newTime;
if (typeof performance !== 'undefined' && performance.now()) {
newTime = performance.now();
@@ -1162,40 +1164,40 @@ function keyRepeat() {
}
var diff = (newTime - prevTime) * config.hfov / 1700;
diff = Math.min(diff, 1.0);
// If minus key is down
if (keysDown[0] && config.keyboardZoom === true) {
setHfov(config.hfov + (speed.hfov * 0.8 + 0.5) * diff);
isKeyDown = true;
}
// If plus key is down
if (keysDown[1] && config.keyboardZoom === true) {
setHfov(config.hfov + (speed.hfov * 0.8 - 0.2) * diff);
isKeyDown = true;
}
// If up arrow or "w" is down
if (keysDown[2] || keysDown[6]) {
// Pan up
config.pitch += (speed.pitch * 0.8 + 0.2) * diff;
isKeyDown = true;
}
// If down arrow or "s" is down
if (keysDown[3] || keysDown[7]) {
// Pan down
config.pitch += (speed.pitch * 0.8 - 0.2) * diff;
isKeyDown = true;
}
// If left arrow or "a" is down
if (keysDown[4] || keysDown[8]) {
// Pan left
config.yaw += (speed.yaw * 0.8 - 0.2) * diff;
isKeyDown = true;
}
// If right arrow or "d" is down
if (keysDown[5] || keysDown[9]) {
// Pan right
@@ -1216,7 +1218,7 @@ function keyRepeat() {
yawDiff = (-config.autoRotate > 0 ? 1 : -1) * Math.min(Math.abs(config.autoRotate * timeDiff), Math.abs(yawDiff));
config.yaw += yawDiff;
}
// Deal with stopping auto rotation after a set delay
if (config.autoRotateStopDelay) {
config.autoRotateStopDelay -= newTime - prevTime;
@@ -1246,7 +1248,7 @@ function keyRepeat() {
if (diff > 0 && !config.autoRotate) {
// "Friction"
var friction = 0.85;
// Yaw
if (!keysDown[4] && !keysDown[5] && !keysDown[8] && !keysDown[9] && !animatedMove.yaw) {
config.yaw += speed.yaw * diff * friction;
@@ -1266,14 +1268,14 @@ function keyRepeat() {
speed.yaw = speed.yaw * 0.8 + (config.yaw - prevYaw) / diff * 0.2;
speed.pitch = speed.pitch * 0.8 + (config.pitch - prevPitch) / diff * 0.2;
speed.hfov = speed.hfov * 0.8 + (config.hfov - prevZoom) / diff * 0.2;
// Limit speed
var maxSpeed = config.autoRotate ? Math.abs(config.autoRotate) : 5;
speed.yaw = Math.min(maxSpeed, Math.max(speed.yaw, -maxSpeed));
speed.pitch = Math.min(maxSpeed, Math.max(speed.pitch, -maxSpeed));
speed.hfov = Math.min(maxSpeed, Math.max(speed.hfov, -maxSpeed));
}
// Stop movement if opposite controls are pressed
if (keysDown[0] && keysDown[1]) {
speed.hfov = 0;
@@ -1300,11 +1302,7 @@ function animateMove(axis) {
t.endPosition === t.startPosition) {
result = t.endPosition;
speed[axis] = 0;
var callback = animatedMove[axis].callback,
callbackArgs = animatedMove[axis].callbackArgs;
delete animatedMove[axis];
if (typeof callback == 'function')
callback(callbackArgs);
}
config[axis] = result;
}
@@ -1372,7 +1370,7 @@ function animate() {
} else if (renderer && (renderer.isLoading() || (config.dynamic === true && update))) {
requestAnimationFrame(animate);
} else {
fireEvent('animateFinished', {pitch: _this.getPitch(), yaw: _this.getYaw(), hfov: _this.getHfov()});
fireEvent('animatefinished', {pitch: _this.getPitch(), yaw: _this.getYaw(), hfov: _this.getHfov()});
animating = false;
prevTime = undefined;
var autoRotateStartTime = config.autoRotateInactivityDelay -
@@ -1438,7 +1436,7 @@ function render() {
}
config.yaw = Math.max(minYaw, Math.min(maxYaw, config.yaw));
}
// Check if we autoRotate in a limited by min and max yaw
// If so reverse direction
if (config.autoRotate !== false && tmpyaw != config.yaw &&
@@ -1462,11 +1460,11 @@ function render() {
if (isNaN(maxPitch))
maxPitch = 90;
config.pitch = Math.max(minPitch, Math.min(maxPitch, config.pitch));
renderer.render(config.pitch * Math.PI / 180, config.yaw * Math.PI / 180, config.hfov * Math.PI / 180, {roll: config.roll * Math.PI / 180});
renderHotSpots();
// Update compass
if (config.compass) {
compass.style.transform = 'rotate(' + (-config.yaw - config.northOffset) + 'deg)';
@@ -1603,7 +1601,7 @@ function renderInit() {
}
} catch(event) {
// Panorama not loaded
// Display error if there is a bad texture
if (event.type == 'webgl error' || event.type == 'no webgl') {
anError();
@@ -1634,17 +1632,17 @@ function renderInitCallback() {
fireEvent('scenechangefadedone');
}, config.sceneFadeDuration);
}
// Show compass if applicable
if (config.compass) {
compass.style.display = 'inline';
} else {
compass.style.display = 'none';
}
// Show hotspots
createHotSpots();
// Hide loading display
infoDisplay.load.box.style.display = 'none';
if (preview !== undefined) {
@@ -1654,7 +1652,7 @@ function renderInitCallback() {
loaded = true;

fireEvent('load');
animateInit();
}

@@ -1853,14 +1851,14 @@ function mergeConfig(sceneId) {
var k, s;
var photoSphereExcludes = ['haov', 'vaov', 'vOffset', 'northOffset', 'horizonPitch', 'horizonRoll'];
specifiedPhotoSphereExcludes = [];
// Merge default config
for (k in defaultConfig) {
if (defaultConfig.hasOwnProperty(k)) {
config[k] = defaultConfig[k];
}
}
// Merge default scene config
for (k in initialConfig.default) {
if (initialConfig.default.hasOwnProperty(k)) {
@@ -1878,7 +1876,7 @@ function mergeConfig(sceneId) {
}
}
}
// Merge current scene config
if ((sceneId !== null) && (sceneId !== '') && (initialConfig.scenes) && (initialConfig.scenes[sceneId])) {
var scene = initialConfig.scenes[sceneId];
@@ -1900,7 +1898,7 @@ function mergeConfig(sceneId) {
}
config.scene = sceneId;
}
// Merge initial config
for (k in initialConfig) {
if (initialConfig.hasOwnProperty(k)) {
@@ -1971,12 +1969,12 @@ function processOptions(isPreview) {
infoDisplay.title.innerHTML = escapeHTML(config[key]);
infoDisplay.container.style.display = 'inline';
break;
case 'author':
infoDisplay.author.innerHTML = config.strings.bylineLabel.replace('%s', escapeHTML(config[key]));
infoDisplay.container.style.display = 'inline';
break;
case 'fallback':
var link = document.createElement('a');
link.href = sanitizeURL(config[key]);
@@ -1989,11 +1987,11 @@ function processOptions(isPreview) {
infoDisplay.errorMsg.innerHTML = ''; // Removes all children nodes
infoDisplay.errorMsg.appendChild(message);
break;
case 'hfov':
setHfov(Number(config[key]));
break;
case 'autoLoad':
if (config[key] === true && renderer === undefined) {
// Show loading box
@@ -2004,7 +2002,7 @@ function processOptions(isPreview) {
init();
}
break;
case 'showZoomCtrl':
if (config[key] && config.showControls != false) {
// Show zoom controls
@@ -2018,7 +2016,7 @@ function processOptions(isPreview) {
case 'showFullscreenCtrl':
if (config[key] && config.showControls != false && ('fullscreen' in document || 'mozFullScreen' in document ||
'webkitIsFullScreen' in document || 'msFullscreenElement' in document)) {
// Show fullscreen control
controls.fullscreen.style.display = 'block';
} else {
@@ -2226,7 +2224,7 @@ function load() {
function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) {
loaded = false;
animatedMove = {};
// Set up fade if specified
var fadeImg, workingPitch, workingYaw, workingHfov;
if (config.sceneFadeDuration && !fadeDone) {
@@ -2246,7 +2244,7 @@ function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) {
return;
}
}
// Set new pointing
if (targetPitch === 'same') {
workingPitch = config.pitch;
@@ -2265,10 +2263,10 @@ function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) {
} else {
workingHfov = targetHfov;
}
// Destroy hot spots from previous scene
destroyHotSpots();
// Create the new config for the scene
mergeConfig(sceneId);

@@ -2387,16 +2385,22 @@ this.getPitch = function() {
* @returns {Viewer} `this`
*/
this.setPitch = function(pitch, animated, callback, callbackArgs) {
latestInteraction = Date.now();
if (Math.abs(pitch - config.pitch) <= eps) {
if (typeof callback == 'function')
callback(callbackArgs);
return this;
}
animated = animated == undefined ? 1000: Number(animated);
if (animated) {
animatedMove.pitch = {
'startTime': Date.now(),
'startPosition': config.pitch,
'endPosition': pitch,
'duration': animated,
'callback': callback,
'callbackArgs': callbackArgs
'duration': animated
}
if (typeof callback == 'function')
setTimeout(function(){callback(callbackArgs)}, animated);
} else {
config.pitch = pitch;
}
@@ -2448,6 +2452,12 @@ this.getYaw = function() {
* @returns {Viewer} `this`
*/
this.setYaw = function(yaw, animated, callback, callbackArgs) {
latestInteraction = Date.now();
if (Math.abs(yaw - config.yaw) <= eps) {
if (typeof callback == 'function')
callback(callbackArgs);
return this;
}
animated = animated == undefined ? 1000: Number(animated);
yaw = ((yaw + 180) % 360) - 180 // Keep in bounds
if (animated) {
@@ -2461,10 +2471,10 @@ this.setYaw = function(yaw, animated, callback, callbackArgs) {
'startTime': Date.now(),
'startPosition': config.yaw,
'endPosition': yaw,
'duration': animated,
'callback': callback,
'callbackArgs': callbackArgs
'duration': animated
}
if (typeof callback == 'function')
setTimeout(function(){callback(callbackArgs)}, animated);
} else {
config.yaw = yaw;
}
@@ -2516,16 +2526,22 @@ this.getHfov = function() {
* @returns {Viewer} `this`
*/
this.setHfov = function(hfov, animated, callback, callbackArgs) {
latestInteraction = Date.now();
if (Math.abs(hfov - config.hfov) <= eps) {
if (typeof callback == 'function')
callback(callbackArgs);
return this;
}
animated = animated == undefined ? 1000: Number(animated);
if (animated) {
animatedMove.hfov = {
'startTime': Date.now(),
'startPosition': config.hfov,
'endPosition': constrainHfov(hfov),
'duration': animated,
'callback': callback,
'callbackArgs': callbackArgs
'duration': animated
}
if (typeof callback == 'function')
setTimeout(function(){callback(callbackArgs)}, animated);
} else {
setHfov(hfov);
}
@@ -2571,16 +2587,20 @@ this.setHfovBounds = function(bounds) {
*/
this.lookAt = function(pitch, yaw, hfov, animated, callback, callbackArgs) {
animated = animated == undefined ? 1000: Number(animated);
if (pitch !== undefined) {
if (pitch !== undefined && Math.abs(pitch - config.pitch) > eps) {
this.setPitch(pitch, animated, callback, callbackArgs);
callback = undefined;
}
if (yaw !== undefined) {
if (yaw !== undefined && Math.abs(yaw - config.yaw) > eps) {
this.setYaw(yaw, animated, callback, callbackArgs);
callback = undefined;
}
if (hfov !== undefined)
if (hfov !== undefined && Math.abs(hfov - config.hfov) > eps) {
this.setHfov(hfov, animated, callback, callbackArgs);
callback = undefined;
}
if (typeof callback == 'function')
callback(callbackArgs);
return this;
}



Loading…
Cancel
Save