Changeset 21683
- Timestamp:
- 04/21/17 11:06:42 (8 years ago)
- Location:
- issm/trunk-jpl/src/m
- Files:
-
- 2 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/m/classes/clusters/generic.js
r21641 r21683 47 47 } //}}} 48 48 this.UploadAndRun = function (md,callbackfunction,callbackerrorfunction,callbackid,fid,toolkitsstring,solutionstring,name,runtimename) { //{{{ 49 49 if (!navigator.onLine) { //{{{ 50 $(callbackid).html(sprintf("%-16s", "NO CONNECTION")).prop("disabled", false); 51 callbackerrorfunction(); 52 return; 53 } //}}} 50 54 var request = new XMLHttpRequest(); 51 55 $(callbackid).html(sprintf("%-16s", "CONNECTING...")).prop("disabled", true); -
issm/trunk-jpl/src/m/plot/applyoptions.js
r21641 r21683 1 function applyoptions(md, data,datatype,options,canvas,gl,node){ //{{{1 function applyoptions(md, data, datatype, options, canvas, gl, node){ //{{{ 2 2 //APPLYOPTIONS - apply colobar, text, cloud, and expdisp options to current plot 3 3 // 4 4 // Usage: 5 // applyoptions(md, data,options)5 // applyoptions(md, data, options) 6 6 // 7 7 // See also: PLOTMODEL, PARSE_OPTIONS 8 8 9 // colorbar {{{9 //{{{ colorbar 10 10 if (options.exist('colorbar')) { 11 11 if (options.getfieldvalue('colorbar')==1) { 12 // Handle movie data {{{12 //{{{ Handle movie data 13 13 if (datatype == 5) { 14 14 data = data[0]; 15 15 } //}}} 16 // Variable options initialization {{{17 var caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]);16 //{{{ Variable options initialization 17 var caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]); 18 18 var colorbarinnerlabels = options.getfieldvalue('colorbarinnerlabels','off'); 19 var ccanvasid, ctitleid,clabelsid,ccanvas,ctitle,clabels,ccontext,cmap,colorbar,cwidth,cheight,cgradient,color,y,x;20 //}}} 21 // Create colorbar labels {{{19 var ccanvasid, ctitleid, clabelsid, ccanvas, ctitle, clabels, ccontext, cmap, colorbar, cwidth, cheight, cgradient, color, y, x; 20 //}}} 21 //{{{ Create colorbar labels 22 22 var labels = []; 23 var cdivisions = options.getfieldvalue('colorbarnticks', 6);23 var cdivisions = options.getfieldvalue('colorbarnticks', 6); 24 24 var caxisdelta = caxis[1] - caxis[0]; 25 var precision = options.getfieldvalue('colorbarprecision', 3);25 var precision = options.getfieldvalue('colorbarprecision', 3); 26 26 if (options.getfieldvalue('log','off')!='off') { 27 27 for (var i=cdivisions; i >= 0; i--) { 28 var scale = (Math.log10(caxis[1])-Math.log10(caxis[0]))/Math.log10(options.getfieldvalue('log', 10));29 labels[i] = (Math.pow(options.getfieldvalue('log', 10),Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log',10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision);28 var scale = (Math.log10(caxis[1])-Math.log10(caxis[0]))/Math.log10(options.getfieldvalue('log', 10)); 29 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision); 30 30 } 31 31 } else { … … 34 34 } 35 35 } //}}} 36 // Initialize colorbar canvas {{{37 ccanvasid = options.getfieldvalue('colorbarid', options.getfieldvalue('canvasid').replace('canvas','colorbar-canvas'));36 //{{{ Initialize colorbar canvas 37 ccanvasid = options.getfieldvalue('colorbarid', options.getfieldvalue('canvasid').replace('canvas','colorbar-canvas')); 38 38 ccanvas = $('#'+ccanvasid)[0]; 39 cwidth = ccanvas.width*options.getfieldvalue('colorbarwidth', 1);40 cheight = ccanvas.height*options.getfieldvalue('colorbarheight', 1);39 cwidth = ccanvas.width*options.getfieldvalue('colorbarwidth', 1); 40 cheight = ccanvas.height*options.getfieldvalue('colorbarheight', 1); 41 41 ccontext = ccanvas.getContext('2d'); 42 ccontext.clearRect(0, 0, cwidth, cheight);42 ccontext.clearRect(0, 0, cwidth, cheight); 43 43 ccontext.beginPath(); 44 44 cmap = options.getfieldvalue('colormap','jet'); 45 45 colorbar = colorbars[cmap]; 46 cgradient = ccontext.createLinearGradient(0, 0,0,cheight);47 //}}} 48 // Draw colorbar gradient {{{46 cgradient = ccontext.createLinearGradient(0, 0, 0, cheight); 47 //}}} 48 //{{{ Draw colorbar gradient 49 49 for (var i=0; i < colorbar.length; i++) { 50 50 color = colorbar[colorbar.length-i-1]; 51 color = [Math.round(color[0]*255), Math.round(color[1]*255),Math.round(color[2]*255)];52 cgradient.addColorStop(i/colorbar.length*(cdivisions/(cdivisions+1.0))+(1.0/(cdivisions+1.0)),'rgba('+color.toString()+', 1.0)');51 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)]; 52 cgradient.addColorStop(i/colorbar.length*(cdivisions/(cdivisions+1.0))+(1.0/(cdivisions+1.0)),'rgba('+color.toString()+', 1.0)'); 53 53 } 54 54 ccontext.fillStyle=cgradient; 55 ccontext.fillRect(0, 0,cwidth,cheight);56 //}}} 57 // Draw colorbar border {{{55 ccontext.fillRect(0, 0, cwidth, cheight); 56 //}}} 57 //{{{ Draw colorbar border 58 58 ccontext.beginPath(); 59 59 ccontext.lineWidth='1'; 60 60 ccontext.strokeStyle=options.getfieldvalue('colorbarfontcolor','black'); 61 ccontext.rect(0, 0,cwidth,cheight);61 ccontext.rect(0, 0, cwidth, cheight); 62 62 ccontext.stroke(); 63 63 //}}} 64 // Draw colorbar labels {{{64 //{{{ Draw colorbar labels 65 65 clabelsid = options.getfieldvalue('colorbarid', ccanvasid).replace('canvas','labels'); 66 66 clabels = $('#'+clabelsid); … … 80 80 clabelstring += '<li><span>'+labels[i]+'</span></li>'; 81 81 ccontext.beginPath(); 82 ccontext.moveTo(0, y);83 ccontext.lineTo(x, y);84 ccontext.moveTo(cwidth-x, y);85 ccontext.lineTo(cwidth, y);82 ccontext.moveTo(0, y); 83 ccontext.lineTo(x, y); 84 ccontext.moveTo(cwidth-x, y); 85 ccontext.lineTo(cwidth, y); 86 86 ccontext.stroke(); 87 87 } 88 88 clabels.append(clabelstring); 89 89 //}}} 90 // Draw colorbar title {{{90 //{{{ Draw colorbar title 91 91 ctitleid = options.getfieldvalue('colorbarid', ccanvasid).replace('canvas','heading'); 92 92 ctitle = $('#'+ctitleid); … … 95 95 } 96 96 } //}}} 97 // texture canvas //{{{98 var tcontext, tcanvas,tcanvasid,tURL,tgradient;97 //{{{ texture canvas 98 var tcontext, tcanvas, tcanvasid, tURL, tgradient; 99 99 tcanvasid = 'texturecanvas'; 100 100 var tcanvas = document.getElementById(tcanvasid); … … 104 104 } 105 105 tcontext = tcanvas.getContext('2d'); 106 tgradient = tcontext.createLinearGradient(0, 0,0,256);106 tgradient = tcontext.createLinearGradient(0, 0, 0, 256); 107 107 108 108 var cmap = options.getfieldvalue('colormap','jet'); … … 110 110 for (var i=0; i < colorbar.length; i++) { 111 111 color = colorbar[colorbar.length-i-1]; 112 color = [Math.round(color[0]*255), Math.round(color[1]*255),Math.round(color[2]*255)];113 tgradient.addColorStop(i/colorbar.length,'rgba('+color.toString()+', 1.0)');112 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)]; 113 tgradient.addColorStop(i/colorbar.length,'rgba('+color.toString()+', 1.0)'); 114 114 } 115 115 116 116 tcontext.fillStyle = tgradient; 117 tcontext.fillRect(0, 0,256,256);117 tcontext.fillRect(0, 0, 256, 256); 118 118 tURL = tcanvas.toDataURL(); 119 node.texture = initTexture(gl, tURL);119 node.texture = initTexture(gl, tURL); 120 120 node.textureCanvas = tcanvas; 121 node.caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]);121 node.caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]); 122 122 //}}} 123 // expdisp contours {{{123 //{{{ expdisp contours 124 124 if (options.exist('expdisp')) { 125 canvas.nodes.expdisp = Node(gl, options);125 canvas.nodes.expdisp = Node(gl, options); 126 126 var node = canvas.nodes.expdisp; 127 127 … … 131 131 var colors = []; 132 132 var rgbcolor = []; 133 var xmin, xmax;134 var ymin, ymax;135 var zmin, zmax;133 var xmin, xmax; 134 var ymin, ymax; 135 var zmin, zmax; 136 136 var scale; 137 137 … … 139 139 var x = options.getfieldvalue('expdisp').x; 140 140 var y = options.getfieldvalue('expdisp').y; 141 var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0);141 var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0); 142 142 143 143 if (options.getfieldvalue('expdisp').z) { … … 147 147 148 148 //Compute coordinates and data range: //{{{ 149 var modelxlim = [ArrayMin(x), ArrayMax(x)];150 var modelylim = [ArrayMin(y), ArrayMax(y)];151 var modelzlim = [ArrayMin(z), ArrayMax(z)];152 var xlim = options.getfieldvalue('xlim', modelxlim);153 var ylim = options.getfieldvalue('ylim', modelylim);154 var zlim = options.getfieldvalue('zlim', modelzlim);149 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 150 var modelylim = [ArrayMin(y), ArrayMax(y)]; 151 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 152 var xlim = options.getfieldvalue('xlim', modelxlim); 153 var ylim = options.getfieldvalue('ylim', modelylim); 154 var zlim = options.getfieldvalue('zlim', modelzlim); 155 155 xmin = xlim[0]; 156 156 xmax = xlim[1]; … … 165 165 node.shaderName = 'colored'; 166 166 node.shader = gl.shaders[node.shaderName].program; 167 node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)];167 node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)]; 168 168 node.translation = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (-2 / scale)]; 169 169 node.modelMatrix = updateModelMatrix(node); … … 178 178 179 179 //retrieve some options 180 var linewidth=options.getfieldvalue('linewidth', 1);180 var linewidth=options.getfieldvalue('linewidth', 1); 181 181 var edgecolor=options.getfieldvalue('edgecolor','black'); //RGBCOLOR? 182 182 … … 199 199 node.buffers = initBuffers(gl, node.arrays); 200 200 } //}}} 201 // cloud of points {{{201 //{{{ cloud of points 202 202 if (options.exist('cloud')) { 203 canvas.nodes.cloud = Node(gl, options);203 canvas.nodes.cloud = Node(gl, options); 204 204 var node = canvas.nodes.cloud; 205 205 … … 209 209 var colors = []; 210 210 var rgbcolor = []; 211 var xmin, xmax;212 var ymin, ymax;213 var zmin, zmax;211 var xmin, xmax; 212 var ymin, ymax; 213 var zmin, zmax; 214 214 var scale; 215 215 … … 217 217 var x = options.getfieldvalue('cloud').x; 218 218 var y = options.getfieldvalue('cloud').y; 219 var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0);219 var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0); 220 220 221 221 if (options.getfieldvalue('cloud').z) { … … 225 225 226 226 //Compute coordinates and data range: //{{{ 227 var modelxlim = [ArrayMin(x), ArrayMax(x)];228 var modelylim = [ArrayMin(y), ArrayMax(y)];229 var modelzlim = [ArrayMin(z), ArrayMax(z)];230 var xlim = options.getfieldvalue('xlim', modelxlim);231 var ylim = options.getfieldvalue('ylim', modelylim);232 var zlim = options.getfieldvalue('zlim', modelzlim);227 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 228 var modelylim = [ArrayMin(y), ArrayMax(y)]; 229 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 230 var xlim = options.getfieldvalue('xlim', modelxlim); 231 var ylim = options.getfieldvalue('ylim', modelylim); 232 var zlim = options.getfieldvalue('zlim', modelzlim); 233 233 xmin = xlim[0]; 234 234 xmax = xlim[1]; … … 243 243 node.shaderName = 'colored'; 244 244 node.shader = gl.shaders[node.shaderName].program; 245 node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)];245 node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)]; 246 246 node.translation = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (-2 / scale)]; 247 247 node.modelMatrix = updateModelMatrix(node); … … 256 256 257 257 //retrieve some options 258 var linewidth=options.getfieldvalue('linewidth', 1);258 var linewidth=options.getfieldvalue('linewidth', 1); 259 259 var edgecolor=options.getfieldvalue('edgecolor','black'); //RGBCOLOR? 260 260 … … 277 277 node.buffers = initBuffers(gl, node.arrays); 278 278 } //}}} 279 280 //text display //{{{ 279 //{{{ text display 281 280 if (options.exist('textlabels')) { 282 var textcanvas, textcanvasid;283 textcanvasid = options.getfieldvalue('textcanvasid', options.getfieldvalue('canvasid')+'-text');281 var textcanvas, textcanvasid; 282 textcanvasid = options.getfieldvalue('textcanvasid', options.getfieldvalue('canvasid')+'-text'); 284 283 textcanvas = $('#'+textcanvasid); 285 284 textcanvas.textlabels = options.getfieldvalue('textlabels',[]); … … 287 286 //setup drawing function for text canvas draw calls 288 287 textcanvas.draw = function(canvas) { 289 var textcontext, textlabels,textlabel,textcanvaswidth,textcanvasheight,textcoordinates;288 var textcontext, textlabels, textlabel, textcanvaswidth, textcanvasheight, textcoordinates; 290 289 var textposition = vec3.create(); 291 290 var mvpMatrix = mat4.create(); … … 304 303 for (text in textlabels) { 305 304 textlabel = textlabels[text]; 306 mat4.multiply(mvpMatrix, canvas.camera Matrix, canvas.nodes.overlay.modelMatrix);305 mat4.multiply(mvpMatrix, canvas.camera.vpMatrix, canvas.nodes.overlay.modelMatrix); 307 306 textposition = vec3.transformMat4(textposition, textlabel.pos, mvpMatrix); 308 307 if (textposition[2] > 1) { //clip coordinates with z > 1 … … 310 309 } 311 310 textcoordinates = [(textposition[0]+1.0)/2.0*textcanvaswidth, (-textposition[1]+1.0)/2.0*textcanvasheight]; //NDC to screenspace 312 textcontext.font = String(options.getfieldvalue('colorbarfontsize', 18))+'px "Lato",Helvetica,Arial,sans-serif';311 textcontext.font = String(options.getfieldvalue('colorbarfontsize', 18))+'px "Lato", Helvetica, Arial, sans-serif'; 313 312 textcontext.fillStyle = options.getfieldvalue('colorbarfontcolor','black'); 314 313 textcontext.strokeStyle = options.getfieldvalue('colorbarfontcolor','black'); … … 321 320 canvas.textcanvas = textcanvas; 322 321 } //}}} 323 //Atmosphere {{{ 322 //{{{ lat long overlay 323 if (options.exist('latlongoverlay')) { 324 var overlaycanvasid = options.getfieldvalue('latlongoverlayid', options.getfieldvalue('canvasid')+'-overlay'); 325 var overlaycanvas = $('#'+overlaycanvasid)[0]; 326 var latitudes = { 327 //"-90": 1, 328 //"-65": .999, 329 "-60": 0.994046875, 330 //"-55": 0.983187500000002, 331 //"-50": 0.97173550854167, 332 "-45": 0.955729166666666, 333 //"-40": 0.94218750000000218, 334 //"-35": 0.94218750000000218, 335 "-30": 0.9226562500000024, 336 //"-25": 0.87934895833333526, 337 //"-20": 0.856572916666669, 338 //"-15": 0.830729166666665, 339 //"-10": 0.803552708333336, 340 //"-5": 0.77395833333333541, 341 "0": 0.74218749999999811, 342 //"5": 0.70950364583333347, 343 //"10": 0.67479166666666823, 344 //"15": 0.63932291666666663, 345 //"20": 0.60171875, 346 //"25": 0.563453125, 347 "30": 0.523390625000001, 348 //"35": 0.48401875, 349 //"40": 0.44296875, 350 "45": 0.4020001, 351 //"50": 0.3578125, 352 //"55": 0.311875, 353 "60": 0.26953124999999978, 354 //"65": 0.225390625, 355 //"70": 0.18125, 356 //"75": 0.13541666666666671, 357 //"80": 0.08953125, 358 //"85": 0.046250000000000013, 359 //"90": 0.0, 360 } 361 var longitudes = [-150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180]; 362 overlaycanvas.draw = function(canvas) { 363 var rect = overlaycanvas.getBoundingClientRect(); 364 overlaycanvas.width = rect.width; 365 overlaycanvas.height = rect.height; 366 var ctx = overlaycanvas.getContext('2d'); 367 var centerx = overlaycanvas.width / 2; 368 var centery = overlaycanvas.height / 2; 369 var radius = (overlaycanvas.height) / 2; 370 ctx.setLineDash([5, 10]); 371 for(latitude in latitudes) { 372 ctx.beginPath(); 373 ctx.arc(centerx, centery, radius * latitudes[latitude], 0, 2 * Math.PI); 374 ctx.stroke(); 375 ctx.font = String(options.getfieldvalue('colorbarfontsize', 18))+'px "Lato", Helvetica, Arial, sans-serif'; 376 ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black'); 377 ctx.strokeStyle = options.getfieldvalue('colorbarfontcolor','black'); 378 ctx.textAlign = 'center'; 379 ctx.textBaseline = 'middle'; 380 ctx.fillText(latitude, centerx, centery + radius * latitudes[latitude]); 381 ctx.strokeText(latitude, centerx, centery + radius * latitudes[latitude]); 382 } 383 ctx.setLineDash([1, 0]); 384 for (longitude in longitudes) { 385 ctx.beginPath(); 386 ctx.moveTo(centerx, centery); 387 ctx.lineTo(centerx + radius * Math.sin(longitudes[longitude] * DEG2RAD), centery + radius * Math.cos(longitudes[longitude] * DEG2RAD)); 388 ctx.stroke(); 389 } 390 } 391 canvas.overlaycanvas = overlaycanvas; 392 } //}}} 393 //{{{ additional rendering nodes 324 394 if (options.exist('render')) { 325 var meshresults = processmesh(md, data,options);395 var meshresults = processmesh(md, data, options); 326 396 var x = meshresults[0]; 327 397 var y = meshresults[1]; … … 331 401 var isplanet = meshresults[5]; 332 402 333 var modelxlim = [ArrayMin(x), ArrayMax(x)];334 var modelylim = [ArrayMin(y), ArrayMax(y)];335 var modelzlim = [ArrayMin(z), ArrayMax(z)];336 var xlim = options.getfieldvalue('xlim', modelxlim);337 var ylim = options.getfieldvalue('ylim', modelylim);338 var zlim = options.getfieldvalue('zlim', modelzlim);403 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 404 var modelylim = [ArrayMin(y), ArrayMax(y)]; 405 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 406 var xlim = options.getfieldvalue('xlim', modelxlim); 407 var ylim = options.getfieldvalue('ylim', modelylim); 408 var zlim = options.getfieldvalue('zlim', modelzlim); 339 409 xmin = xlim[0]; 340 410 xmax = xlim[1]; … … 351 421 //atmosphere 352 422 var node = Node(gl); 353 canvas.nodes[canvas.nodes.length] = node;354 423 node.name = "atmosphere"; 355 424 node.shaderName = "SkyFromSpace"; … … 358 427 node.cullFace = gl.FRONT; 359 428 node.enableCullFace = true; 360 node.mesh = GL.Mesh.icosahedron({size:6371000*atmosphereScale,subdivisions:6}); 361 node.useIndexBuffer = false; 429 node.mesh = GL.Mesh.icosahedron({size: 6371000*atmosphereScale, subdivisions: 6}); 362 430 node.rotation = [0, 0, 0]; 363 431 node.translation = translation; 364 432 node.center = [0, 0, 0]; 365 433 updateModelMatrix(node); 434 canvas.nodes[node.name] = node; 366 435 } 367 436 if (options.getfieldvalue('render',[]).indexOf('space')!=-1) { 368 437 //skysphere 369 438 node = Node(gl); 370 canvas.nodes[canvas.nodes.length] = node;371 439 node.name = "skysphere"; 372 440 node.shaderName = "Textured"; … … 375 443 node.cullFace = gl.FRONT; 376 444 node.enableCullFace = true; 377 node.mesh = GL.Mesh.sphere({size:6371000*20}); 378 node.texture = initTexture(gl,canvas.rootPath+'textures/TychoSkymapII_t4_2k.jpg'); 379 node.useIndexBuffer = false; 445 node.mesh = GL.Mesh.sphere({size: 6371000*20}); 446 node.texture = initTexture(gl, canvas.rootPath+'textures/TychoSkymapII_t4_2k.jpg'); 380 447 node.rotation = [0, 0, 0]; 381 448 node.translation = translation; 382 449 node.center = [0, 0, 0]; 383 450 updateModelMatrix(node); 451 canvas.nodes[node.name] = node; 452 } 453 if (canvas.clouds.enabled) { 454 //clouds 455 for (var i = 0; i < canvas.clouds.quantity; i++) { 456 node = Node(gl); 457 node.name = "clouds" + i; 458 node.shaderName = "Clouds"; 459 node.shader = gl.shaders[node.shaderName]; 460 node.drawOrder = 2; 461 node.cullFace = gl.BACK; 462 node.enableCullFace = true; 463 node.mesh = GL.Mesh.fromURL(canvas.rootPath+'obj/cloud.obj'); 464 node.rotation = [0, 0, 0]; 465 node.scale = [2500, 2500, 2500]; 466 node.translation = [translation[0], translation[1] - 405000, translation[2]]; 467 node.center = [0, 0, 0]; 468 node.animation = {"time": Date.now(),"target": node.translation,"current": node.translation}; 469 updateModelMatrix(node); 470 canvas.nodes[node.name] = node; 471 //canvas.clouds.list 472 } 473 //TODO: Steven, please add <canvas.clouds.quantity> total cloud nodes, randomly spread over the mesh, giving each one a new name and adding them to the canvas.clouds.list so that we can track them later. 474 475 } 476 if (options.getfieldvalue('render',[]).indexOf('latlong')!=-1) { 477 //latlong 478 node = Node(gl); 479 node.name = "clouds"; 480 node.shaderName = "Clouds"; 481 node.shader = gl.shaders[node.shaderName]; 482 node.drawOrder = 2; 483 node.cullFace = gl.BACK; 484 node.enableCullFace = true; 485 node.mesh = GL.Mesh.fromURL(canvas.rootPath+'obj/cloud.obj'); 486 node.rotation = [0, 0, 0]; 487 node.scale = [2500, 2500, 2500]; 488 node.translation = [translation[0], translation[1] - 405000, translation[2]]; 489 node.center = [0, 0, 0]; 490 node.animation = {"time": Date.now(),"target": node.translation,"current": node.translation}; 491 updateModelMatrix(node); 492 canvas.nodes[node.name] = node; 384 493 } 385 494 } //}}} -
issm/trunk-jpl/src/m/plot/plot_mesh.js
r21300 r21683 1 function plot_mesh(md, options,canvas) { //{{{1 function plot_mesh(md, options, canvas) { //{{{ 2 2 //PLOT_MESH - Function for plotting wireframe mesh. 3 3 // 4 4 // Usage: 5 // plot_mesh(md, options,canvas);5 // plot_mesh(md, options, canvas); 6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 // declare variables: {{{9 //{{{ declare variables: 10 10 var vertices = []; 11 11 var indices = []; 12 12 var colors = []; 13 13 var nanindices = {}; 14 var xmin, xmax;15 var ymin, ymax;16 var zmin, zmax;17 var scale, matrixscale,vertexscale;14 var xmin, xmax; 15 var ymin, ymax; 16 var zmin, zmax; 17 var scale, matrixscale, vertexscale; 18 18 19 19 //Process data and model 20 var meshresults = processmesh(md,[], options);20 var meshresults = processmesh(md,[], options); 21 21 var x = meshresults[0]; 22 22 var y = meshresults[1]; … … 28 28 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 29 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 31 31 } 32 32 if (md.mesh.classname() == 'mesh3dsurface') { 33 33 matrixscale = 1; 34 vertexscale = options.getfieldvalue('heightscale', 1);34 vertexscale = options.getfieldvalue('heightscale', 1); 35 35 } 36 36 else { … … 38 38 z=md.geometry.surface; 39 39 } 40 matrixscale = options.getfieldvalue('heightscale', 1);40 matrixscale = options.getfieldvalue('heightscale', 1); 41 41 vertexscale = 0; 42 42 } … … 44 44 45 45 //Compute coordinates and data range: 46 var modelxlim = [ArrayMin(x), ArrayMax(x)];47 var modelylim = [ArrayMin(y), ArrayMax(y)];48 var modelzlim = [ArrayMin(z), ArrayMax(z)];49 var xlim = options.getfieldvalue('xlim', modelxlim);50 var ylim = options.getfieldvalue('ylim', modelylim);51 var zlim = options.getfieldvalue('zlim', modelzlim);46 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 47 var modelylim = [ArrayMin(y), ArrayMax(y)]; 48 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 49 var xlim = options.getfieldvalue('xlim', modelxlim); 50 var ylim = options.getfieldvalue('ylim', modelylim); 51 var zlim = options.getfieldvalue('zlim', modelzlim); 52 52 xmin = xlim[0]; 53 53 xmax = xlim[1]; … … 65 65 node.shaderName = "Colored"; 66 66 node.shader = gl.shaders[node.shaderName]; 67 node.lineWidth = options.getfieldvalue('linewidth', 1);67 node.lineWidth = options.getfieldvalue('linewidth', 1); 68 68 node.scale = [1, 1, matrixscale]; 69 69 node.rotation = [-90, 0, 0]; … … 73 73 node.drawOrder = 0; 74 74 node.maskEnabled = options.getfieldvalue('innermask','off') == 'on'; 75 node.maskHeight = options.getfieldvalue('innermaskheight', 150.0)*options.getfieldvalue('heightscale',1);76 node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0,1.0,1.0]);75 node.maskHeight = options.getfieldvalue('innermaskheight', 150.0)*options.getfieldvalue('heightscale', 1); 76 node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]); 77 77 updateModelMatrix(node); 78 78 … … 80 80 var edgecolor = new RGBColor(options.getfieldvalue('edgecolor','black')); 81 81 if (edgecolor.ok) edgecolor = [edgecolor.r/255.0, edgecolor.g/255.0, edgecolor.b/255.0, 1.0]; 82 else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas));82 else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas)); 83 83 84 // node plot {{{84 //{{{ node plot 85 85 if (elements[0].length==6){ //prisms 86 86 } … … 136 136 } 137 137 //}}} 138 node.mesh = GL.Mesh.load({vertices: vertices, colors:colors, triangles:indices}, null, null, gl);138 node.mesh = GL.Mesh.load({vertices: vertices, colors: colors, triangles: indices}, null, null, gl); 139 139 } //}}} -
issm/trunk-jpl/src/m/plot/plot_overlay.js
r21300 r21683 1 function plot_overlay(md, data,options,canvas){ //{{{1 function plot_overlay(md, data, options, canvas){ //{{{ 2 2 //PLOT_OVERLAY - Function for plotting a georeferenced image. 3 3 // 4 4 // Usage: 5 // plot_overlay(md, data,options,canvas);5 // plot_overlay(md, data, options, canvas); 6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 // declare variables: {{{9 //{{{ declare variables: 10 10 var vertices = []; 11 11 var indices = []; 12 12 var texcoords = []; 13 13 var nanindices = {}; 14 var xmin, xmax;15 var ymin, ymax;16 var zmin, zmax;17 var matrixscale, vertexscale;14 var xmin, xmax; 15 var ymin, ymax; 16 var zmin, zmax; 17 var matrixscale, vertexscale; 18 18 19 19 //Process data and model 20 var meshresults = processmesh(md, data,options);20 var meshresults = processmesh(md, data, options); 21 21 var x = meshresults[0]; 22 22 var y = meshresults[1]; … … 28 28 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 29 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 31 31 } 32 32 if (md.mesh.classname() == 'mesh3dsurface') { 33 33 matrixscale = 1; 34 vertexscale = options.getfieldvalue('heightscale', 1);34 vertexscale = options.getfieldvalue('heightscale', 1); 35 35 } 36 36 else { … … 38 38 z=md.geometry.surface; 39 39 } 40 matrixscale = options.getfieldvalue('heightscale', 1);40 matrixscale = options.getfieldvalue('heightscale', 1); 41 41 vertexscale = 0; 42 42 } … … 44 44 45 45 //Compute coordinates and data range: 46 var modelxlim = [ArrayMin(x), ArrayMax(x)];47 var modelylim = [ArrayMin(y), ArrayMax(y)];48 var modelzlim = [ArrayMin(z), ArrayMax(z)];49 var xlim = options.getfieldvalue('xlim', modelxlim);50 var ylim = options.getfieldvalue('ylim', modelylim);51 var zlim = options.getfieldvalue('zlim', modelzlim);46 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 47 var modelylim = [ArrayMin(y), ArrayMax(y)]; 48 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 49 var xlim = options.getfieldvalue('xlim', modelxlim); 50 var ylim = options.getfieldvalue('ylim', modelylim); 51 var zlim = options.getfieldvalue('zlim', modelzlim); 52 52 xmin = xlim[0]; 53 53 xmax = xlim[1]; … … 68 68 node.translation = [0, 0, 0]; 69 69 node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2]; 70 node.texture = initTexture(gl, options.getfieldvalue('overlay_image'));71 node.alpha = options.getfieldvalue('outeralpha', 1.0);70 node.texture = initTexture(gl, options.getfieldvalue('overlay_image')); 71 node.alpha = options.getfieldvalue('outeralpha', 1.0); 72 72 node.drawOrder = 1; 73 73 node.maskEnabled = options.getfieldvalue('outermask','off') == 'on'; 74 node.maskHeight = options.getfieldvalue('outermaskheight', 150.0);75 node.maskColor = options.getfieldvalue('outermaskcolor',[0.0, 0.0,1.0,1.0]);74 node.maskHeight = options.getfieldvalue('outermaskheight', 150.0); 75 node.maskColor = options.getfieldvalue('outermaskcolor',[0.0, 0.0, 1.0, 1.0]); 76 76 updateModelMatrix(node); 77 77 … … 88 88 89 89 //Reclaculate bounds based on otuer radaroverlay 90 modelxlim = [ArrayMin(x), ArrayMax(x)];91 modelylim = [ArrayMin(y), ArrayMax(y)];92 modelzlim = [ArrayMin(z), ArrayMax(z)];90 modelxlim = [ArrayMin(x), ArrayMax(x)]; 91 modelylim = [ArrayMin(y), ArrayMax(y)]; 92 modelzlim = [ArrayMin(z), ArrayMax(z)]; 93 93 xmin = xlim[0]; 94 94 xmax = xlim[1]; … … 159 159 indices[indices.length] = element[2]; 160 160 } 161 node.mesh = GL.Mesh.load({vertices: vertices, coords:texcoords, triangles:indices}, null, null, gl);161 node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords, triangles: indices}, null, null, gl); 162 162 } //}}} -
issm/trunk-jpl/src/m/plot/plot_quiver.js
r21437 r21683 1 function plot_ unit(md,data,datatype,options,canvas) { //{{{2 //PLOT_ UNIT - unit plot, display data1 function plot_quiver(md, options, canvas, updateVel) { //{{{ 2 //PLOT_QUIVER - quiver plot with colors 3 3 // 4 4 // Usage: 5 // plot_ unit(md,data,options,canvas);5 // plot_quiver(md, options, canvas) 6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 //declare variables: {{{ 9 //{{{ declare variables: 10 var vertices = []; 11 var indices = []; 12 var colors = []; 13 var xmin, xmax; 14 var ymin, ymax; 15 var zmin, zmax; 16 var scale, matrixscale, vertexscale; 17 10 18 //Process data and model 11 var meshresults = processmesh(md,data,options); 19 var meshresults = processmesh(md,[], options); 20 12 21 var x = meshresults[0]; 13 22 var y = meshresults[1]; 14 23 var z = meshresults[2]; 15 var elements = meshresults[3]; 24 var elements = meshresults[3]; 16 25 var is2d = meshresults[4]; 17 26 var isplanet = meshresults[5]; 18 19 var vertices = new Float32Array(x.length * 3); 20 var texcoords = new Float32Array(x.length * 2); 21 var indices = new Uint16Array(elements.length * 3); 22 var nanindices = {}; 23 var xmin,xmax; 24 var ymin,ymax; 25 var zmin,zmax; 26 var datamin,datamax,datadelta; 27 var matrixscale,vertexscale; 27 var v = updateVel != undefined ? updateVel.vel : md.initialization.vel; 28 var vx = updateVel != undefined ? updateVel.vx : md.initialization.vx; 29 var vy = updateVel != undefined ? updateVel.vy : md.initialization.vy; 30 28 31 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 32 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);33 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 31 34 } 32 35 if (md.mesh.classname() == 'mesh3dsurface') { 33 36 matrixscale = 1; 34 vertexscale = options.getfieldvalue('heightscale', 1);37 vertexscale = options.getfieldvalue('heightscale', 1); 35 38 } 36 39 else { … … 38 41 z=md.geometry.surface; 39 42 } 40 matrixscale = options.getfieldvalue('heightscale', 1);43 matrixscale = options.getfieldvalue('heightscale', 1); 41 44 vertexscale = 0; 42 45 } … … 44 47 45 48 //Compute coordinates and data range: 46 var modelxlim = [ArrayMin(x), ArrayMax(x)];47 var modelylim = [ArrayMin(y), ArrayMax(y)];48 var modelzlim = [ArrayMin(z), ArrayMax(z)];49 var xlim = options.getfieldvalue('xlim', modelxlim);50 var ylim = options.getfieldvalue('ylim', modelylim);51 var zlim = options.getfieldvalue('zlim', modelzlim);49 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 50 var modelylim = [ArrayMin(y), ArrayMax(y)]; 51 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 52 var xlim = options.getfieldvalue('xlim', modelxlim); 53 var ylim = options.getfieldvalue('ylim', modelylim); 54 var zlim = options.getfieldvalue('zlim', modelzlim); 52 55 xmin = xlim[0]; 53 56 xmax = xlim[1]; … … 56 59 zmin = zlim[0]; 57 60 zmax = zlim[1]; 58 var caxis;59 61 60 62 //Compute gl variables: 61 63 var gl = canvas.gl; 62 64 var node = Node(gl); 63 canvas.nodes[canvas.nodes.length] = node; 64 canvas.unitNode = node; 65 node.name = "unit"; 66 node.shaderName = "Textured"; 65 canvas.nodes["velocity"] = node; 66 node.name = "quiver"; 67 node.shaderName = "Colored"; 67 68 node.shader = gl.shaders[node.shaderName]; 69 node.lineWidth = options.getfieldvalue('linewidth', 1); 68 70 node.scale = [1, 1, matrixscale]; 69 71 node.rotation = [-90, 0, 0]; 70 72 node.translation = [0, 0, 0]; 71 73 node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2]; 72 node.alpha = options.getfieldvalue('alpha',1.0); 73 node.drawOrder = 1; 74 node.drawMode = gl.LINES; 75 node.useIndexBuffer = false; 76 node.drawOrder = 0; 74 77 node.maskEnabled = options.getfieldvalue('innermask','off') == 'on'; 75 node.maskHeight = options.getfieldvalue('innermaskheight',150.0); 76 node.maskColor = options.getfieldvalue('innermaskcolor',[0.0,0.0,1.0,1.0]); 77 node.enabled = options.getfieldvalue('nodata','off') == 'off'; 78 node.maskHeight = options.getfieldvalue('innermaskheight', 150.0)*options.getfieldvalue('heightscale', 1); 79 node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]); 78 80 updateModelMatrix(node); 79 81 80 switch(datatype){ 81 //element plot {{{ 82 case 1: 83 pos=ArrayFindNot(data,NaN); //needed for element on water 84 if (elements[0].length==6){ //prisms 82 //retrieve some options 83 var edgecolor=new RGBColor(options.getfieldvalue('edgecolor','black')); 84 if (edgecolor.ok) edgecolor = [edgecolor.r/255.0, edgecolor.g/255.0, edgecolor.b/255.0, 1.0]; 85 else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas)); 86 87 //{{{ node plot 88 if (elements[0].length==6){ //prisms 89 } 90 else if (elements[0].length==4){ //tetras 91 } 92 else{ //2D triangular elements 93 var xyz = vec3.create(); 94 var xyz = vec3.create(); 95 var direction = vec3.create(); 96 var vertex = vec3.create(); 97 var vertexBase = vec3.create(); 98 var verticesArrow = [vec3.fromValues(0.0, 0.0, 0.0), vec3.fromValues(1.0, 0.0, 0.0), vec3.fromValues(0.667, -0.167, 0.0), vec3.fromValues(1.0, 0.0, 0.0), vec3.fromValues(0.667, 0.166, 0.0), vec3.fromValues(1.0, 0.0, 0.0)]; 99 var magnitude; 100 var color = edgecolor; 101 var scaling = options.getfieldvalue('scaling', 1); 102 var scale; 103 for(var i = 0; i < x.length; i++){ 104 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing 105 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) continue; 106 //Scale vertices 107 xyz = vec3.fromValues(x[i], y[i], z[i]); 108 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; 109 vec3.normalize(direction, xyz); 110 vec3.scale(vertex, direction, magnitude); 111 vec3.copy(vertexBase, vertex); 112 113 scale = scaling*v[i]; 114 var modelMatrix = mat4.create(); 115 var scaleMatrix = mat4.create(); 116 var rotationMatrix = mat4.create(); 117 mat4.scale(scaleMatrix, scaleMatrix, vec3.fromValues(scale, scale, scale)); 118 mat4.rotate(rotationMatrix, rotationMatrix, Math.atan2(vy[i], vx[i]), [0.0, 0.0, 1.0]); 119 mat4.multiply(modelMatrix, rotationMatrix, scaleMatrix); 120 121 var temp = vec3.fromValues(0.0, 0.0, 0.0); 122 for (var j = 0; j < 6; j++){ 123 vec3.transformMat4(vertex, verticesArrow[j], modelMatrix); 124 vec3.add(vertex, vertex, vertexBase); 125 vertices[vertices.length] = vertex[0]; 126 vertices[vertices.length] = vertex[1]; 127 vertices[vertices.length] = vertex[2]; 128 129 colors[colors.length] = color[0]; 130 colors[colors.length] = color[1]; 131 colors[colors.length] = color[2]; 132 colors[colors.length] = color[3]; 85 133 } 86 else if (elements[0].length==4){ //tetras 87 } 88 else{ //2D triangular elements 89 } 90 break; 91 //}}} 92 //node plot {{{ 93 case 2: 94 if (elements[0].length==6){ //prisms 95 } 96 else if (elements[0].length==4){ //tetras 97 } 98 else{ //triangular elements 99 caxis = options.getfieldvalue('caxis',[ArrayMin(data),ArrayMax(data)]); 100 if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log',10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))]; 101 datamin = caxis[0]; 102 datamax = caxis[1]; 103 datadelta = datamax - datamin; 104 105 var xyz = vec3.create(); 106 var direction = vec3.create(); 107 var vertex = vec3.create(); 108 var magnitude; 109 110 for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){ 111 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing 112 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i])) { 113 nanindices[i] = i; 114 vertices[vindex++] = vertex[0]; 115 vertices[vindex++] = vertex[1]; 116 vertices[vindex++] = vertex[2]; 117 118 texcoords[tindex++] = 0.5; 119 texcoords[tindex++] = 0.0; 120 continue; 121 } 122 123 //Scale vertices 124 xyz = vec3.fromValues(x[i], y[i], z[i]); 125 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; 126 vec3.normalize(direction, xyz); 127 vec3.scale(vertex, direction, magnitude); 128 vertices[vindex++] = vertex[0]; 129 vertices[vindex++] = vertex[1]; 130 vertices[vindex++] = vertex[2]; 131 132 texcoords[tindex++] = 0.5; 133 texcoords[tindex++] = clamp((data[i] - datamin) / datadelta, 0.0, 1.0); 134 } 135 136 //linearize the elements array: 137 var element; 138 for(var i = 0, iindex = 0; i < elements.length; i++){ 139 element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; 140 if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; 141 indices[iindex++] = element[0]; 142 indices[iindex++] = element[1]; 143 indices[iindex++] = element[2]; 144 } 145 } 146 node.mesh = GL.Mesh.load({vertices:vertices, coords:texcoords, triangles:indices}, null, null, gl); 147 node.mesh.octree = new GL.Octree(node.mesh); 148 break; 149 //}}} 150 //quiver plot {{{ 151 case 3: 152 if (is2d){ 153 //plot_quiver(x,y,data(:,1),data(:,2),options); 154 } 155 else{ 156 //plot_quiver3(x,y,z,data(:,1),data(:,2),data(:,3),options); 157 } 158 break; 159 //}}} 160 //node transient plot {{{ 161 case 5: 162 if (elements[0].length==6){ //prisms 163 } 164 else if (elements[0].length==4){//tetras 165 } 166 else{ //triangular elements 167 var xyz = vec3.create(); 168 var direction = vec3.create(); 169 var vertex = vec3.create(); 170 var magnitude; 171 var timestamps = data[data.length-1]; 172 for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){ 173 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing 174 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i][0])) { 175 nanindices[i] = i; 176 } 177 else { 178 //Scale vertices 179 xyz = vec3.fromValues(x[i], y[i], z[i]); 180 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; 181 vec3.normalize(direction, xyz); 182 vec3.scale(vertex, direction, magnitude); 183 } 184 vertices[vindex++] = vertex[0]; 185 vertices[vindex++] = vertex[1]; 186 vertices[vindex++] = vertex[2]; 187 } 188 //Transpose data to obtain column addressable data matrix 189 data = data[0].map(function(col, i) { 190 return data.map(function(row) { 191 return row[i] 192 }) 193 }); 194 //Prevent evaluation of datasubarray min/max if caxis exists 195 if (options.exist('caxis')) caxis = options.getfieldvalue('caxis'); 196 else caxis = [ArrayMin(data[0]),ArrayMax(data[0].slice(0,-1))]; 197 if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log',10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))]; 198 //Prepare texcoords to hold array of data values 199 texcoords = []; 200 for(var i = 0; i < data.length; i++){ 201 datamin = caxis[0]; 202 datamax = caxis[1]; 203 datadelta = datamax - datamin; 204 //Precalculate arrays for each datasubarray, trimming off timestamp value by using x.length instead of data[i].length 205 texcoords[i] = new Float32Array(x.length * 2); 206 for(var j = 0, index = 0; j < x.length; j++){ 207 texcoords[i][index++] = 0.5; 208 texcoords[i][index++] = clamp((data[i][j] - datamin) / datadelta, 0.0, 1.0); 209 } 210 } 211 212 //linearize the elements array: 213 var element; 214 for(var i = 0, iindex = 0; i < elements.length; i++){ 215 element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; 216 if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; 217 indices[iindex++] = element[0]; 218 indices[iindex++] = element[1]; 219 indices[iindex++] = element[2]; 220 } 221 var frame = 222 //Initialize movie loop 223 node.movieLoop = canvas.movieOptions.loop; 224 node.movieInterval = 1000 / canvas.movieOptions.fps; 225 node.movieTimestamps = timestamps; 226 node.movieLength = timestamps.length; 227 node.movieFrame = 0; 228 229 var quiverVelFrames = {}; 230 for(var i=0; i < md.results.length; i++){ 231 quiverVelFrames[Math.floor(md.results[i].time)] = md.results[i]; 232 } 233 234 if (canvas.movieHandler) { clearInterval(canvas.movieHandler); } 235 canvas.movieHandler = setInterval(function () { 236 node.movieFrame = canvas.movieFrame; 237 if (canvas.moviePlay && canvas.movieIncrement) { 238 if (canvas.movieReverse) { 239 if (node.movieFrame == 0) { 240 if (node.movieLoop) { 241 node.movieFrame = node.movieLength - 1; 242 } 243 else { 244 toggleMoviePlay(canvas); 245 } 246 } 247 else { 248 node.movieFrame = node.movieFrame - 1; 249 } 250 } 251 else { 252 if (node.movieFrame == node.movieLength - 1) { 253 if (node.movieLoop) { 254 node.movieFrame = 0; 255 } 256 else { 257 toggleMoviePlay(canvas); 258 } 259 } 260 else { 261 node.movieFrame = node.movieFrame + 1; 262 } 263 } 264 } 265 if (canvas.progressBar) { 266 canvas.progressBar.val(node.movieFrame); 267 canvas.progressBar.slider('refresh'); 268 } 269 if (canvas.timeLabel) { canvas.timeLabel.html(node.movieTimestamps[node.movieFrame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); } 270 271 var buffer = node.mesh.getBuffer("coords"); 272 buffer.data = texcoords[node.movieFrame]; 273 buffer.upload(canvas.gl.DYNAMIC_DRAW); 274 node.mesh.octree = new GL.Octree(node.mesh); 275 276 if(options.getfieldvalue('quiver') == 'data'){ 277 plot_quiver(md,options,canvas, {vel:quiverVelFrames[node.movieFrame].Vel, vx:quiverVelFrames[node.movieFrame].Vx, vy:quiverVelFrames[node.movieFrame].Vy}); 278 279 } 280 canvas.movieFrame = node.movieFrame; 281 }, node.movieInterval); 282 if (canvas.progressBar) { 283 canvas.movieFrame = 0; 284 canvas.progressBar.val(0); 285 canvas.progressBar.attr('max', node.movieLength-1); 286 canvas.progressBar.slider('refresh'); 287 } 288 289 } 290 node.mesh = GL.Mesh.load({vertices:vertices, coords:texcoords[0], triangles:indices}, null, null, gl); 291 node.mesh.octree = new GL.Octree(node.mesh); 292 break; 293 //}}} 294 default: 295 throw Error(sprintf("%s%i%s\n",'case ',datatype,' not supported')); 134 } 296 135 } 136 //}}} 137 node.mesh = GL.Mesh.load({vertices: vertices, colors: colors}, null, null, gl); 297 138 } //}}} -
issm/trunk-jpl/src/m/plot/plot_unit.js
r21641 r21683 1 function plot_unit(md, data,datatype,options,canvas){1 function plot_unit(md, data, datatype, options, canvas) { //{{{ 2 2 //PLOT_UNIT - unit plot, display data 3 3 // 4 4 // Usage: 5 // plot_unit(md, data,options,canvas);5 // plot_unit(md, data, options, canvas); 6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 // declare variables: {{{9 //{{{ declare variables: 10 10 //Process data and model 11 var meshresults = processmesh(md, data,options);11 var meshresults = processmesh(md, data, options); 12 12 var x = meshresults[0]; 13 13 var y = meshresults[1]; … … 21 21 var indices = new Uint16Array(elements.length * 3); 22 22 var nanindices = {}; 23 var xmin, xmax;24 var ymin, ymax;25 var zmin, zmax;26 var datamin, datamax,datadelta;27 var matrixscale, vertexscale;23 var xmin, xmax; 24 var ymin, ymax; 25 var zmin, zmax; 26 var datamin, datamax, datadelta; 27 var matrixscale, vertexscale; 28 28 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 29 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 31 31 } 32 32 if (md.mesh.classname() == 'mesh3dsurface') { 33 33 matrixscale = 1; 34 vertexscale = options.getfieldvalue('heightscale', 1);34 vertexscale = options.getfieldvalue('heightscale', 1); 35 35 } 36 36 else { … … 38 38 z=md.geometry.surface; 39 39 } 40 matrixscale = options.getfieldvalue('heightscale', 1);40 matrixscale = options.getfieldvalue('heightscale', 1); 41 41 vertexscale = 0; 42 42 } … … 44 44 45 45 //Compute coordinates and data range: 46 var modelxlim = [ArrayMin(x), ArrayMax(x)];47 var modelylim = [ArrayMin(y), ArrayMax(y)];48 var modelzlim = [ArrayMin(z), ArrayMax(z)];49 var xlim = options.getfieldvalue('xlim', modelxlim);50 var ylim = options.getfieldvalue('ylim', modelylim);51 var zlim = options.getfieldvalue('zlim', modelzlim);46 var modelxlim = [ArrayMin(x), ArrayMax(x)]; 47 var modelylim = [ArrayMin(y), ArrayMax(y)]; 48 var modelzlim = [ArrayMin(z), ArrayMax(z)]; 49 var xlim = options.getfieldvalue('xlim', modelxlim); 50 var ylim = options.getfieldvalue('ylim', modelylim); 51 var zlim = options.getfieldvalue('zlim', modelzlim); 52 52 xmin = xlim[0]; 53 53 xmax = xlim[1]; … … 71 71 node.translation = [0, 0, 0]; 72 72 node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2]; 73 node.alpha = options.getfieldvalue('alpha', 1.0);73 node.alpha = options.getfieldvalue('alpha', 1.0); 74 74 node.drawOrder = 1; 75 75 node.maskEnabled = options.getfieldvalue('innermask','off') == 'on'; 76 node.maskHeight = options.getfieldvalue('innermaskheight', 150.0);77 node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0,1.0,1.0]);76 node.maskHeight = options.getfieldvalue('innermaskheight', 150.0); 77 node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]); 78 78 node.enabled = options.getfieldvalue('nodata','off') == 'off'; 79 79 updateModelMatrix(node); 80 80 81 81 switch(datatype){ 82 // element plot {{{82 //{{{ element plot 83 83 case 1: 84 pos=ArrayFindNot(data, NaN); //needed for element on water84 pos=ArrayFindNot(data, NaN); //needed for element on water 85 85 if (elements[0].length==6){ //prisms 86 86 } … … 91 91 break; 92 92 //}}} 93 // node plot {{{93 //{{{ node plot 94 94 case 2: 95 95 if (elements[0].length==6){ //prisms … … 98 98 } 99 99 else{ //triangular elements 100 caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]);101 if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))];100 caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]); 101 if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10)), Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log', 10))]; 102 102 datamin = caxis[0]; 103 103 datamax = caxis[1]; … … 145 145 } 146 146 } 147 node.mesh = GL.Mesh.load({vertices: vertices, coords:texcoords, triangles:indices}, null, null, gl);147 node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords, triangles: indices}, null, null, gl); 148 148 node.mesh.octree = new GL.Octree(node.mesh); 149 149 break; 150 150 //}}} 151 // quiver plot {{{151 //{{{ quiver plot 152 152 case 3: 153 153 if (is2d){ 154 //plot_quiver(x, y,data(:,1),data(:,2),options);154 //plot_quiver(x, y, data(:, 1), data(:, 2), options); 155 155 } 156 156 else{ 157 //plot_quiver3(x, y,z,data(:,1),data(:,2),data(:,3),options);158 } 159 break; 160 //}}} 161 // node transient plot {{{157 //plot_quiver3(x, y, z, data(:, 1), data(:, 2), data(:, 3), options); 158 } 159 break; 160 //}}} 161 //{{{ node transient plot 162 162 case 5: 163 163 if (elements[0].length==6){ //prisms … … 195 195 //Prevent evaluation of datasubarray min/max if caxis exists 196 196 if (options.exist('caxis')) caxis = options.getfieldvalue('caxis'); 197 else caxis = [ArrayMin(data[0]), ArrayMax(data[0].slice(0,-1))];198 if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))];197 else caxis = [ArrayMin(data[0]), ArrayMax(data[0].slice(0,-1))]; 198 if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10)), Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log', 10))]; 199 199 //Prepare texcoords to hold array of data values 200 200 texcoords = []; … … 222 222 223 223 //Initialize movie loop 224 node.movieLoop = canvas. movieOptions.loop;225 node.movieInterval = 1000 / canvas. movieOptions.fps;224 node.movieLoop = canvas.animation.loop; 225 node.movieInterval = 1000 / canvas.animation.fps; 226 226 node.movieTimestamps = timestamps; 227 227 node.movieLength = timestamps.length; 228 228 node.movieFrame = 0; 229 canvas.data Array= [];229 canvas.dataMarkers.values = []; 230 230 var quiverVelFrames = {}; 231 231 for(var i=0; i < md.results.length; i++){ … … 233 233 } 234 234 235 if (canvas.movieHandler) { clearInterval(canvas.movieHandler); } 236 canvas.movieHandler = setInterval(function () { 237 node.movieFrame = canvas.movieFrame; 238 if (canvas.moviePlay && canvas.movieIncrement) { 239 if (canvas.movieReverse) { 240 if (node.movieFrame == 0) { 241 if (node.movieLoop) { 242 node.movieFrame = node.movieLength - 1; 243 } 244 else { 245 toggleMoviePlay(canvas); 246 } 247 } 248 else { 249 node.movieFrame = node.movieFrame - 1; 250 } 235 if (canvas.animation.handler !== 0) { 236 console.log("clearing..."); 237 clearInterval(canvas.animation.handler) 238 } 239 //TODO: Move this into webgl.js 240 canvas.animation.handler = setInterval(function () { 241 node.movieFrame = canvas.animation.frame; 242 if (canvas.animation.play && canvas.animation.increment) { 243 if (node.movieFrame == node.movieLength - 1) { 244 if (node.movieLoop) { 245 node.movieFrame = 0; 251 246 } 252 247 else { 253 if (node.movieFrame == node.movieLength - 1) { 254 if (node.movieLoop) { 255 node.movieFrame = 0; 256 } 257 else { 258 toggleMoviePlay(canvas); 259 } 260 } 261 else { 262 node.movieFrame = node.movieFrame + 1; 263 } 248 toggleMoviePlay(canvas); 264 249 } 265 250 } 266 if (canvas.progressBar) { 267 canvas.progressBar.val(node.movieFrame); 268 canvas.progressBar.slider('refresh'); 251 else { 252 node.movieFrame = node.movieFrame + 1; 269 253 } 270 if (canvas.timeLabel) { canvas.timeLabel.html(node.movieTimestamps[node.movieFrame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); } 271 272 var buffer = node.mesh.getBuffer("coords"); 273 buffer.data = texcoords[node.movieFrame]; 274 buffer.upload(canvas.gl.DYNAMIC_DRAW); 275 node.mesh.octree = new GL.Octree(node.mesh); 276 node.texcoords = texcoords; 277 if(options.getfieldvalue('quiver') == 'on'){ 278 plot_quiver(md,options,canvas, {vel:quiverVelFrames[node.movieFrame].Vel, vx:quiverVelFrames[node.movieFrame].Vx, vy:quiverVelFrames[node.movieFrame].Vy}); 279 254 if (canvas.animation.lastFrame != canvas.animation.frame) { 255 updateMarker(canvas, false); 280 256 } 281 canvas.movieFrame = node.movieFrame; 282 283 if (canvas.moviePlay || canvas.lastMovieFrame != canvas.movieFrame) { 284 updatePlot(true); 285 } 286 287 }, node.movieInterval); 257 } 258 259 if (canvas.progressBar) { 260 canvas.progressBar.val(node.movieFrame); 261 canvas.progressBar.slider('refresh'); 262 } 263 if (canvas.timeLabel) { canvas.timeLabel.html(node.movieTimestamps[node.movieFrame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); } 264 265 var buffer = node.mesh.getBuffer("coords"); 266 buffer.data = texcoords[node.movieFrame]; 267 buffer.upload(canvas.gl.DYNAMIC_DRAW); 268 node.mesh.octree = new GL.Octree(node.mesh); 269 node.texcoords = texcoords; 270 if(options.getfieldvalue('quiver') == 'on'){ 271 plot_quiver(md, options, canvas, {vel: quiverVelFrames[node.movieFrame].Vel, vx: quiverVelFrames[node.movieFrame].Vx, vy: quiverVelFrames[node.movieFrame].Vy}); 272 } 273 canvas.animation.lastFrame = canvas.animation.frame; 274 canvas.animation.frame = node.movieFrame; 275 }, node.movieInterval); 276 288 277 if (canvas.progressBar) { 289 canvas. movieFrame = 0;278 canvas.animation.frame = 0; 290 279 canvas.progressBar.val(0); 291 280 canvas.progressBar.attr('max', node.movieLength-1); … … 294 283 295 284 } 296 node.mesh = GL.Mesh.load({vertices: vertices, coords:texcoords[0], triangles:indices}, null, null, gl);285 node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords[0], triangles: indices}, null, null, gl); 297 286 node.mesh.octree = new GL.Octree(node.mesh); 298 287 break; 299 288 //}}} 300 289 default: 301 throw Error(sprintf("%s%i%s\n",'case ', datatype,' not supported'));302 } 303 } 290 throw Error(sprintf("%s%i%s\n",'case ', datatype,' not supported')); 291 } 292 } //}}} -
issm/trunk-jpl/src/m/plot/slider.js
r21300 r21683 63 63 callback(parseFloat($(selector).val())); 64 64 }); 65 66 /* 67 NOTE: Slider must be "refreshed" after any JavaScript change to it, as 68 it is an AJAX object. 69 */ 70 $(selector).slider('refresh'); 65 $(selector).slider('refresh'); //Slider must be "refreshed" after any JavaScript change to it, as it is an AJAX object. 71 66 } //}}} 72 67 … … 89 84 */ 90 85 $(selector).appendTo(selector + '-value'); 91 92 /* 93 NOTE: Slider must be "refreshed" after any JavaScript change to it, as 94 it is an AJAX object. 95 */ 96 $(selector).slider('refresh'); 86 $(selector).slider('refresh'); //Slider must be "refreshed" after any JavaScript change to it, as it is an AJAX object. 97 87 } //}}} 98 88 … … 130 120 $(progressBar).attr('max', 1); 131 121 $(progressBar).attr('step', 1); 132 $(progressBar).on('slidestop', function(event, ui){ 133 canvas.movieIncrement = true; 134 canvas.movieFrame = parseInt($(progressBar).val()); 122 $(progressBar).on('slidestart', function(event, ui){ 123 onSlideStart(canvas, progressBar); 135 124 }); 136 125 $(progressBar).on('change', function(event, ui){ 137 canvas.movieFrame = parseInt($(progressBar).val());126 onSlideChange(canvas, progressBar); 138 127 }); 139 $(progressBar).on('slidestart', function(event, ui){ 140 canvas.movieIncrement = false; 141 canvas.movieFrame = parseInt($(progressBar).val()); 128 $(progressBar).on('slidestop', function(event, ui){ 129 onSlideStop(canvas, progressBar); 142 130 }); 143 144 /* 145 NOTE: Slider must be "refreshed" after any JavaScript change to it, as 146 it is an AJAX object. 147 */ 148 $(progressBar).slider('refresh'); 149 150 // Attach progress bar slider to simulation. 151 canvas.progressBar = progressBar; 131 $(progressBar).slider('refresh'); //Slider must be "refreshed" after any JavaScript change to it, as it is an AJAX object. 152 132 153 133 playButton.click(function(){ 154 canvas.moviePlay = !canvas.moviePlay; 155 if (canvas.moviePlay){ 156 playButton.find("span").removeClass("fa-play"); 157 playButton.find("span").addClass("fa-pause"); 158 } 159 else{ 160 playButton.find("span").removeClass("fa-pause"); 161 playButton.find("span").addClass("fa-play"); 162 } 134 toggleMoviePlay(canvas); 163 135 }); 164 136 137 canvas.progressBar = progressBar; 138 canvas.playButton = playButton; 165 139 canvas.timeLabel = timeText; 166 140 } //}}} -
issm/trunk-jpl/src/m/plot/webgl.js
r21641 r21683 1 1 /*This is where we have all our webgl relevant functionality for the plotting routines: */ 2 3 /*This is where we have all our webgl relevant functionality for the plotting routines: */4 5 2 //{{{ Canvas Initialization 6 3 function initCanvas(options) { 7 //Initialize open Gl for each canvas , if needed:4 //Initialize open Gl for each canvas and clear any previous animation handlers, once per plotmodel call: 8 5 canvas = document.getElementById(options.getfieldvalue('canvasid')); 9 6 //var canvas = document.getElementById(options.getfieldvalue('canvasid')); 10 7 if (!canvas.initialized) { 11 8 typedArraySliceSupport(); 12 canvas.gl = initWebGL(canvas,options); 9 if (!isEmptyOrUndefined(canvas.draw) && canvas.draw.handler !== 0) { window.cancelAnimationFrame(canvas.draw.handler); } 10 if (!isEmptyOrUndefined(canvas.animation) && canvas.animation.handler !== 0) { clearInterval(canvas.animation.handler); } 11 initWebGL(canvas, options); 12 initializeMarker(canvas); 13 13 canvas.nodes = []; 14 if (canvas.drawHandler) { window.cancelAnimationFrame(canvas.drawHandler); } 15 draw(canvas,options); 14 draw(canvas); 16 15 canvas.initialized = true; 17 16 } 18 17 return canvas; 19 18 } 20 function initWebGL(canvas,options) { //{{{ 19 function initWebGL(canvas, options) { //{{{ 20 //Initialize canvas.gl on page load, reusing gl context on additional runs 21 21 var gl; 22 try { 23 if (!canvas.gl) { 24 gl = GL.create({canvas:canvas}); 25 // Enable depth testing 26 gl.enable(gl.DEPTH_TEST); 27 // Near things obscure far things 28 gl.depthFunc(gl.LEQUAL); 29 // Enable color blending/overlay 30 gl.enable(gl.BLEND); 31 // Enable face culling 32 gl.enable(gl.CULL_FACE); 33 gl.cullFace(gl.FRONT); 34 // Load shaders and store them in gl object 35 gl.shaders = loadShaders(gl,options.getfieldvalue('rootpath','../../../js/')); 36 37 // Add event listeners for canvas 38 var displayview = options.getfieldvalue('displayview','off') == 'on'; 39 var displayzoom = options.getfieldvalue('displayzoom','off') == 'on'; 40 var mc = new Hammer.Manager(canvas); 41 42 mc.add( new Hammer.Tap({ event: 'singletap' }) ); 43 mc.add(new Hammer.Pan({threshold:0, pointers:0})); 44 mc.add(new Hammer.Pinch({threshold:0})).recognizeWith(mc.get('pan')); 45 mc.on('singletap', function (ev) {onTap(ev,canvas);}); 46 mc.on('panstart panmove', function (ev) {onPan(ev,canvas,displayview);}); 47 mc.on('pinchstart pinchmove', function (ev) {onPinch(ev,canvas,displayview);}); 48 49 //canvas.addEventListener('mousemove', function (ev) {onTap(ev,canvas);}, false); 50 canvas.addEventListener('mousewheel', function (ev) {onZoom(ev,canvas,displayzoom)}, false); 51 canvas.addEventListener('DOMMouseScroll', function (ev) {onZoom(ev,canvas,displayzoom)}, false); 52 } 53 else { 54 gl = canvas.gl; 55 } 56 } 57 catch(e) { 58 console.log(e); 59 return; 22 if (!canvas.gl) { 23 gl = GL.create({canvas: canvas}); 24 gl.enable(gl.DEPTH_TEST); // Enable depth testing 25 gl.depthFunc(gl.LEQUAL); // Near things obscure far things 26 gl.enable(gl.BLEND); // Enable color blending/overlay 27 gl.enable(gl.CULL_FACE); // Enable face culling 28 gl.cullFace(gl.FRONT); 29 gl.shaders = loadShaders(gl, options.getfieldvalue('rootpath', '../../../js/')); // Load shaders and store them in gl object 30 gl.textures = {}; 31 32 // Add event listeners for canvas 33 var displayview = options.getfieldvalue('displayview', 'off') == 'on'; 34 var displayzoom = options.getfieldvalue('displayzoom', 'off') == 'on'; 35 var mc = new Hammer.Manager(canvas); 36 37 mc.add( new Hammer.Tap({event: 'singletap' }) ); 38 mc.add(new Hammer.Pan({threshold: 0, pointers: 0})); 39 mc.add(new Hammer.Pinch({threshold: 0})).recognizeWith(mc.get('pan')); 40 mc.on('singletap', function (ev) {onTap(ev, canvas);}); 41 mc.on('panstart panmove', function (ev) {onPan(ev, canvas, displayview);}); 42 mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);}); 43 44 canvas.addEventListener('mousewheel', function (ev) {onZoom(ev, canvas, displayzoom)}, false); 45 canvas.addEventListener('DOMMouseScroll', function (ev) {onZoom(ev, canvas, displayzoom)}, false); 46 } 47 else { 48 gl = canvas.gl; 60 49 } 61 50 62 51 // Add context state variables 63 //TODO:Group variables in objects for organization and naming64 52 canvas.gl = gl; 65 canvas.rootPath = options.getfieldvalue('rootpath','../../../js/'); 66 canvas.brush = options.getfieldvalue('brush',{'enabled':'off','strength':0.075,'falloff':0.5}); 67 canvas.cameraPosition = vec3.create(); 68 canvas.cameraMatrix = mat4.create(); 69 canvas.controlSensitivity = options.getfieldvalue('controlsensitivity',1); 70 canvas.dataArray = []; 71 canvas.dataMarkersAllowed = options.getfieldvalue('datamarkers','off') == 'on'; 72 canvas.dataMarkersEnabled = true; //if data marker feature is on, user can toggle feature on and off 73 canvas.dataMarkerImage = options.getfieldvalue('datamarkers_image',canvas.rootPath+'textures/data_marker.svg'); 74 canvas.dataMarkerSize = options.getfieldvalue('datamarkerssize',[32,32]); 75 canvas.dataMarkerOptions = options.getfieldvalue('datamarkersoptions',{'enabled':'on','image':canvas.rootPath+'textures/data_marker.svg','size':[32,32],'format':['X: %.2e<br>Y: %.2e<br>Z: %.2e]<br>Value: %0.1f','x','y','z','value'],'animated':false}); 76 canvas.inverseCameraMatrix = mat4.create(); 77 canvas.id = options.getfieldvalue('canvasid','.sim-canvas'); 78 canvas.movieFrame = 0; 79 canvas.moviePlay = true; 80 canvas.movieReverse = false; 81 canvas.movieIncrement = true; 82 canvas.movieOptions = options.getfieldvalue('movieoptions',{'fps':4,'loop':true}); 83 canvas.moviefps = options.getfieldvalue('moviefps',5); 84 canvas.rotation = options.getfieldvalue('view',[0,90]); //0 azimuth, 90 elevation 85 canvas.rotationAzimuthBounds = options.getfieldvalue('azlim',[0,360]); 86 canvas.rotationElevationBounds = options.getfieldvalue('ellim',[-180,180]); 87 canvas.translation = options.getfieldvalue('origin',[0,0,0]); 88 canvas.twod = options.getfieldvalue('2d','off') == 'on'; 89 canvas.view = options.getfieldvalue('view',[0,90]); 90 canvas.viewPanning = options.getfieldvalue('enablepanning','off') == 'on'; 91 canvas.vInverseMatrix = mat4.create(); 92 canvas.zoomBounds = options.getfieldvalue('zoomlim',[0.001,100.0]); 93 canvas.zoom = clamp(options.getfieldvalue('zoom',1.0), canvas.zoomBounds[0], canvas.zoomBounds[1]); 94 canvas.zoomLast = canvas.zoom; 95 var backgroundcolor = new RGBColor(options.getfieldvalue('backgroundcolor','lightcyan')); 53 canvas.textcanvas = null; 54 canvas.overlaycanvas = null; 55 canvas.unitNode = {}; 56 canvas.unitData = {}; 57 canvas.controlSensitivity = options.getfieldvalue('controlsensitivity', 1); 58 canvas.id = options.getfieldvalue('canvasid', '.sim-canvas'); 59 canvas.rootPath = options.getfieldvalue('rootpath', '../../../js/'); 60 canvas.selector = $('#' + canvas.id); 61 var backgroundcolor = new RGBColor(options.getfieldvalue('backgroundcolor', 'lightcyan')); 96 62 if (backgroundcolor.ok) { canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0]; } 97 else { throw Error(sprintf('s%s%s\n','initWebGL error message: cound not find out background color for curent canvas ',canvas)); } 98 63 else { throw Error(sprintf('s%s%s\n','initWebGL error message: cound not find out background color for curent canvas ', canvas)); } 64 65 //Property intiialization, using values from options first, then from default values. 66 var animation = options.getfieldvalue('movies', {}); 67 canvas.animation = { 68 frame: defaultFor(animation.frame, 0), 69 play: defaultFor(animation.play, true), 70 increment: defaultFor(animation.increment, true), 71 fps: defaultFor(animation.fps, 4), 72 loop: defaultFor(animation.loop, true), 73 handler: defaultFor(animation.handler, 0) 74 } 75 var brush = options.getfieldvalue('brush', {}); 76 canvas.brush = { 77 enabled: defaultFor(brush.enabled, false), 78 strength: defaultFor(brush.strength, 0.075), 79 falloff: defaultFor(brush.falloff, 0.5), 80 hit: defaultFor(brush.hit, {}) 81 }; 82 var camera = options.getfieldvalue('camera', {}); 83 canvas.camera = { 84 position: defaultFor(camera.position, vec3.create()), 85 rotation: defaultFor(camera.rotation, vec3.create()), 86 near: defaultFor(camera.near, 1e3), 87 far: defaultFor(camera.far, 1e10), 88 fov: defaultFor(camera.fov, 45), 89 vMatrix: defaultFor(camera.vMatrix, mat4.create()), 90 pMatrix: defaultFor(camera.pMatrix, mat4.create()), 91 vpMatrix: defaultFor(camera.vpMatrix, mat4.create()), 92 vInverseMatrix: defaultFor(camera.vInverseMatrix, mat4.create()), 93 pInverseMatrix: defaultFor(camera.pInverseMatrix, mat4.create()), 94 vpInverseMatrix: defaultFor(camera.vpInverseMatrix, mat4.create()), 95 ready: defaultFor(camera.ready, false) 96 }; 97 var clouds = options.getfieldvalue('clouds', {}); 98 canvas.clouds = { 99 enabled: defaultFor(clouds.enabled, false), 100 height: defaultFor(clouds.height, 7500), 101 quantity: defaultFor(clouds.quantity, 10) 102 }; 103 var dataMarkers = options.getfieldvalue('datamarkers', {}); 104 canvas.dataMarkers = { 105 enabled: defaultFor(dataMarkers.enabled, true), 106 values: defaultFor(dataMarkers.values, []), 107 image: defaultFor(dataMarkers.image, canvas.rootPath+'textures/data_marker.svg'), 108 size: defaultFor(dataMarkers.size, [32, 32]), 109 format: defaultFor(dataMarkers.format, ['X: %.2e<br>Y: %.2e<br>Z: %.2e<br>Value: %0.1f', 'x', 'y', 'z', 'value']), 110 animated: defaultFor(dataMarkers.animated, false), 111 labels: defaultFor(dataMarkers.labels, []), 112 font: defaultFor(dataMarkers.font, ''), 113 marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id)) 114 }; 115 var draw = options.getfieldvalue('draw', {}); 116 canvas.draw = { 117 ready: defaultFor(draw.ready, false), 118 handler: defaultFor(draw.handler, null) 119 }; 120 var view = options.getfieldvalue('view', {}); 121 canvas.view = { 122 position: defaultFor(view.position, [0.0, 0.0, 0.0]), 123 rotation: defaultFor(view.rotation, [0, 90]), 124 zoom: defaultFor(view.zoom, 1.0), 125 zoomLimits: defaultFor(view.zoomLimits, [0.001, 100.0]), 126 lastZoom: defaultFor(view.lastZoom, 1.0), 127 azimuthLimits: defaultFor(view.azimuthLimits, [0, 360]), 128 elevationLimits: defaultFor(view.elevationLimits, [-180, 180]), 129 panningEnabled: defaultFor(view.panningEnabled, false), 130 twod: defaultFor(view.twod, false) 131 }; 132 133 //Override with parameters from URL, if any 99 134 //TODO: Make permalinks more robust and less interdependent on UI 100 //Override with parameters from URL, if any101 135 if (!canvas.usedparemters) { 102 136 function getJsonFromUrl() { 103 137 var query = location.search.substr(1); 104 138 var result = {}; 105 query.split( "&").forEach(function(part) {106 var item = part.split( "=");139 query.split('&').forEach(function(part) { 140 var item = part.split('='); 107 141 result[item[0]] = decodeURIComponent(item[1]); 108 142 }); … … 111 145 parameters = getJsonFromUrl(); 112 146 113 if (parameters["rotation"]) { 114 canvas.rotation = JSON.parse(parameters["rotation"]); 115 } 116 if (parameters["view"]) { 117 canvas.view = JSON.parse(parameters["view"]); 118 } 119 if (parameters["zoom"]) { 120 canvas.zoom = JSON.parse(parameters["zoom"]); 121 } 122 if (parameters["initial"]) { 123 initial = JSON.parse(parameters["initial"]); 147 if (parameters['view']) { 148 canvas.view = JSON.parse(parameters['view']); 149 } 150 if (parameters['initial']) { 151 initial = JSON.parse(parameters['initial']); 124 152 if (!initial) { 125 153 if (typeof SolveGlacier == 'function') { … … 133 161 canvas.usedparemters = true; 134 162 } 135 136 return gl;137 163 } //}}} 138 164 function generatePermalink() { //{{{ 139 var permalink = window.location.origin + window.location.pathname + "?rotation=" + JSON.stringify(canvas.rotation) + "&view=" + JSON.stringify(canvas.view) + "&zoom=" + JSON.stringify(canvas.zoom) + "&initial="+ JSON.stringify(initial);140 window.prompt( "Share this simulation: ", permalink);141 } //}}} 142 function loadShaders(gl, rootPath) { //{{{165 var permalink = window.location.origin + window.location.pathname + '&view=' + JSON.stringify(canvas.view) + '&initial=' + JSON.stringify(initial); 166 window.prompt('Share this simulation: ', permalink); 167 } //}}} 168 function loadShaders(gl, rootPath) { //{{{ 143 169 var shaders = {}; 144 170 shaders.Colored = new GL.Shader.fromURL(rootPath+'shaders/Colored.vsh', rootPath+'shaders/Colored.fsh', null, gl); … … 146 172 shaders.SkyFromSpace = new GL.Shader.fromURL(rootPath+'shaders/SkyFromSpace.vert', rootPath+'shaders/SkyFromSpace.frag', null, gl); 147 173 shaders.GroundFromSpace = new GL.Shader.fromURL(rootPath+'shaders/GroundFromSpace.vert', rootPath+'shaders/GroundFromSpace.frag', null, gl); 174 shaders.Clouds = new GL.Shader.fromURL(rootPath+'shaders/Clouds.vert', rootPath+'shaders/Clouds.frag', null, gl); 148 175 return shaders; 149 176 } //}}} 150 function initTexture(gl,imageSource) { //{{{ 151 return GL.Texture.fromURL(imageSource, {minFilter:gl.LINEAR_MIPMAP_LINEAR, magFilter:gl.LINEAR}, null, gl); 177 function initTexture(gl, imageSource) { //{{{ 178 //Initialize textures, or load from memory if they already exist. 179 if (isEmptyOrUndefined(gl.textures[imageSource])) { 180 gl.textures[imageSource] = GL.Texture.fromURL(imageSource, {minFilter: gl.LINEAR_MIPMAP_LINEAR, magFilter: gl.LINEAR}, null, gl); 181 } 182 return gl.textures[imageSource]; 152 183 } //}}} 153 184 function Node(gl) { //{{{ 154 185 //Returns a Node object that contains default display states for webgl object. center represents pivot point of rotation. 155 186 return { 156 alpha: 1.0,157 buffers: [],158 cullFace: gl.BACK,159 disableDepthTest: false,160 drawMode: gl.TRIANGLES,161 drawOrder: 0,162 enabled: true,163 enableCullFace: true,164 hideOcean: false,165 lineWidth: 1.0,166 maskEnabled: false,167 maskHeight: 150.0,168 maskColor: vec4.fromValues(0.0, 0.0, 1.0, 1.0),169 mesh: null,170 name: 'node',171 shaderName: 'Colored',172 shader: gl.shaders.Colored,173 texture: null,174 useIndexBuffer: true,175 center: vec3.create(),176 scale: vec3.fromValues(1, 1, 1),177 rotation: vec3.create(),178 translation: vec3.create(),179 modelMatrix: mat4.create(),180 rotationMatrix: mat4.create(),181 inverseModelMatrix: mat4.create(),182 inverseRotationMatrix: mat4.create()187 alpha: 1.0, 188 buffers: [], 189 cullFace: gl.BACK, 190 disableDepthTest: false, 191 drawMode: gl.TRIANGLES, 192 drawOrder: 0, 193 enabled: true, 194 enableCullFace: true, 195 hideOcean: false, 196 lineWidth: 1.0, 197 maskEnabled: false, 198 maskHeight: 150.0, 199 maskColor: vec4.fromValues(0.0, 0.0, 1.0, 1.0), 200 mesh: null, 201 name: 'node', 202 shaderName: 'Colored', 203 shader: gl.shaders.Colored, 204 texture: null, 205 useIndexBuffer: true, 206 center: vec3.create(), 207 scale: vec3.fromValues(1, 1, 1), 208 rotation: vec3.create(), 209 translation: vec3.create(), 210 modelMatrix: mat4.create(), 211 rotationMatrix: mat4.create(), 212 inverseModelMatrix: mat4.create(), 213 inverseRotationMatrix: mat4.create() 183 214 }; 184 215 } //}}} 185 216 function debugNodes(canvasid) { //{{{ 186 217 var canvasid = canvasid || '.sim-canvas'; 187 var nodes = $(canvasid)[0].nodes;218 var nodes = document.getElementById(canvasid).nodes; 188 219 console.log(canvasid, 'Nodes:'); 189 220 for (var node in nodes) { … … 196 227 197 228 var translationMatrix = mat4.create(); 198 mat4.translate(translationMatrix, translationMatrix, [-node.center[0],-node.center[1],-node.center[2]]); //scale/rotation centering229 mat4.translate(translationMatrix, translationMatrix, vec3.negate(vec3.create(), node.center)); //scale/rotation centering 199 230 mat4.multiply(modelMatrix, translationMatrix, modelMatrix); 200 231 … … 226 257 node.inverseModelMatrix = mat4.invert(mat4.create(), modelMatrix); 227 258 node.rotationMatrix = rotationMatrix; 228 node.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix); ;259 node.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix); 229 260 } //}}} 230 261 function clamp(value, min, max) { //{{{ 231 262 return Math.max(min, Math.min(value, max)); 232 263 } //}}} 233 function recover(canvasid,name,defaultvalue) { //{{{ 234 var canvas = document.getElementById(canvasid); 235 if (canvas && canvas.hasOwnProperty(name)) { return canvas[name]; } 236 return defaultvalue; 264 function defaultFor(name, value) { //{{{ 265 return typeof name !== 'undefined' ? name : value; 266 } //}}} 267 function isEmptyOrUndefined(object) { //{{{ 268 return object === undefined || Object.getOwnPropertyNames(object).length === 0; 269 } //}}} 270 function recover(canvasid, name, value) { //{{{ 271 //Traverse canvas object tree for property defined by dot delimited string, returning it, or a default value if it is not found. 272 var object = document.getElementById(canvasid); 273 var properties = name.split('.'); 274 for (var i = 0; i < properties.length; ++i) { 275 object = object[properties[i]]; 276 if (typeof object === 'undefined') { break; } 277 } 278 return defaultFor(object, value); 237 279 } //}}} 238 280 function typedArraySliceSupport() { //{{{ … … 279 321 } 280 322 } //}}} 281 function raycast(canvas, x, y) { //{{{282 var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.cameraMatrix, canvas.unitNode.modelMatrix));283 var origin = origin || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 0], inverseMVPMatrix);284 var far = far || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 1.0], inverseMVPMatrix);285 var ray = vec3.subtract(vec3.create(), far, origin);286 287 var mesh = canvas.unitNode.mesh;288 if (!mesh || mesh.ready == false) { return; }289 if (!mesh.octree) { mesh.octree = new GL.Octree(mesh); }290 291 var hit = mesh.octree.testRay(origin, ray, 1e3, 1e10);292 293 if(!hit) { return; }294 295 hit.modelPos = vec3.copy(vec3.create(), hit.pos);296 vec3.transformMat4(hit.pos, hit.pos, canvas.unitNode.modelMatrix);297 vec3.transformMat4(hit.normal, hit.normal, canvas.unitNode.modelMatrix);298 299 return hit;300 } //}}}301 323 //}}} 302 324 //{{{ Interface Functions … … 304 326 //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. 305 327 ev.preventDefault(); 306 if (!(canvas.dataMarkersAllowed && canvas.dataMarkersEnabled)) { return; } 307 initializeMarker(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, true); 308 brushModify(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY); 309 } //}}} 310 function brushModify(canvas, x, y) { //{{{ 328 if (!canvas.dataMarkers.enabled) { return; } 329 var hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY); 330 canvas.dataMarkers.marker.hit = hit; 331 canvas.brush.hit = hit; 332 updateMarker(canvas, true); 333 brushModify(canvas); 334 } //}}} 335 function onPan(ev, canvas, displaylog) { //{{{ 336 ev.preventDefault(); 337 338 if (canvas.dataMarkers.enabled == 'on') { 339 canvas.brush.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY); 340 brushModify(canvas); 341 } 342 343 if (ev.type == 'panstart') { 344 canvas.lastDeltaX = 0; 345 canvas.lastDeltaY = 0; 346 } 347 if (ev.srcEvent.shiftKey || ev.pointers.length == 2) { 348 if (!canvas.view.panningEnabled) return; 349 var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 350 var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 351 352 if (canvas.view.twod) { 353 canvas.view.position[0] += Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaX - Math.sin(DEG2RAD * 0) * deltaY; 354 canvas.view.position[2] += Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaX + Math.cos(DEG2RAD * 0) * deltaY; 355 } 356 else { 357 canvas.view.position[0] += Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaX - Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaY; 358 canvas.view.position[2] += Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaX + Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaY; 359 } 360 } 361 362 else { 363 canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * -2 * canvas.controlSensitivity * RAD2DEG; 364 canvas.view.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG; 365 366 if (canvas.view.rotation[0] > 360) { canvas.view.rotation[0] -= 360; }; 367 if (canvas.view.rotation[0] < -360) { canvas.view.rotation[0] += 360; }; 368 if (canvas.view.rotation[1] > 180) { canvas.view.rotation[1] -= 360; }; 369 if (canvas.view.rotation[1] < -180) { canvas.view.rotation[1] += 360; }; 370 371 canvas.view.rotation[0] = clamp(canvas.view.rotation[0], canvas.view.azimuthLimits[0], canvas.view.azimuthLimits[1]); 372 canvas.view.rotation[1] = clamp(canvas.view.rotation[1], canvas.view.elevationLimits[0], canvas.view.elevationLimits[1]) 373 } 374 canvas.lastDeltaX = ev.deltaX; 375 canvas.lastDeltaY = ev.deltaY; 376 377 repositionMarker(canvas); 378 379 if (displaylog) { console.log(canvas.view.rotation); } 380 } //}}} 381 function onPinch(ev, canvas, displaylog) { //{{{ 382 ev.preventDefault(); 383 if (ev.type == 'pinchstart') { canvas.view.lastZoom = canvas.view.zoom; } 384 else { modifyZoom(ev.scale * canvas.view.lastZoom, canvas, displaylog); } 385 } //}}} 386 function onZoom(ev, canvas, displaylog) { //{{{ 387 ev.preventDefault(); 388 var delta = clamp(ev.scale || ev.wheelDelta || -ev.detail, -1, 1) * canvas.controlSensitivity * canvas.view.zoom / 20; 389 modifyZoom(canvas.view.zoom + delta, canvas, displaylog); 390 } //}}} 391 function modifyZoom(value, canvas, displaylog) { //{{{ 392 canvas.view.zoom = clamp(value, canvas.view.zoomLimits[0], canvas.view.zoomLimits[1]); 393 repositionMarker(canvas); 394 if (displaylog) { console.log(canvas.view.zoom); } 395 } //}}} 396 function modifyDataMarkersEnabled(value, canvas) { //{{{ 397 canvas.dataMarkers.enabled = value; 398 } //}}} 399 function toggleMoviePlay(canvas) { //{{{ 400 canvas.animation.play = !canvas.animation.play; 401 if (canvas.animation.play){ 402 canvas.playButton.find('span').removeClass('fa-play'); 403 canvas.playButton.find('span').addClass('fa-pause'); 404 } 405 else{ 406 canvas.playButton.find('span').removeClass('fa-pause'); 407 canvas.playButton.find('span').addClass('fa-play'); 408 } 409 } //}}} 410 function onSlideStart(canvas, progressBar) { //{{{ 411 if (!isEmptyOrUndefined(canvas.animation)) { 412 canvas.animation.increment = false; 413 canvas.animation.frame = parseInt($(progressBar).val()); 414 //console.log(canvas.animation.frame); 415 //updateMarker(canvas, false); 416 } 417 } //}}} 418 function onSlideChange(canvas, progressBar) { //{{{ 419 if (!isEmptyOrUndefined(canvas.animation)) { 420 canvas.animation.frame = parseInt($(progressBar).val()); 421 //console.log("change"); 422 updateMarker(canvas, false); 423 } 424 } //}}} 425 function onSlideStop(canvas, progressBar) { //{{{ 426 if (!isEmptyOrUndefined(canvas.animation)) { 427 canvas.animation.increment = true; 428 canvas.animation.frame = parseInt($(progressBar).val()); 429 //console.log(canvas.animation.frame); 430 //updateMarker(canvas, false); 431 } 432 } //}}} 433 //}}} 434 //{{{ Interaction Functions 435 function raycast(canvas, x, y) { //{{{ 436 //Performs raycast on canvas.unitNode.mesh using x/y screen coordinates. Returns hit objects with hit position, coords, and indicies of ray-triangle intersection. 437 //TODO: Diagnose marker issues with orthographic views and slr-eustatic updates when switching between basins. 438 var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.camera.vpMatrix, canvas.unitNode.modelMatrix)); 439 var origin = vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 0], inverseMVPMatrix); 440 var far = far || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 1.0], inverseMVPMatrix); 441 var ray = vec3.subtract(vec3.create(), far, origin); 442 443 var mesh = canvas.unitNode.mesh; 444 if (!mesh) { return; } 445 if (!mesh.octree) { mesh.octree = new GL.Octree(mesh); } 446 447 var hit = mesh.octree.testRay(origin, ray, 1e3, 1e10); 448 449 if(!hit) { return; } 450 451 hit.modelPos = vec3.copy(vec3.create(), hit.pos); 452 vec3.transformMat4(hit.pos, hit.pos, canvas.unitNode.modelMatrix); 453 vec3.transformMat4(hit.normal, hit.normal, canvas.unitNode.modelMatrix); 454 455 return hit; 456 } //}}} 457 function brushModify(canvas) { //{{{ 311 458 //This function takes in the canvas and x/y coordinates, performing a raycast against the mesh, and modifies the mesh using a the canvas.brush.strength and canvas.brush.falloff properties. 312 459 //Currently the brush extends to the raycasted element and its immediate neighbors. … … 314 461 if (!canvas.unitNode || canvas.brush.enabled != 'on') { return; } 315 462 316 var hit = raycast(canvas, x, y);463 var hit = canvas.brush.hit; 317 464 318 465 if (hit) { 319 var bufferVertices = canvas.unitNode.mesh.getBuffer( "vertices");466 var bufferVertices = canvas.unitNode.mesh.getBuffer('vertices'); 320 467 var vertices = bufferVertices.data; 321 var bufferCoords = canvas.unitNode.mesh.getBuffer( "coords");468 var bufferCoords = canvas.unitNode.mesh.getBuffer('coords'); 322 469 var coords = bufferCoords.data; 323 470 … … 361 508 bufferCoords.upload(canvas.gl.DYNAMIC_DRAW); 362 509 canvas.unitNode.mesh.octree = new GL.Octree(canvas.unitNode.mesh); 363 } 364 } 365 function initializeMarker(canvas, x, y, reset, origin, far) { //{{{ 366 //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. 367 if (!canvas.unitNode) { return; } 368 369 var hit = raycast(canvas, x, y); 370 371 if (hit) { 372 canvas.lastHit = hit; 373 var dataMarkerSize = canvas.dataMarkerSize; 374 if (!canvas.marker) { 375 $('#' + canvas.id).after( '<img src=' + canvas.dataMarkerImage + ' alt="data marker" width="' + dataMarkerSize[0] + '" height="' + dataMarkerSize[1] + '" id="sim-data-marker-' + canvas.id + '" class="sim-data-marker noselect tooltip" data-tooltip-content="#tooltip-content-data-marker-' + canvas.id + '"></img><span id="tooltip-content-data-marker-' + canvas.id + '"></span>'); 376 $('#sim-data-marker-' + canvas.id).css({ 377 'position': 'absolute', 378 'left': (Math.round(x) - dataMarkerSize[0] / 2) + 'px', 379 'top': (Math.round(y) - dataMarkerSize[1]) + 'px', 380 'width': dataMarkerSize[0] + 'px', 381 'height': dataMarkerSize[1] + 'px', 382 'pointer-events': 'all', 383 'cursor': 'pointer', 384 'display': 'none' 385 }); 386 $('#sim-data-marker-' + canvas.id).tooltipster({ 387 contentAsHTML: 'true', 388 animation: 'grow', 389 maxWidth: 320, 390 maxHeight: 320, 391 zIndex: 1000, 392 trigger: 'custom', 393 triggerOpen: { 394 mouseenter: false, 395 originClick: true, 396 touchstart: false 397 }, 398 triggerClose: { 399 mouseleave: false, 400 originClick: true, 401 touchleave: false 402 }, 403 }); 404 canvas.marker = $('#sim-data-marker-' + canvas.id); 405 canvas.marker.on('click touch', function () { 406 canvas.marker.fadeOut(175); 407 canvas.dataMarkerDisplay.tooltipster('close'); 408 }); 409 canvas.marker.fadeIn(175); 410 } 411 412 canvas.marker.hit = hit; 413 414 if (!canvas.dataMarkerDisplay) { 415 canvas.dataMarkerDisplay = $('#sim-data-marker-' + canvas.id); 416 canvas.dataMarkerDisplay.tooltipster('open'); 417 } 418 419 updatePlot(true); 420 repositionMarker(); 421 if (reset) { modifyDataMarkersEnabled(true,canvas); } 422 } 423 } //}}} 424 function updatePlot(reset) { 425 if (!canvas.lastHit) { return; } 426 var hit = canvas.lastHit; 510 511 //Update clouds if rendered 512 //TODO: Steven, once you update the cloud generation in applyoptions.js, modify this code block to move the clouds as well. We'll want to move them individually later, but moving them all is ok for now. 513 for (var i = 0; i < canvas.clouds.quantity; i++) { 514 if (canvas.nodes['clouds' + i]) { 515 var v1 = vec3.fromValues(vertices[hit.indices[0] * 3], vertices[hit.indices[0] * 3 + 1], vertices[hit.indices[0] * 3 + 2]); 516 var v2 = vec3.fromValues(vertices[hit.indices[1] * 3], vertices[hit.indices[1] * 3 + 1], vertices[hit.indices[1] * 3 + 2]); 517 var v3 = vec3.fromValues(vertices[hit.indices[2] * 3], vertices[hit.indices[2] * 3 + 1], vertices[hit.indices[2] * 3 + 2]); 518 vec3.transformMat4(v1, v1, canvas.unitNode.modelMatrix); 519 vec3.transformMat4(v2, v2, canvas.unitNode.modelMatrix); 520 vec3.transformMat4(v3, v3, canvas.unitNode.modelMatrix); 521 var x = (v1[0] + v2[0] + v3[0]) / 3 + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000))); 522 var y = (v1[1] + v2[1] + v3[1]) / 3 + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000))); 523 var z = (v1[2] + v2[2] + v3[2]) / 3; 524 canvas.nodes['clouds' + i].translation = [x, y + canvas.clouds.height, z]; 525 updateModelMatrix(canvas.nodes['clouds' + i]); 526 } 527 } 528 } 529 } //}}} 530 function initializeMarker(canvas) { //{{{ 531 //Initialize data marker and tooltip display once per page load 532 var marker = $('#' + canvas.dataMarkers.marker.id); 533 var size = canvas.dataMarkers.size; 534 if (!marker.hasClass('tooltipstered')) { 535 marker.css({ 536 'position': 'absolute', 537 'left': -size[0] + 'px', 538 'top': -size[1] + '0px', 539 'width': size[0] + 'px', 540 'height': size[1] + 'px', 541 'pointer-events': 'all', 542 'cursor': 'pointer', 543 'display': 'none' 544 }); 545 marker.tooltipster({ 546 contentAsHTML: true, 547 maxWidth: 320, 548 maxHeight: 320, 549 zIndex: 1000, 550 trigger: 'custom', 551 triggerOpen: { 552 mouseenter: false, 553 originClick: true, 554 touchstart: false 555 }, 556 triggerClose: { 557 mouseleave: false, 558 originClick: true, 559 touchleave: false 560 }, 561 }); 562 marker.on('click touch', function () { 563 marker.fadeOut(175); 564 marker.tooltipster('close'); 565 }); 566 canvas.dataMarkers.marker.selector = marker; 567 } 568 updateMarker(canvas, true); 569 } //}}} 570 function repositionMarker(canvas) { //{{{ 571 //Mover marker to point to mouse position, offset in y by 1 to enable immediate clicking. 572 if (isEmptyOrUndefined(canvas.dataMarkers.marker.hit) || !canvas.camera.ready) { return; } 573 var size = canvas.dataMarkers.size; 574 var screenPoint = vec3.transformMat4(vec3.create(), canvas.dataMarkers.marker.hit.pos, canvas.camera.vpMatrix); 575 //console.log(canvas, canvas.selector, $(canvas.id) 576 var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left; 577 var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top; 578 canvas.dataMarkers.marker.selector.css({ 579 'left': (Math.round(x) - size[0] / 2) + 'px', 580 'top': (Math.round(y) - size[1] + 1) + 'px' 581 }); 582 583 if (canvas.dataMarkers.marker.selector.tooltipster('status').state != 'closed') { canvas.dataMarkers.marker.selector.tooltipster('reposition'); } 584 } //}}} 585 function updateMarker(canvas, reset) { //{{{ 586 //Retrieve data value fields and plots them on data marker popup if a hit has been registered. 587 //TODO: Automatically pick up any field of size md.mesh.numberofelements 588 //If no marker has been placed, no update is needed. If canvas is resimulating and unitNode has not been set yet, wait and try again. 589 if (isEmptyOrUndefined(canvas.dataMarkers.marker.hit)) { return; } 590 if (isEmptyOrUndefined(canvas.unitNode)) { setTimeout( function(){ updateMarker(canvas, reset); }, 750); return; } 591 592 var hit = canvas.dataMarkers.marker.hit; 593 427 594 var coords = canvas.unitNode.mesh.vertexBuffers.coords.data; 428 595 var latitude = md.mesh.lat; … … 431 598 var velocity; 432 599 if (md.results[0]) { 433 thickness = md.results[canvas. movieFrame].Thickness;434 velocity = md.results[canvas. movieFrame].Vel;600 thickness = md.results[canvas.animation.frame].Thickness; 601 velocity = md.results[canvas.animation.frame].Vel; 435 602 } 436 603 else { … … 439 606 } 440 607 441 var hitCoords = [coords[hit.indices[0]*2], coords[hit.indices[0]*2+1],coords[hit.indices[1]*2], coords[hit.indices[1]*2+1],coords[hit.indices[2]*2], coords[hit.indices[2]*2+1]]; 608 //Determine data values at hit position. 609 var hitCoords = [coords[hit.indices[0]*2], coords[hit.indices[0]*2+1], coords[hit.indices[1]*2], coords[hit.indices[1]*2+1], coords[hit.indices[2]*2], coords[hit.indices[2]*2+1]]; 442 610 var hitLatitude = [latitude[hit.indices[0]], latitude[hit.indices[1]], latitude[hit.indices[2]]]; 443 611 var hitLongitude = [longitude[hit.indices[0]], longitude[hit.indices[1]], longitude[hit.indices[2]]]; … … 451 619 var valueThickness = hitThickness[0] * hit.uvw[0] + hitThickness[1] * hit.uvw[1] + hitThickness[2] * hit.uvw[2]; 452 620 var valueVelocity = hitVelocity[0] * hit.uvw[0] + hitVelocity[1] * hit.uvw[1] + hitVelocity[2] * hit.uvw[2]; 453 if (canvas.dataMarkerOptions) { 454 var format = [canvas.dataMarkerOptions.format[0]]; 455 for (var i = 1; i < canvas.dataMarkerOptions.format.length; i++) { 456 var formatString = canvas.dataMarkerOptions.format[i]; 457 if (formatString.toLowerCase() == 'x') { format.push(hit.modelPos[0]); } 458 else if (formatString.toLowerCase() == 'y') { format.push(hit.modelPos[1]); } 459 else if (formatString.toLowerCase() == 'z') { format.push(hit.modelPos[2]); } 460 else if (formatString.toLowerCase() == 'lat') { format.push(valueLatitude); } 461 else if (formatString.toLowerCase() == 'long') { format.push(valueLongitude); } 462 else if (formatString.toLowerCase() == 'thickness') { format.push(valueThickness); } 463 else if (formatString.toLowerCase() == 'vel') { format.push(valueVelocity); } 464 else if (formatString.toLowerCase() == 'value') { format.push(value); } 465 else {format.push(formatString); } 466 } 467 if (canvas.dataMarkerOptions.animated) { 468 var isEmpty = (canvas.dataArray.length == 0); 469 var lastUpdatedIndex = (canvas.dataArray.length-1); 470 var newMovieFrame = (!isEmpty && canvas.dataArray[lastUpdatedIndex][0] != canvas.movieFrame); 471 if (reset) { 472 canvas.dataArray = []; 473 newMovieFrame = true; 474 for (var currentFrame = 0; currentFrame < (canvas.unitNode.movieLength); currentFrame++) { 475 coords = canvas.unitNode.texcoords[currentFrame]; 476 var hitCoords = [coords[hit.indices[0]*2], coords[hit.indices[0]*2+1],coords[hit.indices[1]*2], coords[hit.indices[1]*2+1],coords[hit.indices[2]*2], coords[hit.indices[2]*2+1]]; 477 var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2]; 478 var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2]; 479 var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v; 480 canvas.dataArray.push([currentFrame, value]); 481 } 621 622 //Construct new argument array of the data display format for sprintf using first first argument as the formatSpecifier string and the rest as the additional arguments. 623 var format = canvas.dataMarkers.format.slice(); 624 for (var i = 1; i < format.length; i++) { 625 if (format[i].toLowerCase() == 'x') { format[i] = hit.modelPos[0]; } 626 else if (format[i].toLowerCase() == 'y') { format[i] = hit.modelPos[1]; } 627 else if (format[i].toLowerCase() == 'z') { format[i] = hit.modelPos[2]; } 628 else if (format[i].toLowerCase() == 'lat') { format[i] = valueLatitude; } 629 else if (format[i].toLowerCase() == 'long') { format[i] = valueLongitude; } 630 else if (format[i].toLowerCase() == 'thickness') { format[i] = valueThickness; } 631 else if (format[i].toLowerCase() == 'vel') { format[i] = valueVelocity; } 632 else if (format[i].toLowerCase() == 'value') { format[i] = value; } 633 } 634 635 //Apply changes to tooltip 636 $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, format)); 637 $('#tooltip-content-data-marker-' + canvas.id).css({'font': canvas.dataMarkers.font}); 638 639 //If animated, setup animation loop to update plot as movie plays. 640 if (canvas.dataMarkers.animated) { 641 var isEmpty = (canvas.dataMarkers.values.length == 0); 642 var lastUpdatedIndex = (canvas.dataMarkers.values.length-1); 643 var newMovieFrame = (!isEmpty && canvas.dataMarkers.values[lastUpdatedIndex][0] != canvas.animation.frame); 644 //If new data marker has been placed, reinitialize plot. If not, push new value into plot value array. 645 if (reset) { 646 canvas.dataMarkers.values = []; 647 newMovieFrame = true; 648 for (var currentFrame = 0; currentFrame < (canvas.unitNode.movieLength); currentFrame++) { 649 coords = canvas.unitNode.texcoords[currentFrame]; 650 var hitCoords = [coords[hit.indices[0]*2], coords[hit.indices[0]*2+1], coords[hit.indices[1]*2], coords[hit.indices[1]*2+1], coords[hit.indices[2]*2], coords[hit.indices[2]*2+1]]; 651 var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2]; 652 var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2]; 653 var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v; 654 canvas.dataMarkers.values.push([currentFrame, value]); 482 655 } 483 else {484 if (isEmpty || newMovieFrame){485 canvas.dataArray.push([canvas.movieFrame,value]);486 }656 } 657 else { 658 if (isEmpty || newMovieFrame) { 659 canvas.dataMarkers.values.push([canvas.animation.frame, value]); 487 660 } 488 if (isEmpty || newMovieFrame) { 489 $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, format)); 490 $('#tooltip-content-data-marker-' + canvas.id).css({ 491 'font': canvas.dataMarkerOptions.font 492 }); 493 var dataLabels = {'latitude':valueLatitude,'longitude':valueLongitude,'thickness':valueThickness,'velocity':valueVelocity,'value':value}; 494 var dataDisplay = canvas.dataArray.slice(0,canvas.movieFrame+1); 495 plot('id','#sim-plot','type','bar','width',400,'height',300,'nticks',25,'xlabel','Time','ylabel', 496 'Value','title','Changes Over Time','datalabels',canvas.dataMarkerOptions.labels,'labelvalues',dataLabels,'data',dataDisplay); 497 } 498 } 499 } 500 } 501 502 function repositionMarker() { 503 if (!canvas.unitNode) { return; } 504 if (!canvas.dataMarkerDisplay) { return; } 505 var dataMarkerSize = canvas.dataMarkerSize; 506 var screenPoint = vec3.transformMat4(vec3.create(), canvas.marker.hit.pos, canvas.cameraMatrix); 507 var x = screenPoint[0] * (canvas.width / 2) + canvas.width / 2; 508 var y = -screenPoint[1] * (canvas.height / 2) + canvas.height / 2; 509 canvas.marker.css({ 510 'left': (Math.round(x) - dataMarkerSize[0] / 2) + 'px', 511 'top': (Math.round(y) - dataMarkerSize[1]) + 'px' 512 }); 513 if (canvas.dataMarkerDisplay.tooltipster('status').state != 'closed') { canvas.dataMarkerDisplay.tooltipster('reposition'); } 514 } 515 516 function onPan(ev,canvas,displaylog) { //{{{ 517 ev.preventDefault(); 518 repositionMarker(); 519 brushModify(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY); 520 if (ev.type == 'panstart') { 521 canvas.lastDeltaX = 0; 522 canvas.lastDeltaY = 0; 523 } 524 if (ev.srcEvent.shiftKey || ev.pointers.length == 2) { 525 if (!canvas.viewPanning) return; 526 var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth / canvas.zoom * 2 * canvas.controlSensitivity * 6.371e6; 527 var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight / canvas.zoom * 2 * canvas.controlSensitivity * 6.371e6; 528 529 if (canvas.twod) { 530 canvas.translation[0] += Math.cos(DEG2RAD * canvas.rotation[0]) * deltaX - Math.sin(DEG2RAD * 0) * deltaY; 531 canvas.translation[2] += Math.sin(DEG2RAD * canvas.rotation[0]) * deltaX + Math.cos(DEG2RAD * 0) * deltaY; 532 } 533 else { 534 canvas.translation[0] += Math.cos(DEG2RAD * canvas.rotation[0]) * deltaX - Math.sin(DEG2RAD * canvas.rotation[0]) * deltaY; 535 canvas.translation[2] += Math.sin(DEG2RAD * canvas.rotation[0]) * deltaX + Math.cos(DEG2RAD * canvas.rotation[0]) * deltaY; 536 } 537 } 538 else { 539 canvas.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * -2 * canvas.controlSensitivity * RAD2DEG; 540 canvas.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG; 541 542 if (canvas.rotation[0] > 360) { canvas.rotation[0] -= 360; }; 543 if (canvas.rotation[0] < -360) { canvas.rotation[0] += 360; }; 544 if (canvas.rotation[1] > 180) { canvas.rotation[1] -= 360; }; 545 if (canvas.rotation[1] < -180) { canvas.rotation[1] += 360; }; 546 547 canvas.rotation[0] = clamp(canvas.rotation[0], canvas.rotationAzimuthBounds[0], canvas.rotationAzimuthBounds[1]); 548 canvas.rotation[1] = clamp(canvas.rotation[1], canvas.rotationElevationBounds[0], canvas.rotationElevationBounds[1]) 549 } 550 canvas.lastDeltaX = ev.deltaX; 551 canvas.lastDeltaY = ev.deltaY; 552 553 if (displaylog) { console.log(canvas.rotation); } 554 } //}}} 555 function onPinch(ev,canvas,displaylog) { //{{{ 556 ev.preventDefault(); 557 repositionMarker(); 558 if (ev.type == 'pinchstart') { canvas.zoomLast = canvas.zoom; } 559 else { modifyZoom(ev.scale * canvas.zoomLast, canvas, displaylog); } 560 } //}}} 561 function onZoom(ev,canvas,displaylog) { //{{{ 562 ev.preventDefault(); 563 repositionMarker(); 564 var delta = clamp(ev.scale || ev.wheelDelta || -ev.detail, -1, 1) * canvas.controlSensitivity * canvas.zoom / 20; 565 modifyZoom(canvas.zoom + delta, canvas, displaylog); 566 } //}}} 567 function modifyZoom(value,canvas,displaylog) { //{{{ 568 canvas.zoom = clamp(value, canvas.zoomBounds[0], canvas.zoomBounds[1]); 569 if (displaylog) { console.log(canvas.zoom); } 570 } //}}} 571 function modifyDataMarkersEnabled(value,canvas) { //{{{ 572 canvas.dataMarkersEnabled = value; 573 if (!canvas.dataMarkersEnabled && canvas.marker) { 574 canvas.marker.fadeOut(175); 575 canvas.dataMarkerDisplay.tooltipster('close'); 576 } 577 else if (canvas.dataMarkersEnabled && canvas.marker) { 578 canvas.marker.fadeIn(175); 579 canvas.dataMarkerDisplay.tooltipster('open'); 580 } 581 } //}}} 582 function toggleMoviePlay(canvas) { //{{{ 583 canvas.moviePlay = !canvas.moviePlay; 584 if (canvas.moviePlay){ 585 canvas.playButton.find("span").removeClass("fa-play"); 586 canvas.playButton.find("span").addClass("fa-pause"); 587 } 588 else{ 589 canvas.playButton.find("span").removeClass("fa-pause"); 590 canvas.playButton.find("span").addClass("fa-play"); 661 } 662 663 //Replot data marker popup using update data value array. 664 if (isEmpty || newMovieFrame) { 665 var dataLabels = {'latitude': valueLatitude, 'longitude': valueLongitude, 'thickness': valueThickness, 'velocity': valueVelocity, 'value': value}; 666 var dataDisplay = canvas.dataMarkers.values.slice(0, canvas.animation.frame+1); 667 plot( 668 'id', '#sim-plot', 669 'type', 'bar', 670 'width', 400, 671 'height', 300, 672 'nticks', 25, 673 'xlabel', 'Time', 674 'ylabel', 'Value', 675 'title', 'Changes Over Time', 676 'datalabels', canvas.dataMarkers.labels, 677 'labelvalues', dataLabels, 678 'data', dataDisplay 679 ); 680 } 681 } 682 repositionMarker(canvas); 683 if (reset) { 684 canvas.dataMarkers.marker.selector.fadeIn(175); 685 canvas.dataMarkers.marker.selector.tooltipster('open'); 591 686 } 592 687 } //}}} … … 594 689 //{{{ Drawing Functions 595 690 function updateCameraMatrix(canvas) { //{{{ 596 //Update view matrix and multiply with projection matrix to get the view-projection (camera)matrix.691 //Update view matrix and multiply with projection matrix to get the view-projection matrix. 597 692 var vMatrix = mat4.create(); 598 693 var pMatrix = mat4.create(); … … 604 699 var cameraPosition = vec3.create(); 605 700 606 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); }607 else { mat4.perspective(pMatrix, 45 * DEG2RAD, aspectRatio, 1e3, 1e10); }701 if (canvas.view.twod) { mat4.ortho(pMatrix, -aspectRatio*6.371e6/canvas.view.zoom, aspectRatio*6.371e6/canvas.view.zoom, -6.371e6/canvas.view.zoom, 6.371e6/canvas.view.zoom, canvas.camera.near, canvas.camera.far); } 702 else { mat4.perspective(pMatrix, canvas.camera.fov * DEG2RAD, aspectRatio, canvas.camera.near, canvas.camera.far); } 608 703 609 704 //Apply worldspace translation 610 mat4.translate(translateMatrix, translateMatrix, [-canvas.translation[0],-canvas.translation[1],-canvas.translation[2]]); 611 mat4.multiply(vMatrix, translateMatrix, vMatrix); 705 mat4.translate(vMatrix, translateMatrix, vec3.negate(vec3.create(), canvas.view.position)); 612 706 613 707 //Calculate rotation around camera focal point about worldspace origin 614 if (canvas. twod) {708 if (canvas.view.twod) { 615 709 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * 0, [0, 1, 0]); 616 710 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * 90, [1, 0, 0]); … … 618 712 } 619 713 else { 620 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * canvas. rotation[0], [0, 1, 0]);621 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * canvas. rotation[1], [1, 0, 0]);714 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * canvas.view.rotation[0], [0, 1, 0]); 715 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * canvas.view.rotation[1], [1, 0, 0]); 622 716 mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix); 623 717 } 624 718 625 719 //Apply rotation transform 626 720 mat4.multiply(vMatrix, rotationMatrix, vMatrix); 627 628 //Apply screenspace translation 721 722 //Apply screenspace translation to emulate rotation around point 629 723 mat4.identity(translateMatrix); 630 mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, -6.371e6/canvas. zoom]);724 mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, -6.371e6/canvas.view.zoom]); 631 725 mat4.multiply(vMatrix, translateMatrix, vMatrix); 632 726 633 //Calculate fields for lighting and raycasts634 mat4.invert(canvas.vInverseMatrix, vMatrix);635 636 727 //Apply projection matrix to get camera matrix 637 mat4.multiply(canvas.cameraMatrix, pMatrix, vMatrix); 638 mat4.invert(canvas.inverseCameraMatrix, canvas.cameraMatrix); 639 vec3.transformMat4(canvas.cameraPosition, cameraPosition, canvas.inverseCameraMatrix); 728 mat4.copy(canvas.camera.vMatrix, vMatrix); 729 mat4.multiply(canvas.camera.vpMatrix, pMatrix, vMatrix); 730 731 //Calculate inverse view matrix fields for lighting and raycasts 732 mat4.invert(canvas.camera.vInverseMatrix, canvas.camera.vMatrix); 733 mat4.invert(canvas.camera.vpInverseMatrix, canvas.camera.vpMatrix); 734 735 vec3.transformMat4(canvas.camera.position, cameraPosition, canvas.camera.vpInverseMatrix); 736 canvas.camera.ready = true; 640 737 }//}}} 641 function drawSceneGraphNode(canvas, node) { //{{{738 function drawSceneGraphNode(canvas, node) { //{{{ 642 739 if (!node.enabled) { return; } 643 740 … … 646 743 647 744 var mvpMatrix = mat4.create(); 648 mat4.multiply(mvpMatrix, canvas.cameraMatrix, node.modelMatrix); 745 mat4.multiply(mvpMatrix, canvas.camera.vpMatrix, node.modelMatrix); 746 747 var mvMatrix = mat4.create(); 748 mat4.multiply(mvMatrix, canvas.camera.vMatrix, node.modelMatrix); 749 750 var normalMatrix = mat4.create(); 751 mat4.invert(normalMatrix, mvMatrix); 752 mat4.transpose(normalMatrix, normalMatrix); 649 753 650 754 if (node.texture) { node.texture.bind(0); } … … 660 764 var lightOrigin = vec3.fromValues(0, 0, 0); 661 765 var cameraPositionRelative = vec3.create(); 662 vec3.transformMat4(origin, origin, canvas. vInverseMatrix);766 vec3.transformMat4(origin, origin, canvas.camera.vInverseMatrix); 663 767 vec3.normalize(lightOrigin, lightOrigin); 664 768 vec3.sub(cameraPositionRelative, origin, node.translation); … … 692 796 node.shader.uniforms({ 693 797 m4MVP: mvpMatrix, 798 m4Normal: normalMatrix, 694 799 m4Model: node.modelMatrix, 800 //u_lightPosition: [-lightOrigin[0], -lightOrigin[1], -lightOrigin[2]], 801 u_lightPosition: [1.0, 1.0, 1.0], 802 u_diffuseColor: [1.0, 0.9, 0.9], 695 803 u_texture: 0, 696 804 u_alpha: node.alpha, … … 728 836 gl.disable(gl.CULL_FACE); 729 837 } //}}} 730 function draw(canvas ,options) { //{{{731 if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); }732 838 function draw(canvas) { //{{{ 839 //Ensure all nodes are ready to render 840 //TODO: Come up with better way to check if shaders are ready, or move outside of main draw function 733 841 var nodes = canvas.nodes; 734 if (nodes.length < 1) { 735 canvas.drawHandler = window.requestAnimationFrame(function(time) { draw(canvas,options); }); 736 return; 737 } 738 for (var node in nodes) { 739 if ((nodes[node].texture && nodes[node].texture.ready == false) || nodes[node].shader.ready == false || nodes[node].mesh.ready == false) { 740 canvas.drawHandler = window.requestAnimationFrame(function(time) { draw(canvas,options); }); 741 return; 742 } 743 } 744 745 var rect = canvas.getBoundingClientRect(); 746 canvas.width = rect.width; 747 canvas.height = rect.height; 748 749 var gl = canvas.gl; 750 gl.makeCurrent(); //litegl function to handle switching between multiple canvases 751 gl.viewport(0, 0, rect.width, rect.height); 752 gl.clearColor(canvas.backgroundcolor[0], canvas.backgroundcolor[1], canvas.backgroundcolor[2], canvas.backgroundcolor[3]); 753 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 754 755 updateCameraMatrix(canvas); 756 757 //if (canvas.marker) { canvas.marker.update(); } 758 759 var drawPassNumber = 3; 760 for (var i = drawPassNumber - 1; i >= 0; i--) { 761 for (var node in nodes) { 762 if (nodes[node].drawOrder == i) { drawSceneGraphNode(canvas,nodes[node]); } 763 } 764 } 765 766 canvas.drawHandler = window.requestAnimationFrame(function(time) { draw(canvas,options); }); 842 if (!canvas.draw.ready) { 843 if (nodes.length !== 0) { 844 canvas.draw.ready = true; 845 for (var node in nodes) { 846 if (nodes[node].shader.ready == false) { 847 canvas.draw.ready = false; 848 break; 849 } 850 } 851 852 } 853 } 854 855 //Begin rendering nodes 856 if (canvas.draw.ready) { 857 if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); } 858 if (canvas.overlaycanvas) { canvas.overlaycanvas.draw(canvas); } 859 860 var rect = canvas.getBoundingClientRect(); 861 canvas.width = rect.width; 862 canvas.height = rect.height; 863 864 var gl = canvas.gl; 865 gl.makeCurrent(); //litegl function to handle switching between multiple canvases 866 gl.viewport(0, 0, canvas.width, canvas.height); 867 gl.clearColor(canvas.backgroundcolor[0], canvas.backgroundcolor[1], canvas.backgroundcolor[2], canvas.backgroundcolor[3]); 868 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 869 870 updateCameraMatrix(canvas); 871 872 var drawPassNumber = 3; 873 for (var i = drawPassNumber - 1; i >= 0; i--) { 874 for (var node in nodes) { 875 if (nodes[node].drawOrder == i) { drawSceneGraphNode(canvas, nodes[node]); } 876 } 877 } 878 } 879 880 //Regardless of ready state, schedule next frame to check for ready state and render 881 canvas.draw.handler = window.requestAnimationFrame(function(time) { draw(canvas); }); 767 882 } //}}} 768 883 //}}}
Note:
See TracChangeset
for help on using the changeset viewer.