diff --git a/demos/cube-generated/SolidColorSource.js b/demos/cube-generated/SolidColorSource.js index e46824b48..abbbc0208 100644 --- a/demos/cube-generated/SolidColorSource.js +++ b/demos/cube-generated/SolidColorSource.js @@ -16,18 +16,21 @@ 'use strict'; // Custom tile source for procedurally generated solid color tiles. -function SolidColorSource(width, height) { +function SolidColorSource(width, height, tileSize) { this._width = width; this._height = height; + this._tileSize = tileSize; } -SolidColorSource.prototype._tileText = function(tile) { +SolidColorSource.prototype._tileText = function(tile, width, height) { var components = []; if (tile.face) { components.push("face:" + tile.face); } components.push("x:" + tile.x); components.push("y:" + tile.y); + components.push("width:" + width); + components.push("height:" + height); components.push("zoom:" + tile.z); return components.join(" "); }; @@ -45,11 +48,24 @@ SolidColorSource.prototype._tileColor = function(tile) { }; SolidColorSource.prototype.loadAsset = function(stage, tile, done) { - var width = this._width; - var height = this._height; - var text = this._tileText(tile); + var _width = this._width * (tile.z + 1); + var _height = this._height * (tile.z + 1); + var width; + // Compute tile x remainder + if (this._tileSize * (tile.x + 1) > _width) { + width = (_width / this._tileSize - tile.x) * this._tileSize; + } else { + width = this._tileSize; + } + var height; + // Compute tile y remainder + if (this._tileSize * (tile.y + 1) > _height) { + height = (_height / this._tileSize - tile.y) * this._tileSize; + } else { + height = this._tileSize; + } + var text = this._tileText(tile, width, height); var color = this._tileColor(tile); - // Create the canvas element. var element = document.createElement("canvas"); element.width = width; diff --git a/demos/cube-generated/index.js b/demos/cube-generated/index.js index 59cba30c6..263cc8827 100644 --- a/demos/cube-generated/index.js +++ b/demos/cube-generated/index.js @@ -19,12 +19,12 @@ var viewer = new Marzipano.Viewer(document.getElementById('pano')); // Create procedurally-generated single-color tile source. -var source = new SolidColorSource(512, 512); +var source = new SolidColorSource(1600, 1600, 512); // Create geometry with a very large number of levels. var levels = []; for(var i = 0; i < 32; i++) { - levels.push({ tileSize: 512, size: 512 * Math.pow(2,i) }); + levels.push({ tileSize: 512, size: 800 * Math.pow(2,i) }); } var geometry = new Marzipano.CubeGeometry(levels); diff --git a/src/geometries/Cube.js b/src/geometries/Cube.js index 4308b1131..d1f469b27 100644 --- a/src/geometries/Cube.js +++ b/src/geometries/Cube.js @@ -124,6 +124,8 @@ function CubeTile(face, x, y, z, geometry) { this.z = z; this._geometry = geometry; this._level = geometry.levelList[z]; + // Pre compute last tile size, when all is square, it's 0 + this._tileResidue = this._level.width() % this._level.tileWidth(); } @@ -138,32 +140,44 @@ CubeTile.prototype.rotY = function() { CubeTile.prototype.centerX = function() { - return (this.x + 0.5) / this._level.numHorizontalTiles() - 0.5; + var levelWidth = this._level.width(); + var tileWidth = this._level.tileWidth(); + return (this.x * tileWidth + 0.5 * this.width()) / levelWidth - 0.5; }; CubeTile.prototype.centerY = function() { - return 0.5 - (this.y + 0.5) / this._level.numVerticalTiles(); + var levelHeight = this._level.height(); + var tileHeight = this._level.tileHeight(); + return 0.5 - (this.y * tileHeight + 0.5 * this.height()) / levelHeight; }; CubeTile.prototype.scaleX = function() { - return 1 / this._level.numHorizontalTiles(); + return this.width() / this._level.width(); }; CubeTile.prototype.scaleY = function() { - return 1 / this._level.numVerticalTiles(); + return this.height() / this._level.width(); }; CubeTile.prototype.width = function() { + // Return remainder when it's edge and the tile has residue + if (this.atRightEdge() && this._tileResidue !== 0) { + return this._tileResidue; + } return this._level.tileWidth(); }; CubeTile.prototype.height = function() { - return this._level.tileHeight(); + // Return remainder when it's edge and the tile has residue + if (this.atBottomEdge() && this._tileResidue !== 0) { + return this._tileResidue; + } + return this._level.tileWidth(); }; @@ -458,11 +472,6 @@ function CubeLevel(levelProperties) { this._size = levelProperties.size; this._tileSize = levelProperties.tileSize; - - if (this._size % this._tileSize !== 0) { - throw new Error('Level size is not multiple of tile size: ' + - this._size + ' ' + this._tileSize); - } } inherits(CubeLevel, Level); @@ -538,11 +547,11 @@ CubeLevel.prototype._validateWithParentLevel = function(parentLevel) { * multiple resolution levels. * * The following restrictions apply: - * - All tiles in a level must be square and form a rectangular grid; - * - The size of a level must be a multiple of the tile size; + * - All tiles must be square, except when in the last row or column position, + * and must form a rectangular grid; * - The size of a level must be a multiple of the parent level size; - * - The number of tiles in a level must be a multiple of the number of tiles - * in the parent level. + * - The tile width (respectively, height) for a level must be a submultiple + * of the tile width (respectively, height) for the parent level. * * @param {Object[]} levelPropertiesList Level description * @param {number} levelPropertiesList[].size Cube face size in pixels diff --git a/test/suite/geometries/Cube.js b/test/suite/geometries/Cube.js index 55d28575b..0e7e2056f 100644 --- a/test/suite/geometries/Cube.js +++ b/test/suite/geometries/Cube.js @@ -31,34 +31,6 @@ suite('CubeGeometry', function() { return false; } - suite('malformed levels', function() { - - test('level size must not be smaller than parent level', function() { - assert.throws(function() { - new Cube([{ tileSize: 512, size: 512 }, { tileSize: 512, size: 500 }]); - }); - }); - - test('level size must be multiple of parent level', function() { - assert.throws(function() { - new Cube([{ tileSize: 512, size: 512 }, { tileSize: 512, size: 1000 }]); - }); - }); - - test('number of tiles in level must not be smaller than parent level', function() { - assert.throws(function() { - new Cube([{ tileSize: 128, size: 512 }, { tileSize: 512, size: 1024 }]); - }); - }); - - test('number of tiles in level must be multiple of parent level', function() { - assert.throws(function() { - new Cube([{ tileSize: 256, size: 512 }, { tileSize: 512, size: 512*3 }]); - }); - }); - - }); - suite('levels with constant tile size', function() { var cube = null;