Browse Source

Merge branch 'master' into tour-adoptions

pull/880/head
NiHoel 6 years ago
parent
commit
a4453de809
4 changed files with 121 additions and 37 deletions
  1. +6
    -0
      doc/events.md
  2. +7
    -0
      doc/json-config-parameters.md
  3. +63
    -14
      src/js/libpannellum.js
  4. +45
    -23
      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


+ 7
- 0
doc/json-config-parameters.md View File

@@ -98,6 +98,13 @@ viewer is fullscreen.
If set to `false`, mouse and touch dragging is disabled. Defaults to `true`.


### `friction` (number)

Controls the "friction" that slows down the viewer motion after it is dragged
and released. Higher values mean the motion stops faster. Should be set
(0.0, 1.0]; defaults to 0.15.


### `disableKeyboardCtrl` (boolean)

If set to `true`, keyboard controls are disabled. Defaults to `false`.


+ 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');



+ 45
- 23
src/js/pannellum.js View File

@@ -68,6 +68,7 @@ var config,
externalEventListeners = {},
specifiedPhotoSphereExcludes = [],
update = false, // Should we update when still to render dynamic content
eps = 1e-6,
hotspotsCreated = false;

var defaultConfig = {
@@ -110,6 +111,7 @@ var defaultConfig = {
crossOrigin: 'anonymous',
touchPanSpeedCoeffFactor: 1,
capturedKeyNumbers: [16, 17, 27, 37, 38, 39, 40, 61, 65, 68, 83, 87, 107, 109, 173, 187, 189],
friction: 0.15
};

// Translatable / configurable strings
@@ -676,8 +678,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;
}

@@ -1283,19 +1286,19 @@ function keyRepeat() {
// "Inertia"
if (diff > 0 && !config.autoRotate) {
// "Friction"
var friction = 0.85;
var slowDownFactor = 1 - config.friction;
// Yaw
if (!keysDown[4] && !keysDown[5] && !keysDown[8] && !keysDown[9] && !animatedMove.yaw) {
config.yaw += speed.yaw * diff * friction;
config.yaw += speed.yaw * diff * slowDownFactor;
}
// Pitch
if (!keysDown[2] && !keysDown[3] && !keysDown[6] && !keysDown[7] && !animatedMove.pitch) {
config.pitch += speed.pitch * diff * friction;
config.pitch += speed.pitch * diff * slowDownFactor;
}
// Zoom
if (!keysDown[0] && !keysDown[1] && !animatedMove.hfov) {
setHfov(config.hfov + speed.hfov * diff * friction);
setHfov(config.hfov + speed.hfov * diff * slowDownFactor);
}
}

@@ -1338,11 +1341,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;
}
@@ -1410,6 +1409,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()});
animating = false;
prevTime = undefined;
var autoRotateStartTime = config.autoRotateInactivityDelay -
@@ -2510,16 +2510,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;
}
@@ -2571,6 +2577,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) {
@@ -2584,10 +2596,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;
}
@@ -2639,16 +2651,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);
}
@@ -2748,16 +2766,20 @@ this.setVfovBounds = 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