Change comments TO DO -> TODO. Add automatic recognition of drawers. Matrix as an exposed class.

This commit is contained in:
Aiosa 2023-07-26 20:01:26 +02:00
parent f510301922
commit 3c3842bdce
9 changed files with 208 additions and 146 deletions

View File

@ -28,6 +28,7 @@ module.exports = function(grunt) {
coverageDir = 'coverage/' + dateFormat(new Date(), 'yyyymmdd-HHMMss'), coverageDir = 'coverage/' + dateFormat(new Date(), 'yyyymmdd-HHMMss'),
sources = [ sources = [
"src/openseadragon.js", "src/openseadragon.js",
"src/matrix.js",
"src/fullscreen.js", "src/fullscreen.js",
"src/eventsource.js", "src/eventsource.js",
"src/mousetracker.js", "src/mousetracker.js",
@ -64,7 +65,15 @@ module.exports = function(grunt) {
"src/viewport.js", "src/viewport.js",
"src/tiledimage.js", "src/tiledimage.js",
"src/tilecache.js", "src/tilecache.js",
"src/world.js" "src/world.js",
// Aoisa's webgl drawer - needs optimization, polishing, trimming
// "src/webgl/webGLWrapper.js",
// "src/webgl/visualisationLayer.js",
// "src/webgl/dataLoader.js",
// "src/webgl/webGLContext.js",
// "src/webgl/drawer.js",
// "src/webgl/plainShader.js",
]; ];
var banner = "//! <%= pkg.name %> <%= pkg.version %>\n" + var banner = "//! <%= pkg.name %> <%= pkg.version %>\n" +
@ -195,7 +204,7 @@ module.exports = function(grunt) {
} }
}, },
watch: { watch: {
files: [ "Gruntfile.js", "src/*.js", "images/*" ], files: [ "Gruntfile.js", "src/*.js", "images/*" /*, "src/webgl/*.js" */ ],
tasks: "watchTask" tasks: "watchTask"
}, },
eslint: { eslint: {

124
src/matrix.js Normal file
View File

@ -0,0 +1,124 @@
/*
* OpenSeadragon - Mat3
*
* Copyright (C) 2010-2023 OpenSeadragon contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of CodePlex Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function( $ ){
/**
* Matrix left-to-right system representation
* Modified from https://webglfundamentals.org/webgl/lessons/webgl-2d-matrices.html
*/
$.Mat3 = class Mat3 {
constructor(values){
if(!values) {
values = [
0, 0, 0,
0, 0, 0,
0, 0, 0
];
}
this.values = values;
}
static makeIdentity(){
return new Mat3([
1, 0, 0,
0, 1, 0,
0, 0, 1
]);
}
static makeTranslation(tx, ty) {
return new Mat3([
1, 0, 0,
0, 1, 0,
tx, ty, 1,
]);
}
static makeRotation(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return new Mat3([
c, -s, 0,
s, c, 0,
0, 0, 1,
]);
}
static makeScaling(sx, sy) {
return new Mat3([
sx, 0, 0,
0, sy, 0,
0, 0, 1,
]);
}
multiply(other) {
let a = this.values;
let b = other.values;
var a00 = a[0 * 3 + 0];
var a01 = a[0 * 3 + 1];
var a02 = a[0 * 3 + 2];
var a10 = a[1 * 3 + 0];
var a11 = a[1 * 3 + 1];
var a12 = a[1 * 3 + 2];
var a20 = a[2 * 3 + 0];
var a21 = a[2 * 3 + 1];
var a22 = a[2 * 3 + 2];
var b00 = b[0 * 3 + 0];
var b01 = b[0 * 3 + 1];
var b02 = b[0 * 3 + 2];
var b10 = b[1 * 3 + 0];
var b11 = b[1 * 3 + 1];
var b12 = b[1 * 3 + 2];
var b20 = b[2 * 3 + 0];
var b21 = b[2 * 3 + 1];
var b22 = b[2 * 3 + 2];
return new Mat3([
b00 * a00 + b01 * a10 + b02 * a20,
b00 * a01 + b01 * a11 + b02 * a21,
b00 * a02 + b01 * a12 + b02 * a22,
b10 * a00 + b11 * a10 + b12 * a20,
b10 * a01 + b11 * a11 + b12 * a21,
b10 * a02 + b11 * a12 + b12 * a22,
b20 * a00 + b21 * a10 + b22 * a20,
b20 * a01 + b21 * a11 + b22 * a21,
b20 * a02 + b21 * a12 + b22 * a22,
]);
}
};
}( OpenSeadragon ));

