diff --git a/examples/example-multires.json b/examples/example-multires.json index 40fb386..acb0d24 100644 --- a/examples/example-multires.json +++ b/examples/example-multires.json @@ -4,7 +4,8 @@ "type": "multires", "multiRes": { - "path": "./multires/%l/%s%x%y", + "basePath": "./multires", + "path": "/%l/%s%x%y", "extension": "png", "tileResolution": 256, "maxLevel": 4, diff --git a/examples/multires/fallback/b.png b/examples/multires/fallback/b.png new file mode 100644 index 0000000..8044186 Binary files /dev/null and b/examples/multires/fallback/b.png differ diff --git a/examples/multires/fallback/d.png b/examples/multires/fallback/d.png new file mode 100644 index 0000000..0967efd Binary files /dev/null and b/examples/multires/fallback/d.png differ diff --git a/examples/multires/fallback/f.png b/examples/multires/fallback/f.png new file mode 100644 index 0000000..3733b20 Binary files /dev/null and b/examples/multires/fallback/f.png differ diff --git a/examples/multires/fallback/l.png b/examples/multires/fallback/l.png new file mode 100644 index 0000000..01c90d5 Binary files /dev/null and b/examples/multires/fallback/l.png differ diff --git a/examples/multires/fallback/r.png b/examples/multires/fallback/r.png new file mode 100644 index 0000000..36cfb3d Binary files /dev/null and b/examples/multires/fallback/r.png differ diff --git a/examples/multires/fallback/u.png b/examples/multires/fallback/u.png new file mode 100644 index 0000000..33771e3 Binary files /dev/null and b/examples/multires/fallback/u.png differ diff --git a/src/css/pannellum.css b/src/css/pannellum.css index c7ac4b3..865f98f 100644 --- a/src/css/pannellum.css +++ b/src/css/pannellum.css @@ -313,3 +313,57 @@ div.tooltip:hover:after { cursor:default; display:none; } + +.viewport { + position: relative; + float: left; + overflow: hidden; + width: 100%; + height: 100%; + -webkit-perspective: 700px; + perspective: 700px; +} +.world { + display: none; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + -webkit-transform: translate3d(0px, 0px, 700px) rotateX(0deg) rotateY(0deg) rotateZ(0deg); + transform: translate3d(0px, 0px, 700px) rotateX(0deg) rotateY(0deg) rotateZ(0deg); +} +.face { + position: absolute; + -webkit-transform-origin: 0 0 0; + -webkit-backface-visibility: hidden; + -moz-transform-origin: 0 0 0; + -moz-backface-visibility: hidden; + height: 1000px; + width: 1000px; + background-size: 100% 100%; +} +.fface { + -webkit-transform: translate3d(-500px, -500px, -500px) rotateX(0deg) rotateY(0deg) rotateZ(0deg); + transform: translate3d(-500px, -500px, -500px) rotateX(0deg) rotateY(0deg) rotateZ(0deg); +} +.bface { + -webkit-transform: translate3d(500px, -500px, 500px) rotateX(180deg) rotateY(0deg) rotateZ(180deg); + transform: translate3d(500px, -500px, 500px) rotateX(180deg) rotateY(0deg) rotateZ(180deg); +} +.uface { + -webkit-transform: translate3d(-500px, -500px, 500px) rotateX(270deg) rotateY(0deg) rotateZ(0deg); + transform: translate3d(-500px, -500px, 500px) rotateX(270deg) rotateY(0deg) rotateZ(0deg); +} +.dface { + -webkit-transform: translate3d(-500px, 500px, -500px) rotateX(90deg) rotateY(0deg) rotateZ(0deg); + transform: translate3d(-500px, 500px, -500px) rotateX(90deg) rotateY(0deg) rotateZ(0deg); +} +.lface { + -webkit-transform: translate3d(-500px, -500px, 500px) rotateX(180deg) rotateY(90deg) rotateZ(180deg); + transform: translate3d(-500px, -500px, 500px) rotateX(180deg) rotateY(90deg) rotateZ(180deg); +} +.rface { + -webkit-transform: translate3d(500px, -500px, -500px) rotateX(0deg) rotateY(270deg) rotateZ(0deg); + transform: translate3d(500px, -500px, -500px) rotateX(0deg) rotateY(270deg) rotateZ(0deg); +} diff --git a/src/js/libpannellum.js b/src/js/libpannellum.js index 4899671..ef7ea93 100644 --- a/src/js/libpannellum.js +++ b/src/js/libpannellum.js @@ -1,5 +1,5 @@ /* - * libpannellum - An WebGL based Panorama Renderer + * libpannellum - A WebGL and CSS 3D transform based Panorama Renderer * Copyright (c) 2012-2014 Matthew Petroff * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,8 +27,8 @@ window.libpannellum = (function(window, document, undefined) { * instead of a single image. They should be the order of: * +z, +x, -z, -x, +y, -y. */ -function Renderer(canvas, image, imageType) { - this.canvas = canvas; +function Renderer(container, image, imageType) { + this.canvas = container.querySelector('#canvas'); this.image = image; // Default argument for image type @@ -42,6 +42,28 @@ function Renderer(canvas, image, imageType) { this.init = function(haov, vaov, voffset) { // Enable WebGL on canvas gl = this.canvas.getContext('experimental-webgl', {alpha: false, depth: false}); + + // If there is no WebGL, fall back to CSS 3D transform renderer. + if (!gl && this.imageType == 'multires') { + // Initialize renderer + container.className = 'viewport'; + this.world = container.querySelector('.world'); + this.world.style.display = 'block'; + + // Add images + var path = this.image.basePath + '/fallback/'; + this.world.querySelector('.fface').style.backgroundImage = 'url("' + path + 'f.' + this.image.extension + '")'; + this.world.querySelector('.bface').style.backgroundImage = 'url("' + path + 'b.' + this.image.extension + '")'; + this.world.querySelector('.uface').style.backgroundImage = 'url("' + path + 'u.' + this.image.extension + '")'; + this.world.querySelector('.dface').style.backgroundImage = 'url("' + path + 'd.' + this.image.extension + '")'; + this.world.querySelector('.lface').style.backgroundImage = 'url("' + path + 'l.' + this.image.extension + '")'; + this.world.querySelector('.rface').style.backgroundImage = 'url("' + path + 'r.' + this.image.extension + '")'; + + return; + } + this.image.path = this.image.basePath + this.image.path; + + // Set 2d texture binding var glBindType = gl.TEXTURE_2D; // Create viewport for entire canvas @@ -169,6 +191,14 @@ function Renderer(canvas, image, imageType) { } this.render = function(pitch, yaw, hfov) { + // If no WebGL + if (!gl && this.imageType == 'multires') { + var transform = 'translate3d(0px, 0px, 700px) rotateX(' + pitch + 'rad) rotateY(' + yaw + 'rad) rotateZ(0rad)'; + this.world.style.webkitTransform = transform; + this.world.style.transform = transform; + return; + } + if(this.imageType != 'multires') { // Calculate focal length from horizontal angle of view var focal = 1 / Math.tan(hfov / 2); @@ -231,7 +261,7 @@ function Renderer(canvas, image, imageType) { } this.isLoading = function() { - if (this.imageType == 'multires') { + if (gl && this.imageType == 'multires') { for ( var i = 0; i < program.currentNodes.length; i++ ) { if (!program.currentNodes[i].textureLoaded) { return true; diff --git a/src/js/pannellum.js b/src/js/pannellum.js index c4496d3..77ddc94 100644 --- a/src/js/pannellum.js +++ b/src/js/pannellum.js @@ -52,10 +52,10 @@ function init() { } } else if(config.type == 'multires') { var c = config.multiRes; - if (config.path) { - c.path = config.path + config.multiRes.path; - } else if (tourConfig.path) { - c.path = tourConfig.path + config.multiRes.path; + if (config.basePath) { + c.basePath = config.basePath + config.multiRes.basePath; + } else if (tourConfig.basePath) { + c.basePath = tourConfig.basePath + config.multiRes.basePath; } panoImage = config.multiRes; } else { @@ -65,7 +65,7 @@ function init() { function onImageLoad() { try { - renderer = new libpannellum.renderer(canvas, panoImage, config.type); + renderer = new libpannellum.renderer(document.getElementById('container'), panoImage, config.type); } catch (event) { // Show error message if WebGL is not supported anError(); @@ -116,10 +116,10 @@ function init() { for(var i = 0; i < panoImage.length; i++) { panoImage[i].onload = loadCounter; var p = config.cubeMap[i]; - if (config.path) { - p = config.path + p; - } else if (tourConfig.path) { - p = tourConfig.path + p; + if (config.basePath) { + p = config.basePath + p; + } else if (tourConfig.basePath) { + p = tourConfig.basePath + p; } panoImage[i].src = p; } @@ -128,10 +128,10 @@ function init() { } else { panoImage.onload = onImageLoad; var p = config.panorama; - if (config.path) { - p = config.path + p; - } else if (tourConfig.path) { - p = tourConfig.path + p; + if (config.basePath) { + p = config.basePath + p; + } else if (tourConfig.basePath) { + p = tourConfig.basePath + p; } panoImage.src = p; } @@ -572,7 +572,7 @@ function parseURLParameters() { var c = JSON.parse(request.responseText); // Set JSON file location - c.path = configFromURL.config.substring(0,configFromURL.config.lastIndexOf('/')+1); + c.basePath = configFromURL.config.substring(0,configFromURL.config.lastIndexOf('/')+1); // Merge options for(var k in c) { @@ -592,7 +592,7 @@ function parseURLParameters() { tourConfig = JSON.parse(request.responseText); // Set JSON file location - tourConfig.path = configFromURL.tour.substring(0,configFromURL.tour.lastIndexOf('/')+1); + tourConfig.basePath = configFromURL.tour.substring(0,configFromURL.tour.lastIndexOf('/')+1); // Activate first scene if specified if(tourConfig.default.firstScene) { @@ -660,10 +660,10 @@ function processOptions() { case 'preview': var p = config[key]; - if (config.path) { - p = config.path + p; - } else if (tourConfig.path) { - p = tourConfig.path + p; + if (config.basePath) { + p = config.basePath + p; + } else if (tourConfig.basePath) { + p = tourConfig.basePath + p; } document.body.style.backgroundImage = "url('" + p + "')"; document.body.style.backgroundSize = "auto"; diff --git a/src/pannellum.htm b/src/pannellum.htm index 2d72225..87350b2 100644 --- a/src/pannellum.htm +++ b/src/pannellum.htm @@ -9,7 +9,17 @@