source:
issm/oecreview/Archive/21724-22754/ISSM-21767-21768.diff
Last change on this file was 22755, checked in by , 7 years ago | |
---|---|
File size: 131.7 KB |
-
../trunk-jpl/src/m/plot/webgl.js
5 5 canvas = document.getElementById(options.getfieldvalue('canvasid')); 6 6 //var canvas = document.getElementById(options.getfieldvalue('canvasid')); 7 7 if (!canvas.initialized) { 8 typedArraySliceSupport();9 8 if (!isEmptyOrUndefined(canvas.draw) && canvas.draw.handler !== 0) { window.cancelAnimationFrame(canvas.draw.handler); } 10 9 if (!isEmptyOrUndefined(canvas.animation) && canvas.animation.handler !== 0) { clearInterval(canvas.animation.handler); } 11 10 initWebGL(canvas, options); 12 11 initializeMarker(canvas); 13 canvas.nodes = [];14 12 draw(canvas); 15 13 canvas.initialized = true; 16 14 } … … 18 16 } 19 17 function initWebGL(canvas, options) { //{{{ 20 18 //Initialize canvas.gl on page load, reusing gl context on additional runs 21 var gl ;22 if ( !canvas.gl) {19 var gl = canvas.gl; 20 if (isEmptyOrUndefined(gl)) { 23 21 gl = GL.create({canvas: canvas}); 24 22 gl.enable(gl.DEPTH_TEST); // Enable depth testing 25 23 gl.depthFunc(gl.LEQUAL); // Near things obscure far things … … 30 28 gl.textures = {}; 31 29 32 30 // 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' }) ); 31 var displayview = options.getfieldvalue('displayview', 'off') === 'on'; 32 var displayzoom = options.getfieldvalue('displayzoom', 'off') === 'on'; 33 var mc = new Hammer(canvas); 38 34 mc.add(new Hammer.Pan({threshold: 0, pointers: 0})); 39 35 mc.add(new Hammer.Pinch({threshold: 0})).recognizeWith(mc.get('pan')); 40 mc.on(' singletap', function (ev) {onTap(ev, canvas);});36 mc.on('tap press', function (ev) {onTap(ev, canvas);}); 41 37 mc.on('panstart panmove', function (ev) {onPan(ev, canvas, displayview);}); 42 mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);}); 43 38 mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);}); 44 39 canvas.addEventListener('mousewheel', function (ev) {onZoom(ev, canvas, displayzoom)}, false); 45 40 canvas.addEventListener('DOMMouseScroll', function (ev) {onZoom(ev, canvas, displayzoom)}, false); 41 42 //Add persistent state variables 43 canvas.nodes = {}; 44 canvas.octrees = {}; 45 canvas.unitNode = {}; 46 canvas.unitData = {}; 47 canvas.unitMovieData = {}; 48 canvas.gl = gl; 49 canvas.rootPath = options.getfieldvalue('rootpath', '../../../js/'); 50 canvas.id = options.getfieldvalue('canvasid', '.sim-canvas'); 51 canvas.selector = $('#' + canvas.id); 52 canvas.textcanvas = null; 53 canvas.overlaycanvas = null; 54 55 typedArraySliceSupport(); 46 56 } 47 else {48 gl = canvas.gl;49 }50 57 51 // Add context state variables 52 canvas.gl = gl; 53 canvas.textcanvas = null; 54 canvas.overlaycanvas = null; 55 canvas.unitNode = {}; 56 canvas.unitData = {}; 58 //Add context state variables 57 59 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 60 var backgroundcolor = new RGBColor(options.getfieldvalue('backgroundcolor', 'lightcyan')); 62 61 if (backgroundcolor.ok) { canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0]; } 63 62 else { throw Error(sprintf('s%s%s\n','initWebGL error message: cound not find out background color for curent canvas ', canvas)); } … … 69 68 play: defaultFor(animation.play, true), 70 69 increment: defaultFor(animation.increment, true), 71 70 fps: defaultFor(animation.fps, 4), 71 interval: defaultFor(animation.interval, 1000 / animation.fps), 72 72 loop: defaultFor(animation.loop, true), 73 73 handler: defaultFor(animation.handler, 0) 74 74 } … … 98 98 canvas.clouds = { 99 99 enabled: defaultFor(clouds.enabled, false), 100 100 height: defaultFor(clouds.height, 7500), 101 quantity: defaultFor(clouds.quantity, 10) 101 quantity: defaultFor(clouds.quantity, 10), 102 hit: defaultFor(clouds.hit, {}) 102 103 }; 103 104 var dataMarkers = options.getfieldvalue('datamarkers', {}); 104 105 canvas.dataMarkers = { … … 110 111 animated: defaultFor(dataMarkers.animated, false), 111 112 labels: defaultFor(dataMarkers.labels, []), 112 113 font: defaultFor(dataMarkers.font, ''), 113 marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id)) 114 marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id)), 115 reposition: defaultFor(dataMarkers.reposition, true) 114 116 }; 115 117 var draw = options.getfieldvalue('draw', {}); 116 118 canvas.draw = { … … 133 135 //Override with parameters from URL, if any 134 136 //TODO: Make permalinks more robust and less interdependent on UI 135 137 if (!canvas.usedparemters) { 136 function getJsonFromUrl() { 137 var query = location.search.substr(1); 138 var result = {}; 139 query.split('&').forEach(function(part) { 140 var item = part.split('='); 141 result[item[0]] = decodeURIComponent(item[1]); 142 }); 143 return result; 144 } 145 parameters = getJsonFromUrl(); 146 147 if (parameters['view']) { 148 canvas.view = JSON.parse(parameters['view']); 149 } 138 var parameters = {}; 139 location.search.substr(1).split('&').forEach(function(part) { 140 var item = part.split('='); 141 parameters[item[0]] = decodeURIComponent(item[1]); 142 }); 143 144 if (parameters['pos']) { canvas.view.position = JSON.parse(parameters['pos']); } 145 if (parameters['rot']) { canvas.view.rotation = JSON.parse(parameters['rot']); } 146 if (parameters['zoom']) { canvas.view.zoom = JSON.parse(parameters['zoom']); } 147 if (parameters['twod']) { canvas.view.twod = JSON.parse(parameters['twod']); } 150 148 if (parameters['initial']) { 151 149 initial = JSON.parse(parameters['initial']); 152 150 if (!initial) { 153 if (typeof SolveGlacier == 'function') {151 if (typeof SolveGlacier === 'function') { 154 152 SolveGlacier(); 155 153 } 156 if (typeof SolveSlr == 'function') {154 if (typeof SolveSlr === 'function') { 157 155 SolveSlr(); 158 156 } 159 157 } … … 162 160 } 163 161 } //}}} 164 162 function generatePermalink() { //{{{ 165 var permalink = window.location.origin + window.location.pathname + '&view=' + JSON.stringify(canvas.view) + '&initial=' + JSON.stringify(initial); 163 var permalink = window.location.origin + window.location.pathname + '?' 164 + '&pos=' + encodeURIComponent(JSON.stringify(canvas.view.position)) 165 + '&rot=' + encodeURIComponent(JSON.stringify(canvas.view.rotation)) 166 + '&zoom=' + encodeURIComponent(JSON.stringify(canvas.view.zoom)) 167 + '&twod=' + encodeURIComponent(JSON.stringify(canvas.view.twod)); 166 168 window.prompt('Share this simulation: ', permalink); 167 169 } //}}} 168 170 function loadShaders(gl, rootPath) { //{{{ … … 181 183 } 182 184 return gl.textures[imageSource]; 183 185 } //}}} 184 function Node(gl) { //{{{185 //Returns a Node object that contains default display states for webgl object. center represents pivot point of rotation.186 return {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()214 };215 } //}}}216 function debugNodes(canvasid) { //{{{217 var canvasid = canvasid || '.sim-canvas';218 var nodes = document.getElementById(canvasid).nodes;219 console.log(canvasid, 'Nodes:');220 for (var node in nodes) {221 console.log('name: ', nodes[node].name, ' node: ', nodes[node], ' mesh: ', nodes[node].mesh, ' translation: ', nodes[node].translation, ' center:', nodes[node].center, ' rotation:', nodes[node].rotation);222 }223 return nodes;224 } //}}}225 function updateModelMatrix(node) { //{{{226 var modelMatrix = mat4.create();227 228 var translationMatrix = mat4.create();229 mat4.translate(translationMatrix, translationMatrix, vec3.negate(vec3.create(), node.center)); //scale/rotation centering230 mat4.multiply(modelMatrix, translationMatrix, modelMatrix);231 232 var scaleMatrix = mat4.create();233 mat4.scale(scaleMatrix, scaleMatrix, node.scale);234 mat4.multiply(modelMatrix, scaleMatrix, modelMatrix);235 236 var rotationMatrix = mat4.create();237 var zRotationMatrix = mat4.create();238 mat4.rotate(zRotationMatrix, zRotationMatrix, DEG2RAD * node.rotation[2], [0.0, 0.0, 1.0]);239 mat4.multiply(rotationMatrix, zRotationMatrix, rotationMatrix);240 var yRotationMatrix = mat4.create();241 mat4.rotate(yRotationMatrix, yRotationMatrix, DEG2RAD * node.rotation[1], [0.0, 1.0, 0.0]);242 mat4.multiply(rotationMatrix, yRotationMatrix, rotationMatrix);243 var xRotationMatrix = mat4.create();244 mat4.rotate(xRotationMatrix, xRotationMatrix, DEG2RAD * node.rotation[0], [1.0, 0.0, 0.0]);245 mat4.multiply(rotationMatrix, xRotationMatrix, rotationMatrix);246 mat4.multiply(modelMatrix, rotationMatrix, modelMatrix);247 248 mat4.identity(translationMatrix);249 mat4.translate(translationMatrix, translationMatrix, node.center); //relative translation250 mat4.multiply(modelMatrix, translationMatrix, modelMatrix);251 252 mat4.identity(translationMatrix);253 mat4.translate(translationMatrix, translationMatrix, node.translation); //absolute translation254 mat4.multiply(modelMatrix, translationMatrix, modelMatrix);255 256 node.modelMatrix = modelMatrix;257 node.inverseModelMatrix = mat4.invert(mat4.create(), modelMatrix);258 node.rotationMatrix = rotationMatrix;259 node.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix);260 } //}}}261 186 function clamp(value, min, max) { //{{{ 262 187 return Math.max(min, Math.min(value, max)); 263 188 } //}}} … … 265 190 return typeof name !== 'undefined' ? name : value; 266 191 } //}}} 267 192 function isEmptyOrUndefined(object) { //{{{ 268 return object === undefined || Object.getOwnPropertyNames(object).length === 0;193 return object === undefined || isEmpty(object); 269 194 } //}}} 195 function isEmpty(object) { //{{{ 196 for (var key in object) { 197 return false; 198 } 199 return true; 200 } //}}} 270 201 function recover(canvasid, name, value) { //{{{ 271 202 //Traverse canvas object tree for property defined by dot delimited string, returning it, or a default value if it is not found. 272 203 var object = document.getElementById(canvasid); 273 204 var properties = name.split('.'); 274 for (var i = 0; i < properties.length; ++i) {205 for (var i = 0; i < properties.length; i++) { 275 206 object = object[properties[i]]; 276 if ( typeof object === 'undefined') { break; }207 if (isEmptyOrUndefined(object)) { break; } 277 208 } 278 209 return defaultFor(object, value); 279 210 } //}}} … … 325 256 function onTap(ev, canvas) { //{{{ 326 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. 327 258 ev.preventDefault(); 328 if (!canvas.dataMarkers.enabled) { return; } 329 var hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY); 330 canvas.dataMarkers.marker.hit = hit; 259 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 331 272 canvas.brush.hit = hit; 332 updateMarker(canvas, true); 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 333 280 brushModify(canvas); 334 281 } //}}} 335 282 function onPan(ev, canvas, displaylog) { //{{{ 336 283 ev.preventDefault(); 337 284 338 if (canvas.dataMarkers.enabled == 'on') { 339 canvas.brush.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY); 340 brushModify(canvas); 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 } 341 290 } 342 291 343 if (ev.type == 'panstart') { 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 299 if (ev.type === 'panstart') { 344 300 canvas.lastDeltaX = 0; 345 301 canvas.lastDeltaY = 0; 346 302 } 347 if (ev.srcEvent.shiftKey || ev.pointers.length == 2) {303 if (ev.srcEvent.shiftKey || ev.pointers.length === 2) { 348 304 if (!canvas.view.panningEnabled) return; 349 305 var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; 350 306 var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6; … … 360 316 } 361 317 362 318 else { 363 canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * -2 * canvas.controlSensitivity * RAD2DEG;319 canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * 2 * canvas.controlSensitivity * RAD2DEG; 364 320 canvas.view.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG; 365 321 366 322 if (canvas.view.rotation[0] > 360) { canvas.view.rotation[0] -= 360; }; … … 374 330 canvas.lastDeltaX = ev.deltaX; 375 331 canvas.lastDeltaY = ev.deltaY; 376 332 377 repositionMarker(canvas);333 canvas.dataMarkers.reposition = true; 378 334 379 335 if (displaylog) { console.log(canvas.view.rotation); } 380 336 } //}}} 381 337 function onPinch(ev, canvas, displaylog) { //{{{ 382 338 ev.preventDefault(); 383 if (ev.type == 'pinchstart') { canvas.view.lastZoom = canvas.view.zoom; }339 if (ev.type === 'pinchstart') { canvas.view.lastZoom = canvas.view.zoom; } 384 340 else { modifyZoom(ev.scale * canvas.view.lastZoom, canvas, displaylog); } 385 341 } //}}} 386 342 function onZoom(ev, canvas, displaylog) { //{{{ … … 390 346 } //}}} 391 347 function modifyZoom(value, canvas, displaylog) { //{{{ 392 348 canvas.view.zoom = clamp(value, canvas.view.zoomLimits[0], canvas.view.zoomLimits[1]); 393 repositionMarker(canvas);349 canvas.dataMarkers.reposition = true; 394 350 if (displaylog) { console.log(canvas.view.zoom); } 395 351 } //}}} 396 352 function modifyDataMarkersEnabled(value, canvas) { //{{{ … … 407 363 canvas.playButton.find('span').addClass('fa-play'); 408 364 } 409 365 } //}}} 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 366 //}}} 434 367 //{{{ Interaction Functions 435 function raycast(canvas, x, y ) { //{{{368 function raycast(canvas, x, y, node) { //{{{ 436 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. 437 370 //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));371 var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.camera.vpMatrix, node.modelMatrix)); 439 372 var origin = vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 0], inverseMVPMatrix); 440 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); 441 374 var ray = vec3.subtract(vec3.create(), far, origin); 442 375 443 var mesh = canvas.unitNode.mesh; 376 var mesh = node.mesh; 377 444 378 if (!mesh) { return; } 445 if (! mesh.octree) { mesh.octree = new GL.Octree(mesh); }379 if (!node.octree) { node.octree = new GL.Octree(mesh); } 446 380 447 var hit = mesh.octree.testRay(origin, ray, 1e3, 1e10);381 var hit = node.octree.testRay(origin, ray, 1e3, 1e10); 448 382 449 383 if(!hit) { return; } 450 384 385 if (node.name.startsWith("clouds")) { canvas.clouds.selected = node.name; alert("New selected cloud: " + canvas.clouds.selected); } 386 451 387 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);388 vec3.transformMat4(hit.pos, hit.pos, node.modelMatrix); 389 vec3.transformMat4(hit.normal, hit.normal, node.modelMatrix); 454 390 455 391 return hit; 456 392 } //}}} 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 } 457 405 function brushModify(canvas) { //{{{ 458 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. 459 407 //Currently the brush extends to the raycasted element and its immediate neighbors. … … 506 454 //Update mesh on GPU 507 455 bufferVertices.upload(canvas.gl.DYNAMIC_DRAW); 508 456 bufferCoords.upload(canvas.gl.DYNAMIC_DRAW); 509 canvas.unitNode.mesh.octree = new GL.Octree(canvas.unitNode.mesh); 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 } 457 canvas.unitNode.octree = new GL.Octree(canvas.unitNode.mesh); 528 458 } 529 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 } 530 477 function initializeMarker(canvas) { //{{{ 531 478 //Initialize data marker and tooltip display once per page load 532 479 var marker = $('#' + canvas.dataMarkers.marker.id); … … 562 509 marker.on('click touch', function () { 563 510 marker.fadeOut(175); 564 511 marker.tooltipster('close'); 512 marker.closed = true; 565 513 }); 514 marker.closed = false; 566 515 canvas.dataMarkers.marker.selector = marker; 567 516 } 568 517 updateMarker(canvas, true); … … 569 518 } //}}} 570 519 function repositionMarker(canvas) { //{{{ 571 520 //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; } 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; } 573 523 var size = canvas.dataMarkers.size; 574 524 var screenPoint = vec3.transformMat4(vec3.create(), canvas.dataMarkers.marker.hit.pos, canvas.camera.vpMatrix); 575 //console.log(canvas, canvas.selector, $(canvas.id)576 525 var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left; 577 526 var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top; 578 527 canvas.dataMarkers.marker.selector.css({ … … 579 528 'left': (Math.round(x) - size[0] / 2) + 'px', 580 529 'top': (Math.round(y) - size[1] + 1) + 'px' 581 530 }); 582 583 531 if (canvas.dataMarkers.marker.selector.tooltipster('status').state != 'closed') { canvas.dataMarkers.marker.selector.tooltipster('reposition'); } 532 canvas.dataMarkers.reposition = false; 584 533 } //}}} 585 534 function updateMarker(canvas, reset) { //{{{ 586 535 //Retrieve data value fields and plots them on data marker popup if a hit has been registered. 587 536 //TODO: Automatically pick up any field of size md.mesh.numberofelements 588 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. 589 if ( isEmptyOrUndefined(canvas.dataMarkers.marker.hit)) { return; }590 if (isEmptyOrUndefined(canvas.unitNode) ) { setTimeout( function(){ updateMarker(canvas, reset); }, 750); return; }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; } 591 540 592 541 var hit = canvas.dataMarkers.marker.hit; 593 542 … … 605 554 velocity = md.initialization.vel; 606 555 } 607 556 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]];610 var hitLatitude = [latitude[hit.indices[0]], latitude[hit.indices[1]], latitude[hit.indices[2]]];611 var hitLongitude = [longitude[hit.indices[0]], longitude[hit.indices[1]], longitude[hit.indices[2]]];612 var hitThickness = [thickness[hit.indices[0]], thickness[hit.indices[1]], thickness[hit.indices[2]]];613 var hitVelocity = [velocity[hit.indices[0]], velocity[hit.indices[1]], velocity[hit.indices[2]]];614 var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2];615 var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2];616 var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v;617 var valueLatitude = Math.abs(hitLatitude[0] * hit.uvw[0] + hitLatitude[1] * hit.uvw[1] + hitLatitude[2] * hit.uvw[2]);618 var valueLongitude = Math.abs(hitLongitude[0] * hit.uvw[0] + hitLongitude[1] * hit.uvw[1] + hitLongitude[2] * hit.uvw[2]);619 var valueThickness = hitThickness[0] * hit.uvw[0] + hitThickness[1] * hit.uvw[1] + hitThickness[2] * hit.uvw[2];620 var valueVelocity = hitVelocity[0] * hit.uvw[0] + hitVelocity[1] * hit.uvw[1] + hitVelocity[2] * hit.uvw[2];621 622 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. 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; } 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 } 633 590 } 634 591 635 592 //Apply changes to tooltip 636 $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, format));593 $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, canvas.dataMarkers.format.concat(labels))); 637 594 $('#tooltip-content-data-marker-' + canvas.id).css({'font': canvas.dataMarkers.font}); 638 595 639 596 //If animated, setup animation loop to update plot as movie plays. 640 597 if (canvas.dataMarkers.animated) { 641 var isEmpty = (canvas.dataMarkers.values.length == 0);642 var lastUpdatedIndex = (canvas.dataMarkers.values.length -1);598 var isEmpty = (canvas.dataMarkers.values.length === 0); 599 var lastUpdatedIndex = (canvas.dataMarkers.values.length - 1); 643 600 var newMovieFrame = (!isEmpty && canvas.dataMarkers.values[lastUpdatedIndex][0] != canvas.animation.frame); 644 601 //If new data marker has been placed, reinitialize plot. If not, push new value into plot value array. 645 602 if (reset) { … … 646 603 canvas.dataMarkers.values = []; 647 604 newMovieFrame = true; 648 605 for (var currentFrame = 0; currentFrame < (canvas.unitNode.movieLength); currentFrame++) { 649 coords = canvas.unit Node.texcoords[currentFrame];606 coords = canvas.unitMovieData[currentFrame]; 650 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]]; 651 608 var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2]; 652 609 var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2]; … … 655 612 } 656 613 } 657 614 else { 615 if (canvas.animation.lastFrame > canvas.animation.frame) { 616 canvas.dataMarkers.values = []; 617 } 658 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]; 659 622 canvas.dataMarkers.values.push([canvas.animation.frame, value]); 660 623 } 661 624 } … … 663 626 //Replot data marker popup using update data value array. 664 627 if (isEmpty || newMovieFrame) { 665 628 var dataLabels = {'latitude': valueLatitude, 'longitude': valueLongitude, 'thickness': valueThickness, 'velocity': valueVelocity, 'value': value}; 666 var dataDisplay = canvas.dataMarkers.values.slice(0, canvas.animation.frame +1);629 var dataDisplay = canvas.dataMarkers.values.slice(0, canvas.animation.frame + 1); 667 630 plot( 668 631 'id', '#sim-plot', 669 632 'type', 'bar', … … 679 642 ); 680 643 } 681 644 } 682 repositionMarker(canvas);683 if (reset ) {645 canvas.dataMarkers.reposition = true; 646 if (reset && !canvas.dataMarkers.marker.selector.closed) { 684 647 canvas.dataMarkers.marker.selector.fadeIn(175); 685 648 canvas.dataMarkers.marker.selector.tooltipster('open'); 686 649 } 687 650 } //}}} 651 function animateValue(current, target, duration, stepCallback, doneCallback) { //{{{ 652 //Animates scalar value for length duration, calling callback each step. 653 //TODO: Specify lerp easing as option (cubic, linear, cosine). 654 $({'value':current}).animate({'value':target}, { 655 duration: duration, 656 step: stepCallback, 657 done: doneCallback 658 }); 659 } //}}} 688 660 //}}} 689 661 //{{{ Drawing Functions 690 662 function updateCameraMatrix(canvas) { //{{{ … … 706 678 707 679 //Calculate rotation around camera focal point about worldspace origin 708 680 if (canvas.view.twod) { 709 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * 0, [0, 1, 0]);681 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * 0, [0, 1, 0]); 710 682 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * 90, [1, 0, 0]); 711 683 mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix); 712 684 } 713 685 else { 714 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * canvas.view.rotation[0], [0, 1, 0]);686 mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * (canvas.view.rotation[0] + 90), [0, 1, 0]); 715 687 mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * canvas.view.rotation[1], [1, 0, 0]); 716 688 mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix); 717 689 } … … 734 706 735 707 vec3.transformMat4(canvas.camera.position, cameraPosition, canvas.camera.vpInverseMatrix); 736 708 canvas.camera.ready = true; 709 repositionMarker(canvas); 737 710 }//}}} 738 711 function drawSceneGraphNode(canvas, node) { //{{{ 739 712 if (!node.enabled) { return; } … … 748 721 mat4.multiply(mvMatrix, canvas.camera.vMatrix, node.modelMatrix); 749 722 750 723 var normalMatrix = mat4.create(); 751 mat4.invert(normalMatrix, mvMatrix);724 mat4.invert(normalMatrix, node.modelMatrix); 752 725 mat4.transpose(normalMatrix, normalMatrix); 753 726 754 727 if (node.texture) { node.texture.bind(0); } … … 768 741 vec3.sub(cameraPositionRelative, origin, node.translation); 769 742 cameraHeight = vec3.length(cameraPositionRelative); 770 743 771 var atm = { 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 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. 788 761 }; 789 762 790 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)]; … … 797 770 m4MVP: mvpMatrix, 798 771 m4Normal: normalMatrix, 799 772 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],773 u_lightPosition: lightOrigin, 774 //u_lightPosition: [1.0, 1.0, 1.0], 775 u_diffuseColor: node.diffuseColor, 803 776 u_texture: 0, 804 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, 805 782 u_maskEnabled: node.maskEnabled, 806 783 u_maskHeight: node.maskHeight, 807 784 u_maskColor: node.maskColor, 785 u_pointSize: node.pointSize, 808 786 v3CameraPosition: origin, 809 787 v3Translate: node.translation, 810 788 v3LightPos: lightOrigin, … … 840 818 //TODO: Come up with better way to check if shaders are ready, or move outside of main draw function 841 819 var nodes = canvas.nodes; 842 820 if (!canvas.draw.ready) { 843 if ( nodes.length !== 0) {821 if (Object.keys(nodes).length !== 0) { 844 822 canvas.draw.ready = true; 845 823 for (var node in nodes) { 846 if (nodes[node].shader.ready == false) {824 if (nodes[node].shader.ready === false) { 847 825 canvas.draw.ready = false; 848 826 break; 849 827 } … … 854 832 855 833 //Begin rendering nodes 856 834 if (canvas.draw.ready) { 857 if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); }858 if (canvas.overlaycanvas) { canvas.overlaycanvas.draw(canvas); }859 860 835 var rect = canvas.getBoundingClientRect(); 861 836 canvas.width = rect.width; 862 837 canvas.height = rect.height; … … 869 844 870 845 updateCameraMatrix(canvas); 871 846 847 if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); } 848 if (canvas.overlaycanvas) { canvas.overlaycanvas.draw(canvas); } 849 872 850 var drawPassNumber = 3; 873 for (var i = drawPassNumber - 1; i >= 0; i--) {851 for (var i = drawPassNumber - 1; i >= 0; --i) { 874 852 for (var node in nodes) { 875 if (nodes[node].drawOrder == i) { drawSceneGraphNode(canvas, nodes[node]); }853 if (nodes[node].drawOrder === i) { drawSceneGraphNode(canvas, nodes[node]); } 876 854 } 877 855 } 878 856 } -
../trunk-jpl/src/m/plot/applyoptions.js
1 function applyoptions(md, data, datatype, options, canvas, gl, node){ //{{{1 function applyoptions(md, data, options, canvas){ //{{{ 2 2 //APPLYOPTIONS - apply colobar, text, cloud, and expdisp options to current plot 3 3 // 4 4 // Usage: … … 7 7 // See also: PLOTMODEL, PARSE_OPTIONS 8 8 9 9 //{{{ colorbar 10 var gl = canvas.gl; 10 11 if (options.exist('colorbar')) { 11 12 if (options.getfieldvalue('colorbar')==1) { 12 //{{{ Handle movie data13 if (datatype == 5) {14 data = data[0];15 } //}}}16 13 //{{{ Variable options initialization 17 var caxis = options.getfieldvalue('caxis' ,[ArrayMin(data), ArrayMax(data)]);14 var caxis = options.getfieldvalue('caxis'); 18 15 var colorbarinnerlabels = options.getfieldvalue('colorbarinnerlabels','off'); 19 16 var ccanvasid, ctitleid, clabelsid, ccanvas, ctitle, clabels, ccontext, cmap, colorbar, cwidth, cheight, cgradient, color, y, x; 20 17 //}}} … … 23 20 var cdivisions = options.getfieldvalue('colorbarnticks', 6); 24 21 var caxisdelta = caxis[1] - caxis[0]; 25 22 var precision = options.getfieldvalue('colorbarprecision', 3); 23 var format = options.getfieldvalue('colorbarformat', 'f').toLowerCase(); 26 24 if (options.getfieldvalue('log','off')!='off') { 27 25 for (var i=cdivisions; i >= 0; i--) { 28 26 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); 27 if (format === 'f') { 28 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision); 29 } 30 else if (format === 'e') { 31 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toPrecision(precision); 32 } 33 else { 34 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision); 35 } 30 36 } 31 37 } else { 32 38 for (var i=cdivisions; i >= 0; i--) { 33 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision); 39 if (format === 'f') { 40 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision); 41 } 42 else if (format === 'e') { 43 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toPrecision(precision); 44 } 45 else { 46 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision); 47 } 34 48 } 35 49 } //}}} 36 50 //{{{ Initialize colorbar canvas … … 116 130 tcontext.fillStyle = tgradient; 117 131 tcontext.fillRect(0, 0, 256, 256); 118 132 tURL = tcanvas.toDataURL(); 119 node.texture = initTexture(gl, tURL); 120 node.textureCanvas = tcanvas; 121 node.caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]); 133 canvas.unitNode.texture = initTexture(canvas.gl, tURL); 122 134 //}}} 123 //{{{ expdisp contours124 if (options.exist('expdisp')) {125 canvas.nodes.expdisp = Node(gl, options);126 var node = canvas.nodes.expdisp;127 128 //declare variables: {{{129 var vertices = [];130 var indices = [];131 var colors = [];132 var rgbcolor = [];133 var xmin, xmax;134 var ymin, ymax;135 var zmin, zmax;136 var scale;137 138 //Process data and model139 var x = options.getfieldvalue('expdisp').x;140 var y = options.getfieldvalue('expdisp').y;141 var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0);142 143 if (options.getfieldvalue('expdisp').z) {144 z = options.getfieldvalue('expdisp').z;145 }146 //}}}147 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);155 xmin = xlim[0];156 xmax = xlim[1];157 ymin = ylim[0];158 ymax = ylim[1];159 zmin = zlim[0];160 zmax = zlim[1];161 //}}}162 163 //Compute scaling: //{{{164 var scale = 1 / (xmax - xmin);165 node.shaderName = 'colored';166 node.shader = gl.shaders[node.shaderName].program;167 node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)];168 node.translation = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (-2 / scale)];169 node.modelMatrix = updateModelMatrix(node);170 node.drawMode = gl.LINE_LOOP;171 node.drawOrder = 0;172 node.useIndexBuffer = false;173 node.disableDepthTest = true;174 //}}}175 176 //some defaults:177 colors.itemSize = 4;178 179 //retrieve some options180 var linewidth=options.getfieldvalue('linewidth', 1);181 var edgecolor=options.getfieldvalue('edgecolor','black'); //RGBCOLOR?182 183 vertices.itemSize = 3;184 for(var i=0; i < x.length; i++){185 vertices[vertices.length] = x[i];186 vertices[vertices.length] = y[i];187 vertices[vertices.length] = z[i];188 189 //edgecolor190 rgbcolor = [0.0, 0.0, 0.0];191 colors[colors.length] = rgbcolor[0];192 colors[colors.length] = rgbcolor[1];193 colors[colors.length] = rgbcolor[2];194 colors[colors.length] = 1.0;195 }196 197 //Initalize buffers:198 node.arrays = [vertices, colors];199 node.buffers = initBuffers(gl, node.arrays);200 } //}}}201 //{{{ cloud of points202 if (options.exist('cloud')) {203 canvas.nodes.cloud = Node(gl, options);204 var node = canvas.nodes.cloud;205 206 //declare variables: {{{207 var vertices = [];208 var indices = [];209 var colors = [];210 var rgbcolor = [];211 var xmin, xmax;212 var ymin, ymax;213 var zmin, zmax;214 var scale;215 216 //Process data and model217 var x = options.getfieldvalue('cloud').x;218 var y = options.getfieldvalue('cloud').y;219 var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0);220 221 if (options.getfieldvalue('cloud').z) {222 z = options.getfieldvalue('cloud').z;223 }224 //}}}225 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);233 xmin = xlim[0];234 xmax = xlim[1];235 ymin = ylim[0];236 ymax = ylim[1];237 zmin = zlim[0];238 zmax = zlim[1];239 //}}}240 241 //Compute scaling: //{{{242 var scale = 1 / (xmax - xmin);243 node.shaderName = 'colored';244 node.shader = gl.shaders[node.shaderName].program;245 node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)];246 node.translation = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (-2 / scale)];247 node.modelMatrix = updateModelMatrix(node);248 node.drawMode = gl.POINTS;249 node.drawOrder = 0;250 node.useIndexBuffer = false;251 node.disableDepthTest = true;252 //}}}253 254 //some defaults:255 colors.itemSize = 4;256 257 //retrieve some options258 var linewidth=options.getfieldvalue('linewidth', 1);259 var edgecolor=options.getfieldvalue('edgecolor','black'); //RGBCOLOR?260 261 vertices.itemSize = 3;262 for(var i=0; i < x.length; i++){263 vertices[vertices.length] = x[i];264 vertices[vertices.length] = y[i];265 vertices[vertices.length] = z[i];266 267 //edgecolor268 rgbcolor = [0.0, 0.0, 0.0];269 colors[colors.length] = rgbcolor[0];270 colors[colors.length] = rgbcolor[1];271 colors[colors.length] = rgbcolor[2];272 colors[colors.length] = 1.0;273 }274 275 //Initalize buffers:276 node.arrays = [vertices, colors];277 node.buffers = initBuffers(gl, node.arrays);278 } //}}}279 135 //{{{ text display 280 136 if (options.exist('textlabels')) { 281 137 var textcanvas, textcanvasid; … … 324 180 var overlaycanvasid = options.getfieldvalue('latlongoverlayid', options.getfieldvalue('canvasid')+'-overlay'); 325 181 var overlaycanvas = $('#'+overlaycanvasid)[0]; 326 182 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,183 //'-90': 1, 184 //'-65': .999, 185 '-60': 0.994046875, 186 //'-55': 0.983187500000002, 187 //'-50': 0.97173550854167, 188 '-45': 0.955729166666666, 189 //'-40': 0.94218750000000218, 190 //'-35': 0.94218750000000218, 191 '-30': 0.9226562500000024, 192 //'-25': 0.87934895833333526, 193 //'-20': 0.856572916666669, 194 //'-15': 0.830729166666665, 195 //'-10': 0.803552708333336, 196 //'-5': 0.77395833333333541, 197 '0': 0.74218749999999811, 198 //'5': 0.70950364583333347, 199 //'10': 0.67479166666666823, 200 //'15': 0.63932291666666663, 201 //'20': 0.60171875, 202 //'25': 0.563453125, 203 '30': 0.523390625000001, 204 //'35': 0.48401875, 205 //'40': 0.44296875, 206 '45': 0.4020001, 207 //'50': 0.3578125, 208 //'55': 0.311875, 209 '60': 0.26953124999999978, 210 //'65': 0.225390625, 211 //'70': 0.18125, 212 //'75': 0.13541666666666671, 213 //'80': 0.08953125, 214 //'85': 0.046250000000000013, 215 //'90': 0.0, 360 216 } 361 217 var longitudes = [-150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180]; 362 218 overlaycanvas.draw = function(canvas) { … … 400 256 var is2d = meshresults[4]; 401 257 var isplanet = meshresults[5]; 402 258 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); 409 xmin = xlim[0]; 410 xmax = xlim[1]; 411 ymin = ylim[0]; 412 ymax = ylim[1]; 413 zmin = zlim[0]; 414 zmax = zlim[1]; 259 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]); 260 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]); 261 var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]); 262 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]; 415 265 416 var global = vec3.length([(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2]) < 6371000/10; //tolerance for global models = center is 637100 meters away from center of earth 417 var atmosphereScale = 1.25; 418 var translation = global ? [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2] : [(xmin + xmax) / 2, (ymin + ymax) - 6371000, (zmin + zmax) / 2]; 419 420 if (options.getfieldvalue('render',[]).indexOf('sky')!=-1) { 421 //atmosphere 422 var node = Node(gl); 423 node.name = "atmosphere"; 424 node.shaderName = "SkyFromSpace"; 425 node.shader = gl.shaders[node.shaderName]; 426 node.drawOrder = 1; 427 node.cullFace = gl.FRONT; 428 node.enableCullFace = true; 429 node.mesh = GL.Mesh.icosahedron({size: 6371000*atmosphereScale, subdivisions: 6}); 430 node.rotation = [0, 0, 0]; 431 node.translation = translation; 432 node.center = [0, 0, 0]; 433 updateModelMatrix(node); 434 canvas.nodes[node.name] = node; 266 var renderObjects = options.getfieldvalue('render',{}); 267 if ('sky' in renderObjects && !('sky' in canvas.nodes)) { 268 var object = renderObjects.sky; 269 object = { 270 enabled: defaultFor(object.enabled, true), 271 scale: defaultFor(object.scale, 1), 272 }; 273 if (object.enabled) { 274 var atmosphereScale = 1.25; 275 var mesh = GL.Mesh.icosahedron({size: 6371000 * atmosphereScale, subdivisions: 5}); 276 var texture = initTexture(gl, canvas.rootPath + 'textures/TychoSkymapII_t4_2k.jpg'); 277 node = new Node( 278 'canvas', canvas, 279 'options', options, 280 'name', 'sky', 281 'shaderName', 'SkyFromSpace', 282 'cullFace', gl.FRONT, 283 'mesh', mesh, 284 'texture',texture, 285 'translation',translation 286 ); 287 } 435 288 } 436 if (options.getfieldvalue('render',[]).indexOf('space')!=-1) { 437 //skysphere 438 node = Node(gl); 439 node.name = "skysphere"; 440 node.shaderName = "Textured"; 441 node.shader = gl.shaders[node.shaderName]; 442 node.drawOrder = 2; 443 node.cullFace = gl.FRONT; 444 node.enableCullFace = true; 445 node.mesh = GL.Mesh.sphere({size: 6371000*20}); 446 node.texture = initTexture(gl, canvas.rootPath+'textures/TychoSkymapII_t4_2k.jpg'); 447 node.rotation = [0, 0, 0]; 448 node.translation = translation; 449 node.center = [0, 0, 0]; 450 updateModelMatrix(node); 451 canvas.nodes[node.name] = node; 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) { 296 var mesh = GL.Mesh.sphere({size: 6371000 * 20}); 297 var texture = initTexture(gl, canvas.rootPath + 'textures/TychoSkymapII_t4_2k.jpg'); 298 node = new Node( 299 'canvas', canvas, 300 'options', options, 301 'name', 'space', 302 'shaderName', 'Textured', 303 'cullFace', gl.FRONT, 304 'drawOrder', 2, 305 'mesh', mesh, 306 'texture',texture, 307 'translation',translation 308 ); 309 } 452 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, 324 'name', 'coastlines', 325 'shaderName', 'Colored', 326 'drawMode', gl.LINE_STRIP, 327 'lineWidth', options.getfieldvalue('linewidth', 1), 328 'scale', [object.scale, object.scale, object.scale], 329 'rotation', [-90, 0, 0] 330 ); 331 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none'); 332 } 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, 347 'name', 'graticule', 348 'shaderName', 'Colored', 349 'drawMode', gl.LINE_STRIP, 350 'lineWidth', options.getfieldvalue('linewidth', 1), 351 'scale', [object.scale, object.scale, object.scale], 352 'rotation', [-90, 0, 0] 353 ); 354 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none'); 355 } 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) { 370 var mesh = GL.Mesh.icosahedron({size: object.size, subdivisions: 1}); 371 node = new Node( 372 'canvas', canvas, 373 'options', options, 374 'name', 'cities', 375 'shaderName', 'Colored', 376 'diffuseColor', object.color, 377 'lineWidth', options.getfieldvalue('linewidth', 1), 378 'scale', [object.scale, object.scale, object.scale], 379 'rotation', [-90, 0, 0] 380 ); 381 node.geometryShader('Mesh', mesh, 'Vertices', [object.x, object.y, object.z], 'Indices', object.indices); 382 } 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) { 396 //city 397 var mesh = GL.Mesh.sphere({size: object.size}); 398 node = new Node( 399 'canvas', canvas, 400 'options', options, 401 'name', 'city', 402 'shaderName', 'Colored', 403 'diffuseColor', object.color, 404 'mesh', mesh, 405 'translation', [object.x, object.z, -object.y] 406 ); 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'); 415 var node = canvas.nodes['city']; 416 node.translation = [object.x, object.z, -object.y]; 417 node.updateModelMatrix(); 418 var screenPoint = vec3.transformMat4(vec3.create(), node.translation, canvas.camera.vpMatrix); 419 var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left; 420 var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top; 421 422 ctx.font = String(options.getfieldvalue('colorbarfontsize', 22))+'px Arial Black, sans-serif'; 423 ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black'); 424 ctx.strokeStyle = 'white'; 425 ctx.textAlign = 'center'; 426 ctx.textBaseline = 'middle'; 427 ctx.fillText(object.name, x, y); 428 ctx.strokeText(object.name, x, y); 429 } 430 canvas.overlaycanvas = overlaycanvas; 431 } 432 } 453 433 if (canvas.clouds.enabled) { 454 434 //clouds 455 435 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 436 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 ); 472 449 } 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 450 } 476 if (options.getfieldvalue('render',[]).indexOf('latlong')!=-1) {477 //latlong478 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;493 }494 451 } //}}} 495 452 } //}}} -
../trunk-jpl/src/m/plot/plot_transient_movie.m
6 6 % See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER 7 7 8 8 %prepare subplot 9 subplot(width,width,i); 9 subplot(width,width,i); 10 10 11 11 %xlim 12 12 if exist(options,'transient_movie_field'), -
../trunk-jpl/src/m/plot/webgl_node.js
1 //NODE class definition //{{{ 2 // Description: 3 // Contains all information for rendering an object in WebGL, including mesh, materials, shaders, and other attributes. 4 // Usage: 5 // node=new Node('canvas', canvas); 6 7 function Node() { //{{{ 8 //properties 9 // {{{ 10 var args = Array.prototype.slice.call(arguments); 11 var options = new pairoptions(args.slice(0,args.length)); 12 13 this.canvas = options.getfieldvalue('canvas', null), 14 this.options = options.getfieldvalue('options', null), 15 this.gl = canvas.gl; 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()) 55 //}}} 56 //initialize {{{ 57 //if (this.name in canvas.nodes) abort? 58 this.updateModelMatrix(); 59 this.updateDiffuseColor(); 60 canvas.nodes[this.name] = this; 61 //}}} 62 } //}}} 63 Node.prototype.updateModelMatrix = function() { //{{{ 64 //Update the model matrix if rotation, scale, or translation have been manually modified. 65 var modelMatrix = mat4.create(); 66 67 var translationMatrix = mat4.create(); 68 mat4.translate(translationMatrix, translationMatrix, vec3.negate(vec3.create(), this.center)); //scale/rotation centering 69 mat4.multiply(modelMatrix, translationMatrix, modelMatrix); 70 71 var scaleMatrix = mat4.create(); 72 mat4.scale(scaleMatrix, scaleMatrix, this.scale); 73 mat4.multiply(modelMatrix, scaleMatrix, modelMatrix); 74 75 var rotationMatrix = mat4.create(); 76 var zRotationMatrix = mat4.create(); 77 mat4.rotate(zRotationMatrix, zRotationMatrix, DEG2RAD * this.rotation[2], [0.0, 0.0, 1.0]); 78 mat4.multiply(rotationMatrix, zRotationMatrix, rotationMatrix); 79 var yRotationMatrix = mat4.create(); 80 mat4.rotate(yRotationMatrix, yRotationMatrix, DEG2RAD * this.rotation[1], [0.0, 1.0, 0.0]); 81 mat4.multiply(rotationMatrix, yRotationMatrix, rotationMatrix); 82 var xRotationMatrix = mat4.create(); 83 mat4.rotate(xRotationMatrix, xRotationMatrix, DEG2RAD * this.rotation[0], [1.0, 0.0, 0.0]); 84 mat4.multiply(rotationMatrix, xRotationMatrix, rotationMatrix); 85 mat4.multiply(modelMatrix, rotationMatrix, modelMatrix); 86 87 mat4.identity(translationMatrix); 88 mat4.translate(translationMatrix, translationMatrix, this.center); //relative translation 89 mat4.multiply(modelMatrix, translationMatrix, modelMatrix); 90 91 mat4.identity(translationMatrix); 92 mat4.translate(translationMatrix, translationMatrix, this.translation); //absolute translation 93 mat4.multiply(modelMatrix, translationMatrix, modelMatrix); 94 95 this.modelMatrix = modelMatrix; 96 this.inverseModelMatrix = mat4.invert(mat4.create(), modelMatrix); 97 this.rotationMatrix = rotationMatrix; 98 this.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix); 99 } //}}} 100 Node.prototype.updateDiffuseColor = function() { //{{{ 101 //Update the diffuse color with an RGB color name or vec4 containing r, g, b, and alpha values from 0.0 to 1.0 102 var color = this.diffuseColor; 103 if (typeof color === 'string') { 104 color = new RGBColor(color); 105 if (color.ok) color = [color.r/255.0, color.g/255.0, color.b/255.0, 1.0]; 106 else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas)); 107 } 108 this.diffuseColor = color; 109 } //}}} 110 Node.prototype.transform = function() { //{{{ 111 //Transforms the translation, rotation, or scle fo the node and updates the model matrix. 112 var args = Array.prototype.slice.call(arguments); 113 var options = new pairoptions(args.slice(0,args.length)); 114 115 var translation = options.getfieldvalue('translation', undefined); 116 var rotation = options.getfieldvalue('rotation', undefined); 117 var scale = options.getfieldvalue('scale', undefined); 118 119 if (!isEmptyOrUndefined(translation)) this.translation = translation; 120 if (!isEmptyOrUndefined(rotation)) this.rotation = rotation; 121 if (!isEmptyOrUndefined(scale)) this.scale = scale; 122 this.updateModelMatrix(); 123 } //}}} 124 Node.prototype.patch = function() { //{{{ 125 //Emulates the behavior of MATLAB patch function by constructing a mesh from arguments. 126 //Limitations: 127 // -Expects pair labeled arguments ('FaceColor','none',...). 128 // -Only handles Face/Vertices/FaceVertexCData element/node plots. 129 // -Only supports FaceColor 'interp' and 'none'. 130 131 var args = Array.prototype.slice.call(arguments); 132 var options = new pairoptions(args.slice(0,args.length)); 133 134 var faces = options.getfieldvalue('Faces', undefined); 135 var vertices = options.getfieldvalue('Vertices', undefined); 136 var faceVertexCData = options.getfieldvalue('FaceVertexCData', undefined); 137 var faceColor = options.getfieldvalue('FaceColor', 'interp'); 138 var edgeColor = options.getfieldvalue('EdgeColor', this.diffuseColor); 139 var lineWidth = options.getfieldvalue('linewidth', 1); 140 141 this.faces = faces; 142 this.vertices = vertices; 143 this.diffuseColor = edgeColor; 144 this.updateDiffuseColor(); 145 146 this.patchVertices(faceVertexCData, faces, vertices); 147 this.patchCoords(faceVertexCData, faces, vertices); 148 this.patchIndices(faces, faceColor); 149 150 this.mesh = GL.Mesh.load(this.arrays, null, null, this.gl); 151 //this.mesh.computeNormals(); 152 this.computeOctree(); 153 } //}}} 154 Node.prototype.patchVertices = function(faceVertexCData, faces, vertices) { //{{{ 155 //Patch subfunction for processing xyz vertices. 156 var vertexArray; 157 var face; 158 159 if (isEmptyOrUndefined(faceVertexCData)) { 160 vertexArray = new Float32Array(vertices[0].length * 3); 161 for(var i = 0, v = 0; i < vertices[0].length; i++) { 162 vertexArray[v++] = vertices[0][i]; 163 vertexArray[v++] = vertices[1][i]; 164 vertexArray[v++] = vertices[2][i]; 165 } 166 } 167 else if (!Array.isArray(faceVertexCData[0])) { //indexed plot - faceVertexCData = [0, 2.32, 231.1, ...] 168 if (faceVertexCData.length === faces.length) { //element plot 169 vertexArray = new Float32Array(faces.length * 3 * 3); 170 for(var i = 0, v = 0, t = 0; i < faces.length; i++) { 171 face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1]; 172 for(var j = 0; j < face.length; j++) { 173 if (isNaN(faceVertexCData[i])) { 174 this.nanIndices.add(i); 175 vertexArray[v++] = 0.0; 176 vertexArray[v++] = 0.0; 177 vertexArray[v++] = 0.0; 178 } 179 else { 180 vertexArray[v++] = vertices[0][face[j]]; 181 vertexArray[v++] = vertices[1][face[j]]; 182 vertexArray[v++] = vertices[2][face[j]]; 183 } 184 } 185 } 186 this.computeIndices = false; 187 } 188 else if (faceVertexCData.length === vertices[0].length) { //node plot 189 vertexArray = new Float32Array(vertices[0].length * 3); 190 for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) { 191 if (isNaN(faceVertexCData[i])) { 192 this.nanIndices.add(i); 193 vertexArray[v++] = 0.0; 194 vertexArray[v++] = 0.0; 195 vertexArray[v++] = 0.0; 196 } 197 else { 198 vertexArray[v++] = vertices[0][i]; 199 vertexArray[v++] = vertices[1][i]; 200 vertexArray[v++] = vertices[2][i]; 201 } 202 } 203 } 204 } 205 else if (Array.isArray(faceVertexCData[0])) { //JS specific: precomputed UV coord plot - faceVertexCData = [[0, 0.99, 0.4, ...],[0, 0.99, 0.4, ...]] 206 if (faceVertexCData[0].length === faces.length) { //element plot 207 vertexArray = new Float32Array(faces.length * 3 * 3); 208 for(var i = 0, v = 0, t = 0; i < faces.length; i++) { 209 face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1]; 210 for(var j = 0; j < face.length; j++) { 211 vertexArray[v++] = vertices[0][face[j]]; 212 vertexArray[v++] = vertices[1][face[j]]; 213 vertexArray[v++] = vertices[2][face[j]]; 214 } 215 } 216 this.computeIndices = false; 217 } 218 else if (faceVertexCData[0].length === vertices[0].length) { //node plot 219 vertexArray = new Float32Array(vertices[0].length * 3); 220 for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) { 221 vertexArray[v++] = vertices[0][i]; 222 vertexArray[v++] = vertices[1][i]; 223 vertexArray[v++] = vertices[2][i]; 224 } 225 } 226 } 227 this.arrays.vertices = vertexArray; 228 } //}}} 229 Node.prototype.patchCoords = function(faceVertexCData, faces, vertices) { //{{{ 230 //Patch subfunction for processing texture coords/UVs. 231 var coordArray; 232 var cramge; 233 var caxis = this.caxis; 234 var face; 235 236 if (isEmptyOrUndefined(faceVertexCData)) { return; } 237 238 //Use logarithmic scaling if it is valid 239 if (this.log !== false && this.log !== 'off') { 240 caxis = [ 241 Math.log10(caxis[0]) / Math.log10(this.log), 242 Math.log10(caxis[1]) / Math.log10(this.log) 243 ]; 244 } 245 246 if (!Array.isArray(faceVertexCData[0])) { //indexed plot - faceVertexCData = [0, 2.32, 231.1, ...] 247 if (faceVertexCData.length === faces.length) { //element plot 248 coordArray = new Float32Array(faces.length * 3 * 2); 249 crange = caxis[1] - caxis[0]; 250 for(var i = 0, v = 0, t = 0; i < faces.length; i++) { 251 face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1]; 252 for(var j = 0; j < face.length; j++) { 253 if (isNaN(faceVertexCData[i])) { 254 this.nanIndices.add(i); 255 coordArray[t++] = 0.0; 256 coordArray[t++] = 0.0; 257 } 258 else { 259 coordArray[t++] = 0.5; 260 coordArray[t++] = clamp((faceVertexCData[i] - caxis[0]) / crange, 0.0, 1.0); 261 } 262 } 263 } 264 this.computeIndices = false; 265 } 266 else if (faceVertexCData.length === vertices[0].length) { //node plot 267 coordArray = new Float32Array(vertices[0].length * 2); 268 crange = caxis[1] - caxis[0]; 269 for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) { 270 if (isNaN(faceVertexCData[i])) { 271 this.nanIndices.add(i); 272 coordArray[t++] = 0.0; 273 coordArray[t++] = 0.0; 274 } 275 else { 276 coordArray[t++] = 0.5; 277 coordArray[t++] = clamp((faceVertexCData[i] - caxis[0]) / crange, 0.0, 1.0); 278 } 279 } 280 } 281 } 282 else if (Array.isArray(faceVertexCData[0])) { //JS specific: precomputed UV coord plot - faceVertexCData = [[0, 0.99, 0.4, ...],[0, 0.99, 0.4, ...]] 283 if (faceVertexCData[0].length === faces.length) { //element plot 284 coordArray = new Float32Array(faces.length * 3 * 2); 285 for(var i = 0, v = 0, t = 0; i < faces.length; i++) { 286 face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1]; 287 for(var j = 0; j < face.length; j++) { 288 coordArray[t++] = faceVertexCData[0][i]; 289 coordArray[t++] = faceVertexCData[1][i]; 290 } 291 } 292 this.computeIndices = false; 293 } 294 else if (faceVertexCData[0].length === vertices[0].length) { //node plot 295 coordArray = new Float32Array(vertices[0].length * 2); 296 for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) { 297 coordArray[t++] = faceVertexCData[0][i]; 298 coordArray[t++] = faceVertexCData[1][i]; 299 } 300 } 301 } 302 this.arrays.coords = coordArray; 303 } //}}} 304 Node.prototype.patchIndices = function(faces, faceColor) { //{{{ 305 //Patch subfunction for processing faces/elements/triangles/indices. 306 var indexArray; 307 var face; 308 309 if (faceColor === 'none') { //Check for wireframe mesh rendering 310 if (this.drawMode === this.gl.TRIANGLES) { //NOTE: Stopgap to allow gl.LINE_STRIP nodes render normally. Only use case for faceColor === 'none' is for plot_mesh 311 this.drawMode = this.gl.LINES; 312 } 313 } 314 315 if (this.computeIndices === true && !isEmptyOrUndefined(faces)) { 316 if (!isEmptyOrUndefined(faces[0])) { //Check for 2D format and process if needed 317 if (faceColor !== 'none') { //Check for triangle rendering 318 indexArray = new Uint16Array(faces.length * 3); 319 for(var i = 0, f = 0; i < faces.length; i++) { 320 face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1]; 321 if (this.nanIndices.has(face[0]) || this.nanIndices.has(face[1]) || this.nanIndices.has(face[2])) continue; //Skip triangle if contains NaN value. 322 indexArray[f++] = faces[i][0] - 1; 323 indexArray[f++] = faces[i][1] - 1; 324 indexArray[f++] = faces[i][2] - 1; 325 } 326 } 327 else { //Check for wireframe mesh rendering 328 indexArray = new Uint16Array(faces.length * 6); 329 for(var i = 0, f = 0; i < faces.length; i++) { 330 indexArray[f++] = faces[i][0] - 1; 331 indexArray[f++] = faces[i][1] - 1; 332 indexArray[f++] = faces[i][1] - 1; 333 indexArray[f++] = faces[i][2] - 1; 334 indexArray[f++] = faces[i][2] - 1; 335 indexArray[f++] = faces[i][0] - 1; 336 } 337 } 338 } 339 else { //Else, assume face indices have already been processed 340 indexArray = faces; 341 } 342 this.arrays.triangles = indexArray; 343 } 344 } //}}} 345 Node.prototype.updateBuffer = function() { //{{{ 346 //Updates the mesh buffers provided in place. 347 //NOTE: Only support coord buffers currently. 348 var args = Array.prototype.slice.call(arguments); 349 var options = new pairoptions(args.slice(0,args.length)); 350 351 var coords = options.getfieldvalue('Coords', undefined); 352 var cacheIndex = options.getfieldvalue('CacheIndex', false); 353 354 if (!isEmptyOrUndefined(coords)) { 355 this.patchCoords(coords, this.faces, this.vertices); 356 var buffer = this.mesh.getBuffer("coords"); 357 buffer.data = this.arrays.coords; 358 buffer.upload(this.gl.DYNAMIC_DRAW); 359 } 360 } //}}} 361 Node.prototype.computeOctree = function() { //{{{ 362 //Computes and caches octrees for a node. 363 var octree = this.canvas.octrees[this.name]; 364 if (isEmptyOrUndefined(octree)) { 365 octree = new GL.Octree(this.mesh); 366 } 367 this.canvas.octrees[this.name] = octree; 368 this.octree = octree; 369 } //}}} 370 Node.prototype.geometryShader = function() { //{{{ 371 //Emulates OpenGL geometry shaders by rendering each point as a mesh. 372 //Parameters: 373 // Mesh - the geometry to duplicate for each point. 374 // Vertices - the list of points to shade. 375 // Indices - (optional) ordered list for non-ordered Vertices objects. 376 377 var args = Array.prototype.slice.call(arguments); 378 var options = new pairoptions(args.slice(0,args.length)); 379 380 var mesh = options.getfieldvalue('Mesh', undefined); 381 var vertices = options.getfieldvalue('Vertices', undefined); 382 var indices = options.getfieldvalue('Indices', undefined); 383 384 //For handling key-value object arrays, like xcity 385 for (var i = 0; i < vertices.length; i++) { 386 if (!Array.isArray(vertices[i])) { 387 var array = []; 388 var coordinateObject = vertices[i]; 389 var j = 0; 390 if (isEmptyOrUndefined(indices)) { 391 for (var key in object) { 392 array[j++] = coordinateObject[key]; 393 } 394 } 395 else { 396 for (var k = 0; k < indices.length; k++) { 397 array[j++] = coordinateObject[indices[k]]; 398 } 399 } 400 vertices[i] = array; 401 } 402 } 403 404 var x = vertices[0]; 405 var y = vertices[1]; 406 var z = vertices[2]; 407 var meshVertices = mesh.getBuffer('vertices').data; 408 var meshIndicies = mesh.getIndexBuffer('triangles').data; 409 var indicies = new Uint16Array(meshIndicies.length * x.length); 410 var size = meshVertices.length * x.length / 3; 411 newX = new Float32Array(size); 412 newY = new Float32Array(size); 413 newZ = new Float32Array(size); 414 415 //For each vertex in vertices, instantiate mesh geomtry centered around that point. 416 for(var i = 0, v = 0, e = 0; i < x.length; i++){ 417 var vector = [x[i], y[i], z[i]]; 418 for (var j = 0; j < meshVertices.length;) { 419 newX[v] = meshVertices[j++] + x[i]; 420 newY[v] = meshVertices[j++] + y[i]; 421 newZ[v++] = meshVertices[j++] + z[i]; 422 } 423 var offset = i * meshVertices.length / 3; 424 for (var j = 0; j < meshIndicies.length;) { 425 indicies[e++] = meshIndicies[j++] + offset; 426 } 427 } 428 429 this.patch('Faces', indicies, 'Vertices', [newX, newY, newZ], 'FaceColor', 'interp'); 430 } //}}} 431 Node.prototype.scaleVertices = function(md, x, y, z, scale) { //{{{ 432 //Scales and returns vertices x, y, and z by factor scale. Uses md.geometry.scale for heightscaling in 3d meshes. 433 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]; 445 } 446 } 447 else { 448 z = z.slice(); 449 var zMin = ArrayMin(md.geometry.surface); 450 for(var i = 0; i < z.length; i++) { 451 z[i] = (z[i] - zMin) * scale + zMin; 452 } 453 } 454 return [x, y, z]; 455 } //}}} 456 Node.prototype.mergeVertices = function(x1, y1, z1, elements1, x2, y2, z2, elements2) { //{{{ 457 //Merges and returns two sets of indexed xyz vertices. 458 elements2 = elements2.slice(); 459 for (var i = 0, offset = x1.length; i < elements2.length; i++) { 460 elements2[i] = [elements2[i][0] + offset, elements2[i][1] + offset, elements2[i][2] + offset]; 461 } 462 return {x:x1.concat(x2), y:y1.concat(y2), z:z1.concat(z2), elements:elements1.concat(elements2)}; 463 } //}}} 464 //}}} -
../trunk-jpl/src/m/plot/plot_manager.js
13 13 var data = options.getfieldvalue('data'); 14 14 var canvas = initCanvas(options); 15 15 var gl = canvas.gl; 16 //TODO: each plot_ should add their node to the canvas.node array 16 17 17 //figure out if this is a special plot 18 18 if (typeof data === 'string'){ 19 19 … … 80 80 plot_mesh(md,options,canvas); 81 81 return; 82 82 case 'none': 83 if (!(options.exist('overlay'))){84 plot_none(md,options,nlines,ncols,i);85 }83 //if (!(options.exist('overlay'))){ 84 // plot_none(md,options,nlines,ncols,i); 85 //} 86 86 return; 87 87 case 'penalties': 88 88 plot_penalties(md,options,subplotwidth,i); … … 150 150 plot_thermaltransient_results(md,options,subplotwidth,i); 151 151 return; 152 152 case 'transient_movie': 153 plot_transient_movie(md,options, subplotwidth,i);153 plot_transient_movie(md,options,canvas); 154 154 return; 155 155 case 'transient_results': 156 156 plot_transient_results(md,options,subplotwidth,i); … … 204 204 //plot unit 205 205 plot_unit(md,data2,datatype,options,canvas); 206 206 207 applyoptions(md,data2, datatype,options,canvas,gl,canvas.nodes[canvas.nodes.length-1]);207 applyoptions(md,data2,options,canvas); 208 208 } //}}} -
../trunk-jpl/src/m/plot/plot_unit.js
6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 //{{{ declare variables: 9 //if ('unit' in canvas.nodes) { 10 // if ( 11 // canvas.nodes.unit.updateBuffer('Coords', data); 12 // return; 13 //} 14 //else { 15 16 //{{{ declare variables: 10 17 //Process data and model 11 18 var meshresults = processmesh(md, data, options); 12 19 var x = meshresults[0]; … … 15 22 var elements = meshresults[3]; 16 23 var is2d = meshresults[4]; 17 24 var isplanet = meshresults[5]; 25 if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface; 18 26 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; 28 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 27 //Compute coordinates and data range: 28 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]); 29 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]); 30 var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]); 31 32 //Handle heightscale 33 var vertices, scale; 34 if (md.mesh.classname() !== 'mesh3dsurface') { 35 vertices = [x, y, z]; 36 scale = [1, 1, options.getfieldvalue('heightscale', 1)]; 31 37 } 32 if (md.mesh.classname() == 'mesh3dsurface') {33 matrixscale = 1;34 vertexscale = options.getfieldvalue('heightscale', 1);35 }36 38 else { 37 if (md.geometry.surface) { 38 z=md.geometry.surface; 39 } 40 matrixscale = options.getfieldvalue('heightscale', 1); 41 vertexscale = 0; 39 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1)); 40 scale = [1, 1, 1]; 42 41 } 43 //}}} 44 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); 52 xmin = xlim[0]; 53 xmax = xlim[1]; 54 ymin = ylim[0]; 55 ymax = ylim[1]; 56 zmin = zlim[0]; 57 zmax = zlim[1]; 58 var caxis; 59 42 60 43 //Compute gl variables: 61 var gl = canvas.gl; 62 var node = Node(gl); 63 canvas.nodes[canvas.nodes.length] = node; 44 var edgecolor = options.getfieldvalue('edgecolor', 'black'); 45 var maskzeros = options.getfieldvalue('maskzeros', {}); 46 var node = new Node( 47 'canvas', canvas, 48 'options', options, 49 'name', 'unit', 50 'shaderName', 'Textured', 51 'alpha', options.getfieldvalue('alpha', 1.0), 52 'caxis', options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]), 53 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 54 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2], 55 'diffuseColor', edgecolor, 56 'enabled', options.getfieldvalue('nodata','off') == 'off', 57 'log', options.getfieldvalue('log',false), 58 'maskEnabled', options.getfieldvalue('innermask','off') == 'on', 59 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1), 60 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]), 61 'maskZerosColor', defaultFor(maskzeros.color,[1.0, 1.0, 1.0, 1.0]), 62 'maskZerosEnabled', defaultFor(maskzeros.enabled,false), 63 'maskZerosTolerance', defaultFor(maskzeros.tolerance,1e-3), 64 'maskZerosZeroValue', defaultFor(maskzeros.zeroValue,0.5), 65 'rotation', [-90, 0, 0], 66 'scale', scale 67 ); 68 //} 64 69 canvas.unitNode = node; 65 70 canvas.unitData = data; 66 node.name = "unit"; 67 node.shaderName = "Textured"; 68 node.shader = gl.shaders[node.shaderName]; 69 node.scale = [1, 1, matrixscale]; 70 node.rotation = [-90, 0, 0]; 71 node.translation = [0, 0, 0]; 72 node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2]; 73 node.alpha = options.getfieldvalue('alpha', 1.0); 74 node.drawOrder = 1; 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]); 78 node.enabled = options.getfieldvalue('nodata','off') == 'off'; 79 updateModelMatrix(node); 80 71 //}}} 81 72 switch(datatype){ 82 73 //{{{ element plot 83 74 case 1: 75 //WARNING: NaN are not properly found (NaN != NaN = true) 84 76 pos=ArrayFindNot(data, NaN); //needed for element on water 85 77 if (elements[0].length==6){ //prisms 86 78 } 87 79 else if (elements[0].length==4){ //tetras 88 80 } 89 else{ //2D triangular elements 81 else{ //triangular elements 82 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'flat', 'EdgeColor', edgecolor); 90 83 } 91 84 break; 92 85 //}}} … … 97 90 else if (elements[0].length==4){ //tetras 98 91 } 99 92 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))]; 102 datamin = caxis[0]; 103 datamax = caxis[1]; 104 datadelta = datamax - datamin; 105 106 var xyz = vec3.create(); 107 var direction = vec3.create(); 108 var vertex = vec3.create(); 109 var magnitude; 110 111 for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){ 112 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing 113 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i])) { 114 nanindices[i] = i; 115 vertices[vindex++] = vertex[0]; 116 vertices[vindex++] = vertex[1]; 117 vertices[vindex++] = vertex[2]; 118 119 texcoords[tindex++] = 0.5; 120 texcoords[tindex++] = 0.0; 121 continue; 122 } 123 124 //Scale vertices 125 xyz = vec3.fromValues(x[i], y[i], z[i]); 126 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; 127 vec3.normalize(direction, xyz); 128 vec3.scale(vertex, direction, magnitude); 129 vertices[vindex++] = vertex[0]; 130 vertices[vindex++] = vertex[1]; 131 vertices[vindex++] = vertex[2]; 132 133 texcoords[tindex++] = 0.5; 134 texcoords[tindex++] = clamp((data[i] - datamin) / datadelta, 0.0, 1.0); 135 } 136 137 //linearize the elements array: 138 var element; 139 for(var i = 0, iindex = 0; i < elements.length; i++){ 140 element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; 141 if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; 142 indices[iindex++] = element[0]; 143 indices[iindex++] = element[1]; 144 indices[iindex++] = element[2]; 145 } 93 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'interp', 'EdgeColor', edgecolor); 146 94 } 147 node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords, triangles: indices}, null, null, gl);148 node.mesh.octree = new GL.Octree(node.mesh);149 95 break; 150 96 //}}} 151 97 //{{{ quiver plot … … 158 104 } 159 105 break; 160 106 //}}} 161 //{{{ node transient plot162 case 5:163 if (elements[0].length==6){ //prisms164 }165 else if (elements[0].length==4){//tetras166 }167 else{ //triangular elements168 var xyz = vec3.create();169 var direction = vec3.create();170 var vertex = vec3.create();171 var magnitude;172 var timestamps = data[data.length-1];173 for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){174 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing175 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i][0])) {176 nanindices[i] = i;177 }178 else {179 //Scale vertices180 xyz = vec3.fromValues(x[i], y[i], z[i]);181 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;182 vec3.normalize(direction, xyz);183 vec3.scale(vertex, direction, magnitude);184 }185 vertices[vindex++] = vertex[0];186 vertices[vindex++] = vertex[1];187 vertices[vindex++] = vertex[2];188 }189 //Transpose data to obtain column addressable data matrix190 data = data[0].map(function(col, i) {191 return data.map(function(row) {192 return row[i]193 })194 });195 //Prevent evaluation of datasubarray min/max if caxis exists196 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))];199 //Prepare texcoords to hold array of data values200 texcoords = [];201 for(var i = 0; i < data.length; i++){202 datamin = caxis[0];203 datamax = caxis[1];204 datadelta = datamax - datamin;205 //Precalculate arrays for each datasubarray, trimming off timestamp value by using x.length instead of data[i].length206 texcoords[i] = new Float32Array(x.length * 2);207 for(var j = 0, index = 0; j < x.length; j++){208 texcoords[i][index++] = 0.5;209 texcoords[i][index++] = clamp((data[i][j] - datamin) / datadelta, 0.0, 1.0);210 }211 }212 213 //linearize the elements array:214 var element;215 for(var i = 0, iindex = 0; i < elements.length; i++){216 element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];217 if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;218 indices[iindex++] = element[0];219 indices[iindex++] = element[1];220 indices[iindex++] = element[2];221 }222 223 //Initialize movie loop224 node.movieLoop = canvas.animation.loop;225 node.movieInterval = 1000 / canvas.animation.fps;226 node.movieTimestamps = timestamps;227 node.movieLength = timestamps.length;228 node.movieFrame = 0;229 canvas.dataMarkers.values = [];230 var quiverVelFrames = {};231 for(var i=0; i < md.results.length; i++){232 quiverVelFrames[Math.floor(md.results[i].time)] = md.results[i];233 }234 235 if (canvas.animation.handler !== 0) {236 console.log("clearing...");237 clearInterval(canvas.animation.handler)238 }239 //TODO: Move this into webgl.js240 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;246 }247 else {248 toggleMoviePlay(canvas);249 }250 }251 else {252 node.movieFrame = node.movieFrame + 1;253 }254 if (canvas.animation.lastFrame != canvas.animation.frame) {255 updateMarker(canvas, false);256 }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 277 if (canvas.progressBar) {278 canvas.animation.frame = 0;279 canvas.progressBar.val(0);280 canvas.progressBar.attr('max', node.movieLength-1);281 canvas.progressBar.slider('refresh');282 }283 284 }285 node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords[0], triangles: indices}, null, null, gl);286 node.mesh.octree = new GL.Octree(node.mesh);287 break;288 //}}}289 107 default: 290 throw Error(sprintf( "%s%i%s\n",'case ', datatype,' not supported'));108 throw Error(sprintf('%s%i%s\n','case ', datatype,' not supported')); 291 109 } 292 110 } //}}} -
../trunk-jpl/src/m/plot/plot_overlay.js
6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 if ('overlay' in canvas.nodes && options.getfieldvalue('cachenodes','on') === 'on') return; 10 9 11 //{{{ declare variables: 10 var vertices = [];11 var indices = [];12 var texcoords = [];13 var nanindices = {};14 var xmin, xmax;15 var ymin, ymax;16 var zmin, zmax;17 var matrixscale, vertexscale;18 19 12 //Process data and model 20 var meshresults = processmesh(md, data, options);13 var meshresults = processmesh(md, [], options); 21 14 var x = meshresults[0]; 22 15 var y = meshresults[1]; 23 16 var z = meshresults[2]; … … 24 17 var elements = meshresults[3]; 25 18 var is2d = meshresults[4]; 26 19 var isplanet = meshresults[5]; 27 28 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 20 if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface; 21 22 //Compute coordinates and data range: 23 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]); 24 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]); 25 var zlim = options.getfieldvalue('zlim', [ArrayMin(md.geometry.surface), ArrayMax(md.geometry.surface)]); 26 27 //Handle radaroverlay 28 if (md.radaroverlay.outerx) { 29 var result = Node.prototype.mergeVertices(x, y, z, elements, md.radaroverlay.outerx, md.radaroverlay.outery, md.radaroverlay.outerheight, md.radaroverlay.outerindex); 30 x = result.x; 31 y = result.y; 32 z = result.z; 33 elements = result.elements; 31 34 } 32 if (md.mesh.classname() == 'mesh3dsurface') { 33 matrixscale = 1; 34 vertexscale = options.getfieldvalue('heightscale', 1); 35 36 //Handle heightscale 37 var vertices, scale; 38 if (md.mesh.classname() !== 'mesh3dsurface') { 39 vertices = [x, y, z]; 40 scale = [1, 1, options.getfieldvalue('heightscale', 1)]; 35 41 } 36 42 else { 37 if (md.geometry.surface) { 38 z=md.geometry.surface; 39 } 40 matrixscale = options.getfieldvalue('heightscale', 1); 41 vertexscale = 0; 43 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1)); 44 scale = [1, 1, 1]; 42 45 } 43 //}}}44 46 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);52 xmin = xlim[0];53 xmax = xlim[1];54 ymin = ylim[0];55 ymax = ylim[1];56 zmin = zlim[0];57 zmax = zlim[1];58 59 47 //Compute gl variables: 60 var gl = canvas.gl; 61 var node = Node(gl); 62 canvas.nodes[canvas.nodes.length] = node; 63 node.name = "overlay"; 64 node.shaderName = (options.getfieldvalue('render',[]).indexOf('ground')!=-1) ? "GroundFromSpace" : "Textured"; 65 node.shader = gl.shaders[node.shaderName]; 66 node.scale = [1, 1, matrixscale]; 67 node.rotation = [-90, 0, 0]; 68 node.translation = [0, 0, 0]; 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); 72 node.drawOrder = 1; 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]); 76 updateModelMatrix(node); 48 var edgecolor = options.getfieldvalue('edgecolor', 'black'); 49 var texture = initTexture(gl, options.getfieldvalue('overlay_image')); 50 var node = new Node( 51 'canvas', canvas, 52 'options', options, 53 'name', 'overlay', 54 'shaderName', 'ground' in options.getfieldvalue('render', {}) ? 'GroundFromSpace' : 'Textured', 55 'alpha', options.getfieldvalue('outeralpha', 1.0), 56 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 57 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2], 58 'diffuseColor', 'white', 59 'maskEnabled', options.getfieldvalue('outermask','off') == 'on', 60 'maskHeight', options.getfieldvalue('outermaskheight', 150.0), 61 'maskColor', options.getfieldvalue('outermaskcolor',[0.0, 0.0, 1.0, 1.0]), 62 'texture', texture, 63 'rotation', [-90, 0, 0], 64 'scale', scale 65 ); 66 //}}} 77 67 78 //Handle outer radaroverlay 79 if (md.radaroverlay.outerx) { 80 var newelements = []; 81 for (var i = 0; i < md.radaroverlay.outerindex.length; i++) { 82 newelements[newelements.length] = [md.radaroverlay.outerindex[i][0] + x.length, md.radaroverlay.outerindex[i][1] + y.length, md.radaroverlay.outerindex[i][2] + z.length]; 83 } 84 x = [].concat(x, md.radaroverlay.outerx); 85 y = [].concat(y, md.radaroverlay.outery); 86 z = [].concat(z, md.radaroverlay.outerheight); 87 elements = [].concat(elements, newelements); 88 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)]; 93 xmin = xlim[0]; 94 xmax = xlim[1]; 95 ymin = ylim[0]; 96 ymax = ylim[1]; 97 zmin = zlim[0]; 98 zmax = zlim[1]; 99 100 node.center = [node.center[0], node.center[1], -zmax]; 101 } 68 var xRange = xlim[1] - xlim[0]; 69 var yRange = ylim[1] - ylim[0]; 70 var coordArray = [new Array(x.length), new Array(x.length)]; 71 //generate mesh: 102 72 103 var xrange = modelxlim[1] - modelxlim[0]; 104 var yrange = modelylim[1] - modelylim[0]; 105 106 var xyz = vec3.create(); 107 var direction = vec3.create(); 108 var vertex = vec3.create(); 109 var magnitude; 110 111 //generate mesh: 112 for(var i = 0; i < x.length; i++){ 113 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing 114 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) { 115 nanindices[i] = i; 116 vertices[vertices.length] = vertex[0]; 117 vertices[vertices.length] = vertex[1]; 118 vertices[vertices.length] = vertex[2]; 119 120 texcoords[texcoords.length] = 0.0; 121 texcoords[texcoords.length] = 0.0; 122 continue; 123 } 124 125 if (md.mesh.classname() == 'mesh3dsurface') { 126 //Scale vertices 127 xyz = vec3.fromValues(x[i], y[i], z[i]); 128 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; 129 vec3.normalize(direction, xyz); 130 vec3.scale(vertex, direction, magnitude); 131 vertices[vertices.length] = vertex[0]; 132 vertices[vertices.length] = vertex[1]; 133 vertices[vertices.length] = vertex[2]; 134 135 texcoords[texcoords.length] = Math.atan2(vertex[1], vertex[0]) / (2 * Math.PI) + 0.5; 136 texcoords[texcoords.length] = Math.asin(vertex[2] / magnitude) / Math.PI + 0.5; 137 } 138 else { 139 //Scale vertices 140 xyz = vec3.fromValues(x[i], y[i], z[i]); 73 if (md.mesh.classname() == 'mesh3dsurface') { 74 var xyz, magnitude; 75 for(var i = 0; i < x.length; i++){ 76 xyz = vec3.fromValues(vertices[0][i], vertices[1][i], vertices[2][i]); 141 77 magnitude = vec3.length(xyz); 142 vec3.normalize(direction, xyz); 143 vec3.scale(vertex, direction, magnitude); 144 vertices[vertices.length] = vertex[0]; 145 vertices[vertices.length] = vertex[1]; 146 vertices[vertices.length] = vertex[2]; 147 148 texcoords[texcoords.length] = (x[i] - modelxlim[0]) / xrange; 149 texcoords[texcoords.length] = (y[i] - modelylim[0]) / yrange; 78 79 coordArray[0][i] = Math.atan2(xyz[1], xyz[0]) / (2 * Math.PI) + 0.5; 80 coordArray[1][i] = Math.asin(xyz[2] / magnitude) / Math.PI + 0.5; 150 81 } 151 82 } 152 //linearize the elements array: 153 var element; 154 for(var i = 0; i < elements.length; i++){ 155 element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; 156 if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; 157 indices[indices.length] = element[0]; 158 indices[indices.length] = element[1]; 159 indices[indices.length] = element[2]; 83 else { 84 for(var i = 0; i < x.length; i++){ 85 coordArray[0][i] = (vertices[0][i] - xlim[0]) / xRange; 86 coordArray[1][i] = (vertices[1][i] - ylim[0]) / yRange; 87 } 160 88 } 161 node. mesh = GL.Mesh.load({vertices: vertices, coords: texcoords, triangles: indices}, null, null, gl);89 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', coordArray, 'FaceColor', 'interp', 'EdgeColor', edgecolor); 162 90 } //}}} -
../trunk-jpl/src/m/plot/plot_transient_movie.js
1 function plot_transient_movie(md, options, canvas) { //{{{ 2 //PLOT_TRANSIENT_MOVIE - plot a transient result as a movie 3 // 4 // Usage: 5 // plot_transient_movie(md, options, canvas); 6 // 7 // See also: PLOTMODEL, PLOT_MANAGER 8 9 //loop over the time steps 10 var data = options.getfieldvalue('transient_field_data'); 11 var datatype; 12 var steps = new Array(data.length); 13 for (i = 0; i < steps.length; i++) { 14 steps[i] = i; 15 } 16 17 //calculate caxis 18 if (!options.exist('caxis')) { 19 var range = [Infinity, -Infinity]; 20 var dataresults; 21 for (var i in steps) { 22 dataresults = processdata(md, data[i], options); 23 range[1] = Math.min(range[0], ArrayMin(dataresults[0])); 24 range[2] = Math.max(range[1], ArrayMax(dataresults[0])); 25 } 26 datatype = dataresults[1]; 27 options.addfielddefault('caxis', range); 28 29 } 30 31 //Create unit node if it does not already exist 32 if (!('unit' in canvas.nodes)) { 33 var dataresults = processdata(md, data[i],options); 34 var data2 = dataresults[0]; 35 var datatype = dataresults[1]; 36 37 //plot unit 38 plot_unit(md,data2,datatype,options,canvas); 39 } 40 41 //display movie 42 var node = canvas.nodes.unit; 43 node.options = options; 44 node.alpha = options.getfieldvalue('alpha', 1.0); 45 node.caxis = options.getfieldvalue('caxis'); 46 node.enabled = options.getfieldvalue('nodata', 'off') == 'off'; 47 node.log = options.getfieldvalue('log', false); 48 canvas.unitMovieData = data; 49 canvas.animation.frame = 0; 50 canvas.animation.handler = setInterval(function () { 51 //Update current animation frame 52 var frame = canvas.animation.frame; 53 if (canvas.animation.play) { 54 if (canvas.animation.increment) { 55 if (frame > steps.length - 1) { 56 if (node.movieLoop) { 57 frame = 0; 58 } 59 else { 60 toggleMoviePlay(canvas); 61 } 62 } 63 else { 64 frame = (frame + 1) % steps.length; 65 } 66 } 67 } 68 69 //If frame has changed, update unit node and data marker display. 70 if (frame !== canvas.animation.lastFrame) { 71 node.updateBuffer('Coords', data[frame]); 72 canvas.unitData = data[frame]; 73 if (canvas.dataMarkers.enabled) { 74 updateMarker(canvas, false); 75 } 76 if (canvas.progressBar) { 77 canvas.progressBar.val(frame).slider('refresh'); 78 } 79 if (canvas.timeLabel) { 80 canvas.timeLabel.html(steps[frame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); 81 } 82 if (!isEmptyOrUndefined(canvas.nodes.quiver)) { 83 plot_quiver(md,options,canvas,false); 84 } 85 } 86 87 //Save new frame info. 88 canvas.animation.lastFrame = canvas.animation.frame; 89 canvas.animation.frame = frame; 90 }, canvas.animation.interval); 91 92 //Update progress bar with new frame info. 93 if (canvas.progressBar) { 94 canvas.progressBar.val(canvas.animation.frame); 95 canvas.progressBar.attr('max', steps.length - 1); 96 canvas.progressBar.slider('refresh'); 97 } 98 99 applyoptions(md, [], options, canvas); 100 } //}}} -
../trunk-jpl/src/m/plot/plotdoc.js
4 4 // Usage: 5 5 // plotdoc() 6 6 7 //TODO: Standardize image to overlay_image, heightscale to scaling, colorbarfontsize/color, clarify innermask/outermask, edgecolor implementation, check colormap,7 //TODO: rename innermask/outermask/maskzero and combine 8 8 9 console.log(' WARNING: starred methods (*) are experimental and not guarenteed to be stable');10 9 console.log(' Plot usage: plotmodel(model,varargin)'); 11 10 console.log(' Options: '); 12 11 console.log(' "canvasid": canvas id'); 13 12 console.log(' "data" : what we want to plot'); 14 console.log(' Available values for "data" are: '); 15 console.log(' - any field of the model structure. ex: plot(md,"data","vel"), or plot(md,"data",md.initialization.vel)'); 16 console.log(' - "mesh": draw mesh using trisurf'); 17 console.log(' - "quiver": quiver plot'); 18 console.log(' "2d": renders orthographic camera with view set to [0, 90] (default "off", ex: "on", "off")'); 13 console.log(' Available values for "data" are: '); 14 console.log(' - any field of the model structure. ex: plot(md,"data","vel"), or plot(md,"data",md.initialization.vel)'); 15 console.log(' - "mesh": draw mesh using trisurf'); 16 console.log(' - "quiver": quiver plot'); 19 17 console.log(' "backgroundcolor": plot background color. (default "lightcyan", ex: "green","blue")'); 20 18 console.log(' "brush": specify brush options (default {"strength":0.075,"falloff":0.5})'); 19 console.log(' "enabled": toggle brush (default false, ex: true)'); 20 console.log(' "strength": value that brush will change data points by (ex: 0.075)'); 21 console.log(' "falloff": multiplier that brush will decrease strength by for each successive point away from brush center (ex: 0.5)'); 22 console.log(' "clouds": specify brush options (default {"strength":0.075,"falloff":0.5})'); 23 console.log(' "enabled": toggle clouds (default false, ex: true)'); 24 console.log(' "height": height to spawn clouds at (ex: 7500)'); 25 console.log(' "quantity": quantity of clouds to spawn (ex: 10)'); 21 26 console.log(' "caxis": modify colorbar range. (array of type [a, b] where b>=a)'); 22 27 console.log(' "colorbar": add colorbar (default "off", ex: "on", "off")'); 23 28 console.log(' "colorbarid": colorbar canvas id (string)'); … … 31 36 console.log(' "colorbarheight": multiplier (default 1) to the default height colorbar'); 32 37 console.log(' "colormap": same as standard matlab option (default "jet", ex: "hsv","cool","spring","gray","Ala","Rignot",...)'); 33 38 console.log(' "controlsensitivity": sensitivty of view/zoom changes as a percentage of default (default 1, ex: 0.5, 2.75)'); 34 console.log(' "datamarkers": toggle data marker displays (default "on", ex: "on", "off")'); 35 console.log(' "datamarkers_image": toggle data marker displays (default "on", ex: "on", "off")'); 36 console.log(' "datamarkerssize": specifiy the width and height of the data markers (default [32,32], ex: [24,32], [105,10])'); 37 console.log(' "datamarkersoptions": specifiy options for data markers (default {"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"]}'); 39 console.log(' "datamarkers": object cotaining data marker parameters. See webgl.js for defaults. (ex: {"enabled":true,"format":["<div id="sim-plot"></div>"],"labels":["thickness","velocity","value"],"animated":true})'); 40 console.log(' "enabled": toggle data marker displays (default true, ex: false)'); 41 console.log(' "image": image used for marking the clicked point (ex: "/textures/data_marker.svg")'); 42 console.log(' "labels": when displaying a sim-plot graph, display these model fields. (ex: ["thickness","velocity","value"])'); 43 console.log(' "font": font to be used for display (ex: "24px "Comic Sans MS", cursive")'); 44 console.log(' "format": an array compatible with sprintf that will be displayed as html (ex: ["X: %.2e<br>Y: %.2e<br>Z: %.2e]<br>Value: %0.1f","x","y","z","value"])'); 45 console.log(' "size": specifiy the width and height of the data markers (default [32,32], ex: [24,32], [105,10])'); 38 46 console.log(' "displayview": print view value to console (default "off", ex: "on", "off")'); 39 47 console.log(' "displayzoom": print zoom value to console (default "off", ex: "on", "off")'); 40 48 console.log(' "edgecolor": same as standard matlab option EdgeColor (default "black", ex: color name: "blue" or RGB array: [0.5, 0.2, 0.8])'); 41 49 console.log(' "heightscale": scaling factor to accentuate height. (default 1, ex: 0.5, 100)'); 42 console.log(' "linewidth *": line width for mesh, quiver, and contour plots, currently limited by WebGL to 1. (default 1, ex: 2, 5)');50 console.log(' "linewidth": line width for mesh, quiver, and contour plots, currently limited by WebGL to 1. (default 1, ex: 2, 5)'); 43 51 console.log(' "log": value of log (default 10, ex: 2, Math.E)'); 44 52 console.log(' "mask": list of flags of size numberofnodes or numberofelements. Only "true" values are plotted '); 45 console.log(' "movieoptions": specify movie options (default {"fps":4,"loop":true})'); 53 console.log(' "movies": object cotaining transient plot animation options (ex: {"fps":4,"loop":true})'); 54 console.log(' "maskzeros": object cotaining transient plot animation options (ex: "enabled":true,"color":[1.0, 1.0, 1.0, 1.0],"tolerance":1e-3,"zeroValue":0.5})'); 55 console.log(' "enabled": toggle maskzeros (default false, ex: true)'); 56 console.log(' "color": RGBA color value array with ranges 0.0 to 1.0 (ex: [1.0, 1.0, 1.0, 1.0])'); 57 console.log(' "tolerance": values within this tolerance of the zeroValue will be masked. (default: 1e-3, ex: 2.5e-2)'); 58 console.log(' "zeroValue": the percentage value with range 0.0, to 1.0 of the caxis value around which the data will be masked with the color. (default: 0.5, ex: 0, 1.0, 0.75)'); 46 59 console.log(' "innermask*": Special mask that colors all parts of a data mesh below a height a certain color. provide innermaskheight and innermaskcolor options also (default "off", ex: "on", "off")'); 47 60 console.log(' "outermask*": Special mask that colors all parts of a overlay mesh below a height a certain color. provide outermaskheight and outermaskcolor options also (default "off", ex: "on", "off")'); 48 61 console.log(' "overlay": overlay a radar amplitude image behind (default "off", ex: "on", "off")'); … … 50 63 console.log(' "quiver": add quiver plot overlay for velocities. (default "off", ex: "on", "off")'); 51 64 console.log(' "scaling": scaling factor used by quiver plots. Default is 0.4'); 52 65 console.log(' "alpha": transparency coefficient 0.0 to 1.0, the lower, the more transparent. (default 1.0, ex: 0.5, 0.25)'); 53 console.log(' "azlim": azimuth view limits (ex: [0, 180])'); 54 console.log(' "ellim": elevation view limits (ex: [-90, 90])'); 55 console.log(' "origin": initial camera offset from model center (default [0,0,0.0], ex: [-2, 1.5, 0.01])'); 56 console.log(' "render": toggle sky, ground, and space rendering. (default [], ex: ["sky", "space"], ["ground"])'); 57 console.log(' "viewPanning": enable view origin panning with two-finger touch or shift+mouse drag. (default "off", ex: "on", "off")'); 58 console.log(' "view": initial azimuth and elevation angles for camera (default [0,90], ex: [90, 180]'); 66 console.log(' "render": a object containing a list of default object to render. (default {}, ex: {"sky", "space"})'); 67 console.log(' "sky": render the atmosphere. (ex: {"enabled":true})'); 68 console.log(' "enabled": toggle sky (default false, ex: true)'); 69 console.log(' "space": render space. (ex: {"enabled":true})'); 70 console.log(' "enabled": toggle space (default false, ex: true)'); 71 console.log(' "coastlines": render coastlines. (ex: {"enabled":true})'); 72 console.log(' "enabled": toggle coastlines (default false, ex: true)'); 73 console.log(' "scale": scale coastlines factor (default 1.0, ex: 1.004)'); 74 console.log(' "x": x coordinate array. (ex: [0.0, 10.0, -25.0,...])'); 75 console.log(' "y": y coordinate array. (ex: [0.0, 10.0, -25.0,...])'); 76 console.log(' "z": z coordinate array. (ex: [0.0, 10.0, -25.0,...])'); 77 console.log(' "city": render city. (ex: {"enabled":true})'); 78 console.log(' "enabled": toggle city (default false, ex: true)'); 79 console.log(' "size": radius of city sphere, in meters (default 1.0, ex: 150000)'); 80 console.log(' "color": color of city sphere (ex: "magenta")'); 81 console.log(' "x": x coordinate of city. (ex: 0.0)'); 82 console.log(' "y": y coordinate of city. (ex: 0.0)'); 83 console.log(' "z": z coordinate of city. (ex: 6356700.0)'); 84 console.log(' "cities": render cities. (ex: {"enabled":true})'); 85 console.log(' "enabled": toggle cities (default false, ex: true)'); 86 console.log(' "size": radius of cities spheres, in meters (default 1.0, ex: 80000)'); 87 console.log(' "color": color of cities spheres (ex: "darkviolet")'); 88 console.log(' "x": x coordinate array of cities. (ex: [0.0, 10.0, -25.0,...])'); 89 console.log(' "y": y coordinate array of cities. (ex: [0.0, 10.0, -25.0,...])'); 90 console.log(' "z": z coordinate array of cities. (ex: [0.0, 10.0, -25.0,...])'); 91 console.log(' "graticule": render graticule. (ex: {"enabled":true})'); 92 console.log(' "enabled": toggle graticule (default false, ex: true)'); 93 console.log(' "scale": scale graticule factor (default 1.0, ex: 1.004)'); 94 console.log(' "x": x coordinate array. (ex: [0.0, 10.0, -25.0,...])'); 95 console.log(' "y": y coordinate array. (ex: [0.0, 10.0, -25.0,...])'); 96 console.log(' "z": z coordinate array. (ex: [0.0, 10.0, -25.0,...])'); 97 console.log(' "view": object cotaining view parameters. See webgl.js for defaults. (ex: {"position":[0.0,0.0,0.0],"rotation":[0.0,0.0,0.0],"zoom":1.0,"zoomLimits":[0.01,100.0],"azimuthLimits":[-180,180.0],"elevationLimits":[-90,90.0],"panningEnabled":false,"twod":false})'); 98 console.log(' "position": camera position (ex: [0.0,0.0,0.0])'); 99 console.log(' "rotation": camera rotation (ex: [0.0,0.0,0.0])'); 100 console.log(' "zoom": initial camera zoom as a percentage of default (default 1, ex: 1.5, 0.01)'); 101 console.log(' "zoomLimits": zoom view limits (ex: [0.05, 10])'); 102 console.log(' "azimuthLimits": zoom view limits (ex: [0.05, 10])'); 103 console.log(' "elevationLimits": zoom view limits (ex: [0.05, 10])'); 104 console.log(' "panningEnabled": controls panning with shift + drag mouse or pan gestures (default: false, ex: true)'); 105 console.log(' "twod": controls twod orthographic view (default: false, ex: true)'); 59 106 console.log(' "xlim": x coordinates to fit inside camera (ex: [0, 500])'); 60 107 console.log(' "ylim": y coordinates to fit inside camera (ex: [0, 500])'); 61 108 console.log(' "zlim": z coordinates to fit inside camera (ex: [0, 500])'); 62 console.log(' "zoomlim": zoom view limits (ex: [0.05, 10])'); 63 console.log(' "zoom": initial camera zoom as a percentage of default (default 1, ex: 1.5, 0.01)'); 64 console.log(' "cloud*": plot a cloud of points, given a flat array of 3d coordinates (ex: [0.0, 0.0, 0.0, 1.0, 1.0, 1.0])'); 65 console.log(' "expdisp*": plot exp file on top of a data plot. provide exp file as an argument (use a cell of strings if more than one)'); 66 console.log(' "textlabels*": plot text labels rendered in 3d space, using an array of text/coordinate pairs (ex: [{"pos":[0.0,0.0,0.0],"text":"origin"}])'); 109 console.log(' "transient_field_data": array of data objects (ex: [[0.0,1.0, 2.5, 12.0...],[0.0,1.0, 2.5, 12.0...],...])'); 110 console.log(' "textlabels": plot text labels rendered in 3d space, using an array of text/coordinate pairs (ex: [{"pos":[0.0,0.0,0.0],"text":"origin"}])'); 67 111 68 112 console.log(' '); 69 113 console.log(' Examples:'); -
../trunk-jpl/src/m/plot/processdata.js
14 14 // 15 15 // See also: PLOTMODEL, PROCESSMESH 16 16 17 //variables:18 var datatype;19 20 17 //check format 21 18 if ( data.length ==0 | data === [] | typeof data === 'number' | ArrayAnyNaN(data) ){ 22 19 throw Error('plotmodel error message: data provided is empty'); … … 34 31 } 35 32 36 33 //needed later on 34 var numberofvertices2d, numberofelements2d; 37 35 if ('numberofvertices2d' in md.mesh){ 38 36 numberofvertices2d=md.mesh.numberofvertices2d; 39 37 numberofelements2d=md.mesh.numberofelements2d; … … 44 42 } 45 43 46 44 //initialize datatype 47 datatype=0;45 var datatype=0; 48 46 49 47 //get datasize 50 datasize=data.length;48 var datasize=data.length; 51 49 52 50 //transpose data if necessary 53 51 if (data[0].length > data.length){ … … 63 61 64 62 65 63 //quiver? 66 if ( data[0].length>1){64 if (Array.isArray(data[0])){ 67 65 datatype=3; 68 66 69 67 //check number of columns, add zeros if necessary, … … 114 112 } 115 113 116 114 //element data 117 if (datasize==md.mesh.numberofelements & data[0].length==1){115 if (datasize==md.mesh.numberofelements & !Array.isArray(data[0])){ 118 116 119 117 //Initialize datatype if non patch 120 118 if(datatype!=4 & datatype!=5){ … … 157 155 } 158 156 159 157 //node data 160 if (datasize==md.mesh.numberofvertices ){158 if (datasize==md.mesh.numberofvertices & !Array.isArray(data[0])){ 161 159 datatype=2; 162 160 163 161 //Mask? -
../trunk-jpl/src/m/plot/plot_quiver.js
1 function plot_quiver(md, options, canvas, updateVel) { //{{{1 function plot_quiver(md, options, canvas, noCacheNodesOverride) { //{{{ 2 2 //PLOT_QUIVER - quiver plot with colors 3 3 // 4 4 // Usage: … … 6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 if ('quiver' in canvas.nodes && noCacheNodesOverride && options.getfieldvalue('cachenodes','on') === 'on') return; 10 9 11 //{{{ 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 18 12 //Process data and model 19 var meshresults = processmesh(md,[], options); 20 13 var meshresults = processmesh(md, [], options); 21 14 var x = meshresults[0]; 22 15 var y = meshresults[1]; 23 16 var z = meshresults[2]; … … 24 17 var elements = meshresults[3]; 25 18 var is2d = meshresults[4]; 26 19 var isplanet = meshresults[5]; 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; 20 if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface; 30 21 31 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 32 if (!md.geometry.surface) { 33 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 22 //Compute coordinates and data range: 23 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]); 24 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]); 25 var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]); 26 27 //Only displaying velocity fields for now 28 var v = isEmptyOrUndefined(md.results) ? md.initialization.vel : md.results[canvas.animation.frame].Vel; 29 var vx = isEmptyOrUndefined(md.results) ? md.initialization.vx : md.results[canvas.animation.frame].Vx; 30 var vy = isEmptyOrUndefined(md.results) ? md.initialization.vy : md.results[canvas.animation.frame].Vy; 31 32 //Handle heightscale 33 var vertices, scale; 34 if (md.mesh.classname() !== 'mesh3dsurface') { 35 vertices = [x, y, z]; 36 scale = [1, 1, options.getfieldvalue('heightscale', 1)]; 34 37 } 35 if (md.mesh.classname() == 'mesh3dsurface') {36 matrixscale = 1;37 vertexscale = options.getfieldvalue('heightscale', 1);38 }39 38 else { 40 if (md.geometry.surface) { 41 z=md.geometry.surface; 42 } 43 matrixscale = options.getfieldvalue('heightscale', 1); 44 vertexscale = 0; 39 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1)); 40 scale = [1, 1, 1]; 45 41 } 46 //}}} 47 48 //Compute coordinates and data range: 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); 55 xmin = xlim[0]; 56 xmax = xlim[1]; 57 ymin = ylim[0]; 58 ymax = ylim[1]; 59 zmin = zlim[0]; 60 zmax = zlim[1]; 61 42 62 43 //Compute gl variables: 63 var gl = canvas.gl; 64 var node = Node(gl); 65 canvas.nodes["velocity"] = node; 66 node.name = "quiver"; 67 node.shaderName = "Colored"; 68 node.shader = gl.shaders[node.shaderName]; 69 node.lineWidth = options.getfieldvalue('linewidth', 1); 70 node.scale = [1, 1, matrixscale]; 71 node.rotation = [-90, 0, 0]; 72 node.translation = [0, 0, 0]; 73 node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2]; 74 node.drawMode = gl.LINES; 75 node.useIndexBuffer = false; 76 node.drawOrder = 0; 77 node.maskEnabled = options.getfieldvalue('innermask','off') == 'on'; 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]); 80 updateModelMatrix(node); 81 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 44 var edgecolor = options.getfieldvalue('edgecolor', 'black'); 45 var node = new Node( 46 'canvas', canvas, 47 'options', options, 48 'name', 'quiver', 49 'shaderName', 'Colored', 50 'alpha', options.getfieldvalue('alpha', 1.0), 51 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 52 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2], 53 'drawMode', canvas.gl.LINES, 54 'diffuseColor', edgecolor, 55 'lineWidth', options.getfieldvalue('linewidth', 1), 56 'maskEnabled', options.getfieldvalue('innermask','off') == 'on', 57 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1), 58 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]), 59 'rotation', [-90, 0, 0], 60 'scale', scale 61 ); 62 63 87 64 //{{{ node plot 88 65 if (elements[0].length==6){ //prisms 89 66 } … … 90 67 else if (elements[0].length==4){ //tetras 91 68 } 92 69 else{ //2D triangular elements 70 //Create arow vertices, and use vx/vy to determine rotation before adding to quiver mesh. 71 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)]; 72 73 var newX = []; 74 var newY = []; 75 var newZ = []; 93 76 var xyz = vec3.create(); 94 var xyz = vec3.create();95 var direction = vec3.create();96 77 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 78 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 79 var heightScale = options.getfieldvalue('heightscale', 1); 80 var arrowScale; 81 var modelMatrix = mat4.create(); 82 var scaleMatrix = mat4.create(); 83 var rotationMatrix = mat4.create(); 84 85 for(var i = 0, iX = 0, iY = 0, iZ = 0; i < x.length; i++){ 107 86 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]); 87 arrowScale = v[i] * scaling; 88 scaleMatrix = mat4.create(); 89 mat4.scale(scaleMatrix, mat4.create(), vec3.fromValues(arrowScale, arrowScale, arrowScale)); 90 mat4.rotate(rotationMatrix, mat4.create(), Math.atan2(vy[i], vx[i]), [0.0, 0.0, 1.0]); 119 91 mat4.multiply(modelMatrix, rotationMatrix, scaleMatrix); 120 121 var temp = vec3.fromValues(0.0, 0.0, 0.0);122 92 for (var j = 0; j < 6; j++){ 123 93 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]; 94 vec3.add(vertex, vertex, xyz); 95 newX[iX++] = vertex[0]; 96 newY[iY++] = vertex[1]; 97 newZ[iZ++] = vertex[2]; 133 98 } 134 99 } 100 node.patch('Vertices', [newX, newY, newZ], 'FaceColor', 'none'); 135 101 } 136 102 //}}} 137 node.mesh = GL.Mesh.load({vertices: vertices, colors: colors}, null, null, gl);138 103 } //}}} -
../trunk-jpl/src/m/plot/plot_mesh.js
6 6 // 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 if ('mesh' in canvas.nodes && options.getfieldvalue('cachenodes','on') === 'on') return; 10 9 11 //{{{ declare variables: 10 var vertices = [];11 var indices = [];12 var colors = [];13 var nanindices = {};14 var xmin, xmax;15 var ymin, ymax;16 var zmin, zmax;17 var scale, matrixscale, vertexscale;18 19 12 //Process data and model 20 var meshresults = processmesh(md, [], options);13 var meshresults = processmesh(md, [], options); 21 14 var x = meshresults[0]; 22 15 var y = meshresults[1]; 23 16 var z = meshresults[2]; … … 25 18 var is2d = meshresults[4]; 26 19 var isplanet = meshresults[5]; 27 20 28 //Compue scaling through matrices for 2d meshes and vertices for 3d meshes 29 if (!md.geometry.surface) { 30 md.geometry.surface=NewArrayFill(md.mesh.x.length, 0); 21 //Compute coordinates and data range: 22 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]); 23 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]); 24 var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]); 25 26 //Handle heightscale 27 var vertices, scale; 28 if (md.mesh.classname() !== 'mesh3dsurface') { 29 vertices = [x, y, z]; 30 scale = [1, 1, options.getfieldvalue('heightscale', 1)]; 31 31 } 32 if (md.mesh.classname() == 'mesh3dsurface') {33 matrixscale = 1;34 vertexscale = options.getfieldvalue('heightscale', 1);35 }36 32 else { 37 if (md.geometry.surface) { 38 z=md.geometry.surface; 39 } 40 matrixscale = options.getfieldvalue('heightscale', 1); 41 vertexscale = 0; 33 vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1)); 34 scale = [1, 1, 1]; 42 35 } 36 37 //Compute gl variables: 38 var edgecolor = options.getfieldvalue('edgecolor', 'black'); 39 var node = new Node( 40 'canvas', canvas, 41 'options', options, 42 'name', 'mesh', 43 'shaderName', 'Colored', 44 'alpha', options.getfieldvalue('alpha', 1.0), 45 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 46 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2], 47 'drawMode', canvas.gl.LINES, 48 'diffuseColor', edgecolor, 49 'lineWidth', options.getfieldvalue('linewidth', 1), 50 'maskEnabled', options.getfieldvalue('innermask','off') == 'on', 51 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1), 52 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]), 53 'rotation', [-90, 0, 0], 54 'scale', scale 55 ); 43 56 //}}} 44 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);52 xmin = xlim[0];53 xmax = xlim[1];54 ymin = ylim[0];55 ymax = ylim[1];56 zmin = zlim[0];57 zmax = zlim[1];58 59 //Compute gl variables:60 var gl = canvas.gl;61 gl.makeCurrent();62 var node = Node(gl);63 canvas.nodes[canvas.nodes.length] = node;64 node.name = "mesh";65 node.shaderName = "Colored";66 node.shader = gl.shaders[node.shaderName];67 node.lineWidth = options.getfieldvalue('linewidth', 1);68 node.scale = [1, 1, matrixscale];69 node.rotation = [-90, 0, 0];70 node.translation = [0, 0, 0];71 node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2];72 node.drawMode = gl.LINES;73 node.drawOrder = 0;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]);77 updateModelMatrix(node);78 79 //retrieve some options80 var edgecolor = new RGBColor(options.getfieldvalue('edgecolor','black'));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));83 84 57 //{{{ node plot 85 58 if (elements[0].length==6){ //prisms 86 59 } … … 87 60 else if (elements[0].length==4){ //tetras 88 61 } 89 62 else{ //2D triangular elements 90 var xyz = vec3.create(); 91 var direction = vec3.create(); 92 var vertex = vec3.create(); 93 var magnitude; 94 var color = edgecolor; 95 for(var i = 0; i < x.length; i++){ 96 //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing 97 if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) { 98 nanindices[i] = i; 99 vertices[vertices.length] = vertex[0]; 100 vertices[vertices.length] = vertex[1]; 101 vertices[vertices.length] = vertex[2]; 102 103 colors[colors.length] = color[0]; 104 colors[colors.length] = color[1]; 105 colors[colors.length] = color[2]; 106 colors[colors.length] = color[3]; 107 continue; 108 } 109 //Scale vertices 110 xyz = vec3.fromValues(x[i], y[i], z[i]); 111 magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; 112 vec3.normalize(direction, xyz); 113 vec3.scale(vertex, direction, magnitude); 114 vertices[vertices.length] = vertex[0]; 115 vertices[vertices.length] = vertex[1]; 116 vertices[vertices.length] = vertex[2]; 117 118 colors[colors.length] = color[0]; 119 colors[colors.length] = color[1]; 120 colors[colors.length] = color[2]; 121 colors[colors.length] = color[3]; 122 } 123 124 //linearize the elements array: 125 var element; 126 for(var i = 0; i < elements.length; i++){ 127 element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; 128 if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; 129 indices[indices.length] = element[0]; 130 indices[indices.length] = element[1]; 131 indices[indices.length] = element[1]; 132 indices[indices.length] = element[2]; 133 indices[indices.length] = element[2]; 134 indices[indices.length] = element[0]; 135 } 63 node.patch('Faces', elements, 'Vertices', vertices, 'FaceColor', 'none', 'EdgeColor', edgecolor); 136 64 } 137 65 //}}} 138 node.mesh = GL.Mesh.load({vertices: vertices, colors: colors, triangles: indices}, null, null, gl); 66 //options=options.addfielddefault('title','Mesh'); 67 //options=addfielddefault('colorbar','off'); 68 //applyoptions(md,[],options,canvas); 139 69 } //}}} -
../trunk-jpl/src/m/classes/clusters/generic.js
171 171 } 172 172 return buf; 173 173 } //}}} 174 } 174 }
Note:
See TracBrowser
for help on using the repository browser.