Ignore:
Timestamp:
09/27/16 10:10:21 (9 years ago)
Author:
dlcheng
Message:

CHG (JS): data markers and displays now uses 2d map marker and is more accurate.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/m/plot/webgl.js

    r21205 r21231  
    1010                canvas.gl = initWebGL(canvas,options);
    1111                canvas.nodes = [];
    12                 if (canvas.drawHandler) window.cancelAnimationFrame(canvas.drawHandler);
     12                if (canvas.drawHandler) { window.cancelAnimationFrame(canvas.drawHandler); }
    1313                draw(canvas,options);
    1414                canvas.initialized = true;
     
    2121                if (!canvas.gl) {
    2222                        gl = GL.create({canvas:canvas});
     23                        // Enable depth testing
     24                        gl.enable(gl.DEPTH_TEST);
     25                        // Near things obscure far things
     26                        gl.depthFunc(gl.LEQUAL);
     27                        // Enable color blending/overlay
     28                        gl.enable(gl.BLEND);
     29                        // Enable face culling
     30                        gl.enable(gl.CULL_FACE);
     31                        gl.cullFace(gl.FRONT);
     32                        // Load shaders and store them in gl object
     33                        gl.shaders = loadShaders(gl);
     34                       
     35                        // Add event listeners for canvas
     36                        var displayview = options.getfieldvalue('displayview','off') == 'on';
     37                        var displayzoom = options.getfieldvalue('displayzoom','off') == 'on';
     38                        var mc = new Hammer.Manager(canvas);
     39                       
     40                        mc.add( new Hammer.Tap({ event: 'singletap' }) );
     41                        mc.add(new Hammer.Pan({threshold:0, pointers:0}));
     42                        mc.add(new Hammer.Pinch({threshold:0})).recognizeWith(mc.get('pan'));
     43                        mc.on('singletap', function (ev) {onTap(ev,canvas);});
     44                        mc.on('panstart panmove', function (ev) {onPan(ev,canvas,displayview);});
     45                        mc.on('pinchstart pinchmove', function (ev) {onPinch(ev,canvas,displayview);});
     46                       
     47                        //canvas.addEventListener('mousemove', function (ev) {onTap(ev,canvas);}, false);
     48                        canvas.addEventListener('mousewheel', function (ev) {onZoom(ev,canvas,displayzoom)}, false);
     49                        canvas.addEventListener('DOMMouseScroll', function (ev) {onZoom(ev,canvas,displayzoom)}, false);
    2350                }
    2451                else {
     
    3158        }
    3259       
    33         // Enable depth testing
    34         gl.enable(gl.DEPTH_TEST);
    35         // Near things obscure far things
    36         gl.depthFunc(gl.LEQUAL);
    37         // Enable color blending/overlay
    38         gl.enable(gl.BLEND);
    39         // Enable face culling
    40         gl.enable(gl.CULL_FACE);
    41         gl.cullFace(gl.FRONT);
    42        
    43         // Load shaders and store them in gl object
    44         gl.shaders = loadShaders(gl);
    45        
    4660        // Add context state variables
    4761        //TODO:Group variables in objects for organization and naming
    4862        canvas.gl = gl;
    49         canvas.zoomBounds = options.getfieldvalue('zoomlim',[0.001,100.0]);
    50         canvas.zoom = clamp(options.getfieldvalue('zoom',1.0), canvas.zoomBounds[0], canvas.zoomBounds[1]);
    51         canvas.zoomLast = canvas.zoom;
    5263        canvas.cameraPosition = vec3.create();
    5364        canvas.cameraMatrix = mat4.create();
    54         canvas.vInverseMatrix = mat4.create();
    55         canvas.translation = options.getfieldvalue('origin',[0,0,0]);
    56         canvas.viewPanning = options.getfieldvalue('enablepanning','off') == 'on';
    57         canvas.view = options.getfieldvalue('view',[0,90]); //0 azimuth - up is north, 90 elevation - looking straight down
    58         canvas.rotation = canvas.view;
    59         canvas.rotationAzimuthBounds = options.getfieldvalue('azlim',[0,360]);
    60         canvas.rotationElevationBounds = options.getfieldvalue('ellim',[-180,180]);
    6165        canvas.controlSensitivity = options.getfieldvalue('controlsensitivity',1);
    62         canvas.twod = options.getfieldvalue('2d','off') == 'on';
     66        canvas.dataMarkersAllowed = options.getfieldvalue('datamarkers','off') == 'on';
     67        canvas.dataMarkersEnabled = true; //if data marker feature is on, user can toggle feature on and off
     68        canvas.inverseCameraMatrix = mat4.create();
     69        canvas.id = options.getfieldvalue('canvasid','.sim-canvas');
    6370        canvas.moviePlay = true;
    6471        canvas.movieReverse = false;
    6572        canvas.movieIncrement = true;
    6673        canvas.moviefps = options.getfieldvalue('moviefps',5);
     74        canvas.rotation = options.getfieldvalue('view',[0,90]); //0 azimuth, 90 elevation
     75        canvas.rotationAzimuthBounds = options.getfieldvalue('azlim',[0,360]);
     76        canvas.rotationElevationBounds = options.getfieldvalue('ellim',[-180,180]);
     77        canvas.translation = options.getfieldvalue('origin',[0,0,0]);
     78        canvas.twod = options.getfieldvalue('2d','off') == 'on';
     79        canvas.view = options.getfieldvalue('view',[0,90]);
     80        canvas.viewPanning = options.getfieldvalue('enablepanning','off') == 'on';
     81        canvas.vInverseMatrix = mat4.create();
     82        canvas.zoomBounds = options.getfieldvalue('zoomlim',[0.001,100.0]);
     83        canvas.zoom = clamp(options.getfieldvalue('zoom',1.0), canvas.zoomBounds[0], canvas.zoomBounds[1]);
     84        canvas.zoomLast = canvas.zoom;
    6785        var backgroundcolor = new RGBColor(options.getfieldvalue('backgroundcolor','lightcyan'));
    68         if (backgroundcolor.ok) canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0];
    69         else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out background color for curent canvas ",canvas));
    70        
    71         // Add event listeners for canvas
    72         var displayview = options.getfieldvalue('displayview','off') == 'on';
    73         var displayzoom = options.getfieldvalue('displayzoom','off') == 'on';
    74         var mc = new Hammer.Manager(canvas);
    75        
    76         mc.add(new Hammer.Tap());
    77     mc.add(new Hammer.Pan({threshold:0, pointers:0}));
    78     mc.add(new Hammer.Pinch({threshold:0})).recognizeWith(mc.get('pan'));
    79         mc.on("tap", function (ev) {onTap(ev,canvas);});
    80     mc.on("panstart panmove", function (ev) {onPan(ev,canvas,displayview);});
    81     mc.on("pinchstart pinchmove", function (ev) {onPinch(ev,canvas,displayview);});
    82        
    83         canvas.addEventListener("mousewheel", function (ev) {onZoom(ev,canvas,displayzoom)}, false);
    84         canvas.addEventListener("DOMMouseScroll", function (ev) {onZoom(ev,canvas,displayzoom)}, false);
     86        if (backgroundcolor.ok) { canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0]; }
     87        else { throw Error(sprintf('s%s%s\n','initWebGL error message: cound not find out background color for curent canvas ',canvas)); }
    8588       
    8689        return gl;
     90} //}}}
     91function loadShaders(gl) { //{{{
     92        var shaders = {};
     93        shaders.Colored = new GL.Shader.fromURL('../../../js/shaders/Colored.vsh', '../../../js/shaders/Colored.fsh', null, gl);
     94        shaders.Textured = new GL.Shader.fromURL('../../../js/shaders/Textured.vsh', '../../../js/shaders/Textured.fsh', null, gl);
     95        shaders.SkyFromSpace = new GL.Shader.fromURL('../../../js/shaders/SkyFromSpace.vert', '../../../js/shaders/SkyFromSpace.frag', null, gl);
     96        shaders.GroundFromSpace = new GL.Shader.fromURL('../../../js/shaders/GroundFromSpace.vert', '../../../js/shaders/GroundFromSpace.frag', null, gl);
     97        return shaders;
    8798} //}}}
    8899function initTexture(gl,imageSource) { //{{{
     
    106117                maskColor:vec4.fromValues(0.0, 0.0, 1.0, 1.0),
    107118                mesh:null,
    108                 name:"node",
    109                 shaderName:"Colored",
    110                 shader:gl.shaders["Colored"],
     119                name:'node',
     120                shaderName:'Colored',
     121                shader:gl.shaders.Colored,
    111122                texture:null,
    112123                useIndexBuffer:true,
     
    115126                rotation:vec3.create(),
    116127                translation:vec3.create(),
    117                 modelMatrix:mat4.create()
     128                modelMatrix:mat4.create(),
     129                rotationMatrix:mat4.create(),
     130                inverseModelMatrix:mat4.create(),
     131                inverseRotationMatrix:mat4.create()
    118132        };
    119133} //}}}
    120 function debugNodes(canvasid) {
     134function debugNodes(canvasid) { //{{{
     135        var canvasid = canvasid || '.sim-canvas';
    121136        var nodes = $(canvasid)[0].nodes;
    122         console.log(canvasid, "Nodes:");
     137        console.log(canvasid, 'Nodes:');
    123138        for (var node in nodes) {
    124                 console.log("name", nodes[node]["name"], "translation", nodes[node]["translation"], "center", nodes[node]["center"], "rotation", nodes[node]["rotation"]);
     139                console.log('name: ', nodes[node].name, ' node: ', nodes[node], ' mesh: ', nodes[node].mesh, ' translation: ', nodes[node].translation, ' center:', nodes[node].center, ' rotation:', nodes[node].rotation);
    125140        }
    126141        return nodes;
    127 }
    128 function recalculateModelMatrix(node) { //{{{
     142} //}}}
     143function updateModelMatrix(node) { //{{{
    129144        var modelMatrix = mat4.create();
    130145
    131146        var translationMatrix = mat4.create();
    132         mat4.translate(translationMatrix, translationMatrix, [-node["center"][0],-node["center"][1],-node["center"][2]]); //scale/rotation centering
     147        mat4.translate(translationMatrix, translationMatrix, [-node.center[0],-node.center[1],-node.center[2]]); //scale/rotation centering
    133148        mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
    134149       
    135150        var scaleMatrix = mat4.create();
    136         mat4.scale(scaleMatrix, scaleMatrix, node["scale"]);
     151        mat4.scale(scaleMatrix, scaleMatrix, node.scale);
    137152        mat4.multiply(modelMatrix, scaleMatrix, modelMatrix);
    138153       
     154        var rotationMatrix = mat4.create();
    139155        var zRotationMatrix = mat4.create();   
    140         mat4.rotate(zRotationMatrix, zRotationMatrix, radians(node["rotation"][2]), [0.0, 0.0, 1.0]);
    141         mat4.multiply(modelMatrix, zRotationMatrix, modelMatrix);
     156        mat4.rotate(zRotationMatrix, zRotationMatrix, DEG2RAD * node.rotation[2], [0.0, 0.0, 1.0]);
     157        mat4.multiply(rotationMatrix, zRotationMatrix, rotationMatrix);
    142158        var yRotationMatrix = mat4.create();   
    143         mat4.rotate(yRotationMatrix, yRotationMatrix, radians(node["rotation"][1]), [0.0, 1.0, 0.0]);
    144         mat4.multiply(modelMatrix, yRotationMatrix, modelMatrix);
     159        mat4.rotate(yRotationMatrix, yRotationMatrix, DEG2RAD * node.rotation[1], [0.0, 1.0, 0.0]);
     160        mat4.multiply(rotationMatrix, yRotationMatrix, rotationMatrix);
    145161        var xRotationMatrix = mat4.create();   
    146         mat4.rotate(xRotationMatrix, xRotationMatrix, radians(node["rotation"][0]), [1.0, 0.0, 0.0]);
    147         mat4.multiply(modelMatrix, xRotationMatrix, modelMatrix);
     162        mat4.rotate(xRotationMatrix, xRotationMatrix, DEG2RAD * node.rotation[0], [1.0, 0.0, 0.0]);
     163        mat4.multiply(rotationMatrix, xRotationMatrix, rotationMatrix);
     164        mat4.multiply(modelMatrix, rotationMatrix, modelMatrix);       
    148165       
    149166        mat4.identity(translationMatrix);
    150         mat4.translate(translationMatrix, translationMatrix, node["center"]); //relative translation
     167        mat4.translate(translationMatrix, translationMatrix, node.center); //relative translation
    151168        mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
    152169       
    153170        mat4.identity(translationMatrix);
    154         mat4.translate(translationMatrix, translationMatrix, node["translation"]); //absolute translation
     171        mat4.translate(translationMatrix, translationMatrix, node.translation); //absolute translation
    155172        mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
    156         return modelMatrix;
    157 } //}}}
    158 function raycast(canvas,mesh,x,y) { //{{{
    159         var raytracer = new GL.Raytracer(canvas.cameraMatrix);
    160         var ray = raytracer.getRayForPixel(x, y);
    161         if(!mesh || mesh.ready == false) return;
    162         if(!mesh.octree) mesh.octree = new GL.Octree(mesh);
    163 
    164         var hit = mesh.octree.testRay(canvas.cameraPosition, ray, 1e2, 1e10);
    165        
    166         if(!hit) return;
    167         return hit.pos;
    168 }
    169 function radians (degrees) { //{{{
    170   return degrees * Math.PI / 180;
    171 } //}}}
    172 function degrees (radians) { //{{{
    173   return radians * 180 / Math.PI;
     173       
     174        node.modelMatrix = modelMatrix;
     175        node.inverseModelMatrix = mat4.invert(mat4.create(), modelMatrix);
     176        node.rotationMatrix = rotationMatrix;
     177        node.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix);;
    174178} //}}}
    175179function clamp(value, min, max) { //{{{
     
    177181} //}}}
    178182function recover(canvasid,name,defaultvalue) { //{{{
    179         var canvas  = document.getElementById(canvasid);
    180         if (canvas && canvas.hasOwnProperty(name)) {
    181                 return canvas[name];
    182         }
     183        var canvas = document.getElementById(canvasid);
     184        if (canvas && canvas.hasOwnProperty(name)) { return canvas[name]; }
    183185        return defaultvalue;
    184186} //}}}
     
    186188        //TypedArray compatibility for Safari/IE
    187189        if (typeof Int8Array !== 'undefined') {
    188                 if (!Int8Array.prototype.fill) Int8Array.prototype.fill = Array.prototype.fill;
    189                 if (!Int8Array.prototype.slice) Int8Array.prototype.slice = Array.prototype.slice;
     190                if (!Int8Array.prototype.fill) { Int8Array.prototype.fill = Array.prototype.fill; }
     191                if (!Int8Array.prototype.slice) { Int8Array.prototype.slice = Array.prototype.slice; }
    190192        }
    191193        if (typeof Uint8Array !== 'undefined') {
    192                 if (!Uint8Array.prototype.fill) Uint8Array.prototype.fill = Array.prototype.fill;
    193                 if (!Uint8Array.prototype.slice) Uint8Array.prototype.slice = Array.prototype.slice;
     194                if (!Uint8Array.prototype.fill) { Uint8Array.prototype.fill = Array.prototype.fill; }
     195                if (!Uint8Array.prototype.slice) { Uint8Array.prototype.slice = Array.prototype.slice; }
    194196        }
    195197        if (typeof Uint8ClampedArray !== 'undefined') {
    196                 if (!Uint8ClampedArray.prototype.fill) Uint8ClampedArray.prototype.fill = Array.prototype.fill;
    197                 if (!Uint8ClampedArray.prototype.slice) Uint8ClampedArray.prototype.slice = Array.prototype.slice;
     198                if (!Uint8ClampedArray.prototype.fill) { Uint8ClampedArray.prototype.fill = Array.prototype.fill; }
     199                if (!Uint8ClampedArray.prototype.slice) { Uint8ClampedArray.prototype.slice = Array.prototype.slice; }
    198200        }
    199201        if (typeof Int16Array !== 'undefined') {
    200                 if (!Int16Array.prototype.fill) Int16Array.prototype.fill = Array.prototype.fill;
    201                 if (!Int16Array.prototype.slice) Int16Array.prototype.slice = Array.prototype.slice;
     202                if (!Int16Array.prototype.fill) { Int16Array.prototype.fill = Array.prototype.fill; }
     203                if (!Int16Array.prototype.slice) { Int16Array.prototype.slice = Array.prototype.slice; }
    202204        }
    203205        if (typeof Uint16Array !== 'undefined') {
    204                 if (!Uint16Array.prototype.fill) Uint16Array.prototype.fill = Array.prototype.fill;
    205                 if (!Uint16Array.prototype.slice) Uint16Array.prototype.slice = Array.prototype.slice;
     206                if (!Uint16Array.prototype.fill) { Uint16Array.prototype.fill = Array.prototype.fill; }
     207                if (!Uint16Array.prototype.slice) { Uint16Array.prototype.slice = Array.prototype.slice; }
    206208        }
    207209        if (typeof Int32Array !== 'undefined') {
    208                 if (!Int32Array.prototype.fill) Int32Array.prototype.fill = Array.prototype.fill;
    209                 if (!Int32Array.prototype.slice) Int32Array.prototype.slice = Array.prototype.slice;
     210                if (!Int32Array.prototype.fill) { Int32Array.prototype.fill = Array.prototype.fill; }
     211                if (!Int32Array.prototype.slice) { Int32Array.prototype.slice = Array.prototype.slice; }
    210212        }
    211213        if (typeof Uint32Array !== 'undefined') {
    212                 if (!Uint32Array.prototype.fill) Uint32Array.prototype.fill = Array.prototype.fill;
    213                 if (!Uint32Array.prototype.slice) Uint32Array.prototype.slice = Array.prototype.slice;
     214                if (!Uint32Array.prototype.fill) { Uint32Array.prototype.fill = Array.prototype.fill; }
     215                if (!Uint32Array.prototype.slice) { Uint32Array.prototype.slice = Array.prototype.slice; }
    214216        }
    215217        if (typeof Float32Array !== 'undefined') {
    216                 if (!Float32Array.prototype.fill) Float32Array.prototype.fill = Array.prototype.fill;
    217                 if (!Float32Array.prototype.slice) Float32Array.prototype.slice = Array.prototype.slice;
     218                if (!Float32Array.prototype.fill) { Float32Array.prototype.fill = Array.prototype.fill; }
     219                if (!Float32Array.prototype.slice) { Float32Array.prototype.slice = Array.prototype.slice; }
    218220        }
    219221        if (typeof Float64Array !== 'undefined') {
    220                 if (!Float64Array.prototype.fill) Float64Array.prototype.fill = Array.prototype.fill;
    221                 if (!Float64Array.prototype.slice) Float64Array.prototype.slice = Array.prototype.slice;
     222                if (!Float64Array.prototype.fill) { Float64Array.prototype.fill = Array.prototype.fill; }
     223                if (!Float64Array.prototype.slice) { Float64Array.prototype.slice = Array.prototype.slice; }
    222224        }
    223225        if (typeof TypedArray !== 'undefined') {
    224                 if (!TypedArray.prototype.fill) TypedArray.prototype.fill = Array.prototype.fill;
    225                 if (!TypedArray.prototype.slice) TypedArray.prototype.slice = Array.prototype.slice;
    226         }
     226                if (!TypedArray.prototype.fill) { TypedArray.prototype.fill = Array.prototype.fill; }
     227                if (!TypedArray.prototype.slice) { TypedArray.prototype.slice = Array.prototype.slice; }
     228        }
     229} //}}}
     230function raycast(canvas, origin, ray) { //{{{
     231        var mesh = canvas.unitNode.mesh;
     232        if (!mesh || mesh.ready == false) { return; }
     233        if (!mesh.octree) { mesh.octree = new GL.Octree(mesh); }
     234       
     235        var hit = mesh.octree.testRay(origin, ray, 1e3, 1e10);
     236       
     237        if(!hit) { return; }
     238       
     239        hit.modelPos = vec3.copy(vec3.create(), hit.pos);
     240        vec3.transformMat4(hit.pos, hit.pos, canvas.unitNode.modelMatrix);
     241        vec3.transformMat4(hit.normal, hit.normal, canvas.unitNode.modelMatrix);
     242
     243        return hit;
    227244} //}}}
    228245//}}}
    229 //{{{ Shader Loading
    230 function loadShaders(gl) { //{{{
    231         var shaders = {};
    232         shaders["Colored"] = new GL.Shader.fromURL("../../../js/shaders/Colored.vsh", "../../../js/shaders/Colored.fsh", null, gl);
    233         shaders["Textured"] = new GL.Shader.fromURL("../../../js/shaders/Textured.vsh", "../../../js/shaders/Textured.fsh", null, gl);
    234         shaders["SkyFromSpace"] = new GL.Shader.fromURL("../../../js/shaders/SkyFromSpace.vert", "../../../js/shaders/SkyFromSpace.frag", null, gl);
    235         shaders["GroundFromSpace"] = new GL.Shader.fromURL("../../../js/shaders/GroundFromSpace.vert", "../../../js/shaders/GroundFromSpace.frag", null, gl);
    236         return shaders;
    237 } //}}}
    238246//{{{ Interface Functions
    239 function onTap(ev,canvas) { //{{{
     247function onTap(ev, canvas) { //{{{
     248        //Sets up a marker on a canvas that will track a point on the mesh. Can be dismissed by closing the display or clicking the marker.
    240249        ev.preventDefault();
    241         if (ev.type == 'panstart') {
    242                 canvas.lastDeltaX = 0;
    243                 canvas.lastDeltaY = 0;
    244         }
    245 }
     250        if (!(canvas.dataMarkersAllowed && canvas.dataMarkersEnabled)) { return; }
     251       
     252        var rect = canvas.getBoundingClientRect();
     253        var x = ev.srcEvent.clientX - rect.left;
     254        var y = ev.srcEvent.clientY - rect.top;
     255       
     256        updateMarker(canvas, x, y, true);
     257} //}}}
     258function updateMarker(canvas, x, y, reset, origin, far) { //{{{
     259        //Can be called by onTap to create/reuse a marker, or by the marker's update function. Origin and far are optional and only used by the update function for recreating the raycast.
     260        if (!canvas.unitNode) { return; }
     261       
     262        var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.cameraMatrix, canvas.unitNode.modelMatrix));
     263        var origin = origin || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 0], inverseMVPMatrix);
     264        var far = far || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 1.0], inverseMVPMatrix);
     265        var ray = vec3.subtract(vec3.create(), far, origin);
     266        var hit = raycast(canvas, origin, ray);
     267       
     268        if (hit) {
     269                var u = hit.coords[0][0] * hit.uvw[0] + hit.coords[1][0] * hit.uvw[1] + hit.coords[2][0] * hit.uvw[2];
     270                var v = hit.coords[0][1] * hit.uvw[0] + hit.coords[1][1] * hit.uvw[1] + hit.coords[2][1] * hit.uvw[2];
     271                var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v;
     272               
     273                var rect = canvas.getBoundingClientRect();
     274                var dataMarkerSize = 32;
     275                if (!canvas.marker) {
     276                        $('#' + canvas.id).after( '<img src="../../../js/textures/data-marker.svg" alt="data marker" width="' + dataMarkerSize + '" height="' + dataMarkerSize + '" id="sim-data-marker-' + canvas.id + '" class="sim-data-marker noselect"></img>' );
     277                        $('#sim-data-marker-' + canvas.id).css({
     278                                'position': 'absolute',
     279                                'left': (Math.round(x + rect.left) - dataMarkerSize / 2) + 'px',
     280                                'top': (Math.round(y + rect.top) - dataMarkerSize) + 'px',
     281                                'width': dataMarkerSize + 'px',
     282                                'height': dataMarkerSize + 'px',
     283                                'pointer-events': 'all',
     284                                'cursor': 'pointer',
     285                                'display': 'none'
     286                        });
     287                        canvas.marker = $('#sim-data-marker-' + canvas.id);
     288                        canvas.marker.on('click touch', function () {
     289                                canvas.marker.fadeOut(175);
     290                                canvas.dataMarkerDisplay.stop();
     291                        });
     292                        canvas.marker.fadeIn(175);
     293                }
     294               
     295               
     296                canvas.marker.hit = hit;
     297                canvas.marker.update = function() {
     298                        if (!canvas.unitNode) { return; }
     299                        var screenPoint = vec3.transformMat4(vec3.create(), canvas.marker.hit.pos, canvas.cameraMatrix);
     300                        var x = screenPoint[0] * (canvas.width / 2) + canvas.width / 2;
     301                        var y = -screenPoint[1] * (canvas.height / 2) + canvas.height / 2;
     302                        updateMarker(canvas, Math.round(x), Math.round(y), false, origin, far);
     303                        canvas.marker.css({
     304                                'left': (Math.round(x + rect.left) - dataMarkerSize / 2) + 'px',
     305                                'top': (Math.round(y + rect.top) - dataMarkerSize) + 'px'
     306                        });
     307                };
     308               
     309                if (!canvas.dataMarkerDisplay) {
     310                        var tripToShowData = new Trip([
     311                        {
     312                                content : '<div id="sim-data-marker-content-' + canvas.id + '" class="sim-data-marker-content"><p>X: ' + hit.modelPos [0].toPrecision(3) + ' </p><p>Y: ' + hit.modelPos [1].toPrecision(3) + ' </p><p>Z: ' + hit.modelPos [2].toPrecision(3) + '</p><p>Value: ' + (Math.round(value * 1000) / 1000).toPrecision(3) + '</p></div>',
     313                                position : 'screen-se'
     314                        }],
     315                        {
     316                                onEnd : function(tripIndex) {
     317                                        canvas.marker.fadeOut(175);
     318                                },
     319                                tripTheme : 'dark',
     320                                showCloseBox : true,
     321                                delay: -1
     322                        });
     323                        canvas.dataMarkerDisplay = tripToShowData;
     324                        canvas.dataMarkerDisplay.start();
     325                }
     326                $('#sim-data-marker-content-' + canvas.id).html('<p>X: ' + hit.modelPos [0].toPrecision(3) + ' </p><p>Y: ' + hit.modelPos [1].toPrecision(3) + ' </p><p>Z: ' + hit.modelPos [2].toPrecision(3) + '</p><p>Value: ' + (Math.round(value * 1000) / 1000).toPrecision(3) + '</p>');
     327                               
     328                if (reset) { modifyDataMarkersEnabled(true,canvas); }
     329        }
     330} //}}}
    246331function onPan(ev,canvas,displaylog) { //{{{
    247332        ev.preventDefault();
     
    256341               
    257342                if (canvas.twod) {
    258                         canvas.translation[0] += Math.cos(radians(canvas.rotation[0])) * deltaX - Math.sin(radians(0)) * deltaY;
    259                         canvas.translation[2] += Math.sin(radians(canvas.rotation[0])) * deltaX + Math.cos(radians(0)) * deltaY;
     343                        canvas.translation[0] += Math.cos(DEG2RAD * canvas.rotation[0]) * deltaX - Math.sin(DEG2RAD * 0) * deltaY;
     344                        canvas.translation[2] += Math.sin(DEG2RAD * canvas.rotation[0]) * deltaX + Math.cos(DEG2RAD * 0) * deltaY;
    260345                }
    261346                else {
    262                         canvas.translation[0] += Math.cos(radians(canvas.rotation[0])) * deltaX - Math.sin(radians(canvas.rotation[0])) * deltaY;
    263                         canvas.translation[2] += Math.sin(radians(canvas.rotation[0])) * deltaX + Math.cos(radians(canvas.rotation[0])) * deltaY;
     347                        canvas.translation[0] += Math.cos(DEG2RAD * canvas.rotation[0]) * deltaX - Math.sin(DEG2RAD * canvas.rotation[0]) * deltaY;
     348                        canvas.translation[2] += Math.sin(DEG2RAD * canvas.rotation[0]) * deltaX + Math.cos(DEG2RAD * canvas.rotation[0]) * deltaY;
    264349                }
    265350        }
    266351        else {
    267                 canvas.rotation[0] += degrees((canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * -2 * canvas.controlSensitivity);
    268                 canvas.rotation[1] += degrees((canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity);
    269                
    270                 if (canvas.rotation[0] > 360) {canvas.rotation[0] -= 360};
    271                 if (canvas.rotation[0] < -360) {canvas.rotation[0] += 360};
    272                 if (canvas.rotation[1] > 180) {canvas.rotation[1] -= 360};
    273                 if (canvas.rotation[1] < -180) {canvas.rotation[1] += 360};
     352                canvas.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * -2 * canvas.controlSensitivity * RAD2DEG;
     353                canvas.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG;
     354               
     355                if (canvas.rotation[0] > 360) { canvas.rotation[0] -= 360; };
     356                if (canvas.rotation[0] < -360) { canvas.rotation[0] += 360; };
     357                if (canvas.rotation[1] > 180) { canvas.rotation[1] -= 360; };
     358                if (canvas.rotation[1] < -180) { canvas.rotation[1] += 360; };
    274359               
    275360                canvas.rotation[0] = clamp(canvas.rotation[0], canvas.rotationAzimuthBounds[0], canvas.rotationAzimuthBounds[1]);
     
    279364        canvas.lastDeltaY = ev.deltaY;
    280365
    281         if (displaylog) console.log(canvas.rotation);
     366        if (displaylog) { console.log(canvas.rotation); }
    282367} //}}}
    283368function onPinch(ev,canvas,displaylog) { //{{{
    284369        ev.preventDefault();
    285         if (ev.type == 'pinchstart') {
    286                 canvas.zoomLast = canvas.zoom;
    287         }
    288         else {
    289                 modifyZoom(ev.scale * canvas.zoomLast, canvas, displaylog);
    290         }
     370        if (ev.type == 'pinchstart') { canvas.zoomLast = canvas.zoom; }
     371        else { modifyZoom(ev.scale * canvas.zoomLast, canvas, displaylog); }
    291372} //}}}
    292373function onZoom(ev,canvas,displaylog) { //{{{
     
    297378function modifyZoom(value,canvas,displaylog) { //{{{
    298379        canvas.zoom = clamp(value, canvas.zoomBounds[0], canvas.zoomBounds[1]);
    299         if (displaylog) console.log(canvas.zoom);
     380        if (displaylog) { console.log(canvas.zoom); }
     381} //}}}
     382function modifyDataMarkersEnabled(value,canvas) { //{{{
     383        canvas.dataMarkersEnabled = value;
     384        if (!canvas.dataMarkersEnabled && canvas.marker) {
     385                canvas.marker.fadeOut(175);
     386                canvas.dataMarkerDisplay.stop();
     387        }
     388        else if (canvas.dataMarkersEnabled && canvas.marker) {
     389                canvas.marker.fadeIn(175);
     390                canvas.dataMarkerDisplay.start();
     391        }
    300392} //}}}
    301393//}}}
     
    312404        var cameraPosition = vec3.create();
    313405
    314         if (canvas.twod) {
    315                 mat4.ortho(pMatrix, -aspectRatio*6.371e6/canvas.zoom, aspectRatio*6.371e6/canvas.zoom, -6.371e6/canvas.zoom, 6.371e6/canvas.zoom, -1.0, 1e10);
    316         }
    317         else {
    318                 mat4.perspective(pMatrix, 60 * Math.PI / 180, aspectRatio, 1e2, 1e10);
    319         }
     406        if (canvas.twod) { mat4.ortho(pMatrix, -aspectRatio*6.371e6/canvas.zoom, aspectRatio*6.371e6/canvas.zoom, -6.371e6/canvas.zoom, 6.371e6/canvas.zoom, -1.0, 1e10); }
     407        else { mat4.perspective(pMatrix, 45 * DEG2RAD, aspectRatio, 1e3, 1e10); }
    320408       
    321409        //Apply worldspace translation
    322         mat4.translate(translateMatrix, translateMatrix, [-canvas["translation"][0],-canvas["translation"][1],-canvas["translation"][2]]);
     410        mat4.translate(translateMatrix, translateMatrix, [-canvas.translation[0],-canvas.translation[1],-canvas.translation[2]]);
    323411        mat4.multiply(vMatrix, translateMatrix, vMatrix);
    324412       
    325413        //Calculate rotation around camera focal point about worldspace origin
    326414        if (canvas.twod) {
    327                 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, radians(0), [0, 1, 0]);
    328                 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, radians(90), [1, 0, 0]);
     415                mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * 0, [0, 1, 0]);
     416                mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * 90, [1, 0, 0]);
    329417                mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix);
    330418        }
    331419        else {
    332                 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, radians(canvas.rotation[0]), [0, 1, 0]);
    333                 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, radians(canvas.rotation[1]), [1, 0, 0]);
     420                mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * canvas.rotation[0], [0, 1, 0]);
     421                mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * canvas.rotation[1], [1, 0, 0]);
    334422                mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix);
    335423        }
    336424       
    337         //Apply rotation and scaling transform
     425        //Apply rotation transform
    338426        mat4.multiply(vMatrix, rotationMatrix, vMatrix);
    339427
     
    345433        //Calculate fields for lighting and raycasts
    346434        mat4.invert(canvas.vInverseMatrix, vMatrix);
    347         vec3.transformMat4(canvas.cameraPosition, cameraPosition, canvas.vInverseMatrix);
    348 
     435       
    349436        //Apply projection matrix to get camera matrix
    350437        mat4.multiply(canvas.cameraMatrix, pMatrix, vMatrix);
     438        mat4.invert(canvas.inverseCameraMatrix, canvas.cameraMatrix);
     439        vec3.transformMat4(canvas.cameraPosition, cameraPosition, canvas.inverseCameraMatrix);
    351440}//}}}
    352441function drawSceneGraphNode(canvas,node) { //{{{
    353         if (!node["enabled"]) return;
     442        if (!node.enabled) { return; }
    354443
    355444        var gl = canvas.gl;
     
    357446       
    358447        var mvpMatrix = mat4.create();
    359         mat4.multiply(mvpMatrix, canvas.cameraMatrix, node["modelMatrix"]);
    360        
    361         if (node["texture"]) node["texture"].bind(0);
    362         if (node["disableDepthTest"]) gl.disable(gl.DEPTH_TEST);
    363         if (node["enableCullFace"]) gl.enable(gl.CULL_FACE);
    364 
    365         gl.cullFace(node["cullFace"]);
    366         gl.lineWidth(node["lineWidth"]);
     448        mat4.multiply(mvpMatrix, canvas.cameraMatrix, node.modelMatrix);
     449       
     450        if (node.texture) { node.texture.bind(0); }
     451        if (node.disableDepthTest) { gl.disable(gl.DEPTH_TEST); }
     452        if (node.enableCullFace) { gl.enable(gl.CULL_FACE); }
     453
     454        gl.cullFace(node.cullFace);
     455        gl.lineWidth(node.lineWidth);
    367456        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    368457
     
    373462        vec3.transformMat4(origin, origin, canvas.vInverseMatrix);
    374463        vec3.normalize(lightOrigin, lightOrigin);
    375         vec3.sub(cameraPositionRelative, origin, node["translation"]);
     464        vec3.sub(cameraPositionRelative, origin, node.translation);
    376465        cameraHeight = vec3.length(cameraPositionRelative);
    377466       
     
    401490        var scaleDepth = atm.scaleDepth;
    402491       
    403         node["shader"].uniforms({
     492        node.shader.uniforms({
    404493                m4MVP: mvpMatrix,
    405                 m4Model: node["modelMatrix"],
     494                m4Model: node.modelMatrix,
    406495                u_texture: 0,
    407                 u_alpha: node["alpha"],
    408                 u_maskEnabled: node["maskEnabled"],
    409                 u_maskHeight: node["maskHeight"],
    410                 u_maskColor: node["maskColor"],
     496                u_alpha: node.alpha,
     497                u_maskEnabled: node.maskEnabled,
     498                u_maskHeight: node.maskHeight,
     499                u_maskColor: node.maskColor,
    411500                v3CameraPosition: origin,
    412                 v3Translate: node["translation"],
     501                v3Translate: node.translation,
    413502                v3LightPos: lightOrigin,
    414503                v3InvWavelength: inv_wavelength4,
     
    434523                e: atm.e,
    435524                attenuation: atm.attenuation
    436         });
    437         if (node["useIndexBuffer"] == true) node["shader"].draw(node["mesh"], node["drawMode"], "indices");
    438         else node["shader"].draw(node["mesh"], node["drawMode"]);
    439 
     525        }).draw(node.mesh, node.drawMode, 'triangles');
     526       
    440527        gl.enable(gl.DEPTH_TEST);
    441528        gl.disable(gl.CULL_FACE);
    442529} //}}}
    443530function draw(canvas,options) { //{{{
    444 
    445         // Ensure canvas and gl viewport sizes are the same
    446         if (canvas.width  != canvas.clientWidth || canvas.height != canvas.clientHeight) {
    447                 canvas.width  = canvas.clientWidth;
    448                 canvas.height = canvas.clientHeight;
    449                 canvas.gl.viewport(0, 0, canvas.width, canvas.height);
    450         }
    451        
    452         if (canvas.textcanvas) canvas.textcanvas.draw(canvas);
     531        if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); }
    453532
    454533        var nodes = canvas.nodes;
    455534        if (nodes.length < 1) {
    456                 canvas.drawHandler = window.requestAnimationFrame(function(time) {draw(canvas,options)});
     535                canvas.drawHandler = window.requestAnimationFrame(function(time) { draw(canvas,options); });
    457536                return;
    458537        }
    459         for (var node in nodes) {
    460                 if (nodes[node]["texture"] && nodes[node]["texture"]["ready"] == false || nodes[node]["shader"]["ready"] == false) {
    461                         canvas.drawHandler = window.requestAnimationFrame(function(time) {draw(canvas,options)});
     538        for (var node in nodes) {       
     539                if ((nodes[node].texture && nodes[node].texture.ready == false) || nodes[node].shader.ready == false || nodes[node].mesh.ready == false) {
     540                        canvas.drawHandler = window.requestAnimationFrame(function(time) { draw(canvas,options); });
    462541                        return;
    463542                }
    464543        }
    465544       
     545        var rect = canvas.getBoundingClientRect();
     546        canvas.width  = rect.width;
     547        canvas.height = rect.height;
     548       
    466549        var gl = canvas.gl;
     550        gl.makeCurrent(); //litegl function to handle switching between multiple canvases
     551        gl.viewport(0, 0, rect.width, rect.height);
    467552        gl.clearColor(canvas.backgroundcolor[0], canvas.backgroundcolor[1], canvas.backgroundcolor[2], canvas.backgroundcolor[3]);
    468553        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    469         gl.makeCurrent();
    470554       
    471555        updateCameraMatrix(canvas);
     556       
     557        if (canvas.marker) { canvas.marker.update(); }
    472558       
    473559        var drawPassNumber = 3;
    474560        for (var i = drawPassNumber - 1; i >= 0; i--) {
    475561                for (var node in nodes) {
    476                         if (nodes[node]["drawOrder"] == i) drawSceneGraphNode(canvas,nodes[node]);
    477                 }
    478         }
    479 
    480         canvas.drawHandler = window.requestAnimationFrame(function(time) {draw(canvas,options)});
     562                        if (nodes[node].drawOrder == i) { drawSceneGraphNode(canvas,nodes[node]); }
     563                }
     564        }
     565
     566        canvas.drawHandler = window.requestAnimationFrame(function(time) { draw(canvas,options); });
    481567} //}}}
    482568//}}}
Note: See TracChangeset for help on using the changeset viewer.