Changeset 21911
- Timestamp:
- 08/03/17 15:17:23 (8 years ago)
- Location:
- issm/trunk-jpl/src/m
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/m/array/arrayoperations.js
r19887 r21911 1 1 function ArrayMax(array){ //{{{ 2 return Math.max.apply(null,array); 2 //Calculate array max using for loop instead of Math.max.apply(null, array) to avoid recursive stack overflow in mobile browsers 3 4 var max=-Infinity; 5 6 for (var i=0;i<array.length; i++) { 7 max=Math.max(max,array[i]); 8 } 9 10 return max; 3 11 } //}}} 4 12 function ArrayMax2D(array){ //{{{ 5 13 6 var max= 0;14 var max=-Infinity; 7 15 8 16 for (var i=0;i<array.length;i++){ … … 14 22 } //}}} 15 23 function ArrayMin(array){ //{{{ 16 return Math.min.apply(null,array); 24 //Calculate array min using for loop instead of Math.min.apply(null, array) to avoid recursive stack overflow in mobile browsers 25 26 var min=Infinity; 27 28 for (var i=0;i<array.length; i++) { 29 min=Math.min(min,array[i]); 30 } 31 32 return min; 33 } //}}} 34 function ArrayMin2D(array){ //{{{ 35 36 var min=Infinity; 37 38 for (var i=0;i<array.length;i++){ 39 var subarray=array[i]; 40 min=Math.min(min,ArrayMin(subarray)); 41 } 42 43 return min; 17 44 } //}}} 18 45 function ArraySum(array){ //{{{ … … 66 93 return or; 67 94 68 } //}}}69 function ArrayMin2D(array){ //{{{70 71 var min=ArrayMax2D(array);72 73 for (var i=0;i<array.length;i++){74 var subarray=array[i];75 min=Math.min(min,ArrayMin(subarray));76 }77 78 return min;79 95 } //}}} 80 96 function ListToMatrix(list, elementsPerSubArray) { //{{{ … … 126 142 function ArrayNot(array) { //{{{ 127 143 128 var notarray=array ;144 var notarray=array.slice(); 129 145 for (var i=0;i<array.length;i++)notarray[i]=-array[i]; 130 146 return notarray; … … 138 154 function ArrayPow(array,coefficient) { //{{{ 139 155 140 var powarray=array ;156 var powarray=array.slice(); 141 157 for (var i=0;i<array.length;i++)powarray[i]=Math.pow(array[i],coefficient); 142 158 return powarray; … … 144 160 function ArraySqrt(array) { //{{{ 145 161 146 var sqrtarray=array ;162 var sqrtarray=array.slice(); 147 163 for (var i=0;i<array.length;i++)sqrtarray[i]=Math.sqrt(array[i]); 148 164 return sqrtarray; … … 150 166 function ArrayScale(array,alpha) { //{{{ 151 167 152 for (var i=0;i<array.length;i++)array[i]=array[i]*alpha; 153 168 var scalearray=array.slice(); 169 for (var i=0;i<array.length;i++)scalearray[i]=array[i]*alpha; 170 return scalearray; 154 171 } //}}} 155 172 function ArrayMag(array1,array2) { //{{{ … … 250 267 } //}}} 251 268 function NewArrayFill(size,value) { //{{{ 252 253 return new Array(size).fill(value); 269 270 var array = new Array(size); 271 272 for (var i = 0; i < size; i++) { 273 array[i] = value; 274 } 275 276 return array; 254 277 } //}}} 255 278 function NewArrayFillIncrement(size,start,increment) { //{{{ -
issm/trunk-jpl/src/m/classes/clusters/generic.js
r21768 r21911 53 53 } //}}} 54 54 var request = new XMLHttpRequest(); 55 request.open("POST", this.url, true); 55 56 $(callbackid).html(sprintf("%-16s", "CONNECTING...")).prop("disabled", true); 56 57 request.position = 0; //Keep track of current parsing position in repsonseText … … 157 158 var data = new Blob([nplength,npbuffer,codeversionlength,codeversionbuffer,runtimenamelength,runtimenamebuffer,namelength,namebuffer,toolkitslength,toolkitsbuffer,solutionlength,solutionbuffer,binlength,binbuffer]); 158 159 159 request.open("POST", this.url, true);160 160 request.responseType = 'application/octet-stream'; 161 161 request.send(data); -
issm/trunk-jpl/src/m/plot/applyoptions.js
r21768 r21911 6 6 // 7 7 // See also: PLOTMODEL, PARSE_OPTIONS 8 8 9 9 //{{{ colorbar 10 10 var gl = canvas.gl; … … 16 16 var ccanvasid, ctitleid, clabelsid, ccanvas, ctitle, clabels, ccontext, cmap, colorbar, cwidth, cheight, cgradient, color, y, x; 17 17 //}}} 18 //{{{ Create colorbar labels 18 //{{{ Create colorbar labels 19 19 var labels = []; 20 20 var cdivisions = options.getfieldvalue('colorbarnticks', 6); … … 49 49 } //}}} 50 50 //{{{ Initialize colorbar canvas 51 ccanvasid = options.getfieldvalue('colorbarid', options.getfieldvalue('canvasid').replace('canvas','colorbar-canvas')); 51 ccanvasid = options.getfieldvalue('colorbarid', options.getfieldvalue('canvasid').replace('canvas','colorbar-canvas')); 52 52 ccanvas = $('#'+ccanvasid)[0]; 53 53 cwidth = ccanvas.width*options.getfieldvalue('colorbarwidth', 1); … … 63 63 for (var i=0; i < colorbar.length; i++) { 64 64 color = colorbar[colorbar.length-i-1]; 65 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)]; 65 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)]; 66 66 cgradient.addColorStop(i/colorbar.length*(cdivisions/(cdivisions+1.0))+(1.0/(cdivisions+1.0)),'rgba('+color.toString()+', 1.0)'); 67 67 } … … 107 107 if (options.exist('colorbartitle')) { ctitle.html(options.getfieldvalue('colorbartitle')); } 108 108 //}}} 109 } 109 } 110 110 } //}}} 111 111 //{{{ texture canvas … … 119 119 tcontext = tcanvas.getContext('2d'); 120 120 tgradient = tcontext.createLinearGradient(0, 0, 0, 256); 121 121 122 122 var cmap = options.getfieldvalue('colormap','jet'); 123 123 var colorbar = colorbars[cmap]; 124 124 for (var i=0; i < colorbar.length; i++) { 125 125 color = colorbar[colorbar.length-i-1]; 126 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)]; 126 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)]; 127 127 tgradient.addColorStop(i/colorbar.length,'rgba('+color.toString()+', 1.0)'); 128 128 } 129 129 130 130 tcontext.fillStyle = tgradient; 131 131 tcontext.fillRect(0, 0, 256, 256); … … 134 134 //}}} 135 135 //{{{ text display 136 if (options.exist('textlabels')) { 137 var textcanvas, textcanvasid; 138 textcanvasid = options.getfieldvalue('textcanvasid', options.getfieldvalue('canvasid')+'-text'); 139 textcanvas = $('#'+textcanvasid); 140 textcanvas.textlabels = options.getfieldvalue('textlabels',[]); 136 var overlaycanvasid = options.getfieldvalue('overlayid', options.getfieldvalue('canvasid')+'-overlay'); 137 var overlaycanvas = $('#'+overlaycanvasid)[0]; 138 if (!isEmptyOrUndefined(overlaycanvas)) { 139 //Get drawing context and save reference on main WebGL canvas 140 var ctx = overlaycanvas.getContext('2d'); 141 canvas.overlaycanvas = overlaycanvas; 141 142 142 //setup drawing function for text canvas draw calls 143 textcanvas.draw = function(canvas) { 144 var textcontext, textlabels, textlabel, textcanvaswidth, textcanvasheight, textcoordinates; 145 var textposition = vec3.create(); 146 var mvpMatrix = mat4.create(); 147 148 //ensure correct canvas coordinate scaling 149 textcanvaswidth = this[0].clientWidth; 150 textcanvasheight = this[0].clientHeight; 151 this[0].width = textcanvaswidth; 152 this[0].height = textcanvasheight; 153 154 textcontext = this[0].getContext('2d'); 155 textlabels = options.getfieldvalue('textlabels',[]); 156 textcontext.clearRect(0, 0, textcanvaswidth, textcanvasheight); 157 158 //worldspace to screenspace transformation for text 159 for (text in textlabels) { 160 textlabel = textlabels[text]; 161 mat4.multiply(mvpMatrix, canvas.camera.vpMatrix, canvas.nodes.overlay.modelMatrix); 162 textposition = vec3.transformMat4(textposition, textlabel.pos, mvpMatrix); 163 if (textposition[2] > 1) { //clip coordinates with z > 1 164 continue; 165 } 166 textcoordinates = [(textposition[0]+1.0)/2.0*textcanvaswidth, (-textposition[1]+1.0)/2.0*textcanvasheight]; //NDC to screenspace 167 textcontext.font = String(options.getfieldvalue('colorbarfontsize', 18))+'px "Lato", Helvetica, Arial, sans-serif'; 168 textcontext.fillStyle = options.getfieldvalue('colorbarfontcolor','black'); 169 textcontext.strokeStyle = options.getfieldvalue('colorbarfontcolor','black'); 170 textcontext.textAlign = 'center'; 171 textcontext.textBaseline = 'middle'; 172 textcontext.fillText(textlabel.text, textcoordinates[0], textcoordinates[1]); 173 textcontext.strokeText(textlabel.text, textcoordinates[0], textcoordinates[1]); 174 } 175 } 176 canvas.textcanvas = textcanvas; 177 } //}}} 143 //Resize interal viewport coordinates to match screenspace coordinates 144 var rect = overlaycanvas.getBoundingClientRect(); 145 overlaycanvas.width = rect.width; 146 overlaycanvas.height = rect.height; 147 148 //Clear canvas each frame for any new drawings 149 canvas.overlayHandlers['draw'] = function(overlaycanvas) { 150 ctx.clearRect(0, 0, overlaycanvas.width, overlaycanvas.height); 151 } 152 } 178 153 //{{{ lat long overlay 179 154 if (options.exist('latlongoverlay')) { 180 var overlaycanvasid = options.getfieldvalue('latlongoverlayid', options.getfieldvalue('canvasid')+'-overlay');181 var overlaycanvas = $('#'+overlaycanvasid)[0];182 155 var latitudes = { 183 156 //'-90': 1, 184 157 //'-65': .999, 185 158 '-60': 0.994046875, 186 //'-55': 0.983187500000002,187 //'-50': 0.97173550854167,188 159 '-45': 0.955729166666666, 189 //'-40': 0.94218750000000218,190 //'-35': 0.94218750000000218,191 160 '-30': 0.9226562500000024, 192 //'-25': 0.87934895833333526,193 //'-20': 0.856572916666669,194 161 //'-15': 0.830729166666665, 195 //'-10': 0.803552708333336,196 //'-5': 0.77395833333333541,197 162 '0': 0.74218749999999811, 198 //'5': 0.70950364583333347,199 //'10': 0.67479166666666823,200 163 //'15': 0.63932291666666663, 201 //'20': 0.60171875,202 //'25': 0.563453125,203 164 '30': 0.523390625000001, 204 //'35': 0.48401875,205 //'40': 0.44296875,206 165 '45': 0.4020001, 207 //'50': 0.3578125,208 //'55': 0.311875,209 166 '60': 0.26953124999999978, 210 167 //'65': 0.225390625, 211 //'70': 0.18125,212 //'75': 0.13541666666666671,213 //'80': 0.08953125,214 //'85': 0.046250000000000013,215 168 //'90': 0.0, 216 169 } 217 170 var longitudes = [-150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180]; 218 overlaycanvas.draw = function(canvas) { 219 var rect = overlaycanvas.getBoundingClientRect(); 220 overlaycanvas.width = rect.width; 221 overlaycanvas.height = rect.height; 222 var ctx = overlaycanvas.getContext('2d'); 171 canvas.overlayHandlers['latlong'] = function(canvas) { 172 //Transform from world space to viewport space 223 173 var centerx = overlaycanvas.width / 2; 224 174 var centery = overlaycanvas.height / 2; 225 175 var radius = (overlaycanvas.height) / 2; 176 177 //Draw latitudes 226 178 ctx.setLineDash([5, 10]); 227 179 for(latitude in latitudes) { … … 229 181 ctx.arc(centerx, centery, radius * latitudes[latitude], 0, 2 * Math.PI); 230 182 ctx.stroke(); 231 ctx.font = String(options.getfieldvalue('colorbarfontsize', 18))+'px "Lato", Helvetica, Arial, sans-serif';183 ctx.font = 'bold ' + String(options.getfieldvalue('colorbarfontsize', 18))+'px "Lato", Helvetica, Arial, sans-serif'; 232 184 ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black'); 233 185 ctx.strokeStyle = options.getfieldvalue('colorbarfontcolor','black'); … … 237 189 ctx.strokeText(latitude, centerx, centery + radius * latitudes[latitude]); 238 190 } 191 //Draw longitudes 239 192 ctx.setLineDash([1, 0]); 240 193 for (longitude in longitudes) { … … 245 198 } 246 199 } 247 canvas.overlaycanvas = overlaycanvas; 200 } //}}} 201 if (options.exist('textlabels')) { 202 //Attatch new overlay handler to display text labels 203 var textLabels = options.getfieldvalue('textlabels',[]); 204 canvas.overlayHandlers['text'] = function(canvas) { 205 for (var i = 0; i < textLabels.length; i++) { 206 //Get text label to display 207 var textLabel = textLabels[i]; 208 textLabel = { 209 position: defaultFor(textLabel.position, vec3.create()), 210 text: defaultFor(textLabel.text, ''), 211 fontSize: defaultFor(textLabel.fontSize, 18), 212 fontColor: defaultFor(textLabel.fontColor, 'black'), 213 214 }; 215 216 // function declared in slr-gfm sim-front-end-controller.js 217 // if labels are behind the globe sphere then skip iteartion and do not display them 218 if (isLabelVisible(textLabel)) { 219 //Transform from world space to viewport space 220 var screenPoint = vec3.transformMat4(vec3.create(), textLabel.position, canvas.camera.vpMatrix); 221 var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left; 222 var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top; 223 224 //Draw text 225 ctx.font = 'bold ' + String(textLabel.fontSize) + 'px Arial Black, sans-serif'; 226 ctx.fillStyle = textLabel.fontColor; 227 ctx.strokeStyle = 'white'; 228 ctx.textAlign = 'center'; 229 ctx.textBaseline = 'middle'; 230 ctx.fillText(textLabel.text, x, y); 231 ctx.strokeText(textLabel.text, x, y); 232 } 233 } 234 } 248 235 } //}}} 249 236 //{{{ additional rendering nodes 250 237 if (options.exist('render')) { 251 238 var meshresults = processmesh(md, data, options); 252 var x = meshresults[0]; 253 var y = meshresults[1]; 254 var z = meshresults[2]; 239 var x = meshresults[0]; 240 var y = meshresults[1]; 241 var z = meshresults[2]; 255 242 var elements = meshresults[3]; 256 var is2d = meshresults[4]; 243 var is2d = meshresults[4]; 257 244 var isplanet = meshresults[5]; 258 245 259 246 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]); 260 247 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]); 261 248 var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]); 262 249 263 var global = vec3.length([(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2]) < 6371000/10; //tolerance for global models = center is 637100 meters away from center of earth 264 var translation = global ? [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2] : [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) - 6371000, (zlim[0] + zlim[1]) / 2];265 250 var global = vec3.length([(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2]) < 6371000/10; //tolerance for global models = center is 637100 meters away from center of earth 251 var translation = global ? [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2] : canvas.view.position; 252 266 253 var renderObjects = options.getfieldvalue('render',{}); 267 if ('sky' in renderObjects && !('sky' in canvas.nodes)) { 268 var object = renderObjects.sky; 254 for (var renderObject in renderObjects) { 255 //Modify renderObejct? 256 var object = renderObjects[renderObject]; 269 257 object = { 270 enabled: defaultFor(object.enabled, true), 271 scale: defaultFor(object.scale, 1), 258 enabled: defaultFor(object.enabled, true), //Toggle display of the render object node 259 scale: defaultFor(object.scale, 1), //Model matrix scaling 260 x: defaultFor(object.x, [0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), //x coordinate array 261 y: defaultFor(object.y, [0.0, 0.0, 0.0, 1.0, 0.0, 0.0]), //y coordinate array 262 z: defaultFor(object.z, [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]), //z coordinate array 263 indices: defaultFor(object.indices, []), //indices array 264 name: defaultFor(object.name, 'NY'), //Text to display for cities. 265 size: defaultFor(object.size, 1), //Physical size of the object in meters 266 color: defaultFor(object.color, 'black'), //Diffuse color of object 267 height: defaultFor(object.height, 25000), //Height of object along y axis, currently for clouds only 268 range: defaultFor(object.range, 120000), //Range of sz plane to spawn object, currently for clouds only 269 quantity: defaultFor(object.quantity, 15) //Quantity of objects to display, currently for clouds only 272 270 }; 273 if ( object.enabled) {274 var atmosphereScale = 1.25;275 var mesh = GL.Mesh.icosahedron({size: 6371000 * atmosphereScale, subdivisions: 5});271 if (!object.enabled) { continue; } 272 if ('sky' === renderObject && !('sky' in canvas.nodes)) { 273 var mesh = GL.Mesh.icosahedron({size: 6371000 * canvas.atmosphere.scaleHeight, subdivisions: 5}); 276 274 var texture = initTexture(gl, canvas.rootPath + 'textures/TychoSkymapII_t4_2k.jpg'); 277 275 node = new Node( 278 276 'canvas', canvas, 279 277 'options', options, 278 'renderObject', object, 280 279 'name', 'sky', 281 280 'shaderName', 'SkyFromSpace', … … 286 285 ); 287 286 } 288 } 289 if ('space' in renderObjects && !('space' in canvas.nodes)) { 290 var object = renderObjects.space; 291 object = { 292 enabled: defaultFor(object.enabled, true), 293 scale: defaultFor(object.scale, 1), 294 }; 295 if (object.enabled) { 287 if ('space' === renderObject && !('space' in canvas.nodes)) { 296 288 var mesh = GL.Mesh.sphere({size: 6371000 * 20}); 297 289 var texture = initTexture(gl, canvas.rootPath + 'textures/TychoSkymapII_t4_2k.jpg'); … … 299 291 'canvas', canvas, 300 292 'options', options, 293 'renderObject', object, 301 294 'name', 'space', 302 295 'shaderName', 'Textured', … … 308 301 ); 309 302 } 310 } 311 if ('coastlines' in renderObjects && !('coastlines' in canvas.nodes)) { 312 var object = renderObjects.coastlines; 313 object = { 314 enabled: defaultFor(object.enabled, false), 315 scale: defaultFor(object.scale, 1), 316 x: defaultFor(object.x, {}), 317 y: defaultFor(object.y, {}), 318 z: defaultFor(object.z, {}) 319 }; 320 if (object.enabled) { 321 node = new Node( 322 'canvas', canvas, 323 'options', options, 303 if ('coastlines' === renderObject && !('coastlines' in canvas.nodes)) { 304 node = new Node( 305 'canvas', canvas, 306 'options', options, 307 'renderObject', object, 324 308 'name', 'coastlines', 325 309 'shaderName', 'Colored', … … 331 315 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none'); 332 316 } 333 } 334 if ('graticule' in renderObjects && !('graticule' in canvas.nodes)) { 335 var object = renderObjects.graticule; 336 object = { 337 enabled: defaultFor(object.enabled, false), 338 scale: defaultFor(object.scale, 1), 339 x: defaultFor(object.x, {}), 340 y: defaultFor(object.y, {}), 341 z: defaultFor(object.z, {}) 342 }; 343 if (object.enabled) { 344 node = new Node( 345 'canvas', canvas, 346 'options', options, 317 if ('graticule' === renderObject && !('graticule' in canvas.nodes)) { 318 node = new Node( 319 'canvas', canvas, 320 'options', options, 321 'renderObject', object, 347 322 'name', 'graticule', 348 323 'shaderName', 'Colored', … … 350 325 'lineWidth', options.getfieldvalue('linewidth', 1), 351 326 'scale', [object.scale, object.scale, object.scale], 352 'rotation', [-90, 0, 0]327 'rotation', [-90, 180, 0] 353 328 ); 354 329 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none'); 355 330 } 356 } 357 if ('cities' in renderObjects && !('cities' in canvas.nodes)) { 358 var object = renderObjects.cities; 359 object = { 360 enabled: defaultFor(object.enabled, false), 361 scale: defaultFor(object.scale, 1), 362 size: defaultFor(object.size, 1.5), 363 color: defaultFor(object.color, 'black'), 364 x: defaultFor(object.x, {}), 365 y: defaultFor(object.y, {}), 366 z: defaultFor(object.z, {}), 367 indices: defaultFor(object.indices, {}) 368 }; 369 if (object.enabled) { 331 if ('cities' === renderObject && !('cities' in canvas.nodes)) { 370 332 var mesh = GL.Mesh.icosahedron({size: object.size, subdivisions: 1}); 371 333 node = new Node( 372 334 'canvas', canvas, 373 335 'options', options, 336 'renderObject', object, 374 337 'name', 'cities', 375 'shaderName', 'Colored ',338 'shaderName', 'ColoredDiffuse', 376 339 'diffuseColor', object.color, 377 340 'lineWidth', options.getfieldvalue('linewidth', 1), … … 381 344 node.geometryShader('Mesh', mesh, 'Vertices', [object.x, object.y, object.z], 'Indices', object.indices); 382 345 } 383 } 384 if ('city' in renderObjects) { 385 var object = renderObjects.city; 386 object = { 387 enabled: defaultFor(object.enabled, false), 388 name: defaultFor(object.name, 'NY'), 389 size: defaultFor(object.size, 15000), 390 color: defaultFor(object.color, 'magenta'), 391 x: defaultFor(object.x, {}), 392 y: defaultFor(object.y, {}), 393 z: defaultFor(object.z, {}) 394 }; 395 if (object.enabled) { 346 if ('axis' === renderObject && !('axis' in canvas.nodes)) { 347 node = new Node( 348 'canvas', canvas, 349 'options', options, 350 'renderObject', object, 351 'name', 'axis', 352 'shaderName', 'Colored', 353 'drawMode', gl.LINES, 354 'lineWidth', options.getfieldvalue('linewidth', 1), 355 'scale', [object.scale, object.scale, object.scale], 356 'rotation', [0, 0, 0] 357 ); 358 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none'); 359 } 360 if ('city' === renderObject) { 396 361 //city 397 362 var mesh = GL.Mesh.sphere({size: object.size}); … … 399 364 'canvas', canvas, 400 365 'options', options, 366 'renderObject', object, 401 367 'name', 'city', 402 'shaderName', 'Colored ',368 'shaderName', 'ColoredDiffuse', 403 369 'diffuseColor', object.color, 404 370 'mesh', mesh, 405 371 'translation', [object.x, object.z, -object.y] 406 372 ); 407 408 var overlaycanvasid = options.getfieldvalue('overlayid', options.getfieldvalue('canvasid')+'-overlay'); 409 var overlaycanvas = $('#'+overlaycanvasid)[0]; 410 overlaycanvas.draw = function(canvas) { 411 var rect = overlaycanvas.getBoundingClientRect(); 412 overlaycanvas.width = rect.width; 413 overlaycanvas.height = rect.height; 414 var ctx = overlaycanvas.getContext('2d'); 373 //Attatch new overlay handler to display city name 374 canvas.overlayHandlers['city'] = function(canvas) { 415 375 var node = canvas.nodes['city']; 416 node.translation = [object.x, object.z, -object.y]; 417 node.updateModelMatrix(); 376 var object = node.renderObject; 418 377 var screenPoint = vec3.transformMat4(vec3.create(), node.translation, canvas.camera.vpMatrix); 419 378 var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left; 420 379 var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top; 421 380 422 ctx.font = String(options.getfieldvalue('colorbarfontsize', 22))+'px Arial Black, sans-serif';381 ctx.font = 'bold ' + String(options.getfieldvalue('colorbarfontsize', 22))+'px Arial Black, sans-serif'; 423 382 ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black'); 424 383 ctx.strokeStyle = 'white'; … … 428 387 ctx.strokeText(object.name, x, y); 429 388 } 430 canvas.overlaycanvas = overlaycanvas; 431 } 432 } 433 if (canvas.clouds.enabled) { 434 //clouds 435 for (var i = 0; i < canvas.clouds.quantity; i++) { 389 } 390 if ('clouds' === renderObject && !('clouds0' in canvas.nodes)) { 391 //clouds 436 392 var mesh = GL.Mesh.fromURL(canvas.rootPath+'obj/cloud.obj'); 437 translation = [translation[0] + Math.floor((Math.random() * (1 + 12000 - (-12000)) + (-12000))), translation[1] - 405000, translation[2] + Math.floor((Math.random() * (1 + 12000 - (-12000)) + (-12000)))]; 438 node = new Node( 439 'canvas', canvas, 440 'options', options, 441 'name', 'clouds' + i, 442 'shaderName', 'Textured', 443 'animation', {'time': Date.now(),'target': translation,'current': translation}, 444 'diffuseColor', [0.7,0.7,0.7,1.0], 445 'mesh', mesh, 446 'scale', [2500, 2500, 2500], 447 'translation', translation 448 ); 393 for (var i = 0; i < object.quantity; i++) { 394 //TODO: More options, less magic numbers. Add animation. Better shading. 395 var offset = [ translation[0] + (Math.random() - 0.5) * 2 * object.range, 396 translation[1] + object.height + (Math.random() - 0.5) * 0.2 * object.range, 397 translation[2] + (Math.random() - 0.5) * 2 * object.range]; 398 node = new Node( 399 'canvas', canvas, 400 'options', options, 401 'renderObject', object, 402 'name', 'clouds' + i, 403 'shaderName', 'ColoredDiffuse', 404 'animation', {'time': Date.now(),'target': translation,'current': translation}, 405 'diffuseColor', [0.7,0.7,0.7,1.0], 406 'specularColor', [0.0,0.0,0.0,1.0], 407 'mesh', mesh, 408 'scale', [object.scale, object.scale, object.scale], 409 'translation', offset 410 ); 411 } 449 412 } 450 413 } -
issm/trunk-jpl/src/m/plot/plot_mesh.js
r21768 r21911 31 31 } 32 32 else { 33 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));33 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskscale',{})); 34 34 scale = [1, 1, 1]; 35 35 } -
issm/trunk-jpl/src/m/plot/plot_overlay.js
r21768 r21911 41 41 } 42 42 else { 43 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));43 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskscale',{})); 44 44 scale = [1, 1, 1]; 45 45 } … … 52 52 'options', options, 53 53 'name', 'overlay', 54 'shaderName', 'ground' in options.getfieldvalue('render', {}) ? 'GroundFromSpace' : 'Textured ',54 'shaderName', 'ground' in options.getfieldvalue('render', {}) ? 'GroundFromSpace' : 'TexturedDiffuse', 55 55 'alpha', options.getfieldvalue('outeralpha', 1.0), 56 56 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 57 57 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2], 58 'diffuseColor', 'white', 58 'ambientColor', [0.1, 0.1, 0.1 ,1.0], 59 'diffuseColor', [1.0, 1.0, 1.0 ,1.0], 60 'specularStrength', 0.0, 59 61 'maskEnabled', options.getfieldvalue('outermask','off') == 'on', 60 62 'maskHeight', options.getfieldvalue('outermaskheight', 150.0), … … 65 67 ); 66 68 //}}} 67 69 68 70 var xRange = xlim[1] - xlim[0]; 69 71 var yRange = ylim[1] - ylim[0]; 70 72 var coordArray = [new Array(x.length), new Array(x.length)]; 73 71 74 //generate mesh: 72 73 75 if (md.mesh.classname() == 'mesh3dsurface') { 74 76 var xyz, magnitude; … … 87 89 } 88 90 } 89 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', coordArray, 'FaceColor', 'interp' , 'EdgeColor', edgecolor);91 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', coordArray, 'FaceColor', 'interp'); 90 92 } //}}} -
issm/trunk-jpl/src/m/plot/plot_quiver.js
r21768 r21911 37 37 } 38 38 else { 39 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));39 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskscale',{})); 40 40 scale = [1, 1, 1]; 41 41 } -
issm/trunk-jpl/src/m/plot/plot_unit.js
r21768 r21911 13 13 //} 14 14 //else { 15 15 16 16 //{{{ declare variables: 17 17 //Process data and model … … 37 37 } 38 38 else { 39 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));39 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskscale',{})); 40 40 scale = [1, 1, 1]; 41 41 } 42 42 43 43 //Compute gl variables: 44 var edgecolor = options.getfieldvalue('edgecolor', 'black');44 var edgecolor = options.getfieldvalue('edgecolor', [1.0, 1.0, 1.0 ,1.0]); 45 45 var maskzeros = options.getfieldvalue('maskzeros', {}); 46 46 var node = new Node( … … 48 48 'options', options, 49 49 'name', 'unit', 50 'shaderName', 'Textured ',50 'shaderName', 'TexturedDiffuse', 51 51 'alpha', options.getfieldvalue('alpha', 1.0), 52 52 'caxis', options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]), 53 53 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 54 54 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2], 55 'lightingBias', 0.8, 55 56 'diffuseColor', edgecolor, 57 'specularStrength', 0.0, 56 58 'enabled', options.getfieldvalue('nodata','off') == 'off', 57 59 'log', options.getfieldvalue('log',false), -
issm/trunk-jpl/src/m/plot/webgl.js
r21768 r21911 9 9 if (!isEmptyOrUndefined(canvas.animation) && canvas.animation.handler !== 0) { clearInterval(canvas.animation.handler); } 10 10 initWebGL(canvas, options); 11 initializeMarker(canvas);12 11 draw(canvas); 13 12 canvas.initialized = true; 13 14 //The onStart event triggers once per plotmodel call load after WebGL and canvas initialization are complete 15 canvas.selector.trigger('onStart', [canvas]); 14 16 } 15 17 return canvas; … … 34 36 mc.add(new Hammer.Pan({threshold: 0, pointers: 0})); 35 37 mc.add(new Hammer.Pinch({threshold: 0})).recognizeWith(mc.get('pan')); 36 mc.on('tap press', function (ev) {onTap(ev, canvas);});38 mc.on('tap', function (ev) {onTap(ev, canvas);}); 37 39 mc.on('panstart panmove', function (ev) {onPan(ev, canvas, displayview);}); 38 mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);}); 40 mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);}); 39 41 canvas.addEventListener('mousewheel', function (ev) {onZoom(ev, canvas, displayzoom)}, false); 40 42 canvas.addEventListener('DOMMouseScroll', function (ev) {onZoom(ev, canvas, displayzoom)}, false); … … 46 48 canvas.unitData = {}; 47 49 canvas.unitMovieData = {}; 50 48 51 canvas.gl = gl; 49 52 canvas.rootPath = options.getfieldvalue('rootpath', '../../../js/'); … … 57 60 58 61 //Add context state variables 62 canvas.render = options.getfieldvalue('render', {}); 59 63 canvas.controlSensitivity = options.getfieldvalue('controlsensitivity', 1); 64 canvas.overlayHandlers = {}; 60 65 var backgroundcolor = new RGBColor(options.getfieldvalue('backgroundcolor', 'lightcyan')); 61 66 if (backgroundcolor.ok) { canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0]; } … … 63 68 64 69 //Property intiialization, using values from options first, then from default values. 70 var atmosphere = options.getfieldvalue('atmosphere', {}); 71 canvas.atmosphere = { //Default Values 72 wavelength_r: defaultFor(atmosphere.wavelength_r, 0.65), //0.65 Red wavelength (micrometers) 73 wavelength_g: defaultFor(atmosphere.wavelength_g, 0.57), //0.57 Green wavelength (micrometers) 74 wavelength_b: defaultFor(atmosphere.wavelength_b, 0.475), //0.475 Green wavelength (micrometers) 75 eSun: defaultFor(atmosphere.eSun, 100.0), //20.0 Sun intensity 76 kRayleigh: defaultFor(atmosphere.kRayleigh, 0.0025), //0.0025 Rayleigh scattering amount 77 kMie: defaultFor(atmosphere.kMie, 0.000), //0.01 Mie scattering amount 78 g: defaultFor(atmosphere.g, -0.99), //-0.99 Mie phase asymmetry/direction factor 79 hdr_exposure: defaultFor(atmosphere.hdr_exposure, 0.8), //0.8 High Dynamic Range Exposure 80 scaleHeight: defaultFor(atmosphere.scaleHeight, 1.25), //1.025 Scale of height of atmosphere to earth radius. 81 scaleDepth: defaultFor(atmosphere.scaleDepth, 0.25), //0.25 Percentage altitude at which the atmosphere's average density is found 82 a: defaultFor(atmosphere.a, -0.00287), //-0.00287 Scaling constant a 83 b: defaultFor(atmosphere.b, 0.459), //0.459 Scaling constant b 84 c: defaultFor(atmosphere.c, 3.83), //3.83 Scaling constant c 85 d: defaultFor(atmosphere.d, -6.80), //-6.80 Scaling constant d 86 e: defaultFor(atmosphere.e, 3.6), //5.25 Scaling constant e. Lower when increasing atmosphere scale. 87 attenuation: defaultFor(atmosphere.attenuation, 0.5) //0.5 Strength of atmospheric scattering on ground shading. 88 }; 89 updateAtmosphereParameters(canvas); 65 90 var animation = options.getfieldvalue('movies', {}); 66 91 canvas.animation = { 67 frame: defaultFor(animation.frame, 0),68 play: defaultFor(animation.play, true),69 increment: defaultFor(animation.increment, true),70 fps: defaultFor(animation.fps, 4),71 interval: defaultFor(animation.interval, 1000 / animation.fps),72 loop: defaultFor(animation.loop, true),73 handler: defaultFor(animation.handler, 0)92 frame: defaultFor(animation.frame, 0), 93 play: defaultFor(animation.play, true), 94 increment: defaultFor(animation.increment, true), 95 fps: defaultFor(animation.fps, 4), 96 interval: defaultFor(animation.interval, 1000 / defaultFor(animation.fps, 4)), 97 loop: defaultFor(animation.loop, true), 98 handler: defaultFor(animation.handler, 0) 74 99 } 75 100 var brush = options.getfieldvalue('brush', {}); 76 101 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, {})102 enabled: defaultFor(brush.enabled, false), 103 strength: defaultFor(brush.strength, 0.075), 104 falloff: defaultFor(brush.falloff, 0.5), 105 hit: defaultFor(brush.hit, {}) 81 106 }; 82 107 var camera = options.getfieldvalue('camera', {}); 83 108 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 hit: defaultFor(clouds.hit, {}) 109 position: defaultFor(camera.position, vec3.create()), 110 rotation: defaultFor(camera.rotation, quat.create()), 111 relativePosition: defaultFor(camera.relativePosition, vec3.create()), 112 direction: defaultFor(camera.direction, vec3.create()), 113 near: defaultFor(camera.near, 1e3), 114 far: defaultFor(camera.far, 1e10), 115 fov: defaultFor(camera.fov, 45), 116 vMatrix: defaultFor(camera.vMatrix, mat4.create()), 117 pMatrix: defaultFor(camera.pMatrix, mat4.create()), 118 vpMatrix: defaultFor(camera.vpMatrix, mat4.create()), 119 vInverseMatrix: defaultFor(camera.vInverseMatrix, mat4.create()), 120 pInverseMatrix: defaultFor(camera.pInverseMatrix, mat4.create()), 121 vpInverseMatrix: defaultFor(camera.vpInverseMatrix, mat4.create()), 122 ready: defaultFor(camera.ready, false) 103 123 }; 104 124 var dataMarkers = options.getfieldvalue('datamarkers', {}); 105 125 canvas.dataMarkers = { 106 enabled: defaultFor(dataMarkers.enabled, true),107 values: defaultFor(dataMarkers.values, []),108 image: defaultFor(dataMarkers.image, canvas.rootPath+'textures/data_marker.svg'),109 size: defaultFor(dataMarkers.size, [32, 32]),110 format: defaultFor(dataMarkers.format, ['X: %.2e<br>Y: %.2e<br>Z: %.2e<br>Value: %0.1f', 'x', 'y', 'z', 'value']),111 animated: defaultFor(dataMarkers.animated, false),112 labels: defaultFor(dataMarkers.labels, []),113 font: defaultFor(dataMarkers.font, ''),114 marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id)),115 reposition: defaultFor(dataMarkers.reposition, true)126 enabled: defaultFor(dataMarkers.enabled, true), 127 values: defaultFor(dataMarkers.values, []), 128 image: defaultFor(dataMarkers.image, canvas.rootPath + 'textures/data_marker.svg'), 129 size: defaultFor(dataMarkers.size, [32, 32]), 130 format: defaultFor(dataMarkers.format, ['X: %.2e<br>Y: %.2e<br>Z: %.2e<br>Value: %0.1f', 'x', 'y', 'z', 'value']), 131 animated: defaultFor(dataMarkers.animated, false), 132 labels: defaultFor(dataMarkers.labels, []), 133 font: defaultFor(dataMarkers.font, ''), 134 marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id)), 135 reposition: defaultFor(dataMarkers.reposition, true) 116 136 }; 117 137 var draw = options.getfieldvalue('draw', {}); 118 138 canvas.draw = { 119 ready: defaultFor(draw.ready, false),120 handler: defaultFor(draw.handler, null)139 ready: defaultFor(draw.ready, false), 140 handler: defaultFor(draw.handler, null) 121 141 }; 122 142 var view = options.getfieldvalue('view', {}); 123 143 canvas.view = { 124 position: defaultFor(view.position, [0.0, 0.0, 0.0]), 125 rotation: defaultFor(view.rotation, [0, 90]), 126 zoom: defaultFor(view.zoom, 1.0), 127 zoomLimits: defaultFor(view.zoomLimits, [0.001, 100.0]), 128 lastZoom: defaultFor(view.lastZoom, 1.0), 129 azimuthLimits: defaultFor(view.azimuthLimits, [0, 360]), 130 elevationLimits: defaultFor(view.elevationLimits, [-180, 180]), 131 panningEnabled: defaultFor(view.panningEnabled, false), 132 twod: defaultFor(view.twod, false) 144 position: defaultFor(view.position, [0.0, 0.0, 0.0]), 145 rotation: defaultFor(view.rotation, [0, 90]), 146 zoom: defaultFor(view.zoom, 1.0), 147 zoomLimits: defaultFor(view.zoomLimits, [0.001, 100.0]), 148 lastZoom: defaultFor(view.lastZoom, 1.0), 149 azimuthLimits: defaultFor(view.azimuthLimits, [0, 360]), 150 elevationLimits: defaultFor(view.elevationLimits, [-180, 180]), 151 panningEnabled: defaultFor(view.panningEnabled, false), 152 preventDefaultOnPan: defaultFor(view.preventDefaultOnPan, false), 153 twod: defaultFor(view.twod, false) 133 154 }; 134 155 … … 171 192 var shaders = {}; 172 193 shaders.Colored = new GL.Shader.fromURL(rootPath+'shaders/Colored.vsh', rootPath+'shaders/Colored.fsh', null, gl); 194 shaders.ColoredDiffuse = new GL.Shader.fromURL(rootPath+'shaders/ColoredDiffuse.vsh', rootPath+'shaders/ColoredDiffuse.fsh', null, gl); 173 195 shaders.Textured = new GL.Shader.fromURL(rootPath+'shaders/Textured.vsh', rootPath+'shaders/Textured.fsh', null, gl); 196 shaders.TexturedDiffuse = new GL.Shader.fromURL(rootPath+'shaders/TexturedDiffuse.vsh', rootPath+'shaders/TexturedDiffuse.fsh', null, gl); 174 197 shaders.SkyFromSpace = new GL.Shader.fromURL(rootPath+'shaders/SkyFromSpace.vert', rootPath+'shaders/SkyFromSpace.frag', null, gl); 175 198 shaders.GroundFromSpace = new GL.Shader.fromURL(rootPath+'shaders/GroundFromSpace.vert', rootPath+'shaders/GroundFromSpace.frag', null, gl); 176 shaders.Clouds = new GL.Shader.fromURL(rootPath+'shaders/Clouds.vert', rootPath+'shaders/Clouds.frag', null, gl);177 199 return shaders; 178 200 } //}}} … … 184 206 return gl.textures[imageSource]; 185 207 } //}}} 208 function updateAtmosphereParameters(canvas) { 209 //Precalculate derived atmosphere shader parameters 210 //TODO: Find a better way to structure this 211 var atm = canvas.atmosphere; 212 atm.inv_wavelength4 = [1.0 / Math.pow(atm.wavelength_r, 4), 1.0 / Math.pow(atm.wavelength_g, 4), 1.0 / Math.pow(atm.wavelength_b, 4)]; 213 atm.innerRadius = 6.371e6; 214 atm.innerRadius2 = atm.innerRadius * atm.innerRadius; 215 atm.outerRadius = atm.innerRadius * atm.scaleHeight; 216 atm.outerRadius2 = atm.outerRadius * atm.outerRadius; 217 atm.krESun = atm.kRayleigh * atm.eSun; 218 atm.kmESun = atm.kMie * atm.eSun; 219 atm.kr4PI = atm.kRayleigh * 4 * Math.PI; 220 atm.km4PI = atm.kMie * 4 * Math.PI; 221 atm.scale = 1.0 / (atm.outerRadius - atm.innerRadius); 222 atm.scaleOverScaleDepth = atm.scale / atm.scaleDepth; 223 atm.g2 = atm.g * atm.g; 224 canvas.atmosphere = atm; 225 } 186 226 function clamp(value, min, max) { //{{{ 187 227 return Math.max(min, Math.min(value, max)); … … 253 293 } //}}} 254 294 //}}} 255 //{{{ Inter faceFunctions295 //{{{ Interaction Functions 256 296 function onTap(ev, canvas) { //{{{ 257 //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.258 297 ev.preventDefault(); 259 298 260 if (canvas.clouds.enabled) { 261 for (var i = 0; i < canvas.clouds.quantity; i++) { 262 raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.nodes["clouds" + i]); 263 } 264 } 265 var hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.unitNode); 266 if ('cities' in canvas.nodes) { 267 var hitCities = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.nodes.cities); 268 canvas.nodes.cities.hit = hitCities; 269 updateCities(canvas); 270 } 271 272 canvas.brush.hit = hit; 273 274 if (canvas.dataMarkers.enabled) { 275 canvas.dataMarkers.marker.selector.closed = false; 276 canvas.dataMarkers.marker.hit = hit; 277 updateMarker(canvas, true); 278 } 279 280 brushModify(canvas); 299 var hit = raycastXY(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.unitNode); 300 301 //Trigger any handlers attatched to this canvas event. 302 canvas.selector.trigger('onTap', [ev, canvas, hit]); 281 303 } //}}} 282 304 function onPan(ev, canvas, displaylog) { //{{{ 283 305 ev.preventDefault(); 284 285 if (canvas.dataMarkers.enabled) {286 if (!isEmptyOrUndefined(canvas.unitNode)) {287 canvas.brush.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.unitNode);288 brushModify(canvas);289 }290 }291 292 if (canvas.clouds.enabled) {293 if (!isEmptyOrUndefined(canvas.nodes['overlay'])) {294 canvas.clouds.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.nodes['overlay']);295 updateClouds(canvas);296 }297 }298 306 299 307 if (ev.type === 'panstart') { … … 301 309 canvas.lastDeltaY = 0; 302 310 } 303 if (ev.srcEvent.shiftKey || ev.pointers.length === 2) { 304 if (!canvas.view.panningEnabled) return; 305 var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 306 var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 307 308 if (canvas.view.twod) { 309 canvas.view.position[0] += Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaX - Math.sin(DEG2RAD * 0) * deltaY; 310 canvas.view.position[2] += Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaX + Math.cos(DEG2RAD * 0) * deltaY; 311 312 //Trigger any handlers attatched to this canvas event. 313 canvas.selector.trigger('onPan', [ev, canvas]); 314 315 //If any onPan handler sets preventDefaultOnPan to true, skips default onPan camera behavior 316 if (!canvas.view.preventDefaultOnPan) { 317 //If panning with two fingers or shift key, translate camera center 318 if (ev.srcEvent.shiftKey || ev.pointers.length === 2) { 319 if (canvas.view.panningEnabled) { 320 var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 321 var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 322 323 //TODO: convert canvas.view.rotation from az/el euler to quaternion 324 if (canvas.view.twod) { 325 canvas.view.position[0] += Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaX - Math.sin(DEG2RAD * 0) * deltaY; 326 canvas.view.position[2] += Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaX + Math.cos(DEG2RAD * 0) * deltaY; 327 } 328 else { 329 canvas.view.position[0] += Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaX - Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaY; 330 canvas.view.position[2] += Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaX + Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaY; 331 } 332 } 311 333 } 334 //Else, rotate around camera center 312 335 else { 313 canvas.view.position[0] += Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaX - Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaY; 314 canvas.view.position[2] += Math.sin(DEG2RAD * canvas.view.rotation[0]) * deltaX + Math.cos(DEG2RAD * canvas.view.rotation[0]) * deltaY; 336 canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * 2 * canvas.controlSensitivity * RAD2DEG; 337 canvas.view.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG; 338 339 if (canvas.view.rotation[0] > 360) { canvas.view.rotation[0] -= 360; }; 340 if (canvas.view.rotation[0] < -360) { canvas.view.rotation[0] += 360; }; 341 if (canvas.view.rotation[1] > 180) { canvas.view.rotation[1] -= 360; }; 342 if (canvas.view.rotation[1] < -180) { canvas.view.rotation[1] += 360; }; 343 344 canvas.view.rotation[0] = clamp(canvas.view.rotation[0], canvas.view.azimuthLimits[0], canvas.view.azimuthLimits[1]); 345 canvas.view.rotation[1] = clamp(canvas.view.rotation[1], canvas.view.elevationLimits[0], canvas.view.elevationLimits[1]); 346 347 if (displaylog) { console.log(canvas.view.rotation); } 315 348 } 316 } 317 318 else { 319 canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * 2 * canvas.controlSensitivity * RAD2DEG; 320 canvas.view.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG; 321 322 if (canvas.view.rotation[0] > 360) { canvas.view.rotation[0] -= 360; }; 323 if (canvas.view.rotation[0] < -360) { canvas.view.rotation[0] += 360; }; 324 if (canvas.view.rotation[1] > 180) { canvas.view.rotation[1] -= 360; }; 325 if (canvas.view.rotation[1] < -180) { canvas.view.rotation[1] += 360; }; 326 327 canvas.view.rotation[0] = clamp(canvas.view.rotation[0], canvas.view.azimuthLimits[0], canvas.view.azimuthLimits[1]); 328 canvas.view.rotation[1] = clamp(canvas.view.rotation[1], canvas.view.elevationLimits[0], canvas.view.elevationLimits[1]) 329 } 349 } 350 351 canvas.view.preventDefaultOnPan = false; 330 352 canvas.lastDeltaX = ev.deltaX; 331 353 canvas.lastDeltaY = ev.deltaY; 332 333 canvas.dataMarkers.reposition = true;334 335 if (displaylog) { console.log(canvas.view.rotation); }336 354 } //}}} 337 355 function onPinch(ev, canvas, displaylog) { //{{{ 338 356 ev.preventDefault(); 339 357 if (ev.type === 'pinchstart') { canvas.view.lastZoom = canvas.view.zoom; } 340 else { modifyZoom(ev.scale * canvas.view.lastZoom, canvas, displaylog ); }358 else { modifyZoom(ev.scale * canvas.view.lastZoom, canvas, displaylog, ev, 0); } 341 359 } //}}} 342 360 function onZoom(ev, canvas, displaylog) { //{{{ 343 361 ev.preventDefault(); 344 var delta = clamp(ev.scale || ev.wheelDelta || -ev.detail, -1, 1) * canvas.controlSensitivity * canvas.view.zoom / 20; 345 modifyZoom(canvas.view.zoom + delta, canvas, displaylog); 346 } //}}} 347 function modifyZoom(value, canvas, displaylog) { //{{{ 348 canvas.view.zoom = clamp(value, canvas.view.zoomLimits[0], canvas.view.zoomLimits[1]); 349 canvas.dataMarkers.reposition = true; 350 if (displaylog) { console.log(canvas.view.zoom); } 351 } //}}} 352 function modifyDataMarkersEnabled(value, canvas) { //{{{ 353 canvas.dataMarkers.enabled = value; 362 var delta = clamp(ev.scale || ev.wheelDelta || -ev.detail, -1, 1) * canvas.controlSensitivity * canvas.view.zoom / 2; 363 modifyZoom(canvas.view.zoom + delta, canvas, displaylog, ev, 0); 364 } //}}} 365 function modifyZoom(value, canvas, displaylog, ev, duration) { //{{{ 366 if (isEmptyOrUndefined(duration)) duration = 200; 367 var targetZoom = clamp(value, canvas.view.zoomLimits[0], canvas.view.zoomLimits[1]); 368 var currentZoom = canvas.view.zoom; 369 animateValue( 370 0, 371 1.0, 372 duration, 373 function(value, info) { 374 canvas.view.zoom = currentZoom * (1 - value) + targetZoom * value; 375 if (displaylog) { console.log(canvas.view.zoom); } 376 377 //Trigger any handlers attatched to this canvas event. 378 canvas.selector.trigger('onZoom', [ev, canvas]); 379 } 380 ); 354 381 } //}}} 355 382 function toggleMoviePlay(canvas) { //{{{ … … 364 391 } 365 392 } //}}} 366 //}}} 367 //{{{ Interaction Functions 368 function raycast(canvas, x, y, node) { //{{{ 369 //Performs raycast on canvas.unitNode.mesh using x/y screen coordinates. Returns hit objects with hit position, coords, and indicies of ray-triangle intersection. 393 function screenToWorldPoint(canvas, x, y) { //{{{ 394 var viewportX = (x - canvas.width / 2) / (canvas.width / 2); 395 var viewportY = (canvas.height / 2 - y) / (canvas.height / 2); 396 var origin = vec3.transformMat4(vec3.create(), [viewportX, viewportY, 0], canvas.camera.vpInverseMatrix); 397 return origin; 398 } //}}} 399 function screenToModelRay(canvas, x, y, node) { //{{{ 400 var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.camera.vpMatrix, node.modelMatrix)); 401 var viewportX = (x - canvas.width / 2) / (canvas.width / 2); 402 var viewportY = (canvas.height / 2 - y) / (canvas.height / 2); 403 var origin = vec3.transformMat4(vec3.create(), [viewportX, viewportY, 0], inverseMVPMatrix); 404 var far = vec3.transformMat4(vec3.create(), [viewportX, viewportY, 1.0], inverseMVPMatrix); 405 var direction = vec3.subtract(vec3.create(), far, origin); 406 return {'origin':origin, 'direction':direction}; 407 } //}}} 408 function raycast(canvas, origin, direction, node) { //{{{ 409 //Performs raycast on given node using ray origin and direction vectors. 410 //Returns hit objects with hit position, normals, barycentric coordinates, element number, and indices of ray-triangle intersection. 370 411 //TODO: Diagnose marker issues with orthographic views and slr-eustatic updates when switching between basins. 371 var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.camera.vpMatrix, node.modelMatrix)); 372 var origin = vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 0], inverseMVPMatrix); 373 var far = far || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 1.0], inverseMVPMatrix); 374 var ray = vec3.subtract(vec3.create(), far, origin); 375 376 var mesh = node.mesh; 377 378 if (!mesh) { return; } 379 if (!node.octree) { node.octree = new GL.Octree(mesh); } 380 381 var hit = node.octree.testRay(origin, ray, 1e3, 1e10); 382 383 if(!hit) { return; } 384 385 if (node.name.startsWith("clouds")) { canvas.clouds.selected = node.name; alert("New selected cloud: " + canvas.clouds.selected); } 412 if (!node.octree) { node.octree = new GL.Octree(node.mesh); } 413 414 var hit = node.octree.testRay(origin, direction, 1e3, 1e10); 415 if (!hit) { return; } 386 416 387 417 hit.modelPos = vec3.copy(vec3.create(), hit.pos); 388 418 vec3.transformMat4(hit.pos, hit.pos, node.modelMatrix); 389 vec3.transformMat4(hit.normal, hit.normal, node.modelMatrix); 390 419 391 420 return hit; 392 421 } //}}} 393 function updateCities(canvas) { 394 //Update selected city 395 var hit = canvas.nodes.cities.hit; 396 if (hit) { 397 citiesIndex = Math.floor(hit.indices[0] / ((ArrayMax(canvas.nodes.cities.mesh.getIndexBuffer('triangles').data) + 1) / cities.length)); 398 cityName = cities[citiesIndex]; 399 if (cityName !== $('#gfm-sim-controls-select-city').val()) { 400 $('#gfm-sim-controls-select-city').val(cityName).selectmenu("refresh"); 401 changeCity(canvas); 402 } 403 } 404 } 405 function brushModify(canvas) { //{{{ 406 //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. 407 //Currently the brush extends to the raycasted element and its immediate neighbors. 408 //TODO: Allow variable brush size/additional neighbors. Allow the function to work on multiple models (currently hardcoded to md model). 409 if (!canvas.unitNode || canvas.brush.enabled != 'on') { return; } 410 411 var hit = canvas.brush.hit; 412 413 if (hit) { 414 var bufferVertices = canvas.unitNode.mesh.getBuffer('vertices'); 415 var vertices = bufferVertices.data; 416 var bufferCoords = canvas.unitNode.mesh.getBuffer('coords'); 417 var coords = bufferCoords.data; 418 419 //Query nearby elements and store indicies of affected vertices using pregenerated vertexconnectivity list (from NodeConnectivity) 420 var baseIndices = new Set(hit.indices); 421 var connectedIndices = new Set(hit.indices); 422 var connectedElement; 423 var indices; 424 var lengthIndex = md.mesh.vertexconnectivity[0].length - 1; 425 var length; 426 for (var i = 0; i < 3; i++) { 427 length = md.mesh.vertexconnectivity[hit.indices[i]][lengthIndex]; 428 for (var j = 0; j < length; j++) { 429 //Shift elements down by one (matlab 1-based index to 0-based index) 430 connectedElement = md.mesh.vertexconnectivity[hit.indices[i]][j] - 1; 431 indices = md.mesh.elements[connectedElement]; 432 connectedIndices.add(indices[0] - 1); 433 connectedIndices.add(indices[1] - 1); 434 connectedIndices.add(indices[2] - 1); 435 } 436 } 437 438 //Apply modifications to included vertices in mesh using brush strength and falloff. 439 var strength; 440 for (var index of connectedIndices) { 441 if (!baseIndices.has(index)) { 442 strength = canvas.brush.strength * canvas.brush.falloff; 443 } 444 else { 445 strength = canvas.brush.strength; 446 } 447 vertices[index*3+2] += strength * 100; 448 md.geometry.surface[index] += strength; 449 md.geometry.thickness[index] += strength; 450 coords[index*2+1] += strength; 451 canvas.unitData[index] += strength; 452 } 453 454 //Update mesh on GPU 455 bufferVertices.upload(canvas.gl.DYNAMIC_DRAW); 456 bufferCoords.upload(canvas.gl.DYNAMIC_DRAW); 457 canvas.unitNode.octree = new GL.Octree(canvas.unitNode.mesh); 458 } 459 } //}}} 460 function updateClouds(canvas) { 461 //Update clouds if rendered 462 //TODO: Steven, the hit now queries the radaroverlay. 463 if (canvas.nodes[canvas.clouds.selected]) { 464 var v1 = vec3.fromValues(vertices[hit.indices[0] * 3], vertices[hit.indices[0] * 3 + 1], vertices[hit.indices[0] * 3 + 2]); 465 var v2 = vec3.fromValues(vertices[hit.indices[1] * 3], vertices[hit.indices[1] * 3 + 1], vertices[hit.indices[1] * 3 + 2]); 466 var v3 = vec3.fromValues(vertices[hit.indices[2] * 3], vertices[hit.indices[2] * 3 + 1], vertices[hit.indices[2] * 3 + 2]); 467 vec3.transformMat4(v1, v1, canvas.unitNode.modelMatrix);//move out of brushModify, perhaps onto onPan 468 vec3.transformMat4(v2, v2, canvas.unitNode.modelMatrix); 469 vec3.transformMat4(v3, v3, canvas.unitNode.modelMatrix); 470 var x = (v1[0] + v2[0] + v3[0]) / 3;// + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000))); 471 var y = (v1[1] + v2[1] + v3[1]) / 3;// + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000))); 472 var z = (v1[2] + v2[2] + v3[2]) / 3; 473 canvas.nodes[canvas.clouds.selected].translation = [x, y + canvas.clouds.height, z]; 474 updateModelMatrix(canvas.nodes[canvas.clouds.selected]); 475 } 476 } 477 function initializeMarker(canvas) { //{{{ 478 //Initialize data marker and tooltip display once per page load 479 var marker = $('#' + canvas.dataMarkers.marker.id); 480 var size = canvas.dataMarkers.size; 481 if (!marker.hasClass('tooltipstered')) { 482 marker.css({ 483 'position': 'absolute', 484 'left': -size[0] + 'px', 485 'top': -size[1] + '0px', 486 'width': size[0] + 'px', 487 'height': size[1] + 'px', 488 'pointer-events': 'all', 489 'cursor': 'pointer', 490 'display': 'none' 491 }); 492 marker.tooltipster({ 493 contentAsHTML: true, 494 maxWidth: 320, 495 maxHeight: 320, 496 zIndex: 1000, 497 trigger: 'custom', 498 triggerOpen: { 499 mouseenter: false, 500 originClick: true, 501 touchstart: false 502 }, 503 triggerClose: { 504 mouseleave: false, 505 originClick: true, 506 touchleave: false 507 }, 508 }); 509 marker.on('click touch', function () { 510 marker.fadeOut(175); 511 marker.tooltipster('close'); 512 marker.closed = true; 513 }); 514 marker.closed = false; 515 canvas.dataMarkers.marker.selector = marker; 516 } 517 updateMarker(canvas, true); 518 } //}}} 519 function repositionMarker(canvas) { //{{{ 520 //Mover marker to point to mouse position, offset in y by 1 to enable immediate clicking. 521 //Return if no marker hit exists, the camera is not rendering, or if no reposition has been scheduled. 522 if (isEmptyOrUndefined(canvas.dataMarkers.marker.hit) || !canvas.camera.ready || !canvas.dataMarkers.reposition) { return; } 523 var size = canvas.dataMarkers.size; 524 var screenPoint = vec3.transformMat4(vec3.create(), canvas.dataMarkers.marker.hit.pos, canvas.camera.vpMatrix); 525 var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left; 526 var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top; 527 canvas.dataMarkers.marker.selector.css({ 528 'left': (Math.round(x) - size[0] / 2) + 'px', 529 'top': (Math.round(y) - size[1] + 1) + 'px' 530 }); 531 if (canvas.dataMarkers.marker.selector.tooltipster('status').state != 'closed') { canvas.dataMarkers.marker.selector.tooltipster('reposition'); } 532 canvas.dataMarkers.reposition = false; 533 } //}}} 534 function updateMarker(canvas, reset) { //{{{ 535 //Retrieve data value fields and plots them on data marker popup if a hit has been registered. 536 //TODO: Automatically pick up any field of size md.mesh.numberofelements 537 //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. 538 if (!canvas.dataMarkers.enabled || isEmptyOrUndefined(canvas.dataMarkers.marker.hit)) { return; } 539 if (isEmptyOrUndefined(canvas.unitNode) || isEmptyOrUndefined(canvas.unitNode.mesh)) { setTimeout( function(){ updateMarker(canvas, reset); }, 750); return; } 540 541 var hit = canvas.dataMarkers.marker.hit; 542 543 var coords = canvas.unitNode.mesh.vertexBuffers.coords.data; 544 var latitude = md.mesh.lat; 545 var longitude = md.mesh.long; 546 var thickness; 547 var velocity; 548 if (md.results[0]) { 549 thickness = md.results[canvas.animation.frame].Thickness; 550 velocity = md.results[canvas.animation.frame].Vel; 551 } 552 else { 553 thickness = md.geometry.thickness; 554 velocity = md.initialization.vel; 555 } 556 557 //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. 558 var labels = canvas.dataMarkers.labels.slice(); 559 for (var i = 0; i < labels.length; i++) { 560 if (labels[i].toLowerCase() === 'x') { labels[i] = hit.modelPos[0]; } 561 else if (labels[i].toLowerCase() === 'y') { labels[i] = hit.modelPos[1]; } 562 else if (labels[i].toLowerCase() === 'z') { labels[i] = hit.modelPos[2]; } 563 else if (labels[i].toLowerCase() === 'latitude') { 564 var hitLatitude = [latitude[hit.indices[0]], latitude[hit.indices[1]], latitude[hit.indices[2]]]; 565 var valueLatitude = Math.abs(hitLatitude[0] * hit.uvw[0] + hitLatitude[1] * hit.uvw[1] + hitLatitude[2] * hit.uvw[2]); 566 labels[i] = valueLatitude; 567 } 568 else if (labels[i].toLowerCase() === 'longitude') { 569 var hitLongitude = [longitude[hit.indices[0]], longitude[hit.indices[1]], longitude[hit.indices[2]]]; 570 var valueLongitude = Math.abs(hitLongitude[0] * hit.uvw[0] + hitLongitude[1] * hit.uvw[1] + hitLongitude[2] * hit.uvw[2]); 571 labels[i] = valueLongitude; 572 } 573 else if (labels[i].toLowerCase() === 'thickness') { 574 var hitThickness = [thickness[hit.indices[0]], thickness[hit.indices[1]], thickness[hit.indices[2]]]; 575 var valueThickness = hitThickness[0] * hit.uvw[0] + hitThickness[1] * hit.uvw[1] + hitThickness[2] * hit.uvw[2]; 576 labels[i] = valueThickness; 577 } 578 else if (labels[i].toLowerCase() === 'velocity') { 579 var hitVelocity = [velocity[hit.indices[0]], velocity[hit.indices[1]], velocity[hit.indices[2]]]; 580 var valueVelocity = hitVelocity[0] * hit.uvw[0] + hitVelocity[1] * hit.uvw[1] + hitVelocity[2] * hit.uvw[2]; 581 labels[i] = valueVelocity; 582 } 583 else if (labels[i].toLowerCase() === 'value') { 584 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]]; 585 var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2]; 586 var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2]; 587 var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v; 588 labels[i] = value; 589 } 590 } 591 592 //Apply changes to tooltip 593 $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, canvas.dataMarkers.format.concat(labels))); 594 $('#tooltip-content-data-marker-' + canvas.id).css({'font': canvas.dataMarkers.font}); 595 596 //If animated, setup animation loop to update plot as movie plays. 597 if (canvas.dataMarkers.animated) { 598 var isEmpty = (canvas.dataMarkers.values.length === 0); 599 var lastUpdatedIndex = (canvas.dataMarkers.values.length - 1); 600 var newMovieFrame = (!isEmpty && canvas.dataMarkers.values[lastUpdatedIndex][0] != canvas.animation.frame); 601 //If new data marker has been placed, reinitialize plot. If not, push new value into plot value array. 602 if (reset) { 603 canvas.dataMarkers.values = []; 604 newMovieFrame = true; 605 for (var currentFrame = 0; currentFrame < (canvas.unitNode.movieLength); currentFrame++) { 606 coords = canvas.unitMovieData[currentFrame]; 607 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 var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2]; 609 var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2]; 610 var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v; 611 canvas.dataMarkers.values.push([currentFrame, value]); 612 } 613 } 614 else { 615 if (canvas.animation.lastFrame > canvas.animation.frame) { 616 canvas.dataMarkers.values = []; 617 } 618 if (isEmpty || newMovieFrame) { 619 coords = canvas.unitMovieData[canvas.animation.frame]; 620 var hitValues = [coords[hit.indices[0]], coords[hit.indices[1]], coords[hit.indices[2]]]; 621 var value = hitValues[0] * hit.uvw[0] + hitValues[1] * hit.uvw[1] + hitValues[2] * hit.uvw[2]; 622 canvas.dataMarkers.values.push([canvas.animation.frame, value]); 623 } 624 } 625 626 //Replot data marker popup using update data value array. 627 if (isEmpty || newMovieFrame) { 628 var dataLabels = {'latitude': valueLatitude, 'longitude': valueLongitude, 'thickness': valueThickness, 'velocity': valueVelocity, 'value': value}; 629 var dataDisplay = canvas.dataMarkers.values.slice(0, canvas.animation.frame + 1); 630 plot( 631 'id', '#sim-plot', 632 'type', 'bar', 633 'width', 400, 634 'height', 300, 635 'nticks', 25, 636 'xlabel', 'Time', 637 'ylabel', 'Value', 638 'title', 'Changes Over Time', 639 'datalabels', canvas.dataMarkers.labels, 640 'labelvalues', dataLabels, 641 'data', dataDisplay 642 ); 643 } 644 } 645 canvas.dataMarkers.reposition = true; 646 if (reset && !canvas.dataMarkers.marker.selector.closed) { 647 canvas.dataMarkers.marker.selector.fadeIn(175); 648 canvas.dataMarkers.marker.selector.tooltipster('open'); 649 } 422 function raycastXY(canvas, x, y, node) { //{{{ 423 //Performs raycast on given node using x and y screenspace coordinates. 424 //Returns hit objects with hit position, normals, barycentric coordinates, element number, and indices of ray-triangle intersection. 425 //TODO: Diagnose marker issues with orthographic views and slr-eustatic updates when switching between basins. 426 var ray = screenToModelRay(canvas, x, y, node); 427 return raycast(canvas, ray.origin, ray.direction, node); 650 428 } //}}} 651 429 function animateValue(current, target, duration, stepCallback, doneCallback) { //{{{ … … 669 447 var elevationRotationMatrix = mat4.create(); 670 448 var aspectRatio = canvas.clientWidth / canvas.clientHeight; 671 var cameraPosition = vec3.create(); 672 673 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); } 674 else { mat4.perspective(pMatrix, canvas.camera.fov * DEG2RAD, aspectRatio, canvas.camera.near, canvas.camera.far); } 449 var camera = canvas.camera; 450 var view = canvas.view; 451 452 if (view.twod) { mat4.ortho(pMatrix, -aspectRatio*6.371e6/view.zoom, aspectRatio*6.371e6/view.zoom, -6.371e6/view.zoom, 6.371e6/view.zoom, camera.near, camera.far); } 453 else { mat4.perspective(pMatrix, camera.fov * DEG2RAD, aspectRatio, camera.near, camera.far); } 675 454 676 455 //Apply worldspace translation 677 mat4.translate(vMatrix, translateMatrix, vec3.negate(vec3.create(), canvas.view.position));456 mat4.translate(vMatrix, translateMatrix, vec3.negate(vec3.create(), view.position)); 678 457 679 458 //Calculate rotation around camera focal point about worldspace origin 680 if ( canvas.view.twod) {459 if (view.twod) { 681 460 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * 0, [0, 1, 0]); 682 461 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * 90, [1, 0, 0]); … … 684 463 } 685 464 else { 686 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * ( canvas.view.rotation[0] + 90), [0, 1, 0]);687 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * canvas.view.rotation[1], [1, 0, 0]);465 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * (view.rotation[0] + 90), [0, 1, 0]); 466 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * view.rotation[1], [1, 0, 0]); 688 467 mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix); 468 //var quaternionWorldX = Node.prototype.eulerToQuaternion(0, 0, DEG2RAD * (view.rotation[0])); 469 //var quaternionWorldY = Node.prototype.eulerToQuaternion(0, DEG2RAD * (view.rotation[1]), 0); 470 //var quaternionWorldZ = Node.prototype.eulerToQuaternion(DEG2RAD * (view.rotation[2]), 0, 0); 471 //var quaternionTemp = quat.multiply(quat.create(), quaternionWorldY, quaternionWorldX); 472 //quat.multiply(camera.rotation, quaternionWorldZ, quaternionTemp); 473 //mat4.fromQuat(rotationMatrix, camera.rotation); 689 474 } 690 475 … … 694 479 //Apply screenspace translation to emulate rotation around point 695 480 mat4.identity(translateMatrix); 696 mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, -6.371e6/ canvas.view.zoom]);481 mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, -6.371e6/view.zoom]); 697 482 mat4.multiply(vMatrix, translateMatrix, vMatrix); 698 483 699 484 //Apply projection matrix to get camera matrix 700 mat4.copy(ca nvas.camera.vMatrix, vMatrix);701 mat4.multiply(ca nvas.camera.vpMatrix, pMatrix, vMatrix);485 mat4.copy(camera.vMatrix, vMatrix); 486 mat4.multiply(camera.vpMatrix, pMatrix, vMatrix); 702 487 703 488 //Calculate inverse view matrix fields for lighting and raycasts 704 mat4.invert(canvas.camera.vInverseMatrix, canvas.camera.vMatrix); 705 mat4.invert(canvas.camera.vpInverseMatrix, canvas.camera.vpMatrix); 706 707 vec3.transformMat4(canvas.camera.position, cameraPosition, canvas.camera.vpInverseMatrix); 708 canvas.camera.ready = true; 709 repositionMarker(canvas); 489 mat4.invert(camera.vInverseMatrix, camera.vMatrix); 490 mat4.invert(camera.vpInverseMatrix, camera.vpMatrix); 491 492 vec3.transformMat4(camera.position, vec3.create(), camera.vInverseMatrix); 493 vec3.sub(camera.relativePosition, camera.position, view.position); 494 vec3.normalize(camera.direction, camera.relativePosition); 495 496 camera.ready = true; 710 497 }//}}} 711 498 function drawSceneGraphNode(canvas, node) { //{{{ … … 718 505 mat4.multiply(mvpMatrix, canvas.camera.vpMatrix, node.modelMatrix); 719 506 720 var mvMatrix = mat4.create(); 721 mat4.multiply(mvMatrix, canvas.camera.vMatrix, node.modelMatrix); 722 723 var normalMatrix = mat4.create(); 724 mat4.invert(normalMatrix, node.modelMatrix); 725 mat4.transpose(normalMatrix, normalMatrix); 507 var normalMatrix = mat3.create(); 508 var tempMatrix = mat4.create(); 509 mat4.invert(tempMatrix, node.modelMatrix); 510 mat4.transpose(tempMatrix, tempMatrix); 511 mat3.fromMat4(normalMatrix, tempMatrix); 726 512 727 513 if (node.texture) { node.texture.bind(0); } … … 732 518 gl.lineWidth(node.lineWidth); 733 519 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 734 520 735 521 //Setup for light that originates from camera 736 var origin = vec3.fromValues(0, 0, 0); 737 var lightOrigin = vec3.fromValues(0, 0, 0); 738 var cameraPositionRelative = vec3.create(); 739 vec3.transformMat4(origin, origin, canvas.camera.vInverseMatrix); 740 vec3.normalize(lightOrigin, lightOrigin); 741 vec3.sub(cameraPositionRelative, origin, node.translation); 742 cameraHeight = vec3.length(cameraPositionRelative); 743 744 var atm = { //Default Values 745 wavelength_r: 0.65, //0.65 Red wavelength (micrometers) 746 wavelength_g: 0.57, //0.57 Green wavelength (micrometers) 747 wavelength_b: 0.475, //0.475 Green wavelength (micrometers) 748 eSun: 100.0, //20.0 Sun intensity 749 kRayleigh: 0.0025, //0.0025 Rayleigh scattering amount 750 kMie: 0.000, //0.01 Mie scattering amount 751 g: -0.99, //-0.99 Mie phase asymmetry/direction factor 752 hdr_exposure: 0.8, //0.8 High Dynamic Range Exposure 753 scale: 1.25, //1.025 Scale of atmosphere. WARNING: Change atmosphereScale in applyoptions.js, and scaling constants. 754 scaleDepth: 0.25, //0.25 Percentage altitude at which the atmosphere's average density is found 755 a: -0.00287, //-0.00287 Scaling constant a 756 b: 0.459, //0.459 Scaling constant b 757 c: 3.83, //3.83 Scaling constant c 758 d: -6.80, //-6.80 Scaling constant d 759 e: 3.6, //5.25 Scaling constant e. Lower when increasing atmosphere scale. 760 attenuation: 0.5 //0.5 Strength of atmospheric scattering on ground shading. 761 }; 762 763 var inv_wavelength4 = [1.0 / Math.pow(atm.wavelength_r, 4), 1.0 / Math.pow(atm.wavelength_g, 4), 1.0 / Math.pow(atm.wavelength_b, 4)]; 764 var innerRadius = 6.371e6; 765 var outerRadius = innerRadius*atm.scale; 766 var scale = 1.0 / (outerRadius - innerRadius); 767 var scaleDepth = atm.scaleDepth; 522 var atm = canvas.atmosphere; 523 var lightOrigin = vec3.create(); 768 524 769 525 node.shader.uniforms({ 770 m4MVP: mvpMatrix, 771 m4Normal: normalMatrix, 772 m4Model: node.modelMatrix, 773 u_lightPosition: lightOrigin, 774 //u_lightPosition: [1.0, 1.0, 1.0], 775 u_diffuseColor: node.diffuseColor, 776 u_texture: 0, 777 u_alpha: node.alpha, 778 u_maskZerosColor: node.maskZerosColor, 779 u_maskZerosEnabled: node.maskZerosEnabled, 780 u_maskZerosTolerance: node.maskZerosTolerance, 781 u_maskZerosZeroValue: node.maskZerosZeroValue, 782 u_maskEnabled: node.maskEnabled, 783 u_maskHeight: node.maskHeight, 784 u_maskColor: node.maskColor, 785 u_pointSize: node.pointSize, 786 v3CameraPosition: origin, 787 v3Translate: node.translation, 788 v3LightPos: lightOrigin, 789 v3InvWavelength: inv_wavelength4, 790 fOuterRadius: outerRadius, 791 fOuterRadius2: outerRadius * outerRadius, 792 fInnerRadius: innerRadius, 793 fInnerRadius2: innerRadius * innerRadius, 794 fKrESun: atm.kRayleigh * atm.eSun, 795 fKmESun: atm.kMie * atm.eSun, 796 fKr4PI: atm.kRayleigh * 4 * Math.PI, 797 fKm4PI: atm.kMie * 4 * Math.PI, 798 fScale: scale, 799 fScaleDepth: scaleDepth, 800 fScaleOverScaleDepth: scale/scaleDepth, 801 v3LightPosFrag: lightOrigin, 802 fHdrExposure: atm.hdr_exposure, 803 g: atm.g, 804 g2: atm.g * atm.g, 805 a: atm.a, 806 b: atm.b, 807 c: atm.c, 808 d: atm.d, 809 e: atm.e, 810 attenuation: atm.attenuation 526 m4MVP: mvpMatrix, 527 m3Normal: normalMatrix, 528 m4Model: node.modelMatrix, 529 u_alpha: node.alpha, 530 u_ambientColor: node.ambientColor, 531 u_cameraPosition: canvas.camera.position, 532 u_diffuseColor: node.diffuseColor, 533 u_lightDirection: canvas.camera.direction, 534 u_lightingBias: node.lightingBias, 535 u_maskZerosColor: node.maskZerosColor, 536 u_maskZerosEnabled: node.maskZerosEnabled, 537 u_maskZerosTolerance: node.maskZerosTolerance, 538 u_maskZerosZeroValue: node.maskZerosZeroValue, 539 u_maskEnabled: node.maskEnabled, 540 u_maskHeight: node.maskHeight, 541 u_maskColor: node.maskColor, 542 u_pointSize: node.pointSize, 543 u_specularColor: node.specularColor, 544 u_specularPower: node.specularPower, 545 u_specularStrength: node.specularStrength, 546 u_texture: 0, 547 v3CameraPosition: canvas.camera.position, 548 v3Translate: node.translation, 549 v3LightPos: lightOrigin, 550 v3InvWavelength: atm.inv_wavelength4, 551 fOuterRadius: atm.outerRadius, 552 fOuterRadius2: atm.outerRadius2, 553 fInnerRadius: atm.innerRadius, 554 fInnerRadius2: atm.innerRadius2, 555 fKrESun: atm.krESun, 556 fKmESun: atm.kmESun, 557 fKr4PI: atm.kr4PI, 558 fKm4PI: atm.km4PI, 559 fScale: atm.scale, 560 fScaleDepth: atm.scaleDepth, 561 fScaleOverScaleDepth: atm.scaleOverScaleDepth, 562 v3LightPosFrag: lightOrigin, 563 fHdrExposure: atm.hdr_exposure, 564 g: atm.g, 565 g2: atm.g2, 566 a: atm.a, 567 b: atm.b, 568 c: atm.c, 569 d: atm.d, 570 e: atm.e, 571 attenuation: atm.attenuation 811 572 }).draw(node.mesh, node.drawMode, 'triangles'); 812 573 … … 814 575 gl.disable(gl.CULL_FACE); 815 576 } //}}} 577 function canvasResize(canvas) { 578 var rect = canvas.getBoundingClientRect(); 579 canvas.width = rect.width; 580 canvas.height = rect.height; 581 canvas.gl.viewport(0, 0, canvas.width, canvas.height); 582 583 if (!isEmptyOrUndefined(canvas.overlaycanvas)) { 584 rect = canvas.overlaycanvas.getBoundingClientRect(); 585 canvas.overlaycanvas.width = rect.width; 586 canvas.overlaycanvas.height = rect.height; 587 } 588 } 816 589 function draw(canvas) { //{{{ 817 590 //Ensure all nodes are ready to render … … 833 606 //Begin rendering nodes 834 607 if (canvas.draw.ready) { 835 var rect = canvas.getBoundingClientRect(); 836 canvas.width = rect.width; 837 canvas.height = rect.height; 608 //Handle canvas resizing and viewport/screenspace coordinate synchronization 609 canvasResize(canvas); 838 610 839 611 var gl = canvas.gl; 840 612 gl.makeCurrent(); //litegl function to handle switching between multiple canvases 841 gl.viewport(0, 0, canvas.width, canvas.height);842 613 gl.clearColor(canvas.backgroundcolor[0], canvas.backgroundcolor[1], canvas.backgroundcolor[2], canvas.backgroundcolor[3]); 843 614 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); … … 845 616 updateCameraMatrix(canvas); 846 617 847 if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); } 848 if (canvas.overlaycanvas) { canvas.overlaycanvas.draw(canvas); } 618 //Trigger any handlers attatched to this canvas event. 619 canvas.selector.trigger('onPreRender', [canvas]); 620 621 for (var handler in canvas.overlayHandlers) { canvas.overlayHandlers[handler](canvas); } 849 622 850 623 var drawPassNumber = 3; -
issm/trunk-jpl/src/m/plot/webgl_node.js
r21768 r21911 6 6 7 7 function Node() { //{{{ 8 //properties 8 //properties 9 9 // {{{ 10 10 var args = Array.prototype.slice.call(arguments); … … 15 15 this.gl = canvas.gl; 16 16 17 this.alpha = options.getfieldvalue('alpha', 1.0), 18 this.animation = options.getfieldvalue('animation', {}), 19 this.arrays = options.getfieldvalue('arrays', {}), 20 this.caxis = options.getfieldvalue('caxis', [0.0, 1.0]), 21 this.center = options.getfieldvalue('center', vec3.create()), 22 this.cullFace = options.getfieldvalue('cullFace', this.gl.BACK), 23 this.computeIndices = options.getfieldvalue('computeIndices', true), 24 this.disableDepthTest = options.getfieldvalue('disableDepthTest', false), 25 this.diffuseColor = options.getfieldvalue('diffuseColor', [0.0, 0.0, 0.0, 1.0]), 26 this.drawMode = options.getfieldvalue('drawMode', this.gl.TRIANGLES), 27 this.drawOrder = options.getfieldvalue('drawOrder', 1), 28 this.enabled = options.getfieldvalue('enabled', true), 29 this.enableCullFace = options.getfieldvalue('enableCullFace', true), 30 this.hideOcean = options.getfieldvalue('hideOcean', false), 31 this.lineWidth = options.getfieldvalue('lineWidth', 1.0), 32 this.log = options.getfieldvalue('log', false), 33 this.maskColor = options.getfieldvalue('maskColor', vec4.fromValues(0.0, 0.0, 1.0, 1.0)), 34 this.maskEnabled = options.getfieldvalue('maskEnabled', false), 35 this.maskHeight = options.getfieldvalue('maskHeight', 150.0), 36 this.maskZerosColor = options.getfieldvalue('maskZerosColor', [1.0, 1.0, 1.0, 1.0]), 37 this.maskZerosEnabled = options.getfieldvalue('maskZerosEnabled', false), 38 this.maskZerosTolerance = options.getfieldvalue('maskZerosTolerance', 1e-6), 39 this.maskZerosZeroValue = options.getfieldvalue('maskZerosZeroValue', 0.5), 40 this.mesh = options.getfieldvalue('mesh', undefined), 41 this.name = options.getfieldvalue('name', 'node'), 42 this.nanIndices = options.getfieldvalue('nanIndices', new Set()), 43 this.octree = options.getfieldvalue('octree', undefined), 44 this.pointSize = options.getfieldvalue('pointSize', 15.0), 45 this.shaderName = options.getfieldvalue('shaderName', 'Colored'), 46 this.shader = options.getfieldvalue('shader', this.gl.shaders[this.shaderName]), 47 this.texture = options.getfieldvalue('texture', undefined), 48 this.scale = options.getfieldvalue('scale', vec3.fromValues(1, 1, 1)), 49 this.rotation = options.getfieldvalue('rotation', vec3.create()), 50 this.translation = options.getfieldvalue('translation', vec3.create()), 51 this.modelMatrix = options.getfieldvalue('modelMatrix', mat4.create()), 52 this.rotationMatrix = options.getfieldvalue('rotationMatrix', mat4.create()), 53 this.inverseModelMatrix = options.getfieldvalue('inverseModelMatrix', mat4.create()), 54 this.inverseRotationMatrix = options.getfieldvalue('inverseRotationMatrix', mat4.create()) 17 this.alpha = options.getfieldvalue('alpha', 1.0); //Shading transparency. 18 this.ambientColor = options.getfieldvalue('ambientColor', [0.0, 0.0, 0.0, 1.0]); //Ambient color used in lighting. 19 this.animation = options.getfieldvalue('animation', {}); //Animtation parameters. 20 this.arrays = options.getfieldvalue('arrays', {}); //Storage for webgl arrays. 21 this.caxis = options.getfieldvalue('caxis', [0.0, 1.0]); //Color axis for texturing. 22 this.center = options.getfieldvalue('center', vec3.create()); //Center of rotation/scaling. 23 this.cullFace = options.getfieldvalue('cullFace', this.gl.BACK); //GL enum for face culling back/front faces. 24 this.computeIndices = options.getfieldvalue('computeIndices', true); //Specifies whether or not indices need to be computed during patching. 25 this.disableDepthTest = options.getfieldvalue('disableDepthTest', false); //GL enum for enabling/disabling depth testing. 26 this.diffuseColor = options.getfieldvalue('diffuseColor', [0.0, 0.0, 0.0, 1.0]); //Diffuse color in vec4 rgba format. 27 this.drawMode = options.getfieldvalue('drawMode', this.gl.TRIANGLES); //GL enum for draw mode. 28 this.drawOrder = options.getfieldvalue('drawOrder', 1); //Drawing order for non-depth tested/transparent objects. Higher numbers are drawn. first. 29 this.enabled = options.getfieldvalue('enabled', true); //Toggles display of this nodde. 30 this.enableCullFace = options.getfieldvalue('enableCullFace', true); //Toggles use of face culling. 31 this.hideOcean = options.getfieldvalue('hideOcean', false); //ISSM shader uniform controlling ocean masking 32 this.lineWidth = options.getfieldvalue('lineWidth', 1.0); //Controls width of gl lines. No reliable support across windows platforms. 33 this.lightingBias = options.getfieldvalue('lightingBias', 0.0); //Controls width of gl lines. No reliable support across windows platforms. 34 this.log = options.getfieldvalue('log', false); //Controls logarithmic color axis scaling for texturing. 35 this.maskColor = options.getfieldvalue('maskColor', vec4.fromValues(0.0, 0.0, 1.0, 1.0)); //ISSM shader uniform controlling ocean masking color. 36 this.maskEnabled = options.getfieldvalue('maskEnabled', false); //ISSM shader uniform toggling ocean masking. 37 this.maskHeight = options.getfieldvalue('maskHeight', 150.0); //ISSM shader uniform controlling height at which ocean masking is cut off. 38 this.maskZerosColor = options.getfieldvalue('maskZerosColor', [1.0, 1.0, 1.0, 1.0]); //ISSM shader uniform controlling value masking color. 39 this.maskZerosEnabled = options.getfieldvalue('maskZerosEnabled', false); //ISSM shader uniform toggling value masking. 40 this.maskZerosTolerance = options.getfieldvalue('maskZerosTolerance', 1e-6); //ISSM shader uniform controlling tolerance of value to zero value when masking. 41 this.maskZerosZeroValue = options.getfieldvalue('maskZerosZeroValue', 0.5); //ISSM shader uniform controlling zero value masking offset. 42 this.mesh = options.getfieldvalue('mesh', undefined); //Litegl GL.Mesh class used for drawing. 43 this.name = options.getfieldvalue('name', 'node'); //Name of node. 44 this.nanIndices = options.getfieldvalue('nanIndices', new Set()); //Set of NaN indices to mask out of mesh. 45 this.octree = options.getfieldvalue('octree', undefined); //Fast raytracing octree object. 46 this.pointSize = options.getfieldvalue('pointSize', 15.0); //Size of points when displaying GL.POINTS. 47 this.shaderName = options.getfieldvalue('shaderName', 'Colored'); //Name of shader to use. 48 this.shader = options.getfieldvalue('shader', this.gl.shaders[this.shaderName]); //Compiled shader object. 49 this.specularColor = options.getfieldvalue('specularColor', [1.0, 1.0, 1.0, 1.0]); //Specular reflection color used in lighting. 50 this.specularStrength = options.getfieldvalue('specularStrength', 1.0); //Specular reflection power - represents specular highlight sharpness. 51 this.specularPower = options.getfieldvalue('specularPower', 5); //Specular reflection power - represents specular highlight sharpness. 52 this.texture = options.getfieldvalue('texture', undefined); //GL texture object. 53 this.scale = options.getfieldvalue('scale', vec3.fromValues(1, 1, 1)); //XYZ scaling of the node. 54 this.renderObject = options.getfieldvalue('renderObject', {}); //Field for additional render object state information not necessarily related to node display. 55 this.rotation = options.getfieldvalue('rotation', vec3.create()); //XYZ rotation of the node. 56 this.rotationQuaternion = options.getfieldvalue('rotationQuaternion', quat.create()); //Quaternion rotation of the node. Not currently in use. 57 this.translation = options.getfieldvalue('translation', vec3.create()); //XYZ translation of the node. 58 this.modelMatrix = options.getfieldvalue('modelMatrix', mat4.create()); //Model matrix computed from updateModelMatrix function. 59 this.translationMatrix = options.getfieldvalue('translationMatrix', mat4.create()); //Intermediate translation matrix computed from updateModelMatrix function. 60 this.rotationMatrix = options.getfieldvalue('rotationMatrix', mat4.create()); //Intermediate rotation matrix computed from updateModelMatrix function. 61 this.scaleMatrix = options.getfieldvalue('scaleMatrix', mat4.create()); //Intermediate scale matrix computed from updateModelMatrix function. 62 this.inverseModelMatrix = options.getfieldvalue('inverseModelMatrix', mat4.create()); //Inverse model matrix. 63 this.inverseRotationMatrix = options.getfieldvalue('inverseRotationMatrix', mat4.create()); //Inverse rotation matrix. 55 64 //}}} 56 65 //initialize {{{ 57 //if (this.name in canvas.nodes) abort? 66 //if (this.name in canvas.nodes) abort? 58 67 this.updateModelMatrix(); 59 68 this.updateDiffuseColor(); 60 69 canvas.nodes[this.name] = this; 61 70 //}}} 71 } //}}} 72 Node.prototype.eulerToQuaternion = function(pitch, roll, yaw) { //{{{ 73 var t0 = Math.cos(yaw * 0.5); 74 var t1 = Math.sin(yaw * 0.5); 75 var t2 = Math.cos(roll * 0.5); 76 var t3 = Math.sin(roll * 0.5); 77 var t4 = Math.cos(pitch * 0.5); 78 var t5 = Math.sin(pitch * 0.5); 79 80 var w = t0 * t2 * t4 + t1 * t3 * t5; 81 var x = t0 * t3 * t4 - t1 * t2 * t5; 82 var y = t0 * t2 * t5 + t1 * t3 * t4; 83 var z = t1 * t2 * t4 - t0 * t3 * t5; 84 return quat.fromValues(x, y, z, w); 85 } //}}} 86 Node.prototype.quaternionToEuler = function(q) { //{{{ 87 var ysqr = q[1] * q[1]; 88 89 // roll (x-axis rotation) 90 var t0 = +2.0 * (q[3] * q[0] + q[1] * q[2]); 91 var t1 = +1.0 - 2.0 * (q[0] * q[0] + ysqr); 92 var roll = Math.atan2(t0, t1); 93 94 // pitch (y-axis rotation) 95 var t2 = +2.0 * (q[3] * q[1] - q[2] * q[0]); 96 t2 = t2 > 1.0 ? 1.0 : t2; 97 t2 = t2 < -1.0 ? -1.0 : t2; 98 var pitch = Math.asin(t2); 99 100 // yaw (z-axis rotation) 101 var t3 = +2.0 * (q[3] * q[2] + q[0] * q[1]); 102 var t4 = +1.0 - 2.0 * (ysqr + q[2] * q[2]); 103 var yaw = Math.atan2(t3, t4); 104 105 return [pitch * RAD2DEG, roll * RAD2DEG, yaw * RAD2DEG]; 62 106 } //}}} 63 107 Node.prototype.updateModelMatrix = function() { //{{{ … … 83 127 mat4.rotate(xRotationMatrix, xRotationMatrix, DEG2RAD * this.rotation[0], [1.0, 0.0, 0.0]); 84 128 mat4.multiply(rotationMatrix, xRotationMatrix, rotationMatrix); 85 mat4.multiply(modelMatrix, rotationMatrix, modelMatrix); 129 mat4.multiply(modelMatrix, rotationMatrix, modelMatrix); 130 131 //var rotationQuaternionX = this.eulerToQuaternion(0, -DEG2RAD * this.rotation[0], 0); 132 //var rotationQuaternionY = this.eulerToQuaternion(DEG2RAD * this.rotation[1], 0, 0); 133 //mat4.fromQuat(this.rotationMatrix, quat.multiply(quat.create(), rotationQuaternionY, rotationQuaternionX)); 134 135 //mat4.multiply(this.modelMatrix, this.rotationMatrix, this.modelMatrix); 136 86 137 87 138 mat4.identity(translationMatrix); … … 124 175 Node.prototype.patch = function() { //{{{ 125 176 //Emulates the behavior of MATLAB patch function by constructing a mesh from arguments. 126 //Limitations: 177 //Limitations: 127 178 // -Expects pair labeled arguments ('FaceColor','none',...). 128 179 // -Only handles Face/Vertices/FaceVertexCData element/node plots. … … 149 200 150 201 this.mesh = GL.Mesh.load(this.arrays, null, null, this.gl); 151 //this.mesh.computeNormals();202 this.mesh.computeNormals(); 152 203 this.computeOctree(); 153 204 } //}}} … … 239 290 if (this.log !== false && this.log !== 'off') { 240 291 caxis = [ 241 Math.log10(caxis[0]) / Math.log10(this.log), 292 Math.log10(caxis[0]) / Math.log10(this.log), 242 293 Math.log10(caxis[1]) / Math.log10(this.log) 243 294 ]; … … 389 440 var j = 0; 390 441 if (isEmptyOrUndefined(indices)) { 391 for (var key in object) { 442 for (var key in coordinateObject) { 443 console.log(key); 392 444 array[j++] = coordinateObject[key]; 393 445 } … … 407 459 var meshVertices = mesh.getBuffer('vertices').data; 408 460 var meshIndicies = mesh.getIndexBuffer('triangles').data; 409 var indic ies = new Uint16Array(meshIndicies.length * x.length);461 var indices = new Uint16Array(meshIndicies.length * x.length); 410 462 var size = meshVertices.length * x.length / 3; 411 463 newX = new Float32Array(size); … … 423 475 var offset = i * meshVertices.length / 3; 424 476 for (var j = 0; j < meshIndicies.length;) { 425 indic ies[e++] = meshIndicies[j++] + offset;426 } 427 } 428 429 this.patch('Faces', indic ies, 'Vertices', [newX, newY, newZ], 'FaceColor', 'interp');430 } //}}} 431 Node.prototype.scaleVertices = function(md, x, y, z, scale) { //{{{477 indices[e++] = meshIndicies[j++] + offset; 478 } 479 } 480 481 this.patch('Faces', indices, 'Vertices', [newX, newY, newZ], 'FaceColor', 'interp'); 482 } //}}} 483 Node.prototype.scaleVertices = function(md, x, y, z, elements, scale, maskObject) { //{{{ 432 484 //Scales and returns vertices x, y, and z by factor scale. Uses md.geometry.scale for heightscaling in 3d meshes. 433 485 if (md.mesh.classname() === 'mesh3dsurface') { 434 var xyz, magnitude; 435 x = x.slice(); 436 y = y.slice(); 437 z = z.slice(); 438 for(var i = 0; i < x.length; i++) { 439 xyz = vec3.fromValues(x[i], y[i], z[i]); 440 magnitude = 1 + md.geometry.surface[i] * scale / vec3.length(xyz); 441 vec3.scale(xyz, xyz, magnitude); 442 x[i] = xyz[0]; 443 y[i] = xyz[1]; 444 z[i] = xyz[2]; 486 if (!maskObject.enabled) { 487 var xyz, magnitude; 488 x = x.slice(); 489 y = y.slice(); 490 z = z.slice(); 491 for(var i = 0; i < x.length; i++) { 492 xyz = vec3.fromValues(x[i], y[i], z[i]); 493 magnitude = 1 + md.geometry.surface[i] * scale / vec3.length(xyz); 494 vec3.scale(xyz, xyz, magnitude); 495 x[i] = xyz[0]; 496 y[i] = xyz[1]; 497 z[i] = xyz[2]; 498 } 499 } 500 else { 501 var mask = maskObject.mask; 502 var maskScale = maskObject.scale; 503 var element; 504 for (var i = 0; i < mask.length; i++) { 505 if (mask[i] === 1) { 506 element = elements[i]; 507 for (var j = 0; j < 3; j++) { 508 xyz = vec3.fromValues(x[element[j] - 1], y[element[j] - 1], z[element[j] - 1]); 509 magnitude = 1 + md.geometry.surface[element[j] - 1] * scale * maskScale / vec3.length(xyz); 510 vec3.scale(xyz, xyz, magnitude); 511 x[element[j] - 1] = xyz[0]; 512 y[element[j] - 1] = xyz[1]; 513 z[element[j] - 1] = xyz[2]; 514 } 515 516 } 517 } 445 518 } 446 519 } -
issm/trunk-jpl/src/m/solve/WriteData.js
r21147 r21911 60 60 else{ 61 61 if (!IsArray(data)) data=data*scale; 62 else ArrayScale(data,scale);62 else data=ArrayScale(data,scale); 63 63 } 64 64 }
Note:
See TracChangeset
for help on using the changeset viewer.