@@ -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, | |||
@@ -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); | |||
} |
@@ -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; | |||
@@ -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"; | |||
@@ -9,7 +9,17 @@ | |||
<body> | |||
<div id="page"> | |||
<div id="container"><canvas id="canvas"></div> | |||
<div id="container"> | |||
<canvas id="canvas"></canvas> | |||
<div class="world"> | |||
<div class="face fface"></div> | |||
<div class="face bface"></div> | |||
<div class="face uface"></div> | |||
<div class="face dface"></div> | |||
<div class="face lface"></div> | |||
<div class="face rface"></div> | |||
</div> | |||
</div> | |||
<div id="panorama_info"> | |||
<div id="title_box"></div> | |||