View File

@ -1473,7 +1473,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @param {Number} levelOpacity * @param {Number} levelOpacity
* @param {Number} currentTime * @param {Number} currentTime
* @param {Boolean} lowestLevel * @param {Boolean} lowestLevel
* @returns {Boolean} whether the opacity of this tile has changed * @returns {Boolean} true if blending did not yet finish
*/ */
_blendTile: function(tile, x, y, level, levelOpacity, currentTime, lowestLevel ){ _blendTile: function(tile, x, y, level, levelOpacity, currentTime, lowestLevel ){
let blendTimeMillis = 1000 * this.blendTime, let blendTimeMillis = 1000 * this.blendTime,

View File

@ -455,23 +455,17 @@ $.Viewer = function( options ) {
$.console.warn('No valid drawers were selected. Using the default value.'); $.console.warn('No valid drawers were selected. Using the default value.');
} }
// extend the drawerOptions object with additional properties to pass to the Drawer implementation // extend the drawerOptions object with additional properties to pass to the Drawer implementation
this.drawer = null; // TO DO: how to deal with the possibility that none of the requested drawers are supported? // TODO: how to deal with the possibility that none of the requested drawers are supported?
this.drawer = null;
for(let i = 0; i < drawersToTry.length; i++){ for(let i = 0; i < drawersToTry.length; i++){
let Drawer = drawersToTry[i];
let optsKey = null; //todo necessary? why not to use class names as drawer IDs
// replace text-based option with appropriate constructor let optsKey = drawersToTry[i];
if (Drawer === 'canvas'){ let Drawer = $.determineDrawer(optsKey);
Drawer = $.CanvasDrawer; if (!Drawer) {
optsKey = 'canvas';
} else if (Drawer === 'html'){
Drawer = $.HTMLDrawer;
optsKey = 'html';
} else if (Drawer === 'webgl'){
Drawer = $.WebGLDrawer;
optsKey = 'webgl';
} else {
optsKey = 'custom'; optsKey = 'custom';
} //todo will raise error anyway...
} else {
// if the drawer is supported, create it and break the loop // if the drawer is supported, create it and break the loop
if (Drawer.isSupported()){ if (Drawer.isSupported()){
this.drawer = new Drawer({ this.drawer = new Drawer({
@ -485,6 +479,9 @@ $.Viewer = function( options ) {
break; break;
} }
} }
}
if(this.drawer === null){ if(this.drawer === null){
$.console.error('No drawer could be created!'); $.console.error('No drawer could be created!');
throw('Error with creating the selected drawer(s)'); throw('Error with creating the selected drawer(s)');
@ -4002,4 +3999,22 @@ function onFlip() {
this.viewport.toggleFlip(); this.viewport.toggleFlip();
} }
/**
* Find drawer
*/
$.determineDrawer = function( id ){
for (let property in OpenSeadragon) {
const drawer = OpenSeadragon[ property ],
proto = drawer.prototype;
if( proto &&
proto instanceof OpenSeadragon.DrawerBase &&
$.isFunction( proto.getType ) &&
proto.getType.call( drawer ) === id
){
return drawer;
}
}
return null;
};
}( OpenSeadragon )); }( OpenSeadragon ));

View File

@ -35,92 +35,6 @@
(function( $ ){ (function( $ ){
// internal class Mat3: implements matrix operations
// Modified from https://webglfundamentals.org/webgl/lessons/webgl-2d-matrices.html
class Mat3{
constructor(values){
if(!values) {
values = [
0, 0, 0,
0, 0, 0,
0, 0, 0
];
}
this.values = values;
}
static makeIdentity(){
return new Mat3([
1, 0, 0,
0, 1, 0,
0, 0, 1
]);
}
static makeTranslation(tx, ty) {
return new Mat3([
1, 0, 0,
0, 1, 0,
tx, ty, 1,
]);
}
static makeRotation(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return new Mat3([
c, -s, 0,
s, c, 0,
0, 0, 1,
]);
}
static makeScaling(sx, sy) {
return new Mat3([
sx, 0, 0,
0, sy, 0,
0, 0, 1,
]);
}
multiply(other) {
let a = this.values;
let b = other.values;
var a00 = a[0 * 3 + 0];
var a01 = a[0 * 3 + 1];
var a02 = a[0 * 3 + 2];
var a10 = a[1 * 3 + 0];
var a11 = a[1 * 3 + 1];
var a12 = a[1 * 3 + 2];
var a20 = a[2 * 3 + 0];
var a21 = a[2 * 3 + 1];
var a22 = a[2 * 3 + 2];
var b00 = b[0 * 3 + 0];
var b01 = b[0 * 3 + 1];
var b02 = b[0 * 3 + 2];
var b10 = b[1 * 3 + 0];
var b11 = b[1 * 3 + 1];
var b12 = b[1 * 3 + 2];
var b20 = b[2 * 3 + 0];
var b21 = b[2 * 3 + 1];
var b22 = b[2 * 3 + 2];
return new Mat3([
b00 * a00 + b01 * a10 + b02 * a20,
b00 * a01 + b01 * a11 + b02 * a21,
b00 * a02 + b01 * a12 + b02 * a22,
b10 * a00 + b11 * a10 + b12 * a20,
b10 * a01 + b11 * a11 + b12 * a21,
b10 * a02 + b11 * a12 + b12 * a22,
b20 * a00 + b21 * a10 + b22 * a20,
b20 * a01 + b21 * a11 + b22 * a21,
b20 * a02 + b21 * a12 + b22 * a22,
]);
}
}
/** /**
* @class WebGLDrawer * @class WebGLDrawer
* @memberof OpenSeadragon * @memberof OpenSeadragon
@ -277,9 +191,9 @@
let flipMultiplier = this.viewport.flipped ? -1 : 1; let flipMultiplier = this.viewport.flipped ? -1 : 1;
// calculate view matrix for viewer // calculate view matrix for viewer
let posMatrix = Mat3.makeTranslation(-viewport.center.x, -viewport.center.y); let posMatrix = $.Mat3.makeTranslation(-viewport.center.x, -viewport.center.y);
let scaleMatrix = Mat3.makeScaling(2 / viewport.bounds.width * flipMultiplier, -2 / viewport.bounds.height); let scaleMatrix = $.Mat3.makeScaling(2 / viewport.bounds.width * flipMultiplier, -2 / viewport.bounds.height);
let rotMatrix = Mat3.makeRotation(-viewport.rotation); let rotMatrix = $.Mat3.makeRotation(-viewport.rotation);
let viewMatrix = scaleMatrix.multiply(rotMatrix).multiply(posMatrix); let viewMatrix = scaleMatrix.multiply(rotMatrix).multiply(posMatrix);
gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null);
@ -343,10 +257,10 @@
let imageRotation = tiledImage.getRotation(true); let imageRotation = tiledImage.getRotation(true);
// if needed, handle the tiledImage being rotated // if needed, handle the tiledImage being rotated
if( imageRotation % 360 !== 0){ if( imageRotation % 360 !== 0){
let imageRotationMatrix = Mat3.makeRotation(-imageRotation * Math.PI / 180); let imageRotationMatrix = $.Mat3.makeRotation(-imageRotation * Math.PI / 180);
let imageCenter = tiledImage.getBoundsNoRotate(true).getCenter(); let imageCenter = tiledImage.getBoundsNoRotate(true).getCenter();
let t1 = Mat3.makeTranslation(imageCenter.x, imageCenter.y); let t1 = $.Mat3.makeTranslation(imageCenter.x, imageCenter.y);
let t2 = Mat3.makeTranslation(-imageCenter.x, -imageCenter.y); let t2 = $.Mat3.makeTranslation(-imageCenter.x, -imageCenter.y);
// update the view matrix to account for this image's rotation // update the view matrix to account for this image's rotation
let localMatrix = t1.multiply(imageRotationMatrix).multiply(t2); let localMatrix = t1.multiply(imageRotationMatrix).multiply(t2);
@ -572,7 +486,7 @@
let w = right - x; let w = right - x;
let h = bottom - y; let h = bottom - y;
let matrix = new Mat3([ let matrix = new $.Mat3([
w, 0, 0, w, 0, 0,
0, h, 0, 0, h, 0,
x, y, 1, x, y, 1,
@ -580,11 +494,11 @@
if(tile.flipped){ if(tile.flipped){
// flip the tile around the center of the unit quad // flip the tile around the center of the unit quad
let t1 = Mat3.makeTranslation(0.5, 0); let t1 = $.Mat3.makeTranslation(0.5, 0);
let t2 = Mat3.makeTranslation(-0.5, 0); let t2 = $.Mat3.makeTranslation(-0.5, 0);
// update the view matrix to account for this image's rotation // update the view matrix to account for this image's rotation
let localMatrix = t1.multiply(Mat3.makeScaling(-1, 1)).multiply(t2); let localMatrix = t1.multiply($.Mat3.makeScaling(-1, 1)).multiply(t2);
matrix = matrix.multiply(localMatrix); matrix = matrix.multiply(localMatrix);
} }
@ -798,7 +712,7 @@
gl.enableVertexAttribArray(this._secondPass.aTexturePosition); gl.enableVertexAttribArray(this._secondPass.aTexturePosition);
// set the matrix that transforms the framebuffer to clip space // set the matrix that transforms the framebuffer to clip space
let matrix = Mat3.makeScaling(2, 2).multiply(Mat3.makeTranslation(-0.5, -0.5)); let matrix = $.Mat3.makeScaling(2, 2).multiply($.Mat3.makeTranslation(-0.5, -0.5));
gl.uniformMatrix3fv(this._secondPass.uMatrix, false, matrix.values); gl.uniformMatrix3fv(this._secondPass.uMatrix, false, matrix.values);
} }
@ -957,8 +871,6 @@
} catch (e){ } catch (e){
$.console.error('Error uploading image data to WebGL', e); $.console.error('Error uploading image data to WebGL', e);
} }
} }
_imageUnloadedHandler(event){ _imageUnloadedHandler(event){

View File

@ -30,7 +30,10 @@ let viewer;
$('#create-drawer').on('click',function(){ $('#create-drawer').on('click',function(){
let drawerType = $('#select-drawer').val(); let drawerType = $('#select-drawer').val();
let num = Math.floor($('#input-number').val()); let num = Math.floor($('#input-number').val());
run(drawerType, num);
});
function run(drawerType, num) {
if(viewer){ if(viewer){
viewer.destroy(); viewer.destroy();
} }
@ -57,8 +60,7 @@ $('#create-drawer').on('click',function(){
viewer.viewport.panBy(new OpenSeadragon.Point( dist * m/2, 0)); viewer.viewport.panBy(new OpenSeadragon.Point( dist * m/2, 0));
}, 1000); }, 1000);
}
});
function makeViewer(drawerType){ function makeViewer(drawerType){
let viewer = OpenSeadragon({ let viewer = OpenSeadragon({