[22755] | 1 | Index: ../trunk-jpl/src/m/plot/webgl.js
|
---|
| 2 | ===================================================================
|
---|
| 3 | --- ../trunk-jpl/src/m/plot/webgl.js (revision 21767)
|
---|
| 4 | +++ ../trunk-jpl/src/m/plot/webgl.js (revision 21768)
|
---|
| 5 | @@ -5,12 +5,10 @@
|
---|
| 6 | canvas = document.getElementById(options.getfieldvalue('canvasid'));
|
---|
| 7 | //var canvas = document.getElementById(options.getfieldvalue('canvasid'));
|
---|
| 8 | if (!canvas.initialized) {
|
---|
| 9 | - typedArraySliceSupport();
|
---|
| 10 | if (!isEmptyOrUndefined(canvas.draw) && canvas.draw.handler !== 0) { window.cancelAnimationFrame(canvas.draw.handler); }
|
---|
| 11 | if (!isEmptyOrUndefined(canvas.animation) && canvas.animation.handler !== 0) { clearInterval(canvas.animation.handler); }
|
---|
| 12 | initWebGL(canvas, options);
|
---|
| 13 | initializeMarker(canvas);
|
---|
| 14 | - canvas.nodes = [];
|
---|
| 15 | draw(canvas);
|
---|
| 16 | canvas.initialized = true;
|
---|
| 17 | }
|
---|
| 18 | @@ -18,8 +16,8 @@
|
---|
| 19 | }
|
---|
| 20 | function initWebGL(canvas, options) { //{{{
|
---|
| 21 | //Initialize canvas.gl on page load, reusing gl context on additional runs
|
---|
| 22 | - var gl;
|
---|
| 23 | - if (!canvas.gl) {
|
---|
| 24 | + var gl = canvas.gl;
|
---|
| 25 | + if (isEmptyOrUndefined(gl)) {
|
---|
| 26 | gl = GL.create({canvas: canvas});
|
---|
| 27 | gl.enable(gl.DEPTH_TEST); // Enable depth testing
|
---|
| 28 | gl.depthFunc(gl.LEQUAL); // Near things obscure far things
|
---|
| 29 | @@ -30,34 +28,35 @@
|
---|
| 30 | gl.textures = {};
|
---|
| 31 |
|
---|
| 32 | // Add event listeners for canvas
|
---|
| 33 | - var displayview = options.getfieldvalue('displayview', 'off') == 'on';
|
---|
| 34 | - var displayzoom = options.getfieldvalue('displayzoom', 'off') == 'on';
|
---|
| 35 | - var mc = new Hammer.Manager(canvas);
|
---|
| 36 | -
|
---|
| 37 | - mc.add( new Hammer.Tap({event: 'singletap' }) );
|
---|
| 38 | + var displayview = options.getfieldvalue('displayview', 'off') === 'on';
|
---|
| 39 | + var displayzoom = options.getfieldvalue('displayzoom', 'off') === 'on';
|
---|
| 40 | + var mc = new Hammer(canvas);
|
---|
| 41 | mc.add(new Hammer.Pan({threshold: 0, pointers: 0}));
|
---|
| 42 | mc.add(new Hammer.Pinch({threshold: 0})).recognizeWith(mc.get('pan'));
|
---|
| 43 | - mc.on('singletap', function (ev) {onTap(ev, canvas);});
|
---|
| 44 | + mc.on('tap press', function (ev) {onTap(ev, canvas);});
|
---|
| 45 | mc.on('panstart panmove', function (ev) {onPan(ev, canvas, displayview);});
|
---|
| 46 | - mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);});
|
---|
| 47 | -
|
---|
| 48 | + mc.on('pinchstart pinchmove', function (ev) {onPinch(ev, canvas, displayview);});
|
---|
| 49 | canvas.addEventListener('mousewheel', function (ev) {onZoom(ev, canvas, displayzoom)}, false);
|
---|
| 50 | canvas.addEventListener('DOMMouseScroll', function (ev) {onZoom(ev, canvas, displayzoom)}, false);
|
---|
| 51 | +
|
---|
| 52 | + //Add persistent state variables
|
---|
| 53 | + canvas.nodes = {};
|
---|
| 54 | + canvas.octrees = {};
|
---|
| 55 | + canvas.unitNode = {};
|
---|
| 56 | + canvas.unitData = {};
|
---|
| 57 | + canvas.unitMovieData = {};
|
---|
| 58 | + canvas.gl = gl;
|
---|
| 59 | + canvas.rootPath = options.getfieldvalue('rootpath', '../../../js/');
|
---|
| 60 | + canvas.id = options.getfieldvalue('canvasid', '.sim-canvas');
|
---|
| 61 | + canvas.selector = $('#' + canvas.id);
|
---|
| 62 | + canvas.textcanvas = null;
|
---|
| 63 | + canvas.overlaycanvas = null;
|
---|
| 64 | +
|
---|
| 65 | + typedArraySliceSupport();
|
---|
| 66 | }
|
---|
| 67 | - else {
|
---|
| 68 | - gl = canvas.gl;
|
---|
| 69 | - }
|
---|
| 70 |
|
---|
| 71 | - // Add context state variables
|
---|
| 72 | - canvas.gl = gl;
|
---|
| 73 | - canvas.textcanvas = null;
|
---|
| 74 | - canvas.overlaycanvas = null;
|
---|
| 75 | - canvas.unitNode = {};
|
---|
| 76 | - canvas.unitData = {};
|
---|
| 77 | + //Add context state variables
|
---|
| 78 | canvas.controlSensitivity = options.getfieldvalue('controlsensitivity', 1);
|
---|
| 79 | - canvas.id = options.getfieldvalue('canvasid', '.sim-canvas');
|
---|
| 80 | - canvas.rootPath = options.getfieldvalue('rootpath', '../../../js/');
|
---|
| 81 | - canvas.selector = $('#' + canvas.id);
|
---|
| 82 | var backgroundcolor = new RGBColor(options.getfieldvalue('backgroundcolor', 'lightcyan'));
|
---|
| 83 | if (backgroundcolor.ok) { canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0]; }
|
---|
| 84 | else { throw Error(sprintf('s%s%s\n','initWebGL error message: cound not find out background color for curent canvas ', canvas)); }
|
---|
| 85 | @@ -69,6 +68,7 @@
|
---|
| 86 | play: defaultFor(animation.play, true),
|
---|
| 87 | increment: defaultFor(animation.increment, true),
|
---|
| 88 | fps: defaultFor(animation.fps, 4),
|
---|
| 89 | + interval: defaultFor(animation.interval, 1000 / animation.fps),
|
---|
| 90 | loop: defaultFor(animation.loop, true),
|
---|
| 91 | handler: defaultFor(animation.handler, 0)
|
---|
| 92 | }
|
---|
| 93 | @@ -98,7 +98,8 @@
|
---|
| 94 | canvas.clouds = {
|
---|
| 95 | enabled: defaultFor(clouds.enabled, false),
|
---|
| 96 | height: defaultFor(clouds.height, 7500),
|
---|
| 97 | - quantity: defaultFor(clouds.quantity, 10)
|
---|
| 98 | + quantity: defaultFor(clouds.quantity, 10),
|
---|
| 99 | + hit: defaultFor(clouds.hit, {})
|
---|
| 100 | };
|
---|
| 101 | var dataMarkers = options.getfieldvalue('datamarkers', {});
|
---|
| 102 | canvas.dataMarkers = {
|
---|
| 103 | @@ -110,7 +111,8 @@
|
---|
| 104 | animated: defaultFor(dataMarkers.animated, false),
|
---|
| 105 | labels: defaultFor(dataMarkers.labels, []),
|
---|
| 106 | font: defaultFor(dataMarkers.font, ''),
|
---|
| 107 | - marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id))
|
---|
| 108 | + marker: defaultFor(dataMarkers.marker, document.getElementById('sim-data-marker-' + canvas.id)),
|
---|
| 109 | + reposition: defaultFor(dataMarkers.reposition, true)
|
---|
| 110 | };
|
---|
| 111 | var draw = options.getfieldvalue('draw', {});
|
---|
| 112 | canvas.draw = {
|
---|
| 113 | @@ -133,27 +135,23 @@
|
---|
| 114 | //Override with parameters from URL, if any
|
---|
| 115 | //TODO: Make permalinks more robust and less interdependent on UI
|
---|
| 116 | if (!canvas.usedparemters) {
|
---|
| 117 | - function getJsonFromUrl() {
|
---|
| 118 | - var query = location.search.substr(1);
|
---|
| 119 | - var result = {};
|
---|
| 120 | - query.split('&').forEach(function(part) {
|
---|
| 121 | - var item = part.split('=');
|
---|
| 122 | - result[item[0]] = decodeURIComponent(item[1]);
|
---|
| 123 | - });
|
---|
| 124 | - return result;
|
---|
| 125 | - }
|
---|
| 126 | - parameters = getJsonFromUrl();
|
---|
| 127 | -
|
---|
| 128 | - if (parameters['view']) {
|
---|
| 129 | - canvas.view = JSON.parse(parameters['view']);
|
---|
| 130 | - }
|
---|
| 131 | + var parameters = {};
|
---|
| 132 | + location.search.substr(1).split('&').forEach(function(part) {
|
---|
| 133 | + var item = part.split('=');
|
---|
| 134 | + parameters[item[0]] = decodeURIComponent(item[1]);
|
---|
| 135 | + });
|
---|
| 136 | +
|
---|
| 137 | + if (parameters['pos']) { canvas.view.position = JSON.parse(parameters['pos']); }
|
---|
| 138 | + if (parameters['rot']) { canvas.view.rotation = JSON.parse(parameters['rot']); }
|
---|
| 139 | + if (parameters['zoom']) { canvas.view.zoom = JSON.parse(parameters['zoom']); }
|
---|
| 140 | + if (parameters['twod']) { canvas.view.twod = JSON.parse(parameters['twod']); }
|
---|
| 141 | if (parameters['initial']) {
|
---|
| 142 | initial = JSON.parse(parameters['initial']);
|
---|
| 143 | if (!initial) {
|
---|
| 144 | - if (typeof SolveGlacier == 'function') {
|
---|
| 145 | + if (typeof SolveGlacier === 'function') {
|
---|
| 146 | SolveGlacier();
|
---|
| 147 | }
|
---|
| 148 | - if (typeof SolveSlr == 'function') {
|
---|
| 149 | + if (typeof SolveSlr === 'function') {
|
---|
| 150 | SolveSlr();
|
---|
| 151 | }
|
---|
| 152 | }
|
---|
| 153 | @@ -162,7 +160,11 @@
|
---|
| 154 | }
|
---|
| 155 | } //}}}
|
---|
| 156 | function generatePermalink() { //{{{
|
---|
| 157 | - var permalink = window.location.origin + window.location.pathname + '&view=' + JSON.stringify(canvas.view) + '&initial=' + JSON.stringify(initial);
|
---|
| 158 | + var permalink = window.location.origin + window.location.pathname + '?'
|
---|
| 159 | + + '&pos=' + encodeURIComponent(JSON.stringify(canvas.view.position))
|
---|
| 160 | + + '&rot=' + encodeURIComponent(JSON.stringify(canvas.view.rotation))
|
---|
| 161 | + + '&zoom=' + encodeURIComponent(JSON.stringify(canvas.view.zoom))
|
---|
| 162 | + + '&twod=' + encodeURIComponent(JSON.stringify(canvas.view.twod));
|
---|
| 163 | window.prompt('Share this simulation: ', permalink);
|
---|
| 164 | } //}}}
|
---|
| 165 | function loadShaders(gl, rootPath) { //{{{
|
---|
| 166 | @@ -181,83 +183,6 @@
|
---|
| 167 | }
|
---|
| 168 | return gl.textures[imageSource];
|
---|
| 169 | } //}}}
|
---|
| 170 | -function Node(gl) { //{{{
|
---|
| 171 | - //Returns a Node object that contains default display states for webgl object. center represents pivot point of rotation.
|
---|
| 172 | - return {
|
---|
| 173 | - alpha: 1.0,
|
---|
| 174 | - buffers: [],
|
---|
| 175 | - cullFace: gl.BACK,
|
---|
| 176 | - disableDepthTest: false,
|
---|
| 177 | - drawMode: gl.TRIANGLES,
|
---|
| 178 | - drawOrder: 0,
|
---|
| 179 | - enabled: true,
|
---|
| 180 | - enableCullFace: true,
|
---|
| 181 | - hideOcean: false,
|
---|
| 182 | - lineWidth: 1.0,
|
---|
| 183 | - maskEnabled: false,
|
---|
| 184 | - maskHeight: 150.0,
|
---|
| 185 | - maskColor: vec4.fromValues(0.0, 0.0, 1.0, 1.0),
|
---|
| 186 | - mesh: null,
|
---|
| 187 | - name: 'node',
|
---|
| 188 | - shaderName: 'Colored',
|
---|
| 189 | - shader: gl.shaders.Colored,
|
---|
| 190 | - texture: null,
|
---|
| 191 | - useIndexBuffer: true,
|
---|
| 192 | - center: vec3.create(),
|
---|
| 193 | - scale: vec3.fromValues(1, 1, 1),
|
---|
| 194 | - rotation: vec3.create(),
|
---|
| 195 | - translation: vec3.create(),
|
---|
| 196 | - modelMatrix: mat4.create(),
|
---|
| 197 | - rotationMatrix: mat4.create(),
|
---|
| 198 | - inverseModelMatrix: mat4.create(),
|
---|
| 199 | - inverseRotationMatrix: mat4.create()
|
---|
| 200 | - };
|
---|
| 201 | -} //}}}
|
---|
| 202 | -function debugNodes(canvasid) { //{{{
|
---|
| 203 | - var canvasid = canvasid || '.sim-canvas';
|
---|
| 204 | - var nodes = document.getElementById(canvasid).nodes;
|
---|
| 205 | - console.log(canvasid, 'Nodes:');
|
---|
| 206 | - for (var node in nodes) {
|
---|
| 207 | - 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);
|
---|
| 208 | - }
|
---|
| 209 | - return nodes;
|
---|
| 210 | -} //}}}
|
---|
| 211 | -function updateModelMatrix(node) { //{{{
|
---|
| 212 | - var modelMatrix = mat4.create();
|
---|
| 213 | -
|
---|
| 214 | - var translationMatrix = mat4.create();
|
---|
| 215 | - mat4.translate(translationMatrix, translationMatrix, vec3.negate(vec3.create(), node.center)); //scale/rotation centering
|
---|
| 216 | - mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
|
---|
| 217 | -
|
---|
| 218 | - var scaleMatrix = mat4.create();
|
---|
| 219 | - mat4.scale(scaleMatrix, scaleMatrix, node.scale);
|
---|
| 220 | - mat4.multiply(modelMatrix, scaleMatrix, modelMatrix);
|
---|
| 221 | -
|
---|
| 222 | - var rotationMatrix = mat4.create();
|
---|
| 223 | - var zRotationMatrix = mat4.create();
|
---|
| 224 | - mat4.rotate(zRotationMatrix, zRotationMatrix, DEG2RAD * node.rotation[2], [0.0, 0.0, 1.0]);
|
---|
| 225 | - mat4.multiply(rotationMatrix, zRotationMatrix, rotationMatrix);
|
---|
| 226 | - var yRotationMatrix = mat4.create();
|
---|
| 227 | - mat4.rotate(yRotationMatrix, yRotationMatrix, DEG2RAD * node.rotation[1], [0.0, 1.0, 0.0]);
|
---|
| 228 | - mat4.multiply(rotationMatrix, yRotationMatrix, rotationMatrix);
|
---|
| 229 | - var xRotationMatrix = mat4.create();
|
---|
| 230 | - mat4.rotate(xRotationMatrix, xRotationMatrix, DEG2RAD * node.rotation[0], [1.0, 0.0, 0.0]);
|
---|
| 231 | - mat4.multiply(rotationMatrix, xRotationMatrix, rotationMatrix);
|
---|
| 232 | - mat4.multiply(modelMatrix, rotationMatrix, modelMatrix);
|
---|
| 233 | -
|
---|
| 234 | - mat4.identity(translationMatrix);
|
---|
| 235 | - mat4.translate(translationMatrix, translationMatrix, node.center); //relative translation
|
---|
| 236 | - mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
|
---|
| 237 | -
|
---|
| 238 | - mat4.identity(translationMatrix);
|
---|
| 239 | - mat4.translate(translationMatrix, translationMatrix, node.translation); //absolute translation
|
---|
| 240 | - mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
|
---|
| 241 | -
|
---|
| 242 | - node.modelMatrix = modelMatrix;
|
---|
| 243 | - node.inverseModelMatrix = mat4.invert(mat4.create(), modelMatrix);
|
---|
| 244 | - node.rotationMatrix = rotationMatrix;
|
---|
| 245 | - node.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix);
|
---|
| 246 | -} //}}}
|
---|
| 247 | function clamp(value, min, max) { //{{{
|
---|
| 248 | return Math.max(min, Math.min(value, max));
|
---|
| 249 | } //}}}
|
---|
| 250 | @@ -265,15 +190,21 @@
|
---|
| 251 | return typeof name !== 'undefined' ? name : value;
|
---|
| 252 | } //}}}
|
---|
| 253 | function isEmptyOrUndefined(object) { //{{{
|
---|
| 254 | - return object === undefined || Object.getOwnPropertyNames(object).length === 0;
|
---|
| 255 | + return object === undefined || isEmpty(object);
|
---|
| 256 | } //}}}
|
---|
| 257 | +function isEmpty(object) { //{{{
|
---|
| 258 | + for (var key in object) {
|
---|
| 259 | + return false;
|
---|
| 260 | + }
|
---|
| 261 | + return true;
|
---|
| 262 | +} //}}}
|
---|
| 263 | function recover(canvasid, name, value) { //{{{
|
---|
| 264 | //Traverse canvas object tree for property defined by dot delimited string, returning it, or a default value if it is not found.
|
---|
| 265 | var object = document.getElementById(canvasid);
|
---|
| 266 | var properties = name.split('.');
|
---|
| 267 | - for (var i = 0; i < properties.length; ++i) {
|
---|
| 268 | + for (var i = 0; i < properties.length; i++) {
|
---|
| 269 | object = object[properties[i]];
|
---|
| 270 | - if (typeof object === 'undefined') { break; }
|
---|
| 271 | + if (isEmptyOrUndefined(object)) { break; }
|
---|
| 272 | }
|
---|
| 273 | return defaultFor(object, value);
|
---|
| 274 | } //}}}
|
---|
| 275 | @@ -325,26 +256,51 @@
|
---|
| 276 | function onTap(ev, canvas) { //{{{
|
---|
| 277 | //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.
|
---|
| 278 | ev.preventDefault();
|
---|
| 279 | - if (!canvas.dataMarkers.enabled) { return; }
|
---|
| 280 | - var hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY);
|
---|
| 281 | - canvas.dataMarkers.marker.hit = hit;
|
---|
| 282 | +
|
---|
| 283 | + if (canvas.clouds.enabled) {
|
---|
| 284 | + for (var i = 0; i < canvas.clouds.quantity; i++) {
|
---|
| 285 | + raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.nodes["clouds" + i]);
|
---|
| 286 | + }
|
---|
| 287 | + }
|
---|
| 288 | + var hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.unitNode);
|
---|
| 289 | + if ('cities' in canvas.nodes) {
|
---|
| 290 | + var hitCities = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.nodes.cities);
|
---|
| 291 | + canvas.nodes.cities.hit = hitCities;
|
---|
| 292 | + updateCities(canvas);
|
---|
| 293 | + }
|
---|
| 294 | +
|
---|
| 295 | canvas.brush.hit = hit;
|
---|
| 296 | - updateMarker(canvas, true);
|
---|
| 297 | +
|
---|
| 298 | + if (canvas.dataMarkers.enabled) {
|
---|
| 299 | + canvas.dataMarkers.marker.selector.closed = false;
|
---|
| 300 | + canvas.dataMarkers.marker.hit = hit;
|
---|
| 301 | + updateMarker(canvas, true);
|
---|
| 302 | + }
|
---|
| 303 | +
|
---|
| 304 | brushModify(canvas);
|
---|
| 305 | } //}}}
|
---|
| 306 | function onPan(ev, canvas, displaylog) { //{{{
|
---|
| 307 | ev.preventDefault();
|
---|
| 308 |
|
---|
| 309 | - if (canvas.dataMarkers.enabled == 'on') {
|
---|
| 310 | - canvas.brush.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY);
|
---|
| 311 | - brushModify(canvas);
|
---|
| 312 | + if (canvas.dataMarkers.enabled) {
|
---|
| 313 | + if (!isEmptyOrUndefined(canvas.unitNode)) {
|
---|
| 314 | + canvas.brush.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.unitNode);
|
---|
| 315 | + brushModify(canvas);
|
---|
| 316 | + }
|
---|
| 317 | }
|
---|
| 318 |
|
---|
| 319 | - if (ev.type == 'panstart') {
|
---|
| 320 | + if (canvas.clouds.enabled) {
|
---|
| 321 | + if (!isEmptyOrUndefined(canvas.nodes['overlay'])) {
|
---|
| 322 | + canvas.clouds.hit = raycast(canvas, ev.srcEvent.layerX, ev.srcEvent.layerY, canvas.nodes['overlay']);
|
---|
| 323 | + updateClouds(canvas);
|
---|
| 324 | + }
|
---|
| 325 | + }
|
---|
| 326 | +
|
---|
| 327 | + if (ev.type === 'panstart') {
|
---|
| 328 | canvas.lastDeltaX = 0;
|
---|
| 329 | canvas.lastDeltaY = 0;
|
---|
| 330 | }
|
---|
| 331 | - if (ev.srcEvent.shiftKey || ev.pointers.length == 2) {
|
---|
| 332 | + if (ev.srcEvent.shiftKey || ev.pointers.length === 2) {
|
---|
| 333 | if (!canvas.view.panningEnabled) return;
|
---|
| 334 | var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6;
|
---|
| 335 | var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight / canvas.view.zoom * 2 * canvas.controlSensitivity * 6.371e6;
|
---|
| 336 | @@ -360,7 +316,7 @@
|
---|
| 337 | }
|
---|
| 338 |
|
---|
| 339 | else {
|
---|
| 340 | - canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * -2 * canvas.controlSensitivity * RAD2DEG;
|
---|
| 341 | + canvas.view.rotation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * 2 * canvas.controlSensitivity * RAD2DEG;
|
---|
| 342 | canvas.view.rotation[1] += (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * -2 * canvas.controlSensitivity * RAD2DEG;
|
---|
| 343 |
|
---|
| 344 | if (canvas.view.rotation[0] > 360) { canvas.view.rotation[0] -= 360; };
|
---|
| 345 | @@ -374,13 +330,13 @@
|
---|
| 346 | canvas.lastDeltaX = ev.deltaX;
|
---|
| 347 | canvas.lastDeltaY = ev.deltaY;
|
---|
| 348 |
|
---|
| 349 | - repositionMarker(canvas);
|
---|
| 350 | + canvas.dataMarkers.reposition = true;
|
---|
| 351 |
|
---|
| 352 | if (displaylog) { console.log(canvas.view.rotation); }
|
---|
| 353 | } //}}}
|
---|
| 354 | function onPinch(ev, canvas, displaylog) { //{{{
|
---|
| 355 | ev.preventDefault();
|
---|
| 356 | - if (ev.type == 'pinchstart') { canvas.view.lastZoom = canvas.view.zoom; }
|
---|
| 357 | + if (ev.type === 'pinchstart') { canvas.view.lastZoom = canvas.view.zoom; }
|
---|
| 358 | else { modifyZoom(ev.scale * canvas.view.lastZoom, canvas, displaylog); }
|
---|
| 359 | } //}}}
|
---|
| 360 | function onZoom(ev, canvas, displaylog) { //{{{
|
---|
| 361 | @@ -390,7 +346,7 @@
|
---|
| 362 | } //}}}
|
---|
| 363 | function modifyZoom(value, canvas, displaylog) { //{{{
|
---|
| 364 | canvas.view.zoom = clamp(value, canvas.view.zoomLimits[0], canvas.view.zoomLimits[1]);
|
---|
| 365 | - repositionMarker(canvas);
|
---|
| 366 | + canvas.dataMarkers.reposition = true;
|
---|
| 367 | if (displaylog) { console.log(canvas.view.zoom); }
|
---|
| 368 | } //}}}
|
---|
| 369 | function modifyDataMarkersEnabled(value, canvas) { //{{{
|
---|
| 370 | @@ -407,53 +363,45 @@
|
---|
| 371 | canvas.playButton.find('span').addClass('fa-play');
|
---|
| 372 | }
|
---|
| 373 | } //}}}
|
---|
| 374 | -function onSlideStart(canvas, progressBar) { //{{{
|
---|
| 375 | - if (!isEmptyOrUndefined(canvas.animation)) {
|
---|
| 376 | - canvas.animation.increment = false;
|
---|
| 377 | - canvas.animation.frame = parseInt($(progressBar).val());
|
---|
| 378 | - //console.log(canvas.animation.frame);
|
---|
| 379 | - //updateMarker(canvas, false);
|
---|
| 380 | - }
|
---|
| 381 | -} //}}}
|
---|
| 382 | -function onSlideChange(canvas, progressBar) { //{{{
|
---|
| 383 | - if (!isEmptyOrUndefined(canvas.animation)) {
|
---|
| 384 | - canvas.animation.frame = parseInt($(progressBar).val());
|
---|
| 385 | - //console.log("change");
|
---|
| 386 | - updateMarker(canvas, false);
|
---|
| 387 | - }
|
---|
| 388 | -} //}}}
|
---|
| 389 | -function onSlideStop(canvas, progressBar) { //{{{
|
---|
| 390 | - if (!isEmptyOrUndefined(canvas.animation)) {
|
---|
| 391 | - canvas.animation.increment = true;
|
---|
| 392 | - canvas.animation.frame = parseInt($(progressBar).val());
|
---|
| 393 | - //console.log(canvas.animation.frame);
|
---|
| 394 | - //updateMarker(canvas, false);
|
---|
| 395 | - }
|
---|
| 396 | -} //}}}
|
---|
| 397 | //}}}
|
---|
| 398 | //{{{ Interaction Functions
|
---|
| 399 | -function raycast(canvas, x, y) { //{{{
|
---|
| 400 | +function raycast(canvas, x, y, node) { //{{{
|
---|
| 401 | //Performs raycast on canvas.unitNode.mesh using x/y screen coordinates. Returns hit objects with hit position, coords, and indicies of ray-triangle intersection.
|
---|
| 402 | //TODO: Diagnose marker issues with orthographic views and slr-eustatic updates when switching between basins.
|
---|
| 403 | - var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.camera.vpMatrix, canvas.unitNode.modelMatrix));
|
---|
| 404 | + var inverseMVPMatrix = mat4.invert(mat4.create(), mat4.multiply(mat4.create(), canvas.camera.vpMatrix, node.modelMatrix));
|
---|
| 405 | var origin = vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 0], inverseMVPMatrix);
|
---|
| 406 | var far = far || vec3.transformMat4(vec3.create(), [(x - canvas.width / 2) / (canvas.width / 2), (canvas.height / 2 - y) / (canvas.height / 2), 1.0], inverseMVPMatrix);
|
---|
| 407 | var ray = vec3.subtract(vec3.create(), far, origin);
|
---|
| 408 |
|
---|
| 409 | - var mesh = canvas.unitNode.mesh;
|
---|
| 410 | + var mesh = node.mesh;
|
---|
| 411 | +
|
---|
| 412 | if (!mesh) { return; }
|
---|
| 413 | - if (!mesh.octree) { mesh.octree = new GL.Octree(mesh); }
|
---|
| 414 | + if (!node.octree) { node.octree = new GL.Octree(mesh); }
|
---|
| 415 |
|
---|
| 416 | - var hit = mesh.octree.testRay(origin, ray, 1e3, 1e10);
|
---|
| 417 | + var hit = node.octree.testRay(origin, ray, 1e3, 1e10);
|
---|
| 418 |
|
---|
| 419 | if(!hit) { return; }
|
---|
| 420 | -
|
---|
| 421 | +
|
---|
| 422 | + if (node.name.startsWith("clouds")) { canvas.clouds.selected = node.name; alert("New selected cloud: " + canvas.clouds.selected); }
|
---|
| 423 | +
|
---|
| 424 | hit.modelPos = vec3.copy(vec3.create(), hit.pos);
|
---|
| 425 | - vec3.transformMat4(hit.pos, hit.pos, canvas.unitNode.modelMatrix);
|
---|
| 426 | - vec3.transformMat4(hit.normal, hit.normal, canvas.unitNode.modelMatrix);
|
---|
| 427 | + vec3.transformMat4(hit.pos, hit.pos, node.modelMatrix);
|
---|
| 428 | + vec3.transformMat4(hit.normal, hit.normal, node.modelMatrix);
|
---|
| 429 |
|
---|
| 430 | return hit;
|
---|
| 431 | } //}}}
|
---|
| 432 | +function updateCities(canvas) {
|
---|
| 433 | + //Update selected city
|
---|
| 434 | + var hit = canvas.nodes.cities.hit;
|
---|
| 435 | + if (hit) {
|
---|
| 436 | + citiesIndex = Math.floor(hit.indices[0] / ((ArrayMax(canvas.nodes.cities.mesh.getIndexBuffer('triangles').data) + 1) / cities.length));
|
---|
| 437 | + cityName = cities[citiesIndex];
|
---|
| 438 | + if (cityName !== $('#gfm-sim-controls-select-city').val()) {
|
---|
| 439 | + $('#gfm-sim-controls-select-city').val(cityName).selectmenu("refresh");
|
---|
| 440 | + changeCity(canvas);
|
---|
| 441 | + }
|
---|
| 442 | + }
|
---|
| 443 | +}
|
---|
| 444 | function brushModify(canvas) { //{{{
|
---|
| 445 | //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.
|
---|
| 446 | //Currently the brush extends to the raycasted element and its immediate neighbors.
|
---|
| 447 | @@ -506,27 +454,26 @@
|
---|
| 448 | //Update mesh on GPU
|
---|
| 449 | bufferVertices.upload(canvas.gl.DYNAMIC_DRAW);
|
---|
| 450 | bufferCoords.upload(canvas.gl.DYNAMIC_DRAW);
|
---|
| 451 | - canvas.unitNode.mesh.octree = new GL.Octree(canvas.unitNode.mesh);
|
---|
| 452 | -
|
---|
| 453 | - //Update clouds if rendered
|
---|
| 454 | - //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.
|
---|
| 455 | - for (var i = 0; i < canvas.clouds.quantity; i++) {
|
---|
| 456 | - if (canvas.nodes['clouds' + i]) {
|
---|
| 457 | - var v1 = vec3.fromValues(vertices[hit.indices[0] * 3], vertices[hit.indices[0] * 3 + 1], vertices[hit.indices[0] * 3 + 2]);
|
---|
| 458 | - var v2 = vec3.fromValues(vertices[hit.indices[1] * 3], vertices[hit.indices[1] * 3 + 1], vertices[hit.indices[1] * 3 + 2]);
|
---|
| 459 | - var v3 = vec3.fromValues(vertices[hit.indices[2] * 3], vertices[hit.indices[2] * 3 + 1], vertices[hit.indices[2] * 3 + 2]);
|
---|
| 460 | - vec3.transformMat4(v1, v1, canvas.unitNode.modelMatrix);
|
---|
| 461 | - vec3.transformMat4(v2, v2, canvas.unitNode.modelMatrix);
|
---|
| 462 | - vec3.transformMat4(v3, v3, canvas.unitNode.modelMatrix);
|
---|
| 463 | - var x = (v1[0] + v2[0] + v3[0]) / 3 + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000)));
|
---|
| 464 | - var y = (v1[1] + v2[1] + v3[1]) / 3 + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000)));
|
---|
| 465 | - var z = (v1[2] + v2[2] + v3[2]) / 3;
|
---|
| 466 | - canvas.nodes['clouds' + i].translation = [x, y + canvas.clouds.height, z];
|
---|
| 467 | - updateModelMatrix(canvas.nodes['clouds' + i]);
|
---|
| 468 | - }
|
---|
| 469 | - }
|
---|
| 470 | + canvas.unitNode.octree = new GL.Octree(canvas.unitNode.mesh);
|
---|
| 471 | }
|
---|
| 472 | } //}}}
|
---|
| 473 | +function updateClouds(canvas) {
|
---|
| 474 | + //Update clouds if rendered
|
---|
| 475 | + //TODO: Steven, the hit now queries the radaroverlay.
|
---|
| 476 | + if (canvas.nodes[canvas.clouds.selected]) {
|
---|
| 477 | + var v1 = vec3.fromValues(vertices[hit.indices[0] * 3], vertices[hit.indices[0] * 3 + 1], vertices[hit.indices[0] * 3 + 2]);
|
---|
| 478 | + var v2 = vec3.fromValues(vertices[hit.indices[1] * 3], vertices[hit.indices[1] * 3 + 1], vertices[hit.indices[1] * 3 + 2]);
|
---|
| 479 | + var v3 = vec3.fromValues(vertices[hit.indices[2] * 3], vertices[hit.indices[2] * 3 + 1], vertices[hit.indices[2] * 3 + 2]);
|
---|
| 480 | + vec3.transformMat4(v1, v1, canvas.unitNode.modelMatrix);//move out of brushModify, perhaps onto onPan
|
---|
| 481 | + vec3.transformMat4(v2, v2, canvas.unitNode.modelMatrix);
|
---|
| 482 | + vec3.transformMat4(v3, v3, canvas.unitNode.modelMatrix);
|
---|
| 483 | + var x = (v1[0] + v2[0] + v3[0]) / 3;// + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000)));
|
---|
| 484 | + var y = (v1[1] + v2[1] + v3[1]) / 3;// + Math.floor((Math.random() * (1 + 10000 - (-10000)) + (-10000)));
|
---|
| 485 | + var z = (v1[2] + v2[2] + v3[2]) / 3;
|
---|
| 486 | + canvas.nodes[canvas.clouds.selected].translation = [x, y + canvas.clouds.height, z];
|
---|
| 487 | + updateModelMatrix(canvas.nodes[canvas.clouds.selected]);
|
---|
| 488 | + }
|
---|
| 489 | +}
|
---|
| 490 | function initializeMarker(canvas) { //{{{
|
---|
| 491 | //Initialize data marker and tooltip display once per page load
|
---|
| 492 | var marker = $('#' + canvas.dataMarkers.marker.id);
|
---|
| 493 | @@ -562,7 +509,9 @@
|
---|
| 494 | marker.on('click touch', function () {
|
---|
| 495 | marker.fadeOut(175);
|
---|
| 496 | marker.tooltipster('close');
|
---|
| 497 | + marker.closed = true;
|
---|
| 498 | });
|
---|
| 499 | + marker.closed = false;
|
---|
| 500 | canvas.dataMarkers.marker.selector = marker;
|
---|
| 501 | }
|
---|
| 502 | updateMarker(canvas, true);
|
---|
| 503 | @@ -569,10 +518,10 @@
|
---|
| 504 | } //}}}
|
---|
| 505 | function repositionMarker(canvas) { //{{{
|
---|
| 506 | //Mover marker to point to mouse position, offset in y by 1 to enable immediate clicking.
|
---|
| 507 | - if (isEmptyOrUndefined(canvas.dataMarkers.marker.hit) || !canvas.camera.ready) { return; }
|
---|
| 508 | + //Return if no marker hit exists, the camera is not rendering, or if no reposition has been scheduled.
|
---|
| 509 | + if (isEmptyOrUndefined(canvas.dataMarkers.marker.hit) || !canvas.camera.ready || !canvas.dataMarkers.reposition) { return; }
|
---|
| 510 | var size = canvas.dataMarkers.size;
|
---|
| 511 | var screenPoint = vec3.transformMat4(vec3.create(), canvas.dataMarkers.marker.hit.pos, canvas.camera.vpMatrix);
|
---|
| 512 | - //console.log(canvas, canvas.selector, $(canvas.id)
|
---|
| 513 | var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left;
|
---|
| 514 | var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top;
|
---|
| 515 | canvas.dataMarkers.marker.selector.css({
|
---|
| 516 | @@ -579,15 +528,15 @@
|
---|
| 517 | 'left': (Math.round(x) - size[0] / 2) + 'px',
|
---|
| 518 | 'top': (Math.round(y) - size[1] + 1) + 'px'
|
---|
| 519 | });
|
---|
| 520 | -
|
---|
| 521 | if (canvas.dataMarkers.marker.selector.tooltipster('status').state != 'closed') { canvas.dataMarkers.marker.selector.tooltipster('reposition'); }
|
---|
| 522 | + canvas.dataMarkers.reposition = false;
|
---|
| 523 | } //}}}
|
---|
| 524 | function updateMarker(canvas, reset) { //{{{
|
---|
| 525 | //Retrieve data value fields and plots them on data marker popup if a hit has been registered.
|
---|
| 526 | //TODO: Automatically pick up any field of size md.mesh.numberofelements
|
---|
| 527 | //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.
|
---|
| 528 | - if (isEmptyOrUndefined(canvas.dataMarkers.marker.hit)) { return; }
|
---|
| 529 | - if (isEmptyOrUndefined(canvas.unitNode)) { setTimeout( function(){ updateMarker(canvas, reset); }, 750); return; }
|
---|
| 530 | + if (!canvas.dataMarkers.enabled || isEmptyOrUndefined(canvas.dataMarkers.marker.hit)) { return; }
|
---|
| 531 | + if (isEmptyOrUndefined(canvas.unitNode) || isEmptyOrUndefined(canvas.unitNode.mesh)) { setTimeout( function(){ updateMarker(canvas, reset); }, 750); return; }
|
---|
| 532 |
|
---|
| 533 | var hit = canvas.dataMarkers.marker.hit;
|
---|
| 534 |
|
---|
| 535 | @@ -605,41 +554,49 @@
|
---|
| 536 | velocity = md.initialization.vel;
|
---|
| 537 | }
|
---|
| 538 |
|
---|
| 539 | - //Determine data values at hit position.
|
---|
| 540 | - 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]];
|
---|
| 541 | - var hitLatitude = [latitude[hit.indices[0]], latitude[hit.indices[1]], latitude[hit.indices[2]]];
|
---|
| 542 | - var hitLongitude = [longitude[hit.indices[0]], longitude[hit.indices[1]], longitude[hit.indices[2]]];
|
---|
| 543 | - var hitThickness = [thickness[hit.indices[0]], thickness[hit.indices[1]], thickness[hit.indices[2]]];
|
---|
| 544 | - var hitVelocity = [velocity[hit.indices[0]], velocity[hit.indices[1]], velocity[hit.indices[2]]];
|
---|
| 545 | - var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2];
|
---|
| 546 | - var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2];
|
---|
| 547 | - var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v;
|
---|
| 548 | - var valueLatitude = Math.abs(hitLatitude[0] * hit.uvw[0] + hitLatitude[1] * hit.uvw[1] + hitLatitude[2] * hit.uvw[2]);
|
---|
| 549 | - var valueLongitude = Math.abs(hitLongitude[0] * hit.uvw[0] + hitLongitude[1] * hit.uvw[1] + hitLongitude[2] * hit.uvw[2]);
|
---|
| 550 | - var valueThickness = hitThickness[0] * hit.uvw[0] + hitThickness[1] * hit.uvw[1] + hitThickness[2] * hit.uvw[2];
|
---|
| 551 | - var valueVelocity = hitVelocity[0] * hit.uvw[0] + hitVelocity[1] * hit.uvw[1] + hitVelocity[2] * hit.uvw[2];
|
---|
| 552 | -
|
---|
| 553 | //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.
|
---|
| 554 | - var format = canvas.dataMarkers.format.slice();
|
---|
| 555 | - for (var i = 1; i < format.length; i++) {
|
---|
| 556 | - if (format[i].toLowerCase() == 'x') { format[i] = hit.modelPos[0]; }
|
---|
| 557 | - else if (format[i].toLowerCase() == 'y') { format[i] = hit.modelPos[1]; }
|
---|
| 558 | - else if (format[i].toLowerCase() == 'z') { format[i] = hit.modelPos[2]; }
|
---|
| 559 | - else if (format[i].toLowerCase() == 'lat') { format[i] = valueLatitude; }
|
---|
| 560 | - else if (format[i].toLowerCase() == 'long') { format[i] = valueLongitude; }
|
---|
| 561 | - else if (format[i].toLowerCase() == 'thickness') { format[i] = valueThickness; }
|
---|
| 562 | - else if (format[i].toLowerCase() == 'vel') { format[i] = valueVelocity; }
|
---|
| 563 | - else if (format[i].toLowerCase() == 'value') { format[i] = value; }
|
---|
| 564 | + var labels = canvas.dataMarkers.labels.slice();
|
---|
| 565 | + for (var i = 0; i < labels.length; i++) {
|
---|
| 566 | + if (labels[i].toLowerCase() === 'x') { labels[i] = hit.modelPos[0]; }
|
---|
| 567 | + else if (labels[i].toLowerCase() === 'y') { labels[i] = hit.modelPos[1]; }
|
---|
| 568 | + else if (labels[i].toLowerCase() === 'z') { labels[i] = hit.modelPos[2]; }
|
---|
| 569 | + else if (labels[i].toLowerCase() === 'latitude') {
|
---|
| 570 | + var hitLatitude = [latitude[hit.indices[0]], latitude[hit.indices[1]], latitude[hit.indices[2]]];
|
---|
| 571 | + var valueLatitude = Math.abs(hitLatitude[0] * hit.uvw[0] + hitLatitude[1] * hit.uvw[1] + hitLatitude[2] * hit.uvw[2]);
|
---|
| 572 | + labels[i] = valueLatitude;
|
---|
| 573 | + }
|
---|
| 574 | + else if (labels[i].toLowerCase() === 'longitude') {
|
---|
| 575 | + var hitLongitude = [longitude[hit.indices[0]], longitude[hit.indices[1]], longitude[hit.indices[2]]];
|
---|
| 576 | + var valueLongitude = Math.abs(hitLongitude[0] * hit.uvw[0] + hitLongitude[1] * hit.uvw[1] + hitLongitude[2] * hit.uvw[2]);
|
---|
| 577 | + labels[i] = valueLongitude;
|
---|
| 578 | + }
|
---|
| 579 | + else if (labels[i].toLowerCase() === 'thickness') {
|
---|
| 580 | + var hitThickness = [thickness[hit.indices[0]], thickness[hit.indices[1]], thickness[hit.indices[2]]];
|
---|
| 581 | + var valueThickness = hitThickness[0] * hit.uvw[0] + hitThickness[1] * hit.uvw[1] + hitThickness[2] * hit.uvw[2];
|
---|
| 582 | + labels[i] = valueThickness;
|
---|
| 583 | + }
|
---|
| 584 | + else if (labels[i].toLowerCase() === 'velocity') {
|
---|
| 585 | + var hitVelocity = [velocity[hit.indices[0]], velocity[hit.indices[1]], velocity[hit.indices[2]]];
|
---|
| 586 | + var valueVelocity = hitVelocity[0] * hit.uvw[0] + hitVelocity[1] * hit.uvw[1] + hitVelocity[2] * hit.uvw[2];
|
---|
| 587 | + labels[i] = valueVelocity;
|
---|
| 588 | + }
|
---|
| 589 | + else if (labels[i].toLowerCase() === 'value') {
|
---|
| 590 | + 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]];
|
---|
| 591 | + var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2];
|
---|
| 592 | + var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2];
|
---|
| 593 | + var value = canvas.unitNode.caxis[0] * (1.0 - v) + canvas.unitNode.caxis[1] * v;
|
---|
| 594 | + labels[i] = value;
|
---|
| 595 | + }
|
---|
| 596 | }
|
---|
| 597 |
|
---|
| 598 | //Apply changes to tooltip
|
---|
| 599 | - $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, format));
|
---|
| 600 | + $('#tooltip-content-data-marker-' + canvas.id).html(sprintf.apply(null, canvas.dataMarkers.format.concat(labels)));
|
---|
| 601 | $('#tooltip-content-data-marker-' + canvas.id).css({'font': canvas.dataMarkers.font});
|
---|
| 602 |
|
---|
| 603 | //If animated, setup animation loop to update plot as movie plays.
|
---|
| 604 | if (canvas.dataMarkers.animated) {
|
---|
| 605 | - var isEmpty = (canvas.dataMarkers.values.length == 0);
|
---|
| 606 | - var lastUpdatedIndex = (canvas.dataMarkers.values.length-1);
|
---|
| 607 | + var isEmpty = (canvas.dataMarkers.values.length === 0);
|
---|
| 608 | + var lastUpdatedIndex = (canvas.dataMarkers.values.length - 1);
|
---|
| 609 | var newMovieFrame = (!isEmpty && canvas.dataMarkers.values[lastUpdatedIndex][0] != canvas.animation.frame);
|
---|
| 610 | //If new data marker has been placed, reinitialize plot. If not, push new value into plot value array.
|
---|
| 611 | if (reset) {
|
---|
| 612 | @@ -646,7 +603,7 @@
|
---|
| 613 | canvas.dataMarkers.values = [];
|
---|
| 614 | newMovieFrame = true;
|
---|
| 615 | for (var currentFrame = 0; currentFrame < (canvas.unitNode.movieLength); currentFrame++) {
|
---|
| 616 | - coords = canvas.unitNode.texcoords[currentFrame];
|
---|
| 617 | + coords = canvas.unitMovieData[currentFrame];
|
---|
| 618 | 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]];
|
---|
| 619 | var u = hitCoords[0] * hit.uvw[0] + hitCoords[2] * hit.uvw[1] + hitCoords[4] * hit.uvw[2];
|
---|
| 620 | var v = hitCoords[1] * hit.uvw[0] + hitCoords[3] * hit.uvw[1] + hitCoords[5] * hit.uvw[2];
|
---|
| 621 | @@ -655,7 +612,13 @@
|
---|
| 622 | }
|
---|
| 623 | }
|
---|
| 624 | else {
|
---|
| 625 | + if (canvas.animation.lastFrame > canvas.animation.frame) {
|
---|
| 626 | + canvas.dataMarkers.values = [];
|
---|
| 627 | + }
|
---|
| 628 | if (isEmpty || newMovieFrame) {
|
---|
| 629 | + coords = canvas.unitMovieData[canvas.animation.frame];
|
---|
| 630 | + var hitValues = [coords[hit.indices[0]], coords[hit.indices[1]], coords[hit.indices[2]]];
|
---|
| 631 | + var value = hitValues[0] * hit.uvw[0] + hitValues[1] * hit.uvw[1] + hitValues[2] * hit.uvw[2];
|
---|
| 632 | canvas.dataMarkers.values.push([canvas.animation.frame, value]);
|
---|
| 633 | }
|
---|
| 634 | }
|
---|
| 635 | @@ -663,7 +626,7 @@
|
---|
| 636 | //Replot data marker popup using update data value array.
|
---|
| 637 | if (isEmpty || newMovieFrame) {
|
---|
| 638 | var dataLabels = {'latitude': valueLatitude, 'longitude': valueLongitude, 'thickness': valueThickness, 'velocity': valueVelocity, 'value': value};
|
---|
| 639 | - var dataDisplay = canvas.dataMarkers.values.slice(0, canvas.animation.frame+1);
|
---|
| 640 | + var dataDisplay = canvas.dataMarkers.values.slice(0, canvas.animation.frame + 1);
|
---|
| 641 | plot(
|
---|
| 642 | 'id', '#sim-plot',
|
---|
| 643 | 'type', 'bar',
|
---|
| 644 | @@ -679,12 +642,21 @@
|
---|
| 645 | );
|
---|
| 646 | }
|
---|
| 647 | }
|
---|
| 648 | - repositionMarker(canvas);
|
---|
| 649 | - if (reset) {
|
---|
| 650 | + canvas.dataMarkers.reposition = true;
|
---|
| 651 | + if (reset && !canvas.dataMarkers.marker.selector.closed) {
|
---|
| 652 | canvas.dataMarkers.marker.selector.fadeIn(175);
|
---|
| 653 | canvas.dataMarkers.marker.selector.tooltipster('open');
|
---|
| 654 | }
|
---|
| 655 | } //}}}
|
---|
| 656 | +function animateValue(current, target, duration, stepCallback, doneCallback) { //{{{
|
---|
| 657 | + //Animates scalar value for length duration, calling callback each step.
|
---|
| 658 | + //TODO: Specify lerp easing as option (cubic, linear, cosine).
|
---|
| 659 | + $({'value':current}).animate({'value':target}, {
|
---|
| 660 | + duration: duration,
|
---|
| 661 | + step: stepCallback,
|
---|
| 662 | + done: doneCallback
|
---|
| 663 | + });
|
---|
| 664 | +} //}}}
|
---|
| 665 | //}}}
|
---|
| 666 | //{{{ Drawing Functions
|
---|
| 667 | function updateCameraMatrix(canvas) { //{{{
|
---|
| 668 | @@ -706,12 +678,12 @@
|
---|
| 669 |
|
---|
| 670 | //Calculate rotation around camera focal point about worldspace origin
|
---|
| 671 | if (canvas.view.twod) {
|
---|
| 672 | - mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * 0, [0, 1, 0]);
|
---|
| 673 | + mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * 0, [0, 1, 0]);
|
---|
| 674 | mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * 90, [1, 0, 0]);
|
---|
| 675 | mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix);
|
---|
| 676 | }
|
---|
| 677 | else {
|
---|
| 678 | - mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, DEG2RAD * canvas.view.rotation[0], [0, 1, 0]);
|
---|
| 679 | + mat4.rotate(azimuthRotationMatrix, azimuthRotationMatrix, -DEG2RAD * (canvas.view.rotation[0] + 90), [0, 1, 0]);
|
---|
| 680 | mat4.rotate(elevationRotationMatrix, elevationRotationMatrix, DEG2RAD * canvas.view.rotation[1], [1, 0, 0]);
|
---|
| 681 | mat4.multiply(rotationMatrix, elevationRotationMatrix, azimuthRotationMatrix);
|
---|
| 682 | }
|
---|
| 683 | @@ -734,6 +706,7 @@
|
---|
| 684 |
|
---|
| 685 | vec3.transformMat4(canvas.camera.position, cameraPosition, canvas.camera.vpInverseMatrix);
|
---|
| 686 | canvas.camera.ready = true;
|
---|
| 687 | + repositionMarker(canvas);
|
---|
| 688 | }//}}}
|
---|
| 689 | function drawSceneGraphNode(canvas, node) { //{{{
|
---|
| 690 | if (!node.enabled) { return; }
|
---|
| 691 | @@ -748,7 +721,7 @@
|
---|
| 692 | mat4.multiply(mvMatrix, canvas.camera.vMatrix, node.modelMatrix);
|
---|
| 693 |
|
---|
| 694 | var normalMatrix = mat4.create();
|
---|
| 695 | - mat4.invert(normalMatrix, mvMatrix);
|
---|
| 696 | + mat4.invert(normalMatrix, node.modelMatrix);
|
---|
| 697 | mat4.transpose(normalMatrix, normalMatrix);
|
---|
| 698 |
|
---|
| 699 | if (node.texture) { node.texture.bind(0); }
|
---|
| 700 | @@ -768,23 +741,23 @@
|
---|
| 701 | vec3.sub(cameraPositionRelative, origin, node.translation);
|
---|
| 702 | cameraHeight = vec3.length(cameraPositionRelative);
|
---|
| 703 |
|
---|
| 704 | - var atm = { //Default Values
|
---|
| 705 | - wavelength_r: 0.65, //0.65 Red wavelength (micrometers)
|
---|
| 706 | - wavelength_g: 0.57, //0.57 Green wavelength (micrometers)
|
---|
| 707 | - wavelength_b: 0.475, //0.475 Green wavelength (micrometers)
|
---|
| 708 | - eSun: 100.0, //20.0 Sun intensity
|
---|
| 709 | - kRayleigh: 0.0025, //0.0025 Rayleigh scattering amount
|
---|
| 710 | - kMie: 0.000, //0.01 Mie scattering amount
|
---|
| 711 | - g: -0.99, //-0.99 Mie phase asymmetry/direction factor
|
---|
| 712 | - hdr_exposure: 0.8, //0.8 High Dynamic Range Exposure
|
---|
| 713 | - scale: 1.25, //1.025 Scale of atmosphere. WARNING: Change atmosphereScale in applyoptions.js, and scaling constants.
|
---|
| 714 | - scaleDepth: 0.25, //0.25 Percentage altitude at which the atmosphere's average density is found
|
---|
| 715 | - a: -0.00287, //-0.00287 Scaling constant a
|
---|
| 716 | - b: 0.459, //0.459 Scaling constant b
|
---|
| 717 | - c: 3.83, //3.83 Scaling constant c
|
---|
| 718 | - d: -6.80, //-6.80 Scaling constant d
|
---|
| 719 | - e: 3.6, //5.25 Scaling constant e. Lower when increasing atmosphere scale.
|
---|
| 720 | - attenuation: 0.5 //0.5 Strength of atmospheric scattering on ground shading.
|
---|
| 721 | + var atm = { //Default Values
|
---|
| 722 | + wavelength_r: 0.65, //0.65 Red wavelength (micrometers)
|
---|
| 723 | + wavelength_g: 0.57, //0.57 Green wavelength (micrometers)
|
---|
| 724 | + wavelength_b: 0.475, //0.475 Green wavelength (micrometers)
|
---|
| 725 | + eSun: 100.0, //20.0 Sun intensity
|
---|
| 726 | + kRayleigh: 0.0025, //0.0025 Rayleigh scattering amount
|
---|
| 727 | + kMie: 0.000, //0.01 Mie scattering amount
|
---|
| 728 | + g: -0.99, //-0.99 Mie phase asymmetry/direction factor
|
---|
| 729 | + hdr_exposure: 0.8, //0.8 High Dynamic Range Exposure
|
---|
| 730 | + scale: 1.25, //1.025 Scale of atmosphere. WARNING: Change atmosphereScale in applyoptions.js, and scaling constants.
|
---|
| 731 | + scaleDepth: 0.25, //0.25 Percentage altitude at which the atmosphere's average density is found
|
---|
| 732 | + a: -0.00287, //-0.00287 Scaling constant a
|
---|
| 733 | + b: 0.459, //0.459 Scaling constant b
|
---|
| 734 | + c: 3.83, //3.83 Scaling constant c
|
---|
| 735 | + d: -6.80, //-6.80 Scaling constant d
|
---|
| 736 | + e: 3.6, //5.25 Scaling constant e. Lower when increasing atmosphere scale.
|
---|
| 737 | + attenuation: 0.5 //0.5 Strength of atmospheric scattering on ground shading.
|
---|
| 738 | };
|
---|
| 739 |
|
---|
| 740 | 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)];
|
---|
| 741 | @@ -797,14 +770,19 @@
|
---|
| 742 | m4MVP: mvpMatrix,
|
---|
| 743 | m4Normal: normalMatrix,
|
---|
| 744 | m4Model: node.modelMatrix,
|
---|
| 745 | - //u_lightPosition: [-lightOrigin[0], -lightOrigin[1], -lightOrigin[2]],
|
---|
| 746 | - u_lightPosition: [1.0, 1.0, 1.0],
|
---|
| 747 | - u_diffuseColor: [1.0, 0.9, 0.9],
|
---|
| 748 | + u_lightPosition: lightOrigin,
|
---|
| 749 | + //u_lightPosition: [1.0, 1.0, 1.0],
|
---|
| 750 | + u_diffuseColor: node.diffuseColor,
|
---|
| 751 | u_texture: 0,
|
---|
| 752 | u_alpha: node.alpha,
|
---|
| 753 | + u_maskZerosColor: node.maskZerosColor,
|
---|
| 754 | + u_maskZerosEnabled: node.maskZerosEnabled,
|
---|
| 755 | + u_maskZerosTolerance: node.maskZerosTolerance,
|
---|
| 756 | + u_maskZerosZeroValue: node.maskZerosZeroValue,
|
---|
| 757 | u_maskEnabled: node.maskEnabled,
|
---|
| 758 | u_maskHeight: node.maskHeight,
|
---|
| 759 | u_maskColor: node.maskColor,
|
---|
| 760 | + u_pointSize: node.pointSize,
|
---|
| 761 | v3CameraPosition: origin,
|
---|
| 762 | v3Translate: node.translation,
|
---|
| 763 | v3LightPos: lightOrigin,
|
---|
| 764 | @@ -840,10 +818,10 @@
|
---|
| 765 | //TODO: Come up with better way to check if shaders are ready, or move outside of main draw function
|
---|
| 766 | var nodes = canvas.nodes;
|
---|
| 767 | if (!canvas.draw.ready) {
|
---|
| 768 | - if (nodes.length !== 0) {
|
---|
| 769 | + if (Object.keys(nodes).length !== 0) {
|
---|
| 770 | canvas.draw.ready = true;
|
---|
| 771 | for (var node in nodes) {
|
---|
| 772 | - if (nodes[node].shader.ready == false) {
|
---|
| 773 | + if (nodes[node].shader.ready === false) {
|
---|
| 774 | canvas.draw.ready = false;
|
---|
| 775 | break;
|
---|
| 776 | }
|
---|
| 777 | @@ -854,9 +832,6 @@
|
---|
| 778 |
|
---|
| 779 | //Begin rendering nodes
|
---|
| 780 | if (canvas.draw.ready) {
|
---|
| 781 | - if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); }
|
---|
| 782 | - if (canvas.overlaycanvas) { canvas.overlaycanvas.draw(canvas); }
|
---|
| 783 | -
|
---|
| 784 | var rect = canvas.getBoundingClientRect();
|
---|
| 785 | canvas.width = rect.width;
|
---|
| 786 | canvas.height = rect.height;
|
---|
| 787 | @@ -869,10 +844,13 @@
|
---|
| 788 |
|
---|
| 789 | updateCameraMatrix(canvas);
|
---|
| 790 |
|
---|
| 791 | + if (canvas.textcanvas) { canvas.textcanvas.draw(canvas); }
|
---|
| 792 | + if (canvas.overlaycanvas) { canvas.overlaycanvas.draw(canvas); }
|
---|
| 793 | +
|
---|
| 794 | var drawPassNumber = 3;
|
---|
| 795 | - for (var i = drawPassNumber - 1; i >= 0; i--) {
|
---|
| 796 | + for (var i = drawPassNumber - 1; i >= 0; --i) {
|
---|
| 797 | for (var node in nodes) {
|
---|
| 798 | - if (nodes[node].drawOrder == i) { drawSceneGraphNode(canvas, nodes[node]); }
|
---|
| 799 | + if (nodes[node].drawOrder === i) { drawSceneGraphNode(canvas, nodes[node]); }
|
---|
| 800 | }
|
---|
| 801 | }
|
---|
| 802 | }
|
---|
| 803 | Index: ../trunk-jpl/src/m/plot/applyoptions.js
|
---|
| 804 | ===================================================================
|
---|
| 805 | --- ../trunk-jpl/src/m/plot/applyoptions.js (revision 21767)
|
---|
| 806 | +++ ../trunk-jpl/src/m/plot/applyoptions.js (revision 21768)
|
---|
| 807 | @@ -1,4 +1,4 @@
|
---|
| 808 | -function applyoptions(md, data, datatype, options, canvas, gl, node){ //{{{
|
---|
| 809 | +function applyoptions(md, data, options, canvas){ //{{{
|
---|
| 810 | //APPLYOPTIONS - apply colobar, text, cloud, and expdisp options to current plot
|
---|
| 811 | //
|
---|
| 812 | // Usage:
|
---|
| 813 | @@ -7,14 +7,11 @@
|
---|
| 814 | // See also: PLOTMODEL, PARSE_OPTIONS
|
---|
| 815 |
|
---|
| 816 | //{{{ colorbar
|
---|
| 817 | + var gl = canvas.gl;
|
---|
| 818 | if (options.exist('colorbar')) {
|
---|
| 819 | if (options.getfieldvalue('colorbar')==1) {
|
---|
| 820 | - //{{{ Handle movie data
|
---|
| 821 | - if (datatype == 5) {
|
---|
| 822 | - data = data[0];
|
---|
| 823 | - } //}}}
|
---|
| 824 | //{{{ Variable options initialization
|
---|
| 825 | - var caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]);
|
---|
| 826 | + var caxis = options.getfieldvalue('caxis');
|
---|
| 827 | var colorbarinnerlabels = options.getfieldvalue('colorbarinnerlabels','off');
|
---|
| 828 | var ccanvasid, ctitleid, clabelsid, ccanvas, ctitle, clabels, ccontext, cmap, colorbar, cwidth, cheight, cgradient, color, y, x;
|
---|
| 829 | //}}}
|
---|
| 830 | @@ -23,14 +20,31 @@
|
---|
| 831 | var cdivisions = options.getfieldvalue('colorbarnticks', 6);
|
---|
| 832 | var caxisdelta = caxis[1] - caxis[0];
|
---|
| 833 | var precision = options.getfieldvalue('colorbarprecision', 3);
|
---|
| 834 | + var format = options.getfieldvalue('colorbarformat', 'f').toLowerCase();
|
---|
| 835 | if (options.getfieldvalue('log','off')!='off') {
|
---|
| 836 | for (var i=cdivisions; i >= 0; i--) {
|
---|
| 837 | var scale = (Math.log10(caxis[1])-Math.log10(caxis[0]))/Math.log10(options.getfieldvalue('log', 10));
|
---|
| 838 | - labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision);
|
---|
| 839 | + if (format === 'f') {
|
---|
| 840 | + labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision);
|
---|
| 841 | + }
|
---|
| 842 | + else if (format === 'e') {
|
---|
| 843 | + labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toPrecision(precision);
|
---|
| 844 | + }
|
---|
| 845 | + else {
|
---|
| 846 | + labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision);
|
---|
| 847 | + }
|
---|
| 848 | }
|
---|
| 849 | } else {
|
---|
| 850 | for (var i=cdivisions; i >= 0; i--) {
|
---|
| 851 | - labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision);
|
---|
| 852 | + if (format === 'f') {
|
---|
| 853 | + labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision);
|
---|
| 854 | + }
|
---|
| 855 | + else if (format === 'e') {
|
---|
| 856 | + labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toPrecision(precision);
|
---|
| 857 | + }
|
---|
| 858 | + else {
|
---|
| 859 | + labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision);
|
---|
| 860 | + }
|
---|
| 861 | }
|
---|
| 862 | } //}}}
|
---|
| 863 | //{{{ Initialize colorbar canvas
|
---|
| 864 | @@ -116,166 +130,8 @@
|
---|
| 865 | tcontext.fillStyle = tgradient;
|
---|
| 866 | tcontext.fillRect(0, 0, 256, 256);
|
---|
| 867 | tURL = tcanvas.toDataURL();
|
---|
| 868 | - node.texture = initTexture(gl, tURL);
|
---|
| 869 | - node.textureCanvas = tcanvas;
|
---|
| 870 | - node.caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]);
|
---|
| 871 | + canvas.unitNode.texture = initTexture(canvas.gl, tURL);
|
---|
| 872 | //}}}
|
---|
| 873 | - //{{{ expdisp contours
|
---|
| 874 | - if (options.exist('expdisp')) {
|
---|
| 875 | - canvas.nodes.expdisp = Node(gl, options);
|
---|
| 876 | - var node = canvas.nodes.expdisp;
|
---|
| 877 | -
|
---|
| 878 | - //declare variables: {{{
|
---|
| 879 | - var vertices = [];
|
---|
| 880 | - var indices = [];
|
---|
| 881 | - var colors = [];
|
---|
| 882 | - var rgbcolor = [];
|
---|
| 883 | - var xmin, xmax;
|
---|
| 884 | - var ymin, ymax;
|
---|
| 885 | - var zmin, zmax;
|
---|
| 886 | - var scale;
|
---|
| 887 | -
|
---|
| 888 | - //Process data and model
|
---|
| 889 | - var x = options.getfieldvalue('expdisp').x;
|
---|
| 890 | - var y = options.getfieldvalue('expdisp').y;
|
---|
| 891 | - var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0);
|
---|
| 892 | -
|
---|
| 893 | - if (options.getfieldvalue('expdisp').z) {
|
---|
| 894 | - z = options.getfieldvalue('expdisp').z;
|
---|
| 895 | - }
|
---|
| 896 | - //}}}
|
---|
| 897 | -
|
---|
| 898 | - //Compute coordinates and data range: //{{{
|
---|
| 899 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 900 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 901 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 902 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 903 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 904 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 905 | - xmin = xlim[0];
|
---|
| 906 | - xmax = xlim[1];
|
---|
| 907 | - ymin = ylim[0];
|
---|
| 908 | - ymax = ylim[1];
|
---|
| 909 | - zmin = zlim[0];
|
---|
| 910 | - zmax = zlim[1];
|
---|
| 911 | - //}}}
|
---|
| 912 | -
|
---|
| 913 | - //Compute scaling: //{{{
|
---|
| 914 | - var scale = 1 / (xmax - xmin);
|
---|
| 915 | - node.shaderName = 'colored';
|
---|
| 916 | - node.shader = gl.shaders[node.shaderName].program;
|
---|
| 917 | - node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)];
|
---|
| 918 | - node.translation = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (-2 / scale)];
|
---|
| 919 | - node.modelMatrix = updateModelMatrix(node);
|
---|
| 920 | - node.drawMode = gl.LINE_LOOP;
|
---|
| 921 | - node.drawOrder = 0;
|
---|
| 922 | - node.useIndexBuffer = false;
|
---|
| 923 | - node.disableDepthTest = true;
|
---|
| 924 | - //}}}
|
---|
| 925 | -
|
---|
| 926 | - //some defaults:
|
---|
| 927 | - colors.itemSize = 4;
|
---|
| 928 | -
|
---|
| 929 | - //retrieve some options
|
---|
| 930 | - var linewidth=options.getfieldvalue('linewidth', 1);
|
---|
| 931 | - var edgecolor=options.getfieldvalue('edgecolor','black'); //RGBCOLOR?
|
---|
| 932 | -
|
---|
| 933 | - vertices.itemSize = 3;
|
---|
| 934 | - for(var i=0; i < x.length; i++){
|
---|
| 935 | - vertices[vertices.length] = x[i];
|
---|
| 936 | - vertices[vertices.length] = y[i];
|
---|
| 937 | - vertices[vertices.length] = z[i];
|
---|
| 938 | -
|
---|
| 939 | - //edgecolor
|
---|
| 940 | - rgbcolor = [0.0, 0.0, 0.0];
|
---|
| 941 | - colors[colors.length] = rgbcolor[0];
|
---|
| 942 | - colors[colors.length] = rgbcolor[1];
|
---|
| 943 | - colors[colors.length] = rgbcolor[2];
|
---|
| 944 | - colors[colors.length] = 1.0;
|
---|
| 945 | - }
|
---|
| 946 | -
|
---|
| 947 | - //Initalize buffers:
|
---|
| 948 | - node.arrays = [vertices, colors];
|
---|
| 949 | - node.buffers = initBuffers(gl, node.arrays);
|
---|
| 950 | - } //}}}
|
---|
| 951 | - //{{{ cloud of points
|
---|
| 952 | - if (options.exist('cloud')) {
|
---|
| 953 | - canvas.nodes.cloud = Node(gl, options);
|
---|
| 954 | - var node = canvas.nodes.cloud;
|
---|
| 955 | -
|
---|
| 956 | - //declare variables: {{{
|
---|
| 957 | - var vertices = [];
|
---|
| 958 | - var indices = [];
|
---|
| 959 | - var colors = [];
|
---|
| 960 | - var rgbcolor = [];
|
---|
| 961 | - var xmin, xmax;
|
---|
| 962 | - var ymin, ymax;
|
---|
| 963 | - var zmin, zmax;
|
---|
| 964 | - var scale;
|
---|
| 965 | -
|
---|
| 966 | - //Process data and model
|
---|
| 967 | - var x = options.getfieldvalue('cloud').x;
|
---|
| 968 | - var y = options.getfieldvalue('cloud').y;
|
---|
| 969 | - var z = Array.apply(null, Array(x.length)).map(Number.prototype.valueOf, 0);
|
---|
| 970 | -
|
---|
| 971 | - if (options.getfieldvalue('cloud').z) {
|
---|
| 972 | - z = options.getfieldvalue('cloud').z;
|
---|
| 973 | - }
|
---|
| 974 | - //}}}
|
---|
| 975 | -
|
---|
| 976 | - //Compute coordinates and data range: //{{{
|
---|
| 977 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 978 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 979 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 980 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 981 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 982 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 983 | - xmin = xlim[0];
|
---|
| 984 | - xmax = xlim[1];
|
---|
| 985 | - ymin = ylim[0];
|
---|
| 986 | - ymax = ylim[1];
|
---|
| 987 | - zmin = zlim[0];
|
---|
| 988 | - zmax = zlim[1];
|
---|
| 989 | - //}}}
|
---|
| 990 | -
|
---|
| 991 | - //Compute scaling: //{{{
|
---|
| 992 | - var scale = 1 / (xmax - xmin);
|
---|
| 993 | - node.shaderName = 'colored';
|
---|
| 994 | - node.shader = gl.shaders[node.shaderName].program;
|
---|
| 995 | - node.scale = [scale, scale, scale*options.getfieldvalue('heightscale', 1)];
|
---|
| 996 | - node.translation = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (-2 / scale)];
|
---|
| 997 | - node.modelMatrix = updateModelMatrix(node);
|
---|
| 998 | - node.drawMode = gl.POINTS;
|
---|
| 999 | - node.drawOrder = 0;
|
---|
| 1000 | - node.useIndexBuffer = false;
|
---|
| 1001 | - node.disableDepthTest = true;
|
---|
| 1002 | - //}}}
|
---|
| 1003 | -
|
---|
| 1004 | - //some defaults:
|
---|
| 1005 | - colors.itemSize = 4;
|
---|
| 1006 | -
|
---|
| 1007 | - //retrieve some options
|
---|
| 1008 | - var linewidth=options.getfieldvalue('linewidth', 1);
|
---|
| 1009 | - var edgecolor=options.getfieldvalue('edgecolor','black'); //RGBCOLOR?
|
---|
| 1010 | -
|
---|
| 1011 | - vertices.itemSize = 3;
|
---|
| 1012 | - for(var i=0; i < x.length; i++){
|
---|
| 1013 | - vertices[vertices.length] = x[i];
|
---|
| 1014 | - vertices[vertices.length] = y[i];
|
---|
| 1015 | - vertices[vertices.length] = z[i];
|
---|
| 1016 | -
|
---|
| 1017 | - //edgecolor
|
---|
| 1018 | - rgbcolor = [0.0, 0.0, 0.0];
|
---|
| 1019 | - colors[colors.length] = rgbcolor[0];
|
---|
| 1020 | - colors[colors.length] = rgbcolor[1];
|
---|
| 1021 | - colors[colors.length] = rgbcolor[2];
|
---|
| 1022 | - colors[colors.length] = 1.0;
|
---|
| 1023 | - }
|
---|
| 1024 | -
|
---|
| 1025 | - //Initalize buffers:
|
---|
| 1026 | - node.arrays = [vertices, colors];
|
---|
| 1027 | - node.buffers = initBuffers(gl, node.arrays);
|
---|
| 1028 | - } //}}}
|
---|
| 1029 | //{{{ text display
|
---|
| 1030 | if (options.exist('textlabels')) {
|
---|
| 1031 | var textcanvas, textcanvasid;
|
---|
| 1032 | @@ -324,39 +180,39 @@
|
---|
| 1033 | var overlaycanvasid = options.getfieldvalue('latlongoverlayid', options.getfieldvalue('canvasid')+'-overlay');
|
---|
| 1034 | var overlaycanvas = $('#'+overlaycanvasid)[0];
|
---|
| 1035 | var latitudes = {
|
---|
| 1036 | - //"-90": 1,
|
---|
| 1037 | - //"-65": .999,
|
---|
| 1038 | - "-60": 0.994046875,
|
---|
| 1039 | - //"-55": 0.983187500000002,
|
---|
| 1040 | - //"-50": 0.97173550854167,
|
---|
| 1041 | - "-45": 0.955729166666666,
|
---|
| 1042 | - //"-40": 0.94218750000000218,
|
---|
| 1043 | - //"-35": 0.94218750000000218,
|
---|
| 1044 | - "-30": 0.9226562500000024,
|
---|
| 1045 | - //"-25": 0.87934895833333526,
|
---|
| 1046 | - //"-20": 0.856572916666669,
|
---|
| 1047 | - //"-15": 0.830729166666665,
|
---|
| 1048 | - //"-10": 0.803552708333336,
|
---|
| 1049 | - //"-5": 0.77395833333333541,
|
---|
| 1050 | - "0": 0.74218749999999811,
|
---|
| 1051 | - //"5": 0.70950364583333347,
|
---|
| 1052 | - //"10": 0.67479166666666823,
|
---|
| 1053 | - //"15": 0.63932291666666663,
|
---|
| 1054 | - //"20": 0.60171875,
|
---|
| 1055 | - //"25": 0.563453125,
|
---|
| 1056 | - "30": 0.523390625000001,
|
---|
| 1057 | - //"35": 0.48401875,
|
---|
| 1058 | - //"40": 0.44296875,
|
---|
| 1059 | - "45": 0.4020001,
|
---|
| 1060 | - //"50": 0.3578125,
|
---|
| 1061 | - //"55": 0.311875,
|
---|
| 1062 | - "60": 0.26953124999999978,
|
---|
| 1063 | - //"65": 0.225390625,
|
---|
| 1064 | - //"70": 0.18125,
|
---|
| 1065 | - //"75": 0.13541666666666671,
|
---|
| 1066 | - //"80": 0.08953125,
|
---|
| 1067 | - //"85": 0.046250000000000013,
|
---|
| 1068 | - //"90": 0.0,
|
---|
| 1069 | + //'-90': 1,
|
---|
| 1070 | + //'-65': .999,
|
---|
| 1071 | + '-60': 0.994046875,
|
---|
| 1072 | + //'-55': 0.983187500000002,
|
---|
| 1073 | + //'-50': 0.97173550854167,
|
---|
| 1074 | + '-45': 0.955729166666666,
|
---|
| 1075 | + //'-40': 0.94218750000000218,
|
---|
| 1076 | + //'-35': 0.94218750000000218,
|
---|
| 1077 | + '-30': 0.9226562500000024,
|
---|
| 1078 | + //'-25': 0.87934895833333526,
|
---|
| 1079 | + //'-20': 0.856572916666669,
|
---|
| 1080 | + //'-15': 0.830729166666665,
|
---|
| 1081 | + //'-10': 0.803552708333336,
|
---|
| 1082 | + //'-5': 0.77395833333333541,
|
---|
| 1083 | + '0': 0.74218749999999811,
|
---|
| 1084 | + //'5': 0.70950364583333347,
|
---|
| 1085 | + //'10': 0.67479166666666823,
|
---|
| 1086 | + //'15': 0.63932291666666663,
|
---|
| 1087 | + //'20': 0.60171875,
|
---|
| 1088 | + //'25': 0.563453125,
|
---|
| 1089 | + '30': 0.523390625000001,
|
---|
| 1090 | + //'35': 0.48401875,
|
---|
| 1091 | + //'40': 0.44296875,
|
---|
| 1092 | + '45': 0.4020001,
|
---|
| 1093 | + //'50': 0.3578125,
|
---|
| 1094 | + //'55': 0.311875,
|
---|
| 1095 | + '60': 0.26953124999999978,
|
---|
| 1096 | + //'65': 0.225390625,
|
---|
| 1097 | + //'70': 0.18125,
|
---|
| 1098 | + //'75': 0.13541666666666671,
|
---|
| 1099 | + //'80': 0.08953125,
|
---|
| 1100 | + //'85': 0.046250000000000013,
|
---|
| 1101 | + //'90': 0.0,
|
---|
| 1102 | }
|
---|
| 1103 | var longitudes = [-150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180];
|
---|
| 1104 | overlaycanvas.draw = function(canvas) {
|
---|
| 1105 | @@ -400,96 +256,197 @@
|
---|
| 1106 | var is2d = meshresults[4];
|
---|
| 1107 | var isplanet = meshresults[5];
|
---|
| 1108 |
|
---|
| 1109 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 1110 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 1111 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 1112 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 1113 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 1114 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 1115 | - xmin = xlim[0];
|
---|
| 1116 | - xmax = xlim[1];
|
---|
| 1117 | - ymin = ylim[0];
|
---|
| 1118 | - ymax = ylim[1];
|
---|
| 1119 | - zmin = zlim[0];
|
---|
| 1120 | - zmax = zlim[1];
|
---|
| 1121 | + var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
|
---|
| 1122 | + var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
|
---|
| 1123 | + var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
|
---|
| 1124 | +
|
---|
| 1125 | + 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
|
---|
| 1126 | + 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];
|
---|
| 1127 |
|
---|
| 1128 | - 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
|
---|
| 1129 | - var atmosphereScale = 1.25;
|
---|
| 1130 | - var translation = global ? [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2] : [(xmin + xmax) / 2, (ymin + ymax) - 6371000, (zmin + zmax) / 2];
|
---|
| 1131 | -
|
---|
| 1132 | - if (options.getfieldvalue('render',[]).indexOf('sky')!=-1) {
|
---|
| 1133 | - //atmosphere
|
---|
| 1134 | - var node = Node(gl);
|
---|
| 1135 | - node.name = "atmosphere";
|
---|
| 1136 | - node.shaderName = "SkyFromSpace";
|
---|
| 1137 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 1138 | - node.drawOrder = 1;
|
---|
| 1139 | - node.cullFace = gl.FRONT;
|
---|
| 1140 | - node.enableCullFace = true;
|
---|
| 1141 | - node.mesh = GL.Mesh.icosahedron({size: 6371000*atmosphereScale, subdivisions: 6});
|
---|
| 1142 | - node.rotation = [0, 0, 0];
|
---|
| 1143 | - node.translation = translation;
|
---|
| 1144 | - node.center = [0, 0, 0];
|
---|
| 1145 | - updateModelMatrix(node);
|
---|
| 1146 | - canvas.nodes[node.name] = node;
|
---|
| 1147 | + var renderObjects = options.getfieldvalue('render',{});
|
---|
| 1148 | + if ('sky' in renderObjects && !('sky' in canvas.nodes)) {
|
---|
| 1149 | + var object = renderObjects.sky;
|
---|
| 1150 | + object = {
|
---|
| 1151 | + enabled: defaultFor(object.enabled, true),
|
---|
| 1152 | + scale: defaultFor(object.scale, 1),
|
---|
| 1153 | + };
|
---|
| 1154 | + if (object.enabled) {
|
---|
| 1155 | + var atmosphereScale = 1.25;
|
---|
| 1156 | + var mesh = GL.Mesh.icosahedron({size: 6371000 * atmosphereScale, subdivisions: 5});
|
---|
| 1157 | + var texture = initTexture(gl, canvas.rootPath + 'textures/TychoSkymapII_t4_2k.jpg');
|
---|
| 1158 | + node = new Node(
|
---|
| 1159 | + 'canvas', canvas,
|
---|
| 1160 | + 'options', options,
|
---|
| 1161 | + 'name', 'sky',
|
---|
| 1162 | + 'shaderName', 'SkyFromSpace',
|
---|
| 1163 | + 'cullFace', gl.FRONT,
|
---|
| 1164 | + 'mesh', mesh,
|
---|
| 1165 | + 'texture',texture,
|
---|
| 1166 | + 'translation',translation
|
---|
| 1167 | + );
|
---|
| 1168 | + }
|
---|
| 1169 | }
|
---|
| 1170 | - if (options.getfieldvalue('render',[]).indexOf('space')!=-1) {
|
---|
| 1171 | - //skysphere
|
---|
| 1172 | - node = Node(gl);
|
---|
| 1173 | - node.name = "skysphere";
|
---|
| 1174 | - node.shaderName = "Textured";
|
---|
| 1175 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 1176 | - node.drawOrder = 2;
|
---|
| 1177 | - node.cullFace = gl.FRONT;
|
---|
| 1178 | - node.enableCullFace = true;
|
---|
| 1179 | - node.mesh = GL.Mesh.sphere({size: 6371000*20});
|
---|
| 1180 | - node.texture = initTexture(gl, canvas.rootPath+'textures/TychoSkymapII_t4_2k.jpg');
|
---|
| 1181 | - node.rotation = [0, 0, 0];
|
---|
| 1182 | - node.translation = translation;
|
---|
| 1183 | - node.center = [0, 0, 0];
|
---|
| 1184 | - updateModelMatrix(node);
|
---|
| 1185 | - canvas.nodes[node.name] = node;
|
---|
| 1186 | + if ('space' in renderObjects && !('space' in canvas.nodes)) {
|
---|
| 1187 | + var object = renderObjects.space;
|
---|
| 1188 | + object = {
|
---|
| 1189 | + enabled: defaultFor(object.enabled, true),
|
---|
| 1190 | + scale: defaultFor(object.scale, 1),
|
---|
| 1191 | + };
|
---|
| 1192 | + if (object.enabled) {
|
---|
| 1193 | + var mesh = GL.Mesh.sphere({size: 6371000 * 20});
|
---|
| 1194 | + var texture = initTexture(gl, canvas.rootPath + 'textures/TychoSkymapII_t4_2k.jpg');
|
---|
| 1195 | + node = new Node(
|
---|
| 1196 | + 'canvas', canvas,
|
---|
| 1197 | + 'options', options,
|
---|
| 1198 | + 'name', 'space',
|
---|
| 1199 | + 'shaderName', 'Textured',
|
---|
| 1200 | + 'cullFace', gl.FRONT,
|
---|
| 1201 | + 'drawOrder', 2,
|
---|
| 1202 | + 'mesh', mesh,
|
---|
| 1203 | + 'texture',texture,
|
---|
| 1204 | + 'translation',translation
|
---|
| 1205 | + );
|
---|
| 1206 | + }
|
---|
| 1207 | }
|
---|
| 1208 | + if ('coastlines' in renderObjects && !('coastlines' in canvas.nodes)) {
|
---|
| 1209 | + var object = renderObjects.coastlines;
|
---|
| 1210 | + object = {
|
---|
| 1211 | + enabled: defaultFor(object.enabled, false),
|
---|
| 1212 | + scale: defaultFor(object.scale, 1),
|
---|
| 1213 | + x: defaultFor(object.x, {}),
|
---|
| 1214 | + y: defaultFor(object.y, {}),
|
---|
| 1215 | + z: defaultFor(object.z, {})
|
---|
| 1216 | + };
|
---|
| 1217 | + if (object.enabled) {
|
---|
| 1218 | + node = new Node(
|
---|
| 1219 | + 'canvas', canvas,
|
---|
| 1220 | + 'options', options,
|
---|
| 1221 | + 'name', 'coastlines',
|
---|
| 1222 | + 'shaderName', 'Colored',
|
---|
| 1223 | + 'drawMode', gl.LINE_STRIP,
|
---|
| 1224 | + 'lineWidth', options.getfieldvalue('linewidth', 1),
|
---|
| 1225 | + 'scale', [object.scale, object.scale, object.scale],
|
---|
| 1226 | + 'rotation', [-90, 0, 0]
|
---|
| 1227 | + );
|
---|
| 1228 | + node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none');
|
---|
| 1229 | + }
|
---|
| 1230 | + }
|
---|
| 1231 | + if ('graticule' in renderObjects && !('graticule' in canvas.nodes)) {
|
---|
| 1232 | + var object = renderObjects.graticule;
|
---|
| 1233 | + object = {
|
---|
| 1234 | + enabled: defaultFor(object.enabled, false),
|
---|
| 1235 | + scale: defaultFor(object.scale, 1),
|
---|
| 1236 | + x: defaultFor(object.x, {}),
|
---|
| 1237 | + y: defaultFor(object.y, {}),
|
---|
| 1238 | + z: defaultFor(object.z, {})
|
---|
| 1239 | + };
|
---|
| 1240 | + if (object.enabled) {
|
---|
| 1241 | + node = new Node(
|
---|
| 1242 | + 'canvas', canvas,
|
---|
| 1243 | + 'options', options,
|
---|
| 1244 | + 'name', 'graticule',
|
---|
| 1245 | + 'shaderName', 'Colored',
|
---|
| 1246 | + 'drawMode', gl.LINE_STRIP,
|
---|
| 1247 | + 'lineWidth', options.getfieldvalue('linewidth', 1),
|
---|
| 1248 | + 'scale', [object.scale, object.scale, object.scale],
|
---|
| 1249 | + 'rotation', [-90, 0, 0]
|
---|
| 1250 | + );
|
---|
| 1251 | + node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none');
|
---|
| 1252 | + }
|
---|
| 1253 | + }
|
---|
| 1254 | + if ('cities' in renderObjects && !('cities' in canvas.nodes)) {
|
---|
| 1255 | + var object = renderObjects.cities;
|
---|
| 1256 | + object = {
|
---|
| 1257 | + enabled: defaultFor(object.enabled, false),
|
---|
| 1258 | + scale: defaultFor(object.scale, 1),
|
---|
| 1259 | + size: defaultFor(object.size, 1.5),
|
---|
| 1260 | + color: defaultFor(object.color, 'black'),
|
---|
| 1261 | + x: defaultFor(object.x, {}),
|
---|
| 1262 | + y: defaultFor(object.y, {}),
|
---|
| 1263 | + z: defaultFor(object.z, {}),
|
---|
| 1264 | + indices: defaultFor(object.indices, {})
|
---|
| 1265 | + };
|
---|
| 1266 | + if (object.enabled) {
|
---|
| 1267 | + var mesh = GL.Mesh.icosahedron({size: object.size, subdivisions: 1});
|
---|
| 1268 | + node = new Node(
|
---|
| 1269 | + 'canvas', canvas,
|
---|
| 1270 | + 'options', options,
|
---|
| 1271 | + 'name', 'cities',
|
---|
| 1272 | + 'shaderName', 'Colored',
|
---|
| 1273 | + 'diffuseColor', object.color,
|
---|
| 1274 | + 'lineWidth', options.getfieldvalue('linewidth', 1),
|
---|
| 1275 | + 'scale', [object.scale, object.scale, object.scale],
|
---|
| 1276 | + 'rotation', [-90, 0, 0]
|
---|
| 1277 | + );
|
---|
| 1278 | + node.geometryShader('Mesh', mesh, 'Vertices', [object.x, object.y, object.z], 'Indices', object.indices);
|
---|
| 1279 | + }
|
---|
| 1280 | + }
|
---|
| 1281 | + if ('city' in renderObjects) {
|
---|
| 1282 | + var object = renderObjects.city;
|
---|
| 1283 | + object = {
|
---|
| 1284 | + enabled: defaultFor(object.enabled, false),
|
---|
| 1285 | + name: defaultFor(object.name, 'NY'),
|
---|
| 1286 | + size: defaultFor(object.size, 15000),
|
---|
| 1287 | + color: defaultFor(object.color, 'magenta'),
|
---|
| 1288 | + x: defaultFor(object.x, {}),
|
---|
| 1289 | + y: defaultFor(object.y, {}),
|
---|
| 1290 | + z: defaultFor(object.z, {})
|
---|
| 1291 | + };
|
---|
| 1292 | + if (object.enabled) {
|
---|
| 1293 | + //city
|
---|
| 1294 | + var mesh = GL.Mesh.sphere({size: object.size});
|
---|
| 1295 | + node = new Node(
|
---|
| 1296 | + 'canvas', canvas,
|
---|
| 1297 | + 'options', options,
|
---|
| 1298 | + 'name', 'city',
|
---|
| 1299 | + 'shaderName', 'Colored',
|
---|
| 1300 | + 'diffuseColor', object.color,
|
---|
| 1301 | + 'mesh', mesh,
|
---|
| 1302 | + 'translation', [object.x, object.z, -object.y]
|
---|
| 1303 | + );
|
---|
| 1304 | +
|
---|
| 1305 | + var overlaycanvasid = options.getfieldvalue('overlayid', options.getfieldvalue('canvasid')+'-overlay');
|
---|
| 1306 | + var overlaycanvas = $('#'+overlaycanvasid)[0];
|
---|
| 1307 | + overlaycanvas.draw = function(canvas) {
|
---|
| 1308 | + var rect = overlaycanvas.getBoundingClientRect();
|
---|
| 1309 | + overlaycanvas.width = rect.width;
|
---|
| 1310 | + overlaycanvas.height = rect.height;
|
---|
| 1311 | + var ctx = overlaycanvas.getContext('2d');
|
---|
| 1312 | + var node = canvas.nodes['city'];
|
---|
| 1313 | + node.translation = [object.x, object.z, -object.y];
|
---|
| 1314 | + node.updateModelMatrix();
|
---|
| 1315 | + var screenPoint = vec3.transformMat4(vec3.create(), node.translation, canvas.camera.vpMatrix);
|
---|
| 1316 | + var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left;
|
---|
| 1317 | + var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top;
|
---|
| 1318 | +
|
---|
| 1319 | + ctx.font = String(options.getfieldvalue('colorbarfontsize', 22))+'px Arial Black, sans-serif';
|
---|
| 1320 | + ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black');
|
---|
| 1321 | + ctx.strokeStyle = 'white';
|
---|
| 1322 | + ctx.textAlign = 'center';
|
---|
| 1323 | + ctx.textBaseline = 'middle';
|
---|
| 1324 | + ctx.fillText(object.name, x, y);
|
---|
| 1325 | + ctx.strokeText(object.name, x, y);
|
---|
| 1326 | + }
|
---|
| 1327 | + canvas.overlaycanvas = overlaycanvas;
|
---|
| 1328 | + }
|
---|
| 1329 | + }
|
---|
| 1330 | if (canvas.clouds.enabled) {
|
---|
| 1331 | //clouds
|
---|
| 1332 | for (var i = 0; i < canvas.clouds.quantity; i++) {
|
---|
| 1333 | - node = Node(gl);
|
---|
| 1334 | - node.name = "clouds" + i;
|
---|
| 1335 | - node.shaderName = "Clouds";
|
---|
| 1336 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 1337 | - node.drawOrder = 2;
|
---|
| 1338 | - node.cullFace = gl.BACK;
|
---|
| 1339 | - node.enableCullFace = true;
|
---|
| 1340 | - node.mesh = GL.Mesh.fromURL(canvas.rootPath+'obj/cloud.obj');
|
---|
| 1341 | - node.rotation = [0, 0, 0];
|
---|
| 1342 | - node.scale = [2500, 2500, 2500];
|
---|
| 1343 | - node.translation = [translation[0], translation[1] - 405000, translation[2]];
|
---|
| 1344 | - node.center = [0, 0, 0];
|
---|
| 1345 | - node.animation = {"time": Date.now(),"target": node.translation,"current": node.translation};
|
---|
| 1346 | - updateModelMatrix(node);
|
---|
| 1347 | - canvas.nodes[node.name] = node;
|
---|
| 1348 | - //canvas.clouds.list
|
---|
| 1349 | + var mesh = GL.Mesh.fromURL(canvas.rootPath+'obj/cloud.obj');
|
---|
| 1350 | + translation = [translation[0] + Math.floor((Math.random() * (1 + 12000 - (-12000)) + (-12000))), translation[1] - 405000, translation[2] + Math.floor((Math.random() * (1 + 12000 - (-12000)) + (-12000)))];
|
---|
| 1351 | + node = new Node(
|
---|
| 1352 | + 'canvas', canvas,
|
---|
| 1353 | + 'options', options,
|
---|
| 1354 | + 'name', 'clouds' + i,
|
---|
| 1355 | + 'shaderName', 'Textured',
|
---|
| 1356 | + 'animation', {'time': Date.now(),'target': translation,'current': translation},
|
---|
| 1357 | + 'diffuseColor', [0.7,0.7,0.7,1.0],
|
---|
| 1358 | + 'mesh', mesh,
|
---|
| 1359 | + 'scale', [2500, 2500, 2500],
|
---|
| 1360 | + 'translation', translation
|
---|
| 1361 | + );
|
---|
| 1362 | }
|
---|
| 1363 | - //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.
|
---|
| 1364 | -
|
---|
| 1365 | }
|
---|
| 1366 | - if (options.getfieldvalue('render',[]).indexOf('latlong')!=-1) {
|
---|
| 1367 | - //latlong
|
---|
| 1368 | - node = Node(gl);
|
---|
| 1369 | - node.name = "clouds";
|
---|
| 1370 | - node.shaderName = "Clouds";
|
---|
| 1371 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 1372 | - node.drawOrder = 2;
|
---|
| 1373 | - node.cullFace = gl.BACK;
|
---|
| 1374 | - node.enableCullFace = true;
|
---|
| 1375 | - node.mesh = GL.Mesh.fromURL(canvas.rootPath+'obj/cloud.obj');
|
---|
| 1376 | - node.rotation = [0, 0, 0];
|
---|
| 1377 | - node.scale = [2500, 2500, 2500];
|
---|
| 1378 | - node.translation = [translation[0], translation[1] - 405000, translation[2]];
|
---|
| 1379 | - node.center = [0, 0, 0];
|
---|
| 1380 | - node.animation = {"time": Date.now(),"target": node.translation,"current": node.translation};
|
---|
| 1381 | - updateModelMatrix(node);
|
---|
| 1382 | - canvas.nodes[node.name] = node;
|
---|
| 1383 | - }
|
---|
| 1384 | } //}}}
|
---|
| 1385 | } //}}}
|
---|
| 1386 | Index: ../trunk-jpl/src/m/plot/plot_transient_movie.m
|
---|
| 1387 | ===================================================================
|
---|
| 1388 | --- ../trunk-jpl/src/m/plot/plot_transient_movie.m (revision 21767)
|
---|
| 1389 | +++ ../trunk-jpl/src/m/plot/plot_transient_movie.m (revision 21768)
|
---|
| 1390 | @@ -6,7 +6,7 @@
|
---|
| 1391 | % See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER
|
---|
| 1392 |
|
---|
| 1393 | %prepare subplot
|
---|
| 1394 | - subplot(width,width,i);
|
---|
| 1395 | + subplot(width,width,i);
|
---|
| 1396 |
|
---|
| 1397 | %xlim
|
---|
| 1398 | if exist(options,'transient_movie_field'),
|
---|
| 1399 | Index: ../trunk-jpl/src/m/plot/webgl_node.js
|
---|
| 1400 | ===================================================================
|
---|
| 1401 | --- ../trunk-jpl/src/m/plot/webgl_node.js (nonexistent)
|
---|
| 1402 | +++ ../trunk-jpl/src/m/plot/webgl_node.js (revision 21768)
|
---|
| 1403 | @@ -0,0 +1,464 @@
|
---|
| 1404 | +//NODE class definition //{{{
|
---|
| 1405 | +// Description:
|
---|
| 1406 | +// Contains all information for rendering an object in WebGL, including mesh, materials, shaders, and other attributes.
|
---|
| 1407 | +// Usage:
|
---|
| 1408 | +// node=new Node('canvas', canvas);
|
---|
| 1409 | +
|
---|
| 1410 | +function Node() { //{{{
|
---|
| 1411 | + //properties
|
---|
| 1412 | + // {{{
|
---|
| 1413 | + var args = Array.prototype.slice.call(arguments);
|
---|
| 1414 | + var options = new pairoptions(args.slice(0,args.length));
|
---|
| 1415 | +
|
---|
| 1416 | + this.canvas = options.getfieldvalue('canvas', null),
|
---|
| 1417 | + this.options = options.getfieldvalue('options', null),
|
---|
| 1418 | + this.gl = canvas.gl;
|
---|
| 1419 | +
|
---|
| 1420 | + this.alpha = options.getfieldvalue('alpha', 1.0),
|
---|
| 1421 | + this.animation = options.getfieldvalue('animation', {}),
|
---|
| 1422 | + this.arrays = options.getfieldvalue('arrays', {}),
|
---|
| 1423 | + this.caxis = options.getfieldvalue('caxis', [0.0, 1.0]),
|
---|
| 1424 | + this.center = options.getfieldvalue('center', vec3.create()),
|
---|
| 1425 | + this.cullFace = options.getfieldvalue('cullFace', this.gl.BACK),
|
---|
| 1426 | + this.computeIndices = options.getfieldvalue('computeIndices', true),
|
---|
| 1427 | + this.disableDepthTest = options.getfieldvalue('disableDepthTest', false),
|
---|
| 1428 | + this.diffuseColor = options.getfieldvalue('diffuseColor', [0.0, 0.0, 0.0, 1.0]),
|
---|
| 1429 | + this.drawMode = options.getfieldvalue('drawMode', this.gl.TRIANGLES),
|
---|
| 1430 | + this.drawOrder = options.getfieldvalue('drawOrder', 1),
|
---|
| 1431 | + this.enabled = options.getfieldvalue('enabled', true),
|
---|
| 1432 | + this.enableCullFace = options.getfieldvalue('enableCullFace', true),
|
---|
| 1433 | + this.hideOcean = options.getfieldvalue('hideOcean', false),
|
---|
| 1434 | + this.lineWidth = options.getfieldvalue('lineWidth', 1.0),
|
---|
| 1435 | + this.log = options.getfieldvalue('log', false),
|
---|
| 1436 | + this.maskColor = options.getfieldvalue('maskColor', vec4.fromValues(0.0, 0.0, 1.0, 1.0)),
|
---|
| 1437 | + this.maskEnabled = options.getfieldvalue('maskEnabled', false),
|
---|
| 1438 | + this.maskHeight = options.getfieldvalue('maskHeight', 150.0),
|
---|
| 1439 | + this.maskZerosColor = options.getfieldvalue('maskZerosColor', [1.0, 1.0, 1.0, 1.0]),
|
---|
| 1440 | + this.maskZerosEnabled = options.getfieldvalue('maskZerosEnabled', false),
|
---|
| 1441 | + this.maskZerosTolerance = options.getfieldvalue('maskZerosTolerance', 1e-6),
|
---|
| 1442 | + this.maskZerosZeroValue = options.getfieldvalue('maskZerosZeroValue', 0.5),
|
---|
| 1443 | + this.mesh = options.getfieldvalue('mesh', undefined),
|
---|
| 1444 | + this.name = options.getfieldvalue('name', 'node'),
|
---|
| 1445 | + this.nanIndices = options.getfieldvalue('nanIndices', new Set()),
|
---|
| 1446 | + this.octree = options.getfieldvalue('octree', undefined),
|
---|
| 1447 | + this.pointSize = options.getfieldvalue('pointSize', 15.0),
|
---|
| 1448 | + this.shaderName = options.getfieldvalue('shaderName', 'Colored'),
|
---|
| 1449 | + this.shader = options.getfieldvalue('shader', this.gl.shaders[this.shaderName]),
|
---|
| 1450 | + this.texture = options.getfieldvalue('texture', undefined),
|
---|
| 1451 | + this.scale = options.getfieldvalue('scale', vec3.fromValues(1, 1, 1)),
|
---|
| 1452 | + this.rotation = options.getfieldvalue('rotation', vec3.create()),
|
---|
| 1453 | + this.translation = options.getfieldvalue('translation', vec3.create()),
|
---|
| 1454 | + this.modelMatrix = options.getfieldvalue('modelMatrix', mat4.create()),
|
---|
| 1455 | + this.rotationMatrix = options.getfieldvalue('rotationMatrix', mat4.create()),
|
---|
| 1456 | + this.inverseModelMatrix = options.getfieldvalue('inverseModelMatrix', mat4.create()),
|
---|
| 1457 | + this.inverseRotationMatrix = options.getfieldvalue('inverseRotationMatrix', mat4.create())
|
---|
| 1458 | + //}}}
|
---|
| 1459 | + //initialize {{{
|
---|
| 1460 | + //if (this.name in canvas.nodes) abort?
|
---|
| 1461 | + this.updateModelMatrix();
|
---|
| 1462 | + this.updateDiffuseColor();
|
---|
| 1463 | + canvas.nodes[this.name] = this;
|
---|
| 1464 | + //}}}
|
---|
| 1465 | +} //}}}
|
---|
| 1466 | +Node.prototype.updateModelMatrix = function() { //{{{
|
---|
| 1467 | + //Update the model matrix if rotation, scale, or translation have been manually modified.
|
---|
| 1468 | + var modelMatrix = mat4.create();
|
---|
| 1469 | +
|
---|
| 1470 | + var translationMatrix = mat4.create();
|
---|
| 1471 | + mat4.translate(translationMatrix, translationMatrix, vec3.negate(vec3.create(), this.center)); //scale/rotation centering
|
---|
| 1472 | + mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
|
---|
| 1473 | +
|
---|
| 1474 | + var scaleMatrix = mat4.create();
|
---|
| 1475 | + mat4.scale(scaleMatrix, scaleMatrix, this.scale);
|
---|
| 1476 | + mat4.multiply(modelMatrix, scaleMatrix, modelMatrix);
|
---|
| 1477 | +
|
---|
| 1478 | + var rotationMatrix = mat4.create();
|
---|
| 1479 | + var zRotationMatrix = mat4.create();
|
---|
| 1480 | + mat4.rotate(zRotationMatrix, zRotationMatrix, DEG2RAD * this.rotation[2], [0.0, 0.0, 1.0]);
|
---|
| 1481 | + mat4.multiply(rotationMatrix, zRotationMatrix, rotationMatrix);
|
---|
| 1482 | + var yRotationMatrix = mat4.create();
|
---|
| 1483 | + mat4.rotate(yRotationMatrix, yRotationMatrix, DEG2RAD * this.rotation[1], [0.0, 1.0, 0.0]);
|
---|
| 1484 | + mat4.multiply(rotationMatrix, yRotationMatrix, rotationMatrix);
|
---|
| 1485 | + var xRotationMatrix = mat4.create();
|
---|
| 1486 | + mat4.rotate(xRotationMatrix, xRotationMatrix, DEG2RAD * this.rotation[0], [1.0, 0.0, 0.0]);
|
---|
| 1487 | + mat4.multiply(rotationMatrix, xRotationMatrix, rotationMatrix);
|
---|
| 1488 | + mat4.multiply(modelMatrix, rotationMatrix, modelMatrix);
|
---|
| 1489 | +
|
---|
| 1490 | + mat4.identity(translationMatrix);
|
---|
| 1491 | + mat4.translate(translationMatrix, translationMatrix, this.center); //relative translation
|
---|
| 1492 | + mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
|
---|
| 1493 | +
|
---|
| 1494 | + mat4.identity(translationMatrix);
|
---|
| 1495 | + mat4.translate(translationMatrix, translationMatrix, this.translation); //absolute translation
|
---|
| 1496 | + mat4.multiply(modelMatrix, translationMatrix, modelMatrix);
|
---|
| 1497 | +
|
---|
| 1498 | + this.modelMatrix = modelMatrix;
|
---|
| 1499 | + this.inverseModelMatrix = mat4.invert(mat4.create(), modelMatrix);
|
---|
| 1500 | + this.rotationMatrix = rotationMatrix;
|
---|
| 1501 | + this.inverseRotationMatrix = mat4.invert(mat4.create(), rotationMatrix);
|
---|
| 1502 | +} //}}}
|
---|
| 1503 | +Node.prototype.updateDiffuseColor = function() { //{{{
|
---|
| 1504 | + //Update the diffuse color with an RGB color name or vec4 containing r, g, b, and alpha values from 0.0 to 1.0
|
---|
| 1505 | + var color = this.diffuseColor;
|
---|
| 1506 | + if (typeof color === 'string') {
|
---|
| 1507 | + color = new RGBColor(color);
|
---|
| 1508 | + if (color.ok) color = [color.r/255.0, color.g/255.0, color.b/255.0, 1.0];
|
---|
| 1509 | + else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas));
|
---|
| 1510 | + }
|
---|
| 1511 | + this.diffuseColor = color;
|
---|
| 1512 | +} //}}}
|
---|
| 1513 | +Node.prototype.transform = function() { //{{{
|
---|
| 1514 | + //Transforms the translation, rotation, or scle fo the node and updates the model matrix.
|
---|
| 1515 | + var args = Array.prototype.slice.call(arguments);
|
---|
| 1516 | + var options = new pairoptions(args.slice(0,args.length));
|
---|
| 1517 | +
|
---|
| 1518 | + var translation = options.getfieldvalue('translation', undefined);
|
---|
| 1519 | + var rotation = options.getfieldvalue('rotation', undefined);
|
---|
| 1520 | + var scale = options.getfieldvalue('scale', undefined);
|
---|
| 1521 | +
|
---|
| 1522 | + if (!isEmptyOrUndefined(translation)) this.translation = translation;
|
---|
| 1523 | + if (!isEmptyOrUndefined(rotation)) this.rotation = rotation;
|
---|
| 1524 | + if (!isEmptyOrUndefined(scale)) this.scale = scale;
|
---|
| 1525 | + this.updateModelMatrix();
|
---|
| 1526 | +} //}}}
|
---|
| 1527 | +Node.prototype.patch = function() { //{{{
|
---|
| 1528 | + //Emulates the behavior of MATLAB patch function by constructing a mesh from arguments.
|
---|
| 1529 | + //Limitations:
|
---|
| 1530 | + // -Expects pair labeled arguments ('FaceColor','none',...).
|
---|
| 1531 | + // -Only handles Face/Vertices/FaceVertexCData element/node plots.
|
---|
| 1532 | + // -Only supports FaceColor 'interp' and 'none'.
|
---|
| 1533 | +
|
---|
| 1534 | + var args = Array.prototype.slice.call(arguments);
|
---|
| 1535 | + var options = new pairoptions(args.slice(0,args.length));
|
---|
| 1536 | +
|
---|
| 1537 | + var faces = options.getfieldvalue('Faces', undefined);
|
---|
| 1538 | + var vertices = options.getfieldvalue('Vertices', undefined);
|
---|
| 1539 | + var faceVertexCData = options.getfieldvalue('FaceVertexCData', undefined);
|
---|
| 1540 | + var faceColor = options.getfieldvalue('FaceColor', 'interp');
|
---|
| 1541 | + var edgeColor = options.getfieldvalue('EdgeColor', this.diffuseColor);
|
---|
| 1542 | + var lineWidth = options.getfieldvalue('linewidth', 1);
|
---|
| 1543 | +
|
---|
| 1544 | + this.faces = faces;
|
---|
| 1545 | + this.vertices = vertices;
|
---|
| 1546 | + this.diffuseColor = edgeColor;
|
---|
| 1547 | + this.updateDiffuseColor();
|
---|
| 1548 | +
|
---|
| 1549 | + this.patchVertices(faceVertexCData, faces, vertices);
|
---|
| 1550 | + this.patchCoords(faceVertexCData, faces, vertices);
|
---|
| 1551 | + this.patchIndices(faces, faceColor);
|
---|
| 1552 | +
|
---|
| 1553 | + this.mesh = GL.Mesh.load(this.arrays, null, null, this.gl);
|
---|
| 1554 | + //this.mesh.computeNormals();
|
---|
| 1555 | + this.computeOctree();
|
---|
| 1556 | +} //}}}
|
---|
| 1557 | +Node.prototype.patchVertices = function(faceVertexCData, faces, vertices) { //{{{
|
---|
| 1558 | + //Patch subfunction for processing xyz vertices.
|
---|
| 1559 | + var vertexArray;
|
---|
| 1560 | + var face;
|
---|
| 1561 | +
|
---|
| 1562 | + if (isEmptyOrUndefined(faceVertexCData)) {
|
---|
| 1563 | + vertexArray = new Float32Array(vertices[0].length * 3);
|
---|
| 1564 | + for(var i = 0, v = 0; i < vertices[0].length; i++) {
|
---|
| 1565 | + vertexArray[v++] = vertices[0][i];
|
---|
| 1566 | + vertexArray[v++] = vertices[1][i];
|
---|
| 1567 | + vertexArray[v++] = vertices[2][i];
|
---|
| 1568 | + }
|
---|
| 1569 | + }
|
---|
| 1570 | + else if (!Array.isArray(faceVertexCData[0])) { //indexed plot - faceVertexCData = [0, 2.32, 231.1, ...]
|
---|
| 1571 | + if (faceVertexCData.length === faces.length) { //element plot
|
---|
| 1572 | + vertexArray = new Float32Array(faces.length * 3 * 3);
|
---|
| 1573 | + for(var i = 0, v = 0, t = 0; i < faces.length; i++) {
|
---|
| 1574 | + face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1];
|
---|
| 1575 | + for(var j = 0; j < face.length; j++) {
|
---|
| 1576 | + if (isNaN(faceVertexCData[i])) {
|
---|
| 1577 | + this.nanIndices.add(i);
|
---|
| 1578 | + vertexArray[v++] = 0.0;
|
---|
| 1579 | + vertexArray[v++] = 0.0;
|
---|
| 1580 | + vertexArray[v++] = 0.0;
|
---|
| 1581 | + }
|
---|
| 1582 | + else {
|
---|
| 1583 | + vertexArray[v++] = vertices[0][face[j]];
|
---|
| 1584 | + vertexArray[v++] = vertices[1][face[j]];
|
---|
| 1585 | + vertexArray[v++] = vertices[2][face[j]];
|
---|
| 1586 | + }
|
---|
| 1587 | + }
|
---|
| 1588 | + }
|
---|
| 1589 | + this.computeIndices = false;
|
---|
| 1590 | + }
|
---|
| 1591 | + else if (faceVertexCData.length === vertices[0].length) { //node plot
|
---|
| 1592 | + vertexArray = new Float32Array(vertices[0].length * 3);
|
---|
| 1593 | + for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) {
|
---|
| 1594 | + if (isNaN(faceVertexCData[i])) {
|
---|
| 1595 | + this.nanIndices.add(i);
|
---|
| 1596 | + vertexArray[v++] = 0.0;
|
---|
| 1597 | + vertexArray[v++] = 0.0;
|
---|
| 1598 | + vertexArray[v++] = 0.0;
|
---|
| 1599 | + }
|
---|
| 1600 | + else {
|
---|
| 1601 | + vertexArray[v++] = vertices[0][i];
|
---|
| 1602 | + vertexArray[v++] = vertices[1][i];
|
---|
| 1603 | + vertexArray[v++] = vertices[2][i];
|
---|
| 1604 | + }
|
---|
| 1605 | + }
|
---|
| 1606 | + }
|
---|
| 1607 | + }
|
---|
| 1608 | + else if (Array.isArray(faceVertexCData[0])) { //JS specific: precomputed UV coord plot - faceVertexCData = [[0, 0.99, 0.4, ...],[0, 0.99, 0.4, ...]]
|
---|
| 1609 | + if (faceVertexCData[0].length === faces.length) { //element plot
|
---|
| 1610 | + vertexArray = new Float32Array(faces.length * 3 * 3);
|
---|
| 1611 | + for(var i = 0, v = 0, t = 0; i < faces.length; i++) {
|
---|
| 1612 | + face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1];
|
---|
| 1613 | + for(var j = 0; j < face.length; j++) {
|
---|
| 1614 | + vertexArray[v++] = vertices[0][face[j]];
|
---|
| 1615 | + vertexArray[v++] = vertices[1][face[j]];
|
---|
| 1616 | + vertexArray[v++] = vertices[2][face[j]];
|
---|
| 1617 | + }
|
---|
| 1618 | + }
|
---|
| 1619 | + this.computeIndices = false;
|
---|
| 1620 | + }
|
---|
| 1621 | + else if (faceVertexCData[0].length === vertices[0].length) { //node plot
|
---|
| 1622 | + vertexArray = new Float32Array(vertices[0].length * 3);
|
---|
| 1623 | + for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) {
|
---|
| 1624 | + vertexArray[v++] = vertices[0][i];
|
---|
| 1625 | + vertexArray[v++] = vertices[1][i];
|
---|
| 1626 | + vertexArray[v++] = vertices[2][i];
|
---|
| 1627 | + }
|
---|
| 1628 | + }
|
---|
| 1629 | + }
|
---|
| 1630 | + this.arrays.vertices = vertexArray;
|
---|
| 1631 | +} //}}}
|
---|
| 1632 | +Node.prototype.patchCoords = function(faceVertexCData, faces, vertices) { //{{{
|
---|
| 1633 | + //Patch subfunction for processing texture coords/UVs.
|
---|
| 1634 | + var coordArray;
|
---|
| 1635 | + var cramge;
|
---|
| 1636 | + var caxis = this.caxis;
|
---|
| 1637 | + var face;
|
---|
| 1638 | +
|
---|
| 1639 | + if (isEmptyOrUndefined(faceVertexCData)) { return; }
|
---|
| 1640 | +
|
---|
| 1641 | + //Use logarithmic scaling if it is valid
|
---|
| 1642 | + if (this.log !== false && this.log !== 'off') {
|
---|
| 1643 | + caxis = [
|
---|
| 1644 | + Math.log10(caxis[0]) / Math.log10(this.log),
|
---|
| 1645 | + Math.log10(caxis[1]) / Math.log10(this.log)
|
---|
| 1646 | + ];
|
---|
| 1647 | + }
|
---|
| 1648 | +
|
---|
| 1649 | + if (!Array.isArray(faceVertexCData[0])) { //indexed plot - faceVertexCData = [0, 2.32, 231.1, ...]
|
---|
| 1650 | + if (faceVertexCData.length === faces.length) { //element plot
|
---|
| 1651 | + coordArray = new Float32Array(faces.length * 3 * 2);
|
---|
| 1652 | + crange = caxis[1] - caxis[0];
|
---|
| 1653 | + for(var i = 0, v = 0, t = 0; i < faces.length; i++) {
|
---|
| 1654 | + face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1];
|
---|
| 1655 | + for(var j = 0; j < face.length; j++) {
|
---|
| 1656 | + if (isNaN(faceVertexCData[i])) {
|
---|
| 1657 | + this.nanIndices.add(i);
|
---|
| 1658 | + coordArray[t++] = 0.0;
|
---|
| 1659 | + coordArray[t++] = 0.0;
|
---|
| 1660 | + }
|
---|
| 1661 | + else {
|
---|
| 1662 | + coordArray[t++] = 0.5;
|
---|
| 1663 | + coordArray[t++] = clamp((faceVertexCData[i] - caxis[0]) / crange, 0.0, 1.0);
|
---|
| 1664 | + }
|
---|
| 1665 | + }
|
---|
| 1666 | + }
|
---|
| 1667 | + this.computeIndices = false;
|
---|
| 1668 | + }
|
---|
| 1669 | + else if (faceVertexCData.length === vertices[0].length) { //node plot
|
---|
| 1670 | + coordArray = new Float32Array(vertices[0].length * 2);
|
---|
| 1671 | + crange = caxis[1] - caxis[0];
|
---|
| 1672 | + for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) {
|
---|
| 1673 | + if (isNaN(faceVertexCData[i])) {
|
---|
| 1674 | + this.nanIndices.add(i);
|
---|
| 1675 | + coordArray[t++] = 0.0;
|
---|
| 1676 | + coordArray[t++] = 0.0;
|
---|
| 1677 | + }
|
---|
| 1678 | + else {
|
---|
| 1679 | + coordArray[t++] = 0.5;
|
---|
| 1680 | + coordArray[t++] = clamp((faceVertexCData[i] - caxis[0]) / crange, 0.0, 1.0);
|
---|
| 1681 | + }
|
---|
| 1682 | + }
|
---|
| 1683 | + }
|
---|
| 1684 | + }
|
---|
| 1685 | + else if (Array.isArray(faceVertexCData[0])) { //JS specific: precomputed UV coord plot - faceVertexCData = [[0, 0.99, 0.4, ...],[0, 0.99, 0.4, ...]]
|
---|
| 1686 | + if (faceVertexCData[0].length === faces.length) { //element plot
|
---|
| 1687 | + coordArray = new Float32Array(faces.length * 3 * 2);
|
---|
| 1688 | + for(var i = 0, v = 0, t = 0; i < faces.length; i++) {
|
---|
| 1689 | + face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1];
|
---|
| 1690 | + for(var j = 0; j < face.length; j++) {
|
---|
| 1691 | + coordArray[t++] = faceVertexCData[0][i];
|
---|
| 1692 | + coordArray[t++] = faceVertexCData[1][i];
|
---|
| 1693 | + }
|
---|
| 1694 | + }
|
---|
| 1695 | + this.computeIndices = false;
|
---|
| 1696 | + }
|
---|
| 1697 | + else if (faceVertexCData[0].length === vertices[0].length) { //node plot
|
---|
| 1698 | + coordArray = new Float32Array(vertices[0].length * 2);
|
---|
| 1699 | + for(var i = 0, v = 0, t = 0; i < vertices[0].length; i++) {
|
---|
| 1700 | + coordArray[t++] = faceVertexCData[0][i];
|
---|
| 1701 | + coordArray[t++] = faceVertexCData[1][i];
|
---|
| 1702 | + }
|
---|
| 1703 | + }
|
---|
| 1704 | + }
|
---|
| 1705 | + this.arrays.coords = coordArray;
|
---|
| 1706 | +} //}}}
|
---|
| 1707 | +Node.prototype.patchIndices = function(faces, faceColor) { //{{{
|
---|
| 1708 | + //Patch subfunction for processing faces/elements/triangles/indices.
|
---|
| 1709 | + var indexArray;
|
---|
| 1710 | + var face;
|
---|
| 1711 | +
|
---|
| 1712 | + if (faceColor === 'none') { //Check for wireframe mesh rendering
|
---|
| 1713 | + 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
|
---|
| 1714 | + this.drawMode = this.gl.LINES;
|
---|
| 1715 | + }
|
---|
| 1716 | + }
|
---|
| 1717 | +
|
---|
| 1718 | + if (this.computeIndices === true && !isEmptyOrUndefined(faces)) {
|
---|
| 1719 | + if (!isEmptyOrUndefined(faces[0])) { //Check for 2D format and process if needed
|
---|
| 1720 | + if (faceColor !== 'none') { //Check for triangle rendering
|
---|
| 1721 | + indexArray = new Uint16Array(faces.length * 3);
|
---|
| 1722 | + for(var i = 0, f = 0; i < faces.length; i++) {
|
---|
| 1723 | + face = [faces[i][0] - 1, faces[i][1] - 1, faces[i][2] - 1];
|
---|
| 1724 | + if (this.nanIndices.has(face[0]) || this.nanIndices.has(face[1]) || this.nanIndices.has(face[2])) continue; //Skip triangle if contains NaN value.
|
---|
| 1725 | + indexArray[f++] = faces[i][0] - 1;
|
---|
| 1726 | + indexArray[f++] = faces[i][1] - 1;
|
---|
| 1727 | + indexArray[f++] = faces[i][2] - 1;
|
---|
| 1728 | + }
|
---|
| 1729 | + }
|
---|
| 1730 | + else { //Check for wireframe mesh rendering
|
---|
| 1731 | + indexArray = new Uint16Array(faces.length * 6);
|
---|
| 1732 | + for(var i = 0, f = 0; i < faces.length; i++) {
|
---|
| 1733 | + indexArray[f++] = faces[i][0] - 1;
|
---|
| 1734 | + indexArray[f++] = faces[i][1] - 1;
|
---|
| 1735 | + indexArray[f++] = faces[i][1] - 1;
|
---|
| 1736 | + indexArray[f++] = faces[i][2] - 1;
|
---|
| 1737 | + indexArray[f++] = faces[i][2] - 1;
|
---|
| 1738 | + indexArray[f++] = faces[i][0] - 1;
|
---|
| 1739 | + }
|
---|
| 1740 | + }
|
---|
| 1741 | + }
|
---|
| 1742 | + else { //Else, assume face indices have already been processed
|
---|
| 1743 | + indexArray = faces;
|
---|
| 1744 | + }
|
---|
| 1745 | + this.arrays.triangles = indexArray;
|
---|
| 1746 | + }
|
---|
| 1747 | +} //}}}
|
---|
| 1748 | +Node.prototype.updateBuffer = function() { //{{{
|
---|
| 1749 | + //Updates the mesh buffers provided in place.
|
---|
| 1750 | + //NOTE: Only support coord buffers currently.
|
---|
| 1751 | + var args = Array.prototype.slice.call(arguments);
|
---|
| 1752 | + var options = new pairoptions(args.slice(0,args.length));
|
---|
| 1753 | +
|
---|
| 1754 | + var coords = options.getfieldvalue('Coords', undefined);
|
---|
| 1755 | + var cacheIndex = options.getfieldvalue('CacheIndex', false);
|
---|
| 1756 | +
|
---|
| 1757 | + if (!isEmptyOrUndefined(coords)) {
|
---|
| 1758 | + this.patchCoords(coords, this.faces, this.vertices);
|
---|
| 1759 | + var buffer = this.mesh.getBuffer("coords");
|
---|
| 1760 | + buffer.data = this.arrays.coords;
|
---|
| 1761 | + buffer.upload(this.gl.DYNAMIC_DRAW);
|
---|
| 1762 | + }
|
---|
| 1763 | +} //}}}
|
---|
| 1764 | +Node.prototype.computeOctree = function() { //{{{
|
---|
| 1765 | + //Computes and caches octrees for a node.
|
---|
| 1766 | + var octree = this.canvas.octrees[this.name];
|
---|
| 1767 | + if (isEmptyOrUndefined(octree)) {
|
---|
| 1768 | + octree = new GL.Octree(this.mesh);
|
---|
| 1769 | + }
|
---|
| 1770 | + this.canvas.octrees[this.name] = octree;
|
---|
| 1771 | + this.octree = octree;
|
---|
| 1772 | +} //}}}
|
---|
| 1773 | +Node.prototype.geometryShader = function() { //{{{
|
---|
| 1774 | + //Emulates OpenGL geometry shaders by rendering each point as a mesh.
|
---|
| 1775 | + //Parameters:
|
---|
| 1776 | + // Mesh - the geometry to duplicate for each point.
|
---|
| 1777 | + // Vertices - the list of points to shade.
|
---|
| 1778 | + // Indices - (optional) ordered list for non-ordered Vertices objects.
|
---|
| 1779 | +
|
---|
| 1780 | + var args = Array.prototype.slice.call(arguments);
|
---|
| 1781 | + var options = new pairoptions(args.slice(0,args.length));
|
---|
| 1782 | +
|
---|
| 1783 | + var mesh = options.getfieldvalue('Mesh', undefined);
|
---|
| 1784 | + var vertices = options.getfieldvalue('Vertices', undefined);
|
---|
| 1785 | + var indices = options.getfieldvalue('Indices', undefined);
|
---|
| 1786 | +
|
---|
| 1787 | + //For handling key-value object arrays, like xcity
|
---|
| 1788 | + for (var i = 0; i < vertices.length; i++) {
|
---|
| 1789 | + if (!Array.isArray(vertices[i])) {
|
---|
| 1790 | + var array = [];
|
---|
| 1791 | + var coordinateObject = vertices[i];
|
---|
| 1792 | + var j = 0;
|
---|
| 1793 | + if (isEmptyOrUndefined(indices)) {
|
---|
| 1794 | + for (var key in object) {
|
---|
| 1795 | + array[j++] = coordinateObject[key];
|
---|
| 1796 | + }
|
---|
| 1797 | + }
|
---|
| 1798 | + else {
|
---|
| 1799 | + for (var k = 0; k < indices.length; k++) {
|
---|
| 1800 | + array[j++] = coordinateObject[indices[k]];
|
---|
| 1801 | + }
|
---|
| 1802 | + }
|
---|
| 1803 | + vertices[i] = array;
|
---|
| 1804 | + }
|
---|
| 1805 | + }
|
---|
| 1806 | +
|
---|
| 1807 | + var x = vertices[0];
|
---|
| 1808 | + var y = vertices[1];
|
---|
| 1809 | + var z = vertices[2];
|
---|
| 1810 | + var meshVertices = mesh.getBuffer('vertices').data;
|
---|
| 1811 | + var meshIndicies = mesh.getIndexBuffer('triangles').data;
|
---|
| 1812 | + var indicies = new Uint16Array(meshIndicies.length * x.length);
|
---|
| 1813 | + var size = meshVertices.length * x.length / 3;
|
---|
| 1814 | + newX = new Float32Array(size);
|
---|
| 1815 | + newY = new Float32Array(size);
|
---|
| 1816 | + newZ = new Float32Array(size);
|
---|
| 1817 | +
|
---|
| 1818 | + //For each vertex in vertices, instantiate mesh geomtry centered around that point.
|
---|
| 1819 | + for(var i = 0, v = 0, e = 0; i < x.length; i++){
|
---|
| 1820 | + var vector = [x[i], y[i], z[i]];
|
---|
| 1821 | + for (var j = 0; j < meshVertices.length;) {
|
---|
| 1822 | + newX[v] = meshVertices[j++] + x[i];
|
---|
| 1823 | + newY[v] = meshVertices[j++] + y[i];
|
---|
| 1824 | + newZ[v++] = meshVertices[j++] + z[i];
|
---|
| 1825 | + }
|
---|
| 1826 | + var offset = i * meshVertices.length / 3;
|
---|
| 1827 | + for (var j = 0; j < meshIndicies.length;) {
|
---|
| 1828 | + indicies[e++] = meshIndicies[j++] + offset;
|
---|
| 1829 | + }
|
---|
| 1830 | + }
|
---|
| 1831 | +
|
---|
| 1832 | + this.patch('Faces', indicies, 'Vertices', [newX, newY, newZ], 'FaceColor', 'interp');
|
---|
| 1833 | +} //}}}
|
---|
| 1834 | +Node.prototype.scaleVertices = function(md, x, y, z, scale) { //{{{
|
---|
| 1835 | + //Scales and returns vertices x, y, and z by factor scale. Uses md.geometry.scale for heightscaling in 3d meshes.
|
---|
| 1836 | + if (md.mesh.classname() === 'mesh3dsurface') {
|
---|
| 1837 | + var xyz, magnitude;
|
---|
| 1838 | + x = x.slice();
|
---|
| 1839 | + y = y.slice();
|
---|
| 1840 | + z = z.slice();
|
---|
| 1841 | + for(var i = 0; i < x.length; i++) {
|
---|
| 1842 | + xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 1843 | + magnitude = 1 + md.geometry.surface[i] * scale / vec3.length(xyz);
|
---|
| 1844 | + vec3.scale(xyz, xyz, magnitude);
|
---|
| 1845 | + x[i] = xyz[0];
|
---|
| 1846 | + y[i] = xyz[1];
|
---|
| 1847 | + z[i] = xyz[2];
|
---|
| 1848 | + }
|
---|
| 1849 | + }
|
---|
| 1850 | + else {
|
---|
| 1851 | + z = z.slice();
|
---|
| 1852 | + var zMin = ArrayMin(md.geometry.surface);
|
---|
| 1853 | + for(var i = 0; i < z.length; i++) {
|
---|
| 1854 | + z[i] = (z[i] - zMin) * scale + zMin;
|
---|
| 1855 | + }
|
---|
| 1856 | + }
|
---|
| 1857 | + return [x, y, z];
|
---|
| 1858 | +} //}}}
|
---|
| 1859 | +Node.prototype.mergeVertices = function(x1, y1, z1, elements1, x2, y2, z2, elements2) { //{{{
|
---|
| 1860 | + //Merges and returns two sets of indexed xyz vertices.
|
---|
| 1861 | + elements2 = elements2.slice();
|
---|
| 1862 | + for (var i = 0, offset = x1.length; i < elements2.length; i++) {
|
---|
| 1863 | + elements2[i] = [elements2[i][0] + offset, elements2[i][1] + offset, elements2[i][2] + offset];
|
---|
| 1864 | + }
|
---|
| 1865 | + return {x:x1.concat(x2), y:y1.concat(y2), z:z1.concat(z2), elements:elements1.concat(elements2)};
|
---|
| 1866 | +} //}}}
|
---|
| 1867 | +//}}}
|
---|
| 1868 | Index: ../trunk-jpl/src/m/plot/plot_manager.js
|
---|
| 1869 | ===================================================================
|
---|
| 1870 | --- ../trunk-jpl/src/m/plot/plot_manager.js (revision 21767)
|
---|
| 1871 | +++ ../trunk-jpl/src/m/plot/plot_manager.js (revision 21768)
|
---|
| 1872 | @@ -13,7 +13,7 @@
|
---|
| 1873 | var data = options.getfieldvalue('data');
|
---|
| 1874 | var canvas = initCanvas(options);
|
---|
| 1875 | var gl = canvas.gl;
|
---|
| 1876 | - //TODO: each plot_ should add their node to the canvas.node array
|
---|
| 1877 | +
|
---|
| 1878 | //figure out if this is a special plot
|
---|
| 1879 | if (typeof data === 'string'){
|
---|
| 1880 |
|
---|
| 1881 | @@ -80,9 +80,9 @@
|
---|
| 1882 | plot_mesh(md,options,canvas);
|
---|
| 1883 | return;
|
---|
| 1884 | case 'none':
|
---|
| 1885 | - if (!(options.exist('overlay'))){
|
---|
| 1886 | - plot_none(md,options,nlines,ncols,i);
|
---|
| 1887 | - }
|
---|
| 1888 | + //if (!(options.exist('overlay'))){
|
---|
| 1889 | + // plot_none(md,options,nlines,ncols,i);
|
---|
| 1890 | + //}
|
---|
| 1891 | return;
|
---|
| 1892 | case 'penalties':
|
---|
| 1893 | plot_penalties(md,options,subplotwidth,i);
|
---|
| 1894 | @@ -150,7 +150,7 @@
|
---|
| 1895 | plot_thermaltransient_results(md,options,subplotwidth,i);
|
---|
| 1896 | return;
|
---|
| 1897 | case 'transient_movie':
|
---|
| 1898 | - plot_transient_movie(md,options,subplotwidth,i);
|
---|
| 1899 | + plot_transient_movie(md,options,canvas);
|
---|
| 1900 | return;
|
---|
| 1901 | case 'transient_results':
|
---|
| 1902 | plot_transient_results(md,options,subplotwidth,i);
|
---|
| 1903 | @@ -204,5 +204,5 @@
|
---|
| 1904 | //plot unit
|
---|
| 1905 | plot_unit(md,data2,datatype,options,canvas);
|
---|
| 1906 |
|
---|
| 1907 | - applyoptions(md,data2,datatype,options,canvas,gl,canvas.nodes[canvas.nodes.length-1]);
|
---|
| 1908 | + applyoptions(md,data2,options,canvas);
|
---|
| 1909 | } //}}}
|
---|
| 1910 | Index: ../trunk-jpl/src/m/plot/plot_unit.js
|
---|
| 1911 | ===================================================================
|
---|
| 1912 | --- ../trunk-jpl/src/m/plot/plot_unit.js (revision 21767)
|
---|
| 1913 | +++ ../trunk-jpl/src/m/plot/plot_unit.js (revision 21768)
|
---|
| 1914 | @@ -6,7 +6,14 @@
|
---|
| 1915 | //
|
---|
| 1916 | // See also: PLOTMODEL, PLOT_MANAGER
|
---|
| 1917 |
|
---|
| 1918 | - //{{{ declare variables:
|
---|
| 1919 | + //if ('unit' in canvas.nodes) {
|
---|
| 1920 | + // if (
|
---|
| 1921 | + // canvas.nodes.unit.updateBuffer('Coords', data);
|
---|
| 1922 | + // return;
|
---|
| 1923 | + //}
|
---|
| 1924 | + //else {
|
---|
| 1925 | +
|
---|
| 1926 | + //{{{ declare variables:
|
---|
| 1927 | //Process data and model
|
---|
| 1928 | var meshresults = processmesh(md, data, options);
|
---|
| 1929 | var x = meshresults[0];
|
---|
| 1930 | @@ -15,78 +22,64 @@
|
---|
| 1931 | var elements = meshresults[3];
|
---|
| 1932 | var is2d = meshresults[4];
|
---|
| 1933 | var isplanet = meshresults[5];
|
---|
| 1934 | + if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface;
|
---|
| 1935 |
|
---|
| 1936 | - var vertices = new Float32Array(x.length * 3);
|
---|
| 1937 | - var texcoords = new Float32Array(x.length * 2);
|
---|
| 1938 | - var indices = new Uint16Array(elements.length * 3);
|
---|
| 1939 | - var nanindices = {};
|
---|
| 1940 | - var xmin, xmax;
|
---|
| 1941 | - var ymin, ymax;
|
---|
| 1942 | - var zmin, zmax;
|
---|
| 1943 | - var datamin, datamax, datadelta;
|
---|
| 1944 | - var matrixscale, vertexscale;
|
---|
| 1945 | - //Compue scaling through matrices for 2d meshes and vertices for 3d meshes
|
---|
| 1946 | - if (!md.geometry.surface) {
|
---|
| 1947 | - md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);
|
---|
| 1948 | + //Compute coordinates and data range:
|
---|
| 1949 | + var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
|
---|
| 1950 | + var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
|
---|
| 1951 | + var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
|
---|
| 1952 | +
|
---|
| 1953 | + //Handle heightscale
|
---|
| 1954 | + var vertices, scale;
|
---|
| 1955 | + if (md.mesh.classname() !== 'mesh3dsurface') {
|
---|
| 1956 | + vertices = [x, y, z];
|
---|
| 1957 | + scale = [1, 1, options.getfieldvalue('heightscale', 1)];
|
---|
| 1958 | }
|
---|
| 1959 | - if (md.mesh.classname() == 'mesh3dsurface') {
|
---|
| 1960 | - matrixscale = 1;
|
---|
| 1961 | - vertexscale = options.getfieldvalue('heightscale', 1);
|
---|
| 1962 | - }
|
---|
| 1963 | else {
|
---|
| 1964 | - if (md.geometry.surface) {
|
---|
| 1965 | - z=md.geometry.surface;
|
---|
| 1966 | - }
|
---|
| 1967 | - matrixscale = options.getfieldvalue('heightscale', 1);
|
---|
| 1968 | - vertexscale = 0;
|
---|
| 1969 | + vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));
|
---|
| 1970 | + scale = [1, 1, 1];
|
---|
| 1971 | }
|
---|
| 1972 | - //}}}
|
---|
| 1973 | -
|
---|
| 1974 | - //Compute coordinates and data range:
|
---|
| 1975 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 1976 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 1977 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 1978 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 1979 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 1980 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 1981 | - xmin = xlim[0];
|
---|
| 1982 | - xmax = xlim[1];
|
---|
| 1983 | - ymin = ylim[0];
|
---|
| 1984 | - ymax = ylim[1];
|
---|
| 1985 | - zmin = zlim[0];
|
---|
| 1986 | - zmax = zlim[1];
|
---|
| 1987 | - var caxis;
|
---|
| 1988 | -
|
---|
| 1989 | +
|
---|
| 1990 | //Compute gl variables:
|
---|
| 1991 | - var gl = canvas.gl;
|
---|
| 1992 | - var node = Node(gl);
|
---|
| 1993 | - canvas.nodes[canvas.nodes.length] = node;
|
---|
| 1994 | + var edgecolor = options.getfieldvalue('edgecolor', 'black');
|
---|
| 1995 | + var maskzeros = options.getfieldvalue('maskzeros', {});
|
---|
| 1996 | + var node = new Node(
|
---|
| 1997 | + 'canvas', canvas,
|
---|
| 1998 | + 'options', options,
|
---|
| 1999 | + 'name', 'unit',
|
---|
| 2000 | + 'shaderName', 'Textured',
|
---|
| 2001 | + 'alpha', options.getfieldvalue('alpha', 1.0),
|
---|
| 2002 | + 'caxis', options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]),
|
---|
| 2003 | + //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
|
---|
| 2004 | + 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
|
---|
| 2005 | + 'diffuseColor', edgecolor,
|
---|
| 2006 | + 'enabled', options.getfieldvalue('nodata','off') == 'off',
|
---|
| 2007 | + 'log', options.getfieldvalue('log',false),
|
---|
| 2008 | + 'maskEnabled', options.getfieldvalue('innermask','off') == 'on',
|
---|
| 2009 | + 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1),
|
---|
| 2010 | + 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]),
|
---|
| 2011 | + 'maskZerosColor', defaultFor(maskzeros.color,[1.0, 1.0, 1.0, 1.0]),
|
---|
| 2012 | + 'maskZerosEnabled', defaultFor(maskzeros.enabled,false),
|
---|
| 2013 | + 'maskZerosTolerance', defaultFor(maskzeros.tolerance,1e-3),
|
---|
| 2014 | + 'maskZerosZeroValue', defaultFor(maskzeros.zeroValue,0.5),
|
---|
| 2015 | + 'rotation', [-90, 0, 0],
|
---|
| 2016 | + 'scale', scale
|
---|
| 2017 | + );
|
---|
| 2018 | + //}
|
---|
| 2019 | canvas.unitNode = node;
|
---|
| 2020 | canvas.unitData = data;
|
---|
| 2021 | - node.name = "unit";
|
---|
| 2022 | - node.shaderName = "Textured";
|
---|
| 2023 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 2024 | - node.scale = [1, 1, matrixscale];
|
---|
| 2025 | - node.rotation = [-90, 0, 0];
|
---|
| 2026 | - node.translation = [0, 0, 0];
|
---|
| 2027 | - node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2];
|
---|
| 2028 | - node.alpha = options.getfieldvalue('alpha', 1.0);
|
---|
| 2029 | - node.drawOrder = 1;
|
---|
| 2030 | - node.maskEnabled = options.getfieldvalue('innermask','off') == 'on';
|
---|
| 2031 | - node.maskHeight = options.getfieldvalue('innermaskheight', 150.0);
|
---|
| 2032 | - node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]);
|
---|
| 2033 | - node.enabled = options.getfieldvalue('nodata','off') == 'off';
|
---|
| 2034 | - updateModelMatrix(node);
|
---|
| 2035 | -
|
---|
| 2036 | + //}}}
|
---|
| 2037 | switch(datatype){
|
---|
| 2038 | //{{{ element plot
|
---|
| 2039 | case 1:
|
---|
| 2040 | + //WARNING: NaN are not properly found (NaN != NaN = true)
|
---|
| 2041 | pos=ArrayFindNot(data, NaN); //needed for element on water
|
---|
| 2042 | if (elements[0].length==6){ //prisms
|
---|
| 2043 | }
|
---|
| 2044 | else if (elements[0].length==4){ //tetras
|
---|
| 2045 | }
|
---|
| 2046 | - else{ //2D triangular elements
|
---|
| 2047 | + else{ //triangular elements
|
---|
| 2048 | + node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'flat', 'EdgeColor', edgecolor);
|
---|
| 2049 | }
|
---|
| 2050 | break;
|
---|
| 2051 | //}}}
|
---|
| 2052 | @@ -97,55 +90,8 @@
|
---|
| 2053 | else if (elements[0].length==4){ //tetras
|
---|
| 2054 | }
|
---|
| 2055 | else{ //triangular elements
|
---|
| 2056 | - caxis = options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]);
|
---|
| 2057 | - 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))];
|
---|
| 2058 | - datamin = caxis[0];
|
---|
| 2059 | - datamax = caxis[1];
|
---|
| 2060 | - datadelta = datamax - datamin;
|
---|
| 2061 | -
|
---|
| 2062 | - var xyz = vec3.create();
|
---|
| 2063 | - var direction = vec3.create();
|
---|
| 2064 | - var vertex = vec3.create();
|
---|
| 2065 | - var magnitude;
|
---|
| 2066 | -
|
---|
| 2067 | - for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){
|
---|
| 2068 | - //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
|
---|
| 2069 | - if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i])) {
|
---|
| 2070 | - nanindices[i] = i;
|
---|
| 2071 | - vertices[vindex++] = vertex[0];
|
---|
| 2072 | - vertices[vindex++] = vertex[1];
|
---|
| 2073 | - vertices[vindex++] = vertex[2];
|
---|
| 2074 | -
|
---|
| 2075 | - texcoords[tindex++] = 0.5;
|
---|
| 2076 | - texcoords[tindex++] = 0.0;
|
---|
| 2077 | - continue;
|
---|
| 2078 | - }
|
---|
| 2079 | -
|
---|
| 2080 | - //Scale vertices
|
---|
| 2081 | - xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 2082 | - magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
|
---|
| 2083 | - vec3.normalize(direction, xyz);
|
---|
| 2084 | - vec3.scale(vertex, direction, magnitude);
|
---|
| 2085 | - vertices[vindex++] = vertex[0];
|
---|
| 2086 | - vertices[vindex++] = vertex[1];
|
---|
| 2087 | - vertices[vindex++] = vertex[2];
|
---|
| 2088 | -
|
---|
| 2089 | - texcoords[tindex++] = 0.5;
|
---|
| 2090 | - texcoords[tindex++] = clamp((data[i] - datamin) / datadelta, 0.0, 1.0);
|
---|
| 2091 | - }
|
---|
| 2092 | -
|
---|
| 2093 | - //linearize the elements array:
|
---|
| 2094 | - var element;
|
---|
| 2095 | - for(var i = 0, iindex = 0; i < elements.length; i++){
|
---|
| 2096 | - element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];
|
---|
| 2097 | - if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;
|
---|
| 2098 | - indices[iindex++] = element[0];
|
---|
| 2099 | - indices[iindex++] = element[1];
|
---|
| 2100 | - indices[iindex++] = element[2];
|
---|
| 2101 | - }
|
---|
| 2102 | + node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'interp', 'EdgeColor', edgecolor);
|
---|
| 2103 | }
|
---|
| 2104 | - node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords, triangles: indices}, null, null, gl);
|
---|
| 2105 | - node.mesh.octree = new GL.Octree(node.mesh);
|
---|
| 2106 | break;
|
---|
| 2107 | //}}}
|
---|
| 2108 | //{{{ quiver plot
|
---|
| 2109 | @@ -158,135 +104,7 @@
|
---|
| 2110 | }
|
---|
| 2111 | break;
|
---|
| 2112 | //}}}
|
---|
| 2113 | - //{{{ node transient plot
|
---|
| 2114 | - case 5:
|
---|
| 2115 | - if (elements[0].length==6){ //prisms
|
---|
| 2116 | - }
|
---|
| 2117 | - else if (elements[0].length==4){//tetras
|
---|
| 2118 | - }
|
---|
| 2119 | - else{ //triangular elements
|
---|
| 2120 | - var xyz = vec3.create();
|
---|
| 2121 | - var direction = vec3.create();
|
---|
| 2122 | - var vertex = vec3.create();
|
---|
| 2123 | - var magnitude;
|
---|
| 2124 | - var timestamps = data[data.length-1];
|
---|
| 2125 | - for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){
|
---|
| 2126 | - //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
|
---|
| 2127 | - if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i][0])) {
|
---|
| 2128 | - nanindices[i] = i;
|
---|
| 2129 | - }
|
---|
| 2130 | - else {
|
---|
| 2131 | - //Scale vertices
|
---|
| 2132 | - xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 2133 | - magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
|
---|
| 2134 | - vec3.normalize(direction, xyz);
|
---|
| 2135 | - vec3.scale(vertex, direction, magnitude);
|
---|
| 2136 | - }
|
---|
| 2137 | - vertices[vindex++] = vertex[0];
|
---|
| 2138 | - vertices[vindex++] = vertex[1];
|
---|
| 2139 | - vertices[vindex++] = vertex[2];
|
---|
| 2140 | - }
|
---|
| 2141 | - //Transpose data to obtain column addressable data matrix
|
---|
| 2142 | - data = data[0].map(function(col, i) {
|
---|
| 2143 | - return data.map(function(row) {
|
---|
| 2144 | - return row[i]
|
---|
| 2145 | - })
|
---|
| 2146 | - });
|
---|
| 2147 | - //Prevent evaluation of datasubarray min/max if caxis exists
|
---|
| 2148 | - if (options.exist('caxis')) caxis = options.getfieldvalue('caxis');
|
---|
| 2149 | - else caxis = [ArrayMin(data[0]), ArrayMax(data[0].slice(0,-1))];
|
---|
| 2150 | - 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))];
|
---|
| 2151 | - //Prepare texcoords to hold array of data values
|
---|
| 2152 | - texcoords = [];
|
---|
| 2153 | - for(var i = 0; i < data.length; i++){
|
---|
| 2154 | - datamin = caxis[0];
|
---|
| 2155 | - datamax = caxis[1];
|
---|
| 2156 | - datadelta = datamax - datamin;
|
---|
| 2157 | - //Precalculate arrays for each datasubarray, trimming off timestamp value by using x.length instead of data[i].length
|
---|
| 2158 | - texcoords[i] = new Float32Array(x.length * 2);
|
---|
| 2159 | - for(var j = 0, index = 0; j < x.length; j++){
|
---|
| 2160 | - texcoords[i][index++] = 0.5;
|
---|
| 2161 | - texcoords[i][index++] = clamp((data[i][j] - datamin) / datadelta, 0.0, 1.0);
|
---|
| 2162 | - }
|
---|
| 2163 | - }
|
---|
| 2164 | -
|
---|
| 2165 | - //linearize the elements array:
|
---|
| 2166 | - var element;
|
---|
| 2167 | - for(var i = 0, iindex = 0; i < elements.length; i++){
|
---|
| 2168 | - element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];
|
---|
| 2169 | - if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;
|
---|
| 2170 | - indices[iindex++] = element[0];
|
---|
| 2171 | - indices[iindex++] = element[1];
|
---|
| 2172 | - indices[iindex++] = element[2];
|
---|
| 2173 | - }
|
---|
| 2174 | -
|
---|
| 2175 | - //Initialize movie loop
|
---|
| 2176 | - node.movieLoop = canvas.animation.loop;
|
---|
| 2177 | - node.movieInterval = 1000 / canvas.animation.fps;
|
---|
| 2178 | - node.movieTimestamps = timestamps;
|
---|
| 2179 | - node.movieLength = timestamps.length;
|
---|
| 2180 | - node.movieFrame = 0;
|
---|
| 2181 | - canvas.dataMarkers.values = [];
|
---|
| 2182 | - var quiverVelFrames = {};
|
---|
| 2183 | - for(var i=0; i < md.results.length; i++){
|
---|
| 2184 | - quiverVelFrames[Math.floor(md.results[i].time)] = md.results[i];
|
---|
| 2185 | - }
|
---|
| 2186 | -
|
---|
| 2187 | - if (canvas.animation.handler !== 0) {
|
---|
| 2188 | - console.log("clearing...");
|
---|
| 2189 | - clearInterval(canvas.animation.handler)
|
---|
| 2190 | - }
|
---|
| 2191 | - //TODO: Move this into webgl.js
|
---|
| 2192 | - canvas.animation.handler = setInterval(function () {
|
---|
| 2193 | - node.movieFrame = canvas.animation.frame;
|
---|
| 2194 | - if (canvas.animation.play && canvas.animation.increment) {
|
---|
| 2195 | - if (node.movieFrame == node.movieLength - 1) {
|
---|
| 2196 | - if (node.movieLoop) {
|
---|
| 2197 | - node.movieFrame = 0;
|
---|
| 2198 | - }
|
---|
| 2199 | - else {
|
---|
| 2200 | - toggleMoviePlay(canvas);
|
---|
| 2201 | - }
|
---|
| 2202 | - }
|
---|
| 2203 | - else {
|
---|
| 2204 | - node.movieFrame = node.movieFrame + 1;
|
---|
| 2205 | - }
|
---|
| 2206 | - if (canvas.animation.lastFrame != canvas.animation.frame) {
|
---|
| 2207 | - updateMarker(canvas, false);
|
---|
| 2208 | - }
|
---|
| 2209 | - }
|
---|
| 2210 | -
|
---|
| 2211 | - if (canvas.progressBar) {
|
---|
| 2212 | - canvas.progressBar.val(node.movieFrame);
|
---|
| 2213 | - canvas.progressBar.slider('refresh');
|
---|
| 2214 | - }
|
---|
| 2215 | - if (canvas.timeLabel) { canvas.timeLabel.html(node.movieTimestamps[node.movieFrame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); }
|
---|
| 2216 | -
|
---|
| 2217 | - var buffer = node.mesh.getBuffer("coords");
|
---|
| 2218 | - buffer.data = texcoords[node.movieFrame];
|
---|
| 2219 | - buffer.upload(canvas.gl.DYNAMIC_DRAW);
|
---|
| 2220 | - node.mesh.octree = new GL.Octree(node.mesh);
|
---|
| 2221 | - node.texcoords = texcoords;
|
---|
| 2222 | - if(options.getfieldvalue('quiver') == 'on'){
|
---|
| 2223 | - plot_quiver(md, options, canvas, {vel: quiverVelFrames[node.movieFrame].Vel, vx: quiverVelFrames[node.movieFrame].Vx, vy: quiverVelFrames[node.movieFrame].Vy});
|
---|
| 2224 | - }
|
---|
| 2225 | - canvas.animation.lastFrame = canvas.animation.frame;
|
---|
| 2226 | - canvas.animation.frame = node.movieFrame;
|
---|
| 2227 | - }, node.movieInterval);
|
---|
| 2228 | -
|
---|
| 2229 | - if (canvas.progressBar) {
|
---|
| 2230 | - canvas.animation.frame = 0;
|
---|
| 2231 | - canvas.progressBar.val(0);
|
---|
| 2232 | - canvas.progressBar.attr('max', node.movieLength-1);
|
---|
| 2233 | - canvas.progressBar.slider('refresh');
|
---|
| 2234 | - }
|
---|
| 2235 | -
|
---|
| 2236 | - }
|
---|
| 2237 | - node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords[0], triangles: indices}, null, null, gl);
|
---|
| 2238 | - node.mesh.octree = new GL.Octree(node.mesh);
|
---|
| 2239 | - break;
|
---|
| 2240 | - //}}}
|
---|
| 2241 | default:
|
---|
| 2242 | - throw Error(sprintf("%s%i%s\n",'case ', datatype,' not supported'));
|
---|
| 2243 | + throw Error(sprintf('%s%i%s\n','case ', datatype,' not supported'));
|
---|
| 2244 | }
|
---|
| 2245 | } //}}}
|
---|
| 2246 | Index: ../trunk-jpl/src/m/plot/plot_overlay.js
|
---|
| 2247 | ===================================================================
|
---|
| 2248 | --- ../trunk-jpl/src/m/plot/plot_overlay.js (revision 21767)
|
---|
| 2249 | +++ ../trunk-jpl/src/m/plot/plot_overlay.js (revision 21768)
|
---|
| 2250 | @@ -6,18 +6,11 @@
|
---|
| 2251 | //
|
---|
| 2252 | // See also: PLOTMODEL, PLOT_MANAGER
|
---|
| 2253 |
|
---|
| 2254 | + if ('overlay' in canvas.nodes && options.getfieldvalue('cachenodes','on') === 'on') return;
|
---|
| 2255 | +
|
---|
| 2256 | //{{{ declare variables:
|
---|
| 2257 | - var vertices = [];
|
---|
| 2258 | - var indices = [];
|
---|
| 2259 | - var texcoords = [];
|
---|
| 2260 | - var nanindices = {};
|
---|
| 2261 | - var xmin, xmax;
|
---|
| 2262 | - var ymin, ymax;
|
---|
| 2263 | - var zmin, zmax;
|
---|
| 2264 | - var matrixscale, vertexscale;
|
---|
| 2265 | -
|
---|
| 2266 | //Process data and model
|
---|
| 2267 | - var meshresults = processmesh(md, data, options);
|
---|
| 2268 | + var meshresults = processmesh(md, [], options);
|
---|
| 2269 | var x = meshresults[0];
|
---|
| 2270 | var y = meshresults[1];
|
---|
| 2271 | var z = meshresults[2];
|
---|
| 2272 | @@ -24,139 +17,74 @@
|
---|
| 2273 | var elements = meshresults[3];
|
---|
| 2274 | var is2d = meshresults[4];
|
---|
| 2275 | var isplanet = meshresults[5];
|
---|
| 2276 | -
|
---|
| 2277 | - //Compue scaling through matrices for 2d meshes and vertices for 3d meshes
|
---|
| 2278 | - if (!md.geometry.surface) {
|
---|
| 2279 | - md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);
|
---|
| 2280 | + if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface;
|
---|
| 2281 | +
|
---|
| 2282 | + //Compute coordinates and data range:
|
---|
| 2283 | + var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
|
---|
| 2284 | + var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
|
---|
| 2285 | + var zlim = options.getfieldvalue('zlim', [ArrayMin(md.geometry.surface), ArrayMax(md.geometry.surface)]);
|
---|
| 2286 | +
|
---|
| 2287 | + //Handle radaroverlay
|
---|
| 2288 | + if (md.radaroverlay.outerx) {
|
---|
| 2289 | + var result = Node.prototype.mergeVertices(x, y, z, elements, md.radaroverlay.outerx, md.radaroverlay.outery, md.radaroverlay.outerheight, md.radaroverlay.outerindex);
|
---|
| 2290 | + x = result.x;
|
---|
| 2291 | + y = result.y;
|
---|
| 2292 | + z = result.z;
|
---|
| 2293 | + elements = result.elements;
|
---|
| 2294 | }
|
---|
| 2295 | - if (md.mesh.classname() == 'mesh3dsurface') {
|
---|
| 2296 | - matrixscale = 1;
|
---|
| 2297 | - vertexscale = options.getfieldvalue('heightscale', 1);
|
---|
| 2298 | +
|
---|
| 2299 | + //Handle heightscale
|
---|
| 2300 | + var vertices, scale;
|
---|
| 2301 | + if (md.mesh.classname() !== 'mesh3dsurface') {
|
---|
| 2302 | + vertices = [x, y, z];
|
---|
| 2303 | + scale = [1, 1, options.getfieldvalue('heightscale', 1)];
|
---|
| 2304 | }
|
---|
| 2305 | else {
|
---|
| 2306 | - if (md.geometry.surface) {
|
---|
| 2307 | - z=md.geometry.surface;
|
---|
| 2308 | - }
|
---|
| 2309 | - matrixscale = options.getfieldvalue('heightscale', 1);
|
---|
| 2310 | - vertexscale = 0;
|
---|
| 2311 | + vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));
|
---|
| 2312 | + scale = [1, 1, 1];
|
---|
| 2313 | }
|
---|
| 2314 | - //}}}
|
---|
| 2315 |
|
---|
| 2316 | - //Compute coordinates and data range:
|
---|
| 2317 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 2318 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 2319 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 2320 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 2321 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 2322 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 2323 | - xmin = xlim[0];
|
---|
| 2324 | - xmax = xlim[1];
|
---|
| 2325 | - ymin = ylim[0];
|
---|
| 2326 | - ymax = ylim[1];
|
---|
| 2327 | - zmin = zlim[0];
|
---|
| 2328 | - zmax = zlim[1];
|
---|
| 2329 | -
|
---|
| 2330 | //Compute gl variables:
|
---|
| 2331 | - var gl = canvas.gl;
|
---|
| 2332 | - var node = Node(gl);
|
---|
| 2333 | - canvas.nodes[canvas.nodes.length] = node;
|
---|
| 2334 | - node.name = "overlay";
|
---|
| 2335 | - node.shaderName = (options.getfieldvalue('render',[]).indexOf('ground')!=-1) ? "GroundFromSpace" : "Textured";
|
---|
| 2336 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 2337 | - node.scale = [1, 1, matrixscale];
|
---|
| 2338 | - node.rotation = [-90, 0, 0];
|
---|
| 2339 | - node.translation = [0, 0, 0];
|
---|
| 2340 | - node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2];
|
---|
| 2341 | - node.texture = initTexture(gl, options.getfieldvalue('overlay_image'));
|
---|
| 2342 | - node.alpha = options.getfieldvalue('outeralpha', 1.0);
|
---|
| 2343 | - node.drawOrder = 1;
|
---|
| 2344 | - node.maskEnabled = options.getfieldvalue('outermask','off') == 'on';
|
---|
| 2345 | - node.maskHeight = options.getfieldvalue('outermaskheight', 150.0);
|
---|
| 2346 | - node.maskColor = options.getfieldvalue('outermaskcolor',[0.0, 0.0, 1.0, 1.0]);
|
---|
| 2347 | - updateModelMatrix(node);
|
---|
| 2348 | + var edgecolor = options.getfieldvalue('edgecolor', 'black');
|
---|
| 2349 | + var texture = initTexture(gl, options.getfieldvalue('overlay_image'));
|
---|
| 2350 | + var node = new Node(
|
---|
| 2351 | + 'canvas', canvas,
|
---|
| 2352 | + 'options', options,
|
---|
| 2353 | + 'name', 'overlay',
|
---|
| 2354 | + 'shaderName', 'ground' in options.getfieldvalue('render', {}) ? 'GroundFromSpace' : 'Textured',
|
---|
| 2355 | + 'alpha', options.getfieldvalue('outeralpha', 1.0),
|
---|
| 2356 | + //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
|
---|
| 2357 | + 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
|
---|
| 2358 | + 'diffuseColor', 'white',
|
---|
| 2359 | + 'maskEnabled', options.getfieldvalue('outermask','off') == 'on',
|
---|
| 2360 | + 'maskHeight', options.getfieldvalue('outermaskheight', 150.0),
|
---|
| 2361 | + 'maskColor', options.getfieldvalue('outermaskcolor',[0.0, 0.0, 1.0, 1.0]),
|
---|
| 2362 | + 'texture', texture,
|
---|
| 2363 | + 'rotation', [-90, 0, 0],
|
---|
| 2364 | + 'scale', scale
|
---|
| 2365 | + );
|
---|
| 2366 | + //}}}
|
---|
| 2367 |
|
---|
| 2368 | - //Handle outer radaroverlay
|
---|
| 2369 | - if (md.radaroverlay.outerx) {
|
---|
| 2370 | - var newelements = [];
|
---|
| 2371 | - for (var i = 0; i < md.radaroverlay.outerindex.length; i++) {
|
---|
| 2372 | - newelements[newelements.length] = [md.radaroverlay.outerindex[i][0] + x.length, md.radaroverlay.outerindex[i][1] + y.length, md.radaroverlay.outerindex[i][2] + z.length];
|
---|
| 2373 | - }
|
---|
| 2374 | - x = [].concat(x, md.radaroverlay.outerx);
|
---|
| 2375 | - y = [].concat(y, md.radaroverlay.outery);
|
---|
| 2376 | - z = [].concat(z, md.radaroverlay.outerheight);
|
---|
| 2377 | - elements = [].concat(elements, newelements);
|
---|
| 2378 | -
|
---|
| 2379 | - //Reclaculate bounds based on otuer radaroverlay
|
---|
| 2380 | - modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 2381 | - modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 2382 | - modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 2383 | - xmin = xlim[0];
|
---|
| 2384 | - xmax = xlim[1];
|
---|
| 2385 | - ymin = ylim[0];
|
---|
| 2386 | - ymax = ylim[1];
|
---|
| 2387 | - zmin = zlim[0];
|
---|
| 2388 | - zmax = zlim[1];
|
---|
| 2389 | -
|
---|
| 2390 | - node.center = [node.center[0], node.center[1], -zmax];
|
---|
| 2391 | - }
|
---|
| 2392 | + var xRange = xlim[1] - xlim[0];
|
---|
| 2393 | + var yRange = ylim[1] - ylim[0];
|
---|
| 2394 | + var coordArray = [new Array(x.length), new Array(x.length)];
|
---|
| 2395 | + //generate mesh:
|
---|
| 2396 |
|
---|
| 2397 | - var xrange = modelxlim[1] - modelxlim[0];
|
---|
| 2398 | - var yrange = modelylim[1] - modelylim[0];
|
---|
| 2399 | -
|
---|
| 2400 | - var xyz = vec3.create();
|
---|
| 2401 | - var direction = vec3.create();
|
---|
| 2402 | - var vertex = vec3.create();
|
---|
| 2403 | - var magnitude;
|
---|
| 2404 | -
|
---|
| 2405 | - //generate mesh:
|
---|
| 2406 | - for(var i = 0; i < x.length; i++){
|
---|
| 2407 | - //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
|
---|
| 2408 | - if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) {
|
---|
| 2409 | - nanindices[i] = i;
|
---|
| 2410 | - vertices[vertices.length] = vertex[0];
|
---|
| 2411 | - vertices[vertices.length] = vertex[1];
|
---|
| 2412 | - vertices[vertices.length] = vertex[2];
|
---|
| 2413 | -
|
---|
| 2414 | - texcoords[texcoords.length] = 0.0;
|
---|
| 2415 | - texcoords[texcoords.length] = 0.0;
|
---|
| 2416 | - continue;
|
---|
| 2417 | - }
|
---|
| 2418 | -
|
---|
| 2419 | - if (md.mesh.classname() == 'mesh3dsurface') {
|
---|
| 2420 | - //Scale vertices
|
---|
| 2421 | - xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 2422 | - magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
|
---|
| 2423 | - vec3.normalize(direction, xyz);
|
---|
| 2424 | - vec3.scale(vertex, direction, magnitude);
|
---|
| 2425 | - vertices[vertices.length] = vertex[0];
|
---|
| 2426 | - vertices[vertices.length] = vertex[1];
|
---|
| 2427 | - vertices[vertices.length] = vertex[2];
|
---|
| 2428 | -
|
---|
| 2429 | - texcoords[texcoords.length] = Math.atan2(vertex[1], vertex[0]) / (2 * Math.PI) + 0.5;
|
---|
| 2430 | - texcoords[texcoords.length] = Math.asin(vertex[2] / magnitude) / Math.PI + 0.5;
|
---|
| 2431 | - }
|
---|
| 2432 | - else {
|
---|
| 2433 | - //Scale vertices
|
---|
| 2434 | - xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 2435 | + if (md.mesh.classname() == 'mesh3dsurface') {
|
---|
| 2436 | + var xyz, magnitude;
|
---|
| 2437 | + for(var i = 0; i < x.length; i++){
|
---|
| 2438 | + xyz = vec3.fromValues(vertices[0][i], vertices[1][i], vertices[2][i]);
|
---|
| 2439 | magnitude = vec3.length(xyz);
|
---|
| 2440 | - vec3.normalize(direction, xyz);
|
---|
| 2441 | - vec3.scale(vertex, direction, magnitude);
|
---|
| 2442 | - vertices[vertices.length] = vertex[0];
|
---|
| 2443 | - vertices[vertices.length] = vertex[1];
|
---|
| 2444 | - vertices[vertices.length] = vertex[2];
|
---|
| 2445 | -
|
---|
| 2446 | - texcoords[texcoords.length] = (x[i] - modelxlim[0]) / xrange;
|
---|
| 2447 | - texcoords[texcoords.length] = (y[i] - modelylim[0]) / yrange;
|
---|
| 2448 | +
|
---|
| 2449 | + coordArray[0][i] = Math.atan2(xyz[1], xyz[0]) / (2 * Math.PI) + 0.5;
|
---|
| 2450 | + coordArray[1][i] = Math.asin(xyz[2] / magnitude) / Math.PI + 0.5;
|
---|
| 2451 | }
|
---|
| 2452 | }
|
---|
| 2453 | - //linearize the elements array:
|
---|
| 2454 | - var element;
|
---|
| 2455 | - for(var i = 0; i < elements.length; i++){
|
---|
| 2456 | - element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];
|
---|
| 2457 | - if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;
|
---|
| 2458 | - indices[indices.length] = element[0];
|
---|
| 2459 | - indices[indices.length] = element[1];
|
---|
| 2460 | - indices[indices.length] = element[2];
|
---|
| 2461 | + else {
|
---|
| 2462 | + for(var i = 0; i < x.length; i++){
|
---|
| 2463 | + coordArray[0][i] = (vertices[0][i] - xlim[0]) / xRange;
|
---|
| 2464 | + coordArray[1][i] = (vertices[1][i] - ylim[0]) / yRange;
|
---|
| 2465 | + }
|
---|
| 2466 | }
|
---|
| 2467 | - node.mesh = GL.Mesh.load({vertices: vertices, coords: texcoords, triangles: indices}, null, null, gl);
|
---|
| 2468 | + node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', coordArray, 'FaceColor', 'interp', 'EdgeColor', edgecolor);
|
---|
| 2469 | } //}}}
|
---|
| 2470 | Index: ../trunk-jpl/src/m/plot/plot_transient_movie.js
|
---|
| 2471 | ===================================================================
|
---|
| 2472 | --- ../trunk-jpl/src/m/plot/plot_transient_movie.js (nonexistent)
|
---|
| 2473 | +++ ../trunk-jpl/src/m/plot/plot_transient_movie.js (revision 21768)
|
---|
| 2474 | @@ -0,0 +1,100 @@
|
---|
| 2475 | +function plot_transient_movie(md, options, canvas) { //{{{
|
---|
| 2476 | + //PLOT_TRANSIENT_MOVIE - plot a transient result as a movie
|
---|
| 2477 | + //
|
---|
| 2478 | + // Usage:
|
---|
| 2479 | + // plot_transient_movie(md, options, canvas);
|
---|
| 2480 | + //
|
---|
| 2481 | + // See also: PLOTMODEL, PLOT_MANAGER
|
---|
| 2482 | +
|
---|
| 2483 | + //loop over the time steps
|
---|
| 2484 | + var data = options.getfieldvalue('transient_field_data');
|
---|
| 2485 | + var datatype;
|
---|
| 2486 | + var steps = new Array(data.length);
|
---|
| 2487 | + for (i = 0; i < steps.length; i++) {
|
---|
| 2488 | + steps[i] = i;
|
---|
| 2489 | + }
|
---|
| 2490 | +
|
---|
| 2491 | + //calculate caxis
|
---|
| 2492 | + if (!options.exist('caxis')) {
|
---|
| 2493 | + var range = [Infinity, -Infinity];
|
---|
| 2494 | + var dataresults;
|
---|
| 2495 | + for (var i in steps) {
|
---|
| 2496 | + dataresults = processdata(md, data[i], options);
|
---|
| 2497 | + range[1] = Math.min(range[0], ArrayMin(dataresults[0]));
|
---|
| 2498 | + range[2] = Math.max(range[1], ArrayMax(dataresults[0]));
|
---|
| 2499 | + }
|
---|
| 2500 | + datatype = dataresults[1];
|
---|
| 2501 | + options.addfielddefault('caxis', range);
|
---|
| 2502 | +
|
---|
| 2503 | + }
|
---|
| 2504 | +
|
---|
| 2505 | + //Create unit node if it does not already exist
|
---|
| 2506 | + if (!('unit' in canvas.nodes)) {
|
---|
| 2507 | + var dataresults = processdata(md, data[i],options);
|
---|
| 2508 | + var data2 = dataresults[0];
|
---|
| 2509 | + var datatype = dataresults[1];
|
---|
| 2510 | +
|
---|
| 2511 | + //plot unit
|
---|
| 2512 | + plot_unit(md,data2,datatype,options,canvas);
|
---|
| 2513 | + }
|
---|
| 2514 | +
|
---|
| 2515 | + //display movie
|
---|
| 2516 | + var node = canvas.nodes.unit;
|
---|
| 2517 | + node.options = options;
|
---|
| 2518 | + node.alpha = options.getfieldvalue('alpha', 1.0);
|
---|
| 2519 | + node.caxis = options.getfieldvalue('caxis');
|
---|
| 2520 | + node.enabled = options.getfieldvalue('nodata', 'off') == 'off';
|
---|
| 2521 | + node.log = options.getfieldvalue('log', false);
|
---|
| 2522 | + canvas.unitMovieData = data;
|
---|
| 2523 | + canvas.animation.frame = 0;
|
---|
| 2524 | + canvas.animation.handler = setInterval(function () {
|
---|
| 2525 | + //Update current animation frame
|
---|
| 2526 | + var frame = canvas.animation.frame;
|
---|
| 2527 | + if (canvas.animation.play) {
|
---|
| 2528 | + if (canvas.animation.increment) {
|
---|
| 2529 | + if (frame > steps.length - 1) {
|
---|
| 2530 | + if (node.movieLoop) {
|
---|
| 2531 | + frame = 0;
|
---|
| 2532 | + }
|
---|
| 2533 | + else {
|
---|
| 2534 | + toggleMoviePlay(canvas);
|
---|
| 2535 | + }
|
---|
| 2536 | + }
|
---|
| 2537 | + else {
|
---|
| 2538 | + frame = (frame + 1) % steps.length;
|
---|
| 2539 | + }
|
---|
| 2540 | + }
|
---|
| 2541 | + }
|
---|
| 2542 | +
|
---|
| 2543 | + //If frame has changed, update unit node and data marker display.
|
---|
| 2544 | + if (frame !== canvas.animation.lastFrame) {
|
---|
| 2545 | + node.updateBuffer('Coords', data[frame]);
|
---|
| 2546 | + canvas.unitData = data[frame];
|
---|
| 2547 | + if (canvas.dataMarkers.enabled) {
|
---|
| 2548 | + updateMarker(canvas, false);
|
---|
| 2549 | + }
|
---|
| 2550 | + if (canvas.progressBar) {
|
---|
| 2551 | + canvas.progressBar.val(frame).slider('refresh');
|
---|
| 2552 | + }
|
---|
| 2553 | + if (canvas.timeLabel) {
|
---|
| 2554 | + canvas.timeLabel.html(steps[frame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr"));
|
---|
| 2555 | + }
|
---|
| 2556 | + if (!isEmptyOrUndefined(canvas.nodes.quiver)) {
|
---|
| 2557 | + plot_quiver(md,options,canvas,false);
|
---|
| 2558 | + }
|
---|
| 2559 | + }
|
---|
| 2560 | +
|
---|
| 2561 | + //Save new frame info.
|
---|
| 2562 | + canvas.animation.lastFrame = canvas.animation.frame;
|
---|
| 2563 | + canvas.animation.frame = frame;
|
---|
| 2564 | + }, canvas.animation.interval);
|
---|
| 2565 | +
|
---|
| 2566 | + //Update progress bar with new frame info.
|
---|
| 2567 | + if (canvas.progressBar) {
|
---|
| 2568 | + canvas.progressBar.val(canvas.animation.frame);
|
---|
| 2569 | + canvas.progressBar.attr('max', steps.length - 1);
|
---|
| 2570 | + canvas.progressBar.slider('refresh');
|
---|
| 2571 | + }
|
---|
| 2572 | +
|
---|
| 2573 | + applyoptions(md, [], options, canvas);
|
---|
| 2574 | +} //}}}
|
---|
| 2575 | Index: ../trunk-jpl/src/m/plot/plotdoc.js
|
---|
| 2576 | ===================================================================
|
---|
| 2577 | --- ../trunk-jpl/src/m/plot/plotdoc.js (revision 21767)
|
---|
| 2578 | +++ ../trunk-jpl/src/m/plot/plotdoc.js (revision 21768)
|
---|
| 2579 | @@ -4,20 +4,25 @@
|
---|
| 2580 | // Usage:
|
---|
| 2581 | // plotdoc()
|
---|
| 2582 |
|
---|
| 2583 | - //TODO: Standardize image to overlay_image, heightscale to scaling, colorbarfontsize/color, clarify innermask/outermask, edgecolor implementation, check colormap,
|
---|
| 2584 | + //TODO: rename innermask/outermask/maskzero and combine
|
---|
| 2585 |
|
---|
| 2586 | - console.log(' WARNING: starred methods (*) are experimental and not guarenteed to be stable');
|
---|
| 2587 | console.log(' Plot usage: plotmodel(model,varargin)');
|
---|
| 2588 | console.log(' Options: ');
|
---|
| 2589 | console.log(' "canvasid": canvas id');
|
---|
| 2590 | console.log(' "data" : what we want to plot');
|
---|
| 2591 | - console.log(' Available values for "data" are: ');
|
---|
| 2592 | - console.log(' - any field of the model structure. ex: plot(md,"data","vel"), or plot(md,"data",md.initialization.vel)');
|
---|
| 2593 | - console.log(' - "mesh": draw mesh using trisurf');
|
---|
| 2594 | - console.log(' - "quiver": quiver plot');
|
---|
| 2595 | - console.log(' "2d": renders orthographic camera with view set to [0, 90] (default "off", ex: "on", "off")');
|
---|
| 2596 | + console.log(' Available values for "data" are: ');
|
---|
| 2597 | + console.log(' - any field of the model structure. ex: plot(md,"data","vel"), or plot(md,"data",md.initialization.vel)');
|
---|
| 2598 | + console.log(' - "mesh": draw mesh using trisurf');
|
---|
| 2599 | + console.log(' - "quiver": quiver plot');
|
---|
| 2600 | console.log(' "backgroundcolor": plot background color. (default "lightcyan", ex: "green","blue")');
|
---|
| 2601 | console.log(' "brush": specify brush options (default {"strength":0.075,"falloff":0.5})');
|
---|
| 2602 | + console.log(' "enabled": toggle brush (default false, ex: true)');
|
---|
| 2603 | + console.log(' "strength": value that brush will change data points by (ex: 0.075)');
|
---|
| 2604 | + console.log(' "falloff": multiplier that brush will decrease strength by for each successive point away from brush center (ex: 0.5)');
|
---|
| 2605 | + console.log(' "clouds": specify brush options (default {"strength":0.075,"falloff":0.5})');
|
---|
| 2606 | + console.log(' "enabled": toggle clouds (default false, ex: true)');
|
---|
| 2607 | + console.log(' "height": height to spawn clouds at (ex: 7500)');
|
---|
| 2608 | + console.log(' "quantity": quantity of clouds to spawn (ex: 10)');
|
---|
| 2609 | console.log(' "caxis": modify colorbar range. (array of type [a, b] where b>=a)');
|
---|
| 2610 | console.log(' "colorbar": add colorbar (default "off", ex: "on", "off")');
|
---|
| 2611 | console.log(' "colorbarid": colorbar canvas id (string)');
|
---|
| 2612 | @@ -31,18 +36,26 @@
|
---|
| 2613 | console.log(' "colorbarheight": multiplier (default 1) to the default height colorbar');
|
---|
| 2614 | console.log(' "colormap": same as standard matlab option (default "jet", ex: "hsv","cool","spring","gray","Ala","Rignot",...)');
|
---|
| 2615 | console.log(' "controlsensitivity": sensitivty of view/zoom changes as a percentage of default (default 1, ex: 0.5, 2.75)');
|
---|
| 2616 | - console.log(' "datamarkers": toggle data marker displays (default "on", ex: "on", "off")');
|
---|
| 2617 | - console.log(' "datamarkers_image": toggle data marker displays (default "on", ex: "on", "off")');
|
---|
| 2618 | - console.log(' "datamarkerssize": specifiy the width and height of the data markers (default [32,32], ex: [24,32], [105,10])');
|
---|
| 2619 | - 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"]}');
|
---|
| 2620 | + 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})');
|
---|
| 2621 | + console.log(' "enabled": toggle data marker displays (default true, ex: false)');
|
---|
| 2622 | + console.log(' "image": image used for marking the clicked point (ex: "/textures/data_marker.svg")');
|
---|
| 2623 | + console.log(' "labels": when displaying a sim-plot graph, display these model fields. (ex: ["thickness","velocity","value"])');
|
---|
| 2624 | + console.log(' "font": font to be used for display (ex: "24px "Comic Sans MS", cursive")');
|
---|
| 2625 | + 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"])');
|
---|
| 2626 | + console.log(' "size": specifiy the width and height of the data markers (default [32,32], ex: [24,32], [105,10])');
|
---|
| 2627 | console.log(' "displayview": print view value to console (default "off", ex: "on", "off")');
|
---|
| 2628 | console.log(' "displayzoom": print zoom value to console (default "off", ex: "on", "off")');
|
---|
| 2629 | console.log(' "edgecolor": same as standard matlab option EdgeColor (default "black", ex: color name: "blue" or RGB array: [0.5, 0.2, 0.8])');
|
---|
| 2630 | console.log(' "heightscale": scaling factor to accentuate height. (default 1, ex: 0.5, 100)');
|
---|
| 2631 | - console.log(' "linewidth*": line width for mesh, quiver, and contour plots, currently limited by WebGL to 1. (default 1, ex: 2, 5)');
|
---|
| 2632 | + console.log(' "linewidth": line width for mesh, quiver, and contour plots, currently limited by WebGL to 1. (default 1, ex: 2, 5)');
|
---|
| 2633 | console.log(' "log": value of log (default 10, ex: 2, Math.E)');
|
---|
| 2634 | console.log(' "mask": list of flags of size numberofnodes or numberofelements. Only "true" values are plotted ');
|
---|
| 2635 | - console.log(' "movieoptions": specify movie options (default {"fps":4,"loop":true})');
|
---|
| 2636 | + console.log(' "movies": object cotaining transient plot animation options (ex: {"fps":4,"loop":true})');
|
---|
| 2637 | + 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})');
|
---|
| 2638 | + console.log(' "enabled": toggle maskzeros (default false, ex: true)');
|
---|
| 2639 | + console.log(' "color": RGBA color value array with ranges 0.0 to 1.0 (ex: [1.0, 1.0, 1.0, 1.0])');
|
---|
| 2640 | + console.log(' "tolerance": values within this tolerance of the zeroValue will be masked. (default: 1e-3, ex: 2.5e-2)');
|
---|
| 2641 | + 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)');
|
---|
| 2642 | 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")');
|
---|
| 2643 | 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")');
|
---|
| 2644 | console.log(' "overlay": overlay a radar amplitude image behind (default "off", ex: "on", "off")');
|
---|
| 2645 | @@ -50,20 +63,51 @@
|
---|
| 2646 | console.log(' "quiver": add quiver plot overlay for velocities. (default "off", ex: "on", "off")');
|
---|
| 2647 | console.log(' "scaling": scaling factor used by quiver plots. Default is 0.4');
|
---|
| 2648 | console.log(' "alpha": transparency coefficient 0.0 to 1.0, the lower, the more transparent. (default 1.0, ex: 0.5, 0.25)');
|
---|
| 2649 | - console.log(' "azlim": azimuth view limits (ex: [0, 180])');
|
---|
| 2650 | - console.log(' "ellim": elevation view limits (ex: [-90, 90])');
|
---|
| 2651 | - console.log(' "origin": initial camera offset from model center (default [0,0,0.0], ex: [-2, 1.5, 0.01])');
|
---|
| 2652 | - console.log(' "render": toggle sky, ground, and space rendering. (default [], ex: ["sky", "space"], ["ground"])');
|
---|
| 2653 | - console.log(' "viewPanning": enable view origin panning with two-finger touch or shift+mouse drag. (default "off", ex: "on", "off")');
|
---|
| 2654 | - console.log(' "view": initial azimuth and elevation angles for camera (default [0,90], ex: [90, 180]');
|
---|
| 2655 | + console.log(' "render": a object containing a list of default object to render. (default {}, ex: {"sky", "space"})');
|
---|
| 2656 | + console.log(' "sky": render the atmosphere. (ex: {"enabled":true})');
|
---|
| 2657 | + console.log(' "enabled": toggle sky (default false, ex: true)');
|
---|
| 2658 | + console.log(' "space": render space. (ex: {"enabled":true})');
|
---|
| 2659 | + console.log(' "enabled": toggle space (default false, ex: true)');
|
---|
| 2660 | + console.log(' "coastlines": render coastlines. (ex: {"enabled":true})');
|
---|
| 2661 | + console.log(' "enabled": toggle coastlines (default false, ex: true)');
|
---|
| 2662 | + console.log(' "scale": scale coastlines factor (default 1.0, ex: 1.004)');
|
---|
| 2663 | + console.log(' "x": x coordinate array. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2664 | + console.log(' "y": y coordinate array. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2665 | + console.log(' "z": z coordinate array. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2666 | + console.log(' "city": render city. (ex: {"enabled":true})');
|
---|
| 2667 | + console.log(' "enabled": toggle city (default false, ex: true)');
|
---|
| 2668 | + console.log(' "size": radius of city sphere, in meters (default 1.0, ex: 150000)');
|
---|
| 2669 | + console.log(' "color": color of city sphere (ex: "magenta")');
|
---|
| 2670 | + console.log(' "x": x coordinate of city. (ex: 0.0)');
|
---|
| 2671 | + console.log(' "y": y coordinate of city. (ex: 0.0)');
|
---|
| 2672 | + console.log(' "z": z coordinate of city. (ex: 6356700.0)');
|
---|
| 2673 | + console.log(' "cities": render cities. (ex: {"enabled":true})');
|
---|
| 2674 | + console.log(' "enabled": toggle cities (default false, ex: true)');
|
---|
| 2675 | + console.log(' "size": radius of cities spheres, in meters (default 1.0, ex: 80000)');
|
---|
| 2676 | + console.log(' "color": color of cities spheres (ex: "darkviolet")');
|
---|
| 2677 | + console.log(' "x": x coordinate array of cities. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2678 | + console.log(' "y": y coordinate array of cities. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2679 | + console.log(' "z": z coordinate array of cities. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2680 | + console.log(' "graticule": render graticule. (ex: {"enabled":true})');
|
---|
| 2681 | + console.log(' "enabled": toggle graticule (default false, ex: true)');
|
---|
| 2682 | + console.log(' "scale": scale graticule factor (default 1.0, ex: 1.004)');
|
---|
| 2683 | + console.log(' "x": x coordinate array. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2684 | + console.log(' "y": y coordinate array. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2685 | + console.log(' "z": z coordinate array. (ex: [0.0, 10.0, -25.0,...])');
|
---|
| 2686 | + 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})');
|
---|
| 2687 | + console.log(' "position": camera position (ex: [0.0,0.0,0.0])');
|
---|
| 2688 | + console.log(' "rotation": camera rotation (ex: [0.0,0.0,0.0])');
|
---|
| 2689 | + console.log(' "zoom": initial camera zoom as a percentage of default (default 1, ex: 1.5, 0.01)');
|
---|
| 2690 | + console.log(' "zoomLimits": zoom view limits (ex: [0.05, 10])');
|
---|
| 2691 | + console.log(' "azimuthLimits": zoom view limits (ex: [0.05, 10])');
|
---|
| 2692 | + console.log(' "elevationLimits": zoom view limits (ex: [0.05, 10])');
|
---|
| 2693 | + console.log(' "panningEnabled": controls panning with shift + drag mouse or pan gestures (default: false, ex: true)');
|
---|
| 2694 | + console.log(' "twod": controls twod orthographic view (default: false, ex: true)');
|
---|
| 2695 | console.log(' "xlim": x coordinates to fit inside camera (ex: [0, 500])');
|
---|
| 2696 | console.log(' "ylim": y coordinates to fit inside camera (ex: [0, 500])');
|
---|
| 2697 | console.log(' "zlim": z coordinates to fit inside camera (ex: [0, 500])');
|
---|
| 2698 | - console.log(' "zoomlim": zoom view limits (ex: [0.05, 10])');
|
---|
| 2699 | - console.log(' "zoom": initial camera zoom as a percentage of default (default 1, ex: 1.5, 0.01)');
|
---|
| 2700 | - 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])');
|
---|
| 2701 | - 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)');
|
---|
| 2702 | - 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"}])');
|
---|
| 2703 | + 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...],...])');
|
---|
| 2704 | + 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"}])');
|
---|
| 2705 |
|
---|
| 2706 | console.log(' ');
|
---|
| 2707 | console.log(' Examples:');
|
---|
| 2708 | Index: ../trunk-jpl/src/m/plot/processdata.js
|
---|
| 2709 | ===================================================================
|
---|
| 2710 | --- ../trunk-jpl/src/m/plot/processdata.js (revision 21767)
|
---|
| 2711 | +++ ../trunk-jpl/src/m/plot/processdata.js (revision 21768)
|
---|
| 2712 | @@ -14,9 +14,6 @@
|
---|
| 2713 | //
|
---|
| 2714 | // See also: PLOTMODEL, PROCESSMESH
|
---|
| 2715 |
|
---|
| 2716 | - //variables:
|
---|
| 2717 | - var datatype;
|
---|
| 2718 | -
|
---|
| 2719 | //check format
|
---|
| 2720 | if ( data.length ==0 | data === [] | typeof data === 'number' | ArrayAnyNaN(data) ){
|
---|
| 2721 | throw Error('plotmodel error message: data provided is empty');
|
---|
| 2722 | @@ -34,6 +31,7 @@
|
---|
| 2723 | }
|
---|
| 2724 |
|
---|
| 2725 | //needed later on
|
---|
| 2726 | + var numberofvertices2d, numberofelements2d;
|
---|
| 2727 | if ('numberofvertices2d' in md.mesh){
|
---|
| 2728 | numberofvertices2d=md.mesh.numberofvertices2d;
|
---|
| 2729 | numberofelements2d=md.mesh.numberofelements2d;
|
---|
| 2730 | @@ -44,10 +42,10 @@
|
---|
| 2731 | }
|
---|
| 2732 |
|
---|
| 2733 | //initialize datatype
|
---|
| 2734 | - datatype=0;
|
---|
| 2735 | + var datatype=0;
|
---|
| 2736 |
|
---|
| 2737 | //get datasize
|
---|
| 2738 | - datasize=data.length;
|
---|
| 2739 | + var datasize=data.length;
|
---|
| 2740 |
|
---|
| 2741 | //transpose data if necessary
|
---|
| 2742 | if (data[0].length > data.length){
|
---|
| 2743 | @@ -63,7 +61,7 @@
|
---|
| 2744 |
|
---|
| 2745 |
|
---|
| 2746 | //quiver?
|
---|
| 2747 | - if (data[0].length>1){
|
---|
| 2748 | + if (Array.isArray(data[0])){
|
---|
| 2749 | datatype=3;
|
---|
| 2750 |
|
---|
| 2751 | //check number of columns, add zeros if necessary,
|
---|
| 2752 | @@ -114,7 +112,7 @@
|
---|
| 2753 | }
|
---|
| 2754 |
|
---|
| 2755 | //element data
|
---|
| 2756 | - if (datasize==md.mesh.numberofelements & data[0].length==1){
|
---|
| 2757 | + if (datasize==md.mesh.numberofelements & !Array.isArray(data[0])){
|
---|
| 2758 |
|
---|
| 2759 | //Initialize datatype if non patch
|
---|
| 2760 | if(datatype!=4 & datatype!=5){
|
---|
| 2761 | @@ -157,7 +155,7 @@
|
---|
| 2762 | }
|
---|
| 2763 |
|
---|
| 2764 | //node data
|
---|
| 2765 | - if (datasize==md.mesh.numberofvertices){
|
---|
| 2766 | + if (datasize==md.mesh.numberofvertices & !Array.isArray(data[0])){
|
---|
| 2767 | datatype=2;
|
---|
| 2768 |
|
---|
| 2769 | //Mask?
|
---|
| 2770 | Index: ../trunk-jpl/src/m/plot/plot_quiver.js
|
---|
| 2771 | ===================================================================
|
---|
| 2772 | --- ../trunk-jpl/src/m/plot/plot_quiver.js (revision 21767)
|
---|
| 2773 | +++ ../trunk-jpl/src/m/plot/plot_quiver.js (revision 21768)
|
---|
| 2774 | @@ -1,4 +1,4 @@
|
---|
| 2775 | -function plot_quiver(md, options, canvas, updateVel) { //{{{
|
---|
| 2776 | +function plot_quiver(md, options, canvas, noCacheNodesOverride) { //{{{
|
---|
| 2777 | //PLOT_QUIVER - quiver plot with colors
|
---|
| 2778 | //
|
---|
| 2779 | // Usage:
|
---|
| 2780 | @@ -6,18 +6,11 @@
|
---|
| 2781 | //
|
---|
| 2782 | // See also: PLOTMODEL, PLOT_MANAGER
|
---|
| 2783 |
|
---|
| 2784 | + if ('quiver' in canvas.nodes && noCacheNodesOverride && options.getfieldvalue('cachenodes','on') === 'on') return;
|
---|
| 2785 | +
|
---|
| 2786 | //{{{ declare variables:
|
---|
| 2787 | - var vertices = [];
|
---|
| 2788 | - var indices = [];
|
---|
| 2789 | - var colors = [];
|
---|
| 2790 | - var xmin, xmax;
|
---|
| 2791 | - var ymin, ymax;
|
---|
| 2792 | - var zmin, zmax;
|
---|
| 2793 | - var scale, matrixscale, vertexscale;
|
---|
| 2794 | -
|
---|
| 2795 | //Process data and model
|
---|
| 2796 | - var meshresults = processmesh(md,[], options);
|
---|
| 2797 | -
|
---|
| 2798 | + var meshresults = processmesh(md, [], options);
|
---|
| 2799 | var x = meshresults[0];
|
---|
| 2800 | var y = meshresults[1];
|
---|
| 2801 | var z = meshresults[2];
|
---|
| 2802 | @@ -24,66 +17,50 @@
|
---|
| 2803 | var elements = meshresults[3];
|
---|
| 2804 | var is2d = meshresults[4];
|
---|
| 2805 | var isplanet = meshresults[5];
|
---|
| 2806 | - var v = updateVel != undefined ? updateVel.vel : md.initialization.vel;
|
---|
| 2807 | - var vx = updateVel != undefined ? updateVel.vx : md.initialization.vx;
|
---|
| 2808 | - var vy = updateVel != undefined ? updateVel.vy : md.initialization.vy;
|
---|
| 2809 | + if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface;
|
---|
| 2810 |
|
---|
| 2811 | - //Compue scaling through matrices for 2d meshes and vertices for 3d meshes
|
---|
| 2812 | - if (!md.geometry.surface) {
|
---|
| 2813 | - md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);
|
---|
| 2814 | + //Compute coordinates and data range:
|
---|
| 2815 | + var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
|
---|
| 2816 | + var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
|
---|
| 2817 | + var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
|
---|
| 2818 | +
|
---|
| 2819 | + //Only displaying velocity fields for now
|
---|
| 2820 | + var v = isEmptyOrUndefined(md.results) ? md.initialization.vel : md.results[canvas.animation.frame].Vel;
|
---|
| 2821 | + var vx = isEmptyOrUndefined(md.results) ? md.initialization.vx : md.results[canvas.animation.frame].Vx;
|
---|
| 2822 | + var vy = isEmptyOrUndefined(md.results) ? md.initialization.vy : md.results[canvas.animation.frame].Vy;
|
---|
| 2823 | +
|
---|
| 2824 | + //Handle heightscale
|
---|
| 2825 | + var vertices, scale;
|
---|
| 2826 | + if (md.mesh.classname() !== 'mesh3dsurface') {
|
---|
| 2827 | + vertices = [x, y, z];
|
---|
| 2828 | + scale = [1, 1, options.getfieldvalue('heightscale', 1)];
|
---|
| 2829 | }
|
---|
| 2830 | - if (md.mesh.classname() == 'mesh3dsurface') {
|
---|
| 2831 | - matrixscale = 1;
|
---|
| 2832 | - vertexscale = options.getfieldvalue('heightscale', 1);
|
---|
| 2833 | - }
|
---|
| 2834 | else {
|
---|
| 2835 | - if (md.geometry.surface) {
|
---|
| 2836 | - z=md.geometry.surface;
|
---|
| 2837 | - }
|
---|
| 2838 | - matrixscale = options.getfieldvalue('heightscale', 1);
|
---|
| 2839 | - vertexscale = 0;
|
---|
| 2840 | + vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));
|
---|
| 2841 | + scale = [1, 1, 1];
|
---|
| 2842 | }
|
---|
| 2843 | - //}}}
|
---|
| 2844 | -
|
---|
| 2845 | - //Compute coordinates and data range:
|
---|
| 2846 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 2847 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 2848 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 2849 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 2850 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 2851 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 2852 | - xmin = xlim[0];
|
---|
| 2853 | - xmax = xlim[1];
|
---|
| 2854 | - ymin = ylim[0];
|
---|
| 2855 | - ymax = ylim[1];
|
---|
| 2856 | - zmin = zlim[0];
|
---|
| 2857 | - zmax = zlim[1];
|
---|
| 2858 | -
|
---|
| 2859 | +
|
---|
| 2860 | //Compute gl variables:
|
---|
| 2861 | - var gl = canvas.gl;
|
---|
| 2862 | - var node = Node(gl);
|
---|
| 2863 | - canvas.nodes["velocity"] = node;
|
---|
| 2864 | - node.name = "quiver";
|
---|
| 2865 | - node.shaderName = "Colored";
|
---|
| 2866 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 2867 | - node.lineWidth = options.getfieldvalue('linewidth', 1);
|
---|
| 2868 | - node.scale = [1, 1, matrixscale];
|
---|
| 2869 | - node.rotation = [-90, 0, 0];
|
---|
| 2870 | - node.translation = [0, 0, 0];
|
---|
| 2871 | - node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2];
|
---|
| 2872 | - node.drawMode = gl.LINES;
|
---|
| 2873 | - node.useIndexBuffer = false;
|
---|
| 2874 | - node.drawOrder = 0;
|
---|
| 2875 | - node.maskEnabled = options.getfieldvalue('innermask','off') == 'on';
|
---|
| 2876 | - node.maskHeight = options.getfieldvalue('innermaskheight', 150.0)*options.getfieldvalue('heightscale', 1);
|
---|
| 2877 | - node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]);
|
---|
| 2878 | - updateModelMatrix(node);
|
---|
| 2879 | -
|
---|
| 2880 | - //retrieve some options
|
---|
| 2881 | - var edgecolor=new RGBColor(options.getfieldvalue('edgecolor','black'));
|
---|
| 2882 | - if (edgecolor.ok) edgecolor = [edgecolor.r/255.0, edgecolor.g/255.0, edgecolor.b/255.0, 1.0];
|
---|
| 2883 | - else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas));
|
---|
| 2884 | -
|
---|
| 2885 | + var edgecolor = options.getfieldvalue('edgecolor', 'black');
|
---|
| 2886 | + var node = new Node(
|
---|
| 2887 | + 'canvas', canvas,
|
---|
| 2888 | + 'options', options,
|
---|
| 2889 | + 'name', 'quiver',
|
---|
| 2890 | + 'shaderName', 'Colored',
|
---|
| 2891 | + 'alpha', options.getfieldvalue('alpha', 1.0),
|
---|
| 2892 | + //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
|
---|
| 2893 | + 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
|
---|
| 2894 | + 'drawMode', canvas.gl.LINES,
|
---|
| 2895 | + 'diffuseColor', edgecolor,
|
---|
| 2896 | + 'lineWidth', options.getfieldvalue('linewidth', 1),
|
---|
| 2897 | + 'maskEnabled', options.getfieldvalue('innermask','off') == 'on',
|
---|
| 2898 | + 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1),
|
---|
| 2899 | + 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]),
|
---|
| 2900 | + 'rotation', [-90, 0, 0],
|
---|
| 2901 | + 'scale', scale
|
---|
| 2902 | + );
|
---|
| 2903 | +
|
---|
| 2904 | +
|
---|
| 2905 | //{{{ node plot
|
---|
| 2906 | if (elements[0].length==6){ //prisms
|
---|
| 2907 | }
|
---|
| 2908 | @@ -90,49 +67,37 @@
|
---|
| 2909 | else if (elements[0].length==4){ //tetras
|
---|
| 2910 | }
|
---|
| 2911 | else{ //2D triangular elements
|
---|
| 2912 | + //Create arow vertices, and use vx/vy to determine rotation before adding to quiver mesh.
|
---|
| 2913 | + 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)];
|
---|
| 2914 | +
|
---|
| 2915 | + var newX = [];
|
---|
| 2916 | + var newY = [];
|
---|
| 2917 | + var newZ = [];
|
---|
| 2918 | var xyz = vec3.create();
|
---|
| 2919 | - var xyz = vec3.create();
|
---|
| 2920 | - var direction = vec3.create();
|
---|
| 2921 | var vertex = vec3.create();
|
---|
| 2922 | - var vertexBase = vec3.create();
|
---|
| 2923 | - 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)];
|
---|
| 2924 | - var magnitude;
|
---|
| 2925 | - var color = edgecolor;
|
---|
| 2926 | var scaling = options.getfieldvalue('scaling', 1);
|
---|
| 2927 | - var scale;
|
---|
| 2928 | - for(var i = 0; i < x.length; i++){
|
---|
| 2929 | - //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
|
---|
| 2930 | - if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) continue;
|
---|
| 2931 | - //Scale vertices
|
---|
| 2932 | + var heightScale = options.getfieldvalue('heightscale', 1);
|
---|
| 2933 | + var arrowScale;
|
---|
| 2934 | + var modelMatrix = mat4.create();
|
---|
| 2935 | + var scaleMatrix = mat4.create();
|
---|
| 2936 | + var rotationMatrix = mat4.create();
|
---|
| 2937 | +
|
---|
| 2938 | + for(var i = 0, iX = 0, iY = 0, iZ = 0; i < x.length; i++){
|
---|
| 2939 | xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 2940 | - magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
|
---|
| 2941 | - vec3.normalize(direction, xyz);
|
---|
| 2942 | - vec3.scale(vertex, direction, magnitude);
|
---|
| 2943 | - vec3.copy(vertexBase, vertex);
|
---|
| 2944 | -
|
---|
| 2945 | - scale = scaling*v[i];
|
---|
| 2946 | - var modelMatrix = mat4.create();
|
---|
| 2947 | - var scaleMatrix = mat4.create();
|
---|
| 2948 | - var rotationMatrix = mat4.create();
|
---|
| 2949 | - mat4.scale(scaleMatrix, scaleMatrix, vec3.fromValues(scale, scale, scale));
|
---|
| 2950 | - mat4.rotate(rotationMatrix, rotationMatrix, Math.atan2(vy[i], vx[i]), [0.0, 0.0, 1.0]);
|
---|
| 2951 | + arrowScale = v[i] * scaling;
|
---|
| 2952 | + scaleMatrix = mat4.create();
|
---|
| 2953 | + mat4.scale(scaleMatrix, mat4.create(), vec3.fromValues(arrowScale, arrowScale, arrowScale));
|
---|
| 2954 | + mat4.rotate(rotationMatrix, mat4.create(), Math.atan2(vy[i], vx[i]), [0.0, 0.0, 1.0]);
|
---|
| 2955 | mat4.multiply(modelMatrix, rotationMatrix, scaleMatrix);
|
---|
| 2956 | -
|
---|
| 2957 | - var temp = vec3.fromValues(0.0, 0.0, 0.0);
|
---|
| 2958 | for (var j = 0; j < 6; j++){
|
---|
| 2959 | vec3.transformMat4(vertex, verticesArrow[j], modelMatrix);
|
---|
| 2960 | - vec3.add(vertex, vertex, vertexBase);
|
---|
| 2961 | - vertices[vertices.length] = vertex[0];
|
---|
| 2962 | - vertices[vertices.length] = vertex[1];
|
---|
| 2963 | - vertices[vertices.length] = vertex[2];
|
---|
| 2964 | -
|
---|
| 2965 | - colors[colors.length] = color[0];
|
---|
| 2966 | - colors[colors.length] = color[1];
|
---|
| 2967 | - colors[colors.length] = color[2];
|
---|
| 2968 | - colors[colors.length] = color[3];
|
---|
| 2969 | + vec3.add(vertex, vertex, xyz);
|
---|
| 2970 | + newX[iX++] = vertex[0];
|
---|
| 2971 | + newY[iY++] = vertex[1];
|
---|
| 2972 | + newZ[iZ++] = vertex[2];
|
---|
| 2973 | }
|
---|
| 2974 | }
|
---|
| 2975 | + node.patch('Vertices', [newX, newY, newZ], 'FaceColor', 'none');
|
---|
| 2976 | }
|
---|
| 2977 | //}}}
|
---|
| 2978 | - node.mesh = GL.Mesh.load({vertices: vertices, colors: colors}, null, null, gl);
|
---|
| 2979 | } //}}}
|
---|
| 2980 | Index: ../trunk-jpl/src/m/plot/plot_mesh.js
|
---|
| 2981 | ===================================================================
|
---|
| 2982 | --- ../trunk-jpl/src/m/plot/plot_mesh.js (revision 21767)
|
---|
| 2983 | +++ ../trunk-jpl/src/m/plot/plot_mesh.js (revision 21768)
|
---|
| 2984 | @@ -6,18 +6,11 @@
|
---|
| 2985 | //
|
---|
| 2986 | // See also: PLOTMODEL, PLOT_MANAGER
|
---|
| 2987 |
|
---|
| 2988 | + if ('mesh' in canvas.nodes && options.getfieldvalue('cachenodes','on') === 'on') return;
|
---|
| 2989 | +
|
---|
| 2990 | //{{{ declare variables:
|
---|
| 2991 | - var vertices = [];
|
---|
| 2992 | - var indices = [];
|
---|
| 2993 | - var colors = [];
|
---|
| 2994 | - var nanindices = {};
|
---|
| 2995 | - var xmin, xmax;
|
---|
| 2996 | - var ymin, ymax;
|
---|
| 2997 | - var zmin, zmax;
|
---|
| 2998 | - var scale, matrixscale, vertexscale;
|
---|
| 2999 | -
|
---|
| 3000 | //Process data and model
|
---|
| 3001 | - var meshresults = processmesh(md,[], options);
|
---|
| 3002 | + var meshresults = processmesh(md, [], options);
|
---|
| 3003 | var x = meshresults[0];
|
---|
| 3004 | var y = meshresults[1];
|
---|
| 3005 | var z = meshresults[2];
|
---|
| 3006 | @@ -25,62 +18,42 @@
|
---|
| 3007 | var is2d = meshresults[4];
|
---|
| 3008 | var isplanet = meshresults[5];
|
---|
| 3009 |
|
---|
| 3010 | - //Compue scaling through matrices for 2d meshes and vertices for 3d meshes
|
---|
| 3011 | - if (!md.geometry.surface) {
|
---|
| 3012 | - md.geometry.surface=NewArrayFill(md.mesh.x.length, 0);
|
---|
| 3013 | + //Compute coordinates and data range:
|
---|
| 3014 | + var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
|
---|
| 3015 | + var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
|
---|
| 3016 | + var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
|
---|
| 3017 | +
|
---|
| 3018 | + //Handle heightscale
|
---|
| 3019 | + var vertices, scale;
|
---|
| 3020 | + if (md.mesh.classname() !== 'mesh3dsurface') {
|
---|
| 3021 | + vertices = [x, y, z];
|
---|
| 3022 | + scale = [1, 1, options.getfieldvalue('heightscale', 1)];
|
---|
| 3023 | }
|
---|
| 3024 | - if (md.mesh.classname() == 'mesh3dsurface') {
|
---|
| 3025 | - matrixscale = 1;
|
---|
| 3026 | - vertexscale = options.getfieldvalue('heightscale', 1);
|
---|
| 3027 | - }
|
---|
| 3028 | else {
|
---|
| 3029 | - if (md.geometry.surface) {
|
---|
| 3030 | - z=md.geometry.surface;
|
---|
| 3031 | - }
|
---|
| 3032 | - matrixscale = options.getfieldvalue('heightscale', 1);
|
---|
| 3033 | - vertexscale = 0;
|
---|
| 3034 | + vertices = Node.prototype.scaleVertices(md, x, y, z, options.getfieldvalue('heightscale', 1));
|
---|
| 3035 | + scale = [1, 1, 1];
|
---|
| 3036 | }
|
---|
| 3037 | +
|
---|
| 3038 | + //Compute gl variables:
|
---|
| 3039 | + var edgecolor = options.getfieldvalue('edgecolor', 'black');
|
---|
| 3040 | + var node = new Node(
|
---|
| 3041 | + 'canvas', canvas,
|
---|
| 3042 | + 'options', options,
|
---|
| 3043 | + 'name', 'mesh',
|
---|
| 3044 | + 'shaderName', 'Colored',
|
---|
| 3045 | + 'alpha', options.getfieldvalue('alpha', 1.0),
|
---|
| 3046 | + //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
|
---|
| 3047 | + 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
|
---|
| 3048 | + 'drawMode', canvas.gl.LINES,
|
---|
| 3049 | + 'diffuseColor', edgecolor,
|
---|
| 3050 | + 'lineWidth', options.getfieldvalue('linewidth', 1),
|
---|
| 3051 | + 'maskEnabled', options.getfieldvalue('innermask','off') == 'on',
|
---|
| 3052 | + 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1),
|
---|
| 3053 | + 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]),
|
---|
| 3054 | + 'rotation', [-90, 0, 0],
|
---|
| 3055 | + 'scale', scale
|
---|
| 3056 | + );
|
---|
| 3057 | //}}}
|
---|
| 3058 | -
|
---|
| 3059 | - //Compute coordinates and data range:
|
---|
| 3060 | - var modelxlim = [ArrayMin(x), ArrayMax(x)];
|
---|
| 3061 | - var modelylim = [ArrayMin(y), ArrayMax(y)];
|
---|
| 3062 | - var modelzlim = [ArrayMin(z), ArrayMax(z)];
|
---|
| 3063 | - var xlim = options.getfieldvalue('xlim', modelxlim);
|
---|
| 3064 | - var ylim = options.getfieldvalue('ylim', modelylim);
|
---|
| 3065 | - var zlim = options.getfieldvalue('zlim', modelzlim);
|
---|
| 3066 | - xmin = xlim[0];
|
---|
| 3067 | - xmax = xlim[1];
|
---|
| 3068 | - ymin = ylim[0];
|
---|
| 3069 | - ymax = ylim[1];
|
---|
| 3070 | - zmin = zlim[0];
|
---|
| 3071 | - zmax = zlim[1];
|
---|
| 3072 | -
|
---|
| 3073 | - //Compute gl variables:
|
---|
| 3074 | - var gl = canvas.gl;
|
---|
| 3075 | - gl.makeCurrent();
|
---|
| 3076 | - var node = Node(gl);
|
---|
| 3077 | - canvas.nodes[canvas.nodes.length] = node;
|
---|
| 3078 | - node.name = "mesh";
|
---|
| 3079 | - node.shaderName = "Colored";
|
---|
| 3080 | - node.shader = gl.shaders[node.shaderName];
|
---|
| 3081 | - node.lineWidth = options.getfieldvalue('linewidth', 1);
|
---|
| 3082 | - node.scale = [1, 1, matrixscale];
|
---|
| 3083 | - node.rotation = [-90, 0, 0];
|
---|
| 3084 | - node.translation = [0, 0, 0];
|
---|
| 3085 | - node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2];
|
---|
| 3086 | - node.drawMode = gl.LINES;
|
---|
| 3087 | - node.drawOrder = 0;
|
---|
| 3088 | - node.maskEnabled = options.getfieldvalue('innermask','off') == 'on';
|
---|
| 3089 | - node.maskHeight = options.getfieldvalue('innermaskheight', 150.0)*options.getfieldvalue('heightscale', 1);
|
---|
| 3090 | - node.maskColor = options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]);
|
---|
| 3091 | - updateModelMatrix(node);
|
---|
| 3092 | -
|
---|
| 3093 | - //retrieve some options
|
---|
| 3094 | - var edgecolor = new RGBColor(options.getfieldvalue('edgecolor','black'));
|
---|
| 3095 | - if (edgecolor.ok) edgecolor = [edgecolor.r/255.0, edgecolor.g/255.0, edgecolor.b/255.0, 1.0];
|
---|
| 3096 | - else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ", canvas));
|
---|
| 3097 | -
|
---|
| 3098 | //{{{ node plot
|
---|
| 3099 | if (elements[0].length==6){ //prisms
|
---|
| 3100 | }
|
---|
| 3101 | @@ -87,53 +60,10 @@
|
---|
| 3102 | else if (elements[0].length==4){ //tetras
|
---|
| 3103 | }
|
---|
| 3104 | else{ //2D triangular elements
|
---|
| 3105 | - var xyz = vec3.create();
|
---|
| 3106 | - var direction = vec3.create();
|
---|
| 3107 | - var vertex = vec3.create();
|
---|
| 3108 | - var magnitude;
|
---|
| 3109 | - var color = edgecolor;
|
---|
| 3110 | - for(var i = 0; i < x.length; i++){
|
---|
| 3111 | - //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
|
---|
| 3112 | - if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) {
|
---|
| 3113 | - nanindices[i] = i;
|
---|
| 3114 | - vertices[vertices.length] = vertex[0];
|
---|
| 3115 | - vertices[vertices.length] = vertex[1];
|
---|
| 3116 | - vertices[vertices.length] = vertex[2];
|
---|
| 3117 | -
|
---|
| 3118 | - colors[colors.length] = color[0];
|
---|
| 3119 | - colors[colors.length] = color[1];
|
---|
| 3120 | - colors[colors.length] = color[2];
|
---|
| 3121 | - colors[colors.length] = color[3];
|
---|
| 3122 | - continue;
|
---|
| 3123 | - }
|
---|
| 3124 | - //Scale vertices
|
---|
| 3125 | - xyz = vec3.fromValues(x[i], y[i], z[i]);
|
---|
| 3126 | - magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
|
---|
| 3127 | - vec3.normalize(direction, xyz);
|
---|
| 3128 | - vec3.scale(vertex, direction, magnitude);
|
---|
| 3129 | - vertices[vertices.length] = vertex[0];
|
---|
| 3130 | - vertices[vertices.length] = vertex[1];
|
---|
| 3131 | - vertices[vertices.length] = vertex[2];
|
---|
| 3132 | -
|
---|
| 3133 | - colors[colors.length] = color[0];
|
---|
| 3134 | - colors[colors.length] = color[1];
|
---|
| 3135 | - colors[colors.length] = color[2];
|
---|
| 3136 | - colors[colors.length] = color[3];
|
---|
| 3137 | - }
|
---|
| 3138 | -
|
---|
| 3139 | - //linearize the elements array:
|
---|
| 3140 | - var element;
|
---|
| 3141 | - for(var i = 0; i < elements.length; i++){
|
---|
| 3142 | - element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];
|
---|
| 3143 | - if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;
|
---|
| 3144 | - indices[indices.length] = element[0];
|
---|
| 3145 | - indices[indices.length] = element[1];
|
---|
| 3146 | - indices[indices.length] = element[1];
|
---|
| 3147 | - indices[indices.length] = element[2];
|
---|
| 3148 | - indices[indices.length] = element[2];
|
---|
| 3149 | - indices[indices.length] = element[0];
|
---|
| 3150 | - }
|
---|
| 3151 | + node.patch('Faces', elements, 'Vertices', vertices, 'FaceColor', 'none', 'EdgeColor', edgecolor);
|
---|
| 3152 | }
|
---|
| 3153 | //}}}
|
---|
| 3154 | - node.mesh = GL.Mesh.load({vertices: vertices, colors: colors, triangles: indices}, null, null, gl);
|
---|
| 3155 | + //options=options.addfielddefault('title','Mesh');
|
---|
| 3156 | + //options=addfielddefault('colorbar','off');
|
---|
| 3157 | + //applyoptions(md,[],options,canvas);
|
---|
| 3158 | } //}}}
|
---|
| 3159 | Index: ../trunk-jpl/src/m/classes/clusters/generic.js
|
---|
| 3160 | ===================================================================
|
---|
| 3161 | --- ../trunk-jpl/src/m/classes/clusters/generic.js (revision 21767)
|
---|
| 3162 | +++ ../trunk-jpl/src/m/classes/clusters/generic.js (revision 21768)
|
---|
| 3163 | @@ -171,4 +171,4 @@
|
---|
| 3164 | }
|
---|
| 3165 | return buf;
|
---|
| 3166 | } //}}}
|
---|
| 3167 | -}
|
---|
| 3168 | +}
|
---|