Skip to content

Commit 03873b1

Browse files
committed
updates bump map alpha and particle array handling
1 parent d923875 commit 03873b1

File tree

5 files changed

+125
-88
lines changed

5 files changed

+125
-88
lines changed

js/bumpMap.js

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const ADD_BUMPMAP = true;
1818
const ADD_CONTOURS = false;
1919

2020
// factor to scale alpha of bump map texture
21-
const BUMPMAP_STRENGTH = 0.7;
21+
const BUMPMAP_ALPHA = 0.6;
2222

2323
// hillshading
2424
const ADD_HILLSHADE = true;
@@ -383,9 +383,6 @@ function updateBumpMap(projection,width,height,visiblePoints,dx,dy){
383383
//if (val < 0.0) { val = 0.0; }
384384
//if (val > 1.0) { val = 1.0; }
385385

386-
// strength scaling
387-
val *= BUMPMAP_STRENGTH;
388-
389386
// sets new scaled brightness value
390387
point[2] = val;
391388
});
@@ -681,16 +678,6 @@ function getPointColor(brightness) {
681678
//const color = d3.interpolatePuBu(1 - brightness);
682679
const color = d3.interpolateGreys(1 - brightness); // from 0 == white to 1 == black
683680

684-
// add overall alpha to bump map texture - this will increase rendering time... will scale brightness instead
685-
//if (BUMPMAP_STRENGTH < 1.0) {
686-
// color = d3.color(color).copy({opacity: BUMPMAP_STRENGTH});
687-
//}
688-
689-
// discrete
690-
//const colorScale = d3.scaleOrdinal(d3.schemePuBuGn[8]); // not working...
691-
//const colorScale = d3.scaleSequential(d3.interpolateBlues);
692-
//const color = colorScale(1-brightness);
693-
694681
return color;
695682
}
696683

@@ -710,6 +697,9 @@ function drawBumpMap(projection, context){
710697

711698
projection.clipAngle(90);
712699

700+
// add global transparency
701+
context.globalAlpha = BUMPMAP_ALPHA;
702+
713703
// draw texture
714704
pointsView.forEach(point => {
715705
// gets ix/iy, lon/lat and brightness of point position
@@ -730,6 +720,9 @@ function drawBumpMap(projection, context){
730720
context.stroke();
731721
});
732722

723+
// Reset the globalAlpha to 1.0 (fully opaque) for future operations
724+
context.globalAlpha = 1.0;
725+
733726
console.timeEnd('drawBumpMap');
734727
}
735728

js/particles.js

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const ADD_PARTICLES = true;
1616

1717
// total number of particles
1818
let numParticles = 10000;
19-
const USE_VARIABLE_NUMPARTICLES = false;
19+
20+
const USE_VARIABLE_NUMPARTICLES = true;
2021

2122
// maximum particle age
2223
const maxAge = 80;
@@ -46,6 +47,9 @@ let vCenter = null; // position vector for center point
4647
// constants
4748
const DEGREE_TO_RADIAN = Math.PI / 180;
4849

50+
// pre-allocate vector
51+
const vector = new Float32Array(2);
52+
4953
// Initialize particles
5054
function initializeParticles() {
5155
// checks if anything to do
@@ -127,15 +131,14 @@ function createParticle(i) {
127131
// moves points according to vector field:
128132
// vx - x direction == lon
129133
// vy - y direction == lat
130-
let vx, vy;
131-
({ vx,vy } = vectorField.getVectorField(lon, lat));
134+
vectorField.getVectorField(lon, lat, vector);
132135

133136
// check if valid
134-
if (!vx || !vy){ return; }
137+
if (!vector[0] || !vector[1]){ return; }
135138

136139
// scale velocities
137-
vx *= VELOCITY_FACTOR;
138-
vy *= VELOCITY_FACTOR;
140+
vector[0] *= VELOCITY_FACTOR; // vx
141+
vector[1] *= VELOCITY_FACTOR; // vy
139142

140143
// or simple vector field
141144
//const lonRad = lon * DEGREE_TO_RADIAN;
@@ -156,8 +159,8 @@ function createParticle(i) {
156159

157160
particles[index] = lon; // lon
158161
particles[index + 1] = lat; // lat
159-
particles[index + 2] = vx; // vx
160-
particles[index + 3] = vy; // vy
162+
particles[index + 2] = vector[0]; // vx
163+
particles[index + 3] = vector[1]; // vy
161164
particles[index + 4] = age; // age
162165
}
163166

@@ -224,7 +227,7 @@ function determineBoundsLonLat(projection,width,height){
224227
// set new bounds
225228
bounds = { lonMin, lonMax, latMin, latMax };
226229

227-
console.log(`determineBoundsLonLat: bounds lon: min/max = ${lonMin}/${lonMax} lat: min/max = ${latMin}/${latMax}`);
230+
//console.log(`determineBoundsLonLat: bounds lon: min/max = ${lonMin}/${lonMax} lat: min/max = ${latMin}/${latMax}`);
228231
}
229232

230233
function updateParticles(projection,width,height) {
@@ -237,7 +240,7 @@ function updateParticles(projection,width,height) {
237240
if (! vectorField.isGradientValid()) return;
238241

239242
//console.time('updateParticles')
240-
console.log(`updateParticles: width/height ${width}/${height}`);
243+
//console.log(`updateParticles: width/height ${width}/${height}`);
241244

242245
// context for animation drawing
243246
//const context = d3.select("#animation").node().getContext("2d");
@@ -274,22 +277,25 @@ function updateParticles(projection,width,height) {
274277
// adapt number of particles to view range
275278
if (USE_VARIABLE_NUMPARTICLES) {
276279
// estimate number of particles based on window size
277-
let estimate = 10 * Math.max(width,height);
278-
console.log(`updateParticles: numParticles ${numParticles} estimate window size ${estimate}`);
280+
//let estimate = 10 * Math.max(width,height);
281+
//console.log(`updateParticles: numParticles ${numParticles} estimate window size ${estimate}`);
279282

280283
// estimate based on bounds range
281-
estimate = (bounds.lonMax - bounds.lonMin) * (bounds.latMax - bounds.latMin);
282-
console.log(`updateParticles: numParticles ${numParticles} estimate bounds range ${estimate}`);
284+
//estimate = (bounds.lonMax - bounds.lonMin) * (bounds.latMax - bounds.latMin);
285+
//console.log(`updateParticles: numParticles ${numParticles} estimate bounds range ${estimate}`);
283286

284-
if (estimate > 20000) {
285-
numParticles = 20000;
286-
} else {
287-
numParticles = 10000;
288-
}
287+
//if (estimate > 20000) {
288+
// numParticles = 20000;
289+
//} else {
290+
// numParticles = 10000;
291+
//}
292+
293+
// check pixel size limit 100 x 100 == 10,000
294+
if (width * height < numParticles) numParticles = Math.floor(width * height * 0.7);
289295

290296
// check if we need to recreate the array
291297
if (particles.length != numParticles * 5) {
292-
console.log(`updateParticles: recreate numParticles * 5 = ${numParticles * 5} particles length = ${particles.length}`);
298+
//console.log(`updateParticles: recreate numParticles * 5 = ${numParticles * 5} particles length = ${particles.length}`);
293299
// re-create new array
294300
particles = new Float32Array(numParticles * 5); // x, y, vx, vy, age
295301
}
@@ -349,18 +355,14 @@ function moveParticles() {
349355
let lon = particles[index];
350356
let lat = particles[index + 1];
351357

352-
let vx,vy;
353-
({ vx, vy } = vectorField.getVectorField(lon, lat));
358+
vectorField.getVectorField(lon, lat, vector);
354359

355360
// check if valid
356-
if (!vx || !vy){ return; }
361+
if (!vector[0] || !vector[1]){ return; }
357362

358363
// scale velocities
359-
vx *= VELOCITY_FACTOR;
360-
vy *= VELOCITY_FACTOR;
361-
362-
particles[index + 2] = vx;
363-
particles[index + 3] = vy;
364+
particles[index + 2] = vector[0] * VELOCITY_FACTOR; // vx
365+
particles[index + 3] = vector[1] * VELOCITY_FACTOR; // vy
364366

365367
// ageing
366368
let age = particles[index + 4];
@@ -441,6 +443,12 @@ function drawParticles(projection, context, width, height) {
441443
colorBuckets[color].length = 0; // set length to zero to avoid costly garbage collection
442444
});
443445

446+
// position vectors
447+
const p0 = [0, 0];
448+
const p1 = [0, 0];
449+
const v0 = [0, 0, 0];
450+
const v1 = [0, 0, 0];
451+
444452
// fill color buckets
445453
for (let i = 0; i < particles.length; i++) {
446454
const index = i * 5;
@@ -457,6 +465,9 @@ function drawParticles(projection, context, width, height) {
457465
const vx = particles[index + 2];
458466
const vy = particles[index + 3];
459467

468+
// velocity strength
469+
const normSq = (vx * vx + vy * vy) / VELOCITY_FACTOR; // in [0,1]
470+
460471
// updated position
461472
const lon1 = lon0 + vx;
462473
const lat1 = lat0 + vy;
@@ -465,35 +476,36 @@ function drawParticles(projection, context, width, height) {
465476
// current point location vector
466477
const lonRad = lon0 * DEGREE_TO_RADIAN;
467478
const latRad = lat0 * DEGREE_TO_RADIAN;
468-
const v0 = [ Math.cos(latRad) * Math.cos(lonRad), Math.cos(latRad) * Math.sin(lonRad), Math.sin(latRad) ];
479+
v0[0] = Math.cos(latRad) * Math.cos(lonRad);
480+
v0[1] = Math.cos(latRad) * Math.sin(lonRad);
481+
v0[2] = Math.sin(latRad);
469482

470483
const lonRad1 = lon1 * DEGREE_TO_RADIAN;
471484
const latRad1 = lat1 * DEGREE_TO_RADIAN;
472-
const v1 = [ Math.cos(latRad1) * Math.cos(lonRad1), Math.cos(latRad1) * Math.sin(lonRad1), Math.sin(latRad1) ];
485+
v1[0] = Math.cos(latRad1) * Math.cos(lonRad1);
486+
v1[1] = Math.cos(latRad1) * Math.sin(lonRad1);
487+
v1[2] = Math.sin(latRad1);
473488

474489
if(! isPointVisibleHemisphere(vCenter,v0)) { continue; }
475490
if(! isPointVisibleHemisphere(vCenter,v1)) { continue; }
476491

477492
// converted to x/y pixel indexing
478-
const p0 = projection([lon0,lat0]);
479-
const p1 = projection([lon1,lat1]);
493+
//([p0[0],p0[1]] = projection([lon0,lat0]));
494+
//([p1[0],p1[1]] = projection([lon1,lat1]));
480495

481496
// check if valid
482-
if (!p0 || isNaN(p0[0]) || isNaN(p0[1])) { continue; }
483-
if (!p1 || isNaN(p1[0]) || isNaN(p1[1])) { continue; }
497+
//if (!p0 || isNaN(p0[0]) || isNaN(p0[1])) { continue; }
498+
//if (!p1 || isNaN(p1[0]) || isNaN(p1[1])) { continue; }
484499

485500
// line points
486-
const [x0,y0] = p0;
487-
const [x1,y1] = p1;
501+
//const [x0,y0] = p0;
502+
//const [x1,y1] = p1;
488503

489504
// check if point is visible area
490505
// doesn't work, returned [x,y] pixel positions are all within globe area...
491506
//if (! isPointClose([x0,y0])) { continue; }
492507
//if (! isPointClose([x1,y1])) { continue; }
493508

494-
// velocity strength
495-
const normSq = (vx * vx + vy * vy) / VELOCITY_FACTOR; // in [0,1]
496-
497509
// coloring
498510
// convert norm to rgb gray scale value
499511
//const val = 155 + Math.floor( normSq * 100.0 );
@@ -517,12 +529,10 @@ function drawParticles(projection, context, width, height) {
517529
const color = colorScale(normSq);
518530

519531
// If this color doesn't have a bucket yet, create an empty array for it
520-
if (!colorBuckets[color]) {
521-
colorBuckets[color] = [];
522-
}
532+
//if (!colorBuckets[color]) { colorBuckets[color] = []; }
523533

524534
// Add the particle to the appropriate color bucket
525-
colorBuckets[color].push([x0,y0,x1,y1]);
535+
colorBuckets[color].push(index);
526536
} // age
527537
}
528538

@@ -535,17 +545,46 @@ function drawParticles(projection, context, width, height) {
535545
if (bucketParticles.length == 0) return;
536546

537547
// draw bucket
538-
context.beginPath();
539-
context.strokeStyle = color;
540-
context.lineWidth = lineWidth; //particleSize;
548+
//context.beginPath();
549+
//context.strokeStyle = color;
550+
//context.lineWidth = lineWidth; //particleSize;
551+
//bucketParticles.forEach(([x0,y0,x1,y1]) => {
552+
// // line
553+
// context.moveTo(x0, y0);
554+
// context.lineTo(x1, y1);
555+
//});
556+
//context.stroke();
557+
558+
const path = new Path2D();
559+
bucketParticles.forEach(index => {
560+
// initial position
561+
// lon/lat positions
562+
const lon0 = particles[index];
563+
const lat0 = particles[index + 1];
564+
565+
const vx = particles[index + 2];
566+
const vy = particles[index + 3];
541567

542-
bucketParticles.forEach(([x0,y0,x1,y1]) => {
543-
// line
544-
context.moveTo(x0, y0);
545-
context.lineTo(x1, y1);
568+
// updated position
569+
const lon1 = lon0 + vx;
570+
const lat1 = lat0 + vy;
571+
572+
// converted to x/y pixel indexing
573+
([p0[0],p0[1]] = projection([lon0,lat0]));
574+
([p1[0],p1[1]] = projection([lon1,lat1]));
575+
576+
// check if valid
577+
if (!p0 || isNaN(p0[0]) || isNaN(p0[1])) { return; }
578+
if (!p1 || isNaN(p1[0]) || isNaN(p1[1])) { return; }
579+
580+
// add line to path
581+
path.moveTo(p0[0], p0[1]);
582+
path.lineTo(p1[0], p1[1]);
546583
});
584+
context.strokeStyle = color;
585+
context.lineWidth = lineWidth;
586+
context.stroke(path); // stroke the entire path at once
547587

548-
context.stroke();
549588
});
550589

551590
// timing

js/streamlines.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ let nLonSteps = 0, nLatSteps = 0;
3333
// constants
3434
const DEGREE_TO_RADIAN = Math.PI / 180;
3535

36+
// pre-allocate vector
37+
const vector = new Float32Array(2);
3638

3739
// Initialize streamlines
3840
function initializeStreamlines() {
@@ -129,11 +131,10 @@ function createPath(n) {
129131
// moves points according to vector field:
130132
// vx - x direction == lon
131133
// vy - y direction == lat
132-
let vx, vy;
133-
({ vx,vy } = vectorField.getVectorField(lon, lat));
134+
vectorField.getVectorField(lon, lat, vector);
134135

135136
// check if valid
136-
if (!vx || !vy){ return; }
137+
if (!vector[0] || !vector[1]){ return; }
137138

138139
// or simple vector field
139140
//const lonRad = lon * DEGREE_TO_RADIAN;
@@ -144,7 +145,7 @@ function createPath(n) {
144145
// check velocity
145146
if (! useRegularLocations) {
146147
// if particle doesn't move, re-create path
147-
const norm = (vx*vx + vy*vy);
148+
const norm = (vector[0]*vector[0] + vector[1]*vector[1]);
148149
if (norm == 0.0) { createPath(n); }
149150
}
150151

@@ -153,19 +154,19 @@ function createPath(n) {
153154
const i = n * numPathLength + m;
154155

155156
// add streamline position
156-
streamlines[i * 4] = lon; // x or lon
157-
streamlines[i * 4 + 1] = lat; // y or lat
158-
streamlines[i * 4 + 2] = vx; // vx
159-
streamlines[i * 4 + 3] = vy; // vy
157+
streamlines[i * 4] = lon; // x or lon
158+
streamlines[i * 4 + 1] = lat; // y or lat
159+
streamlines[i * 4 + 2] = vector[0]; // vx
160+
streamlines[i * 4 + 3] = vector[1]; // vy
160161

161162
// updates position
162-
lon += vx;
163-
lat += vy;
163+
lon += vector[0];
164+
lat += vector[1];
164165

165166
// updates velocity direction
166-
({ vx,vy } = vectorField.getVectorField(lon, lat));
167+
vectorField.getVectorField(lon, lat, vector);
167168
// check if valid
168-
if (!vx || !vy){ return; }
169+
if (!vector[0] || !vector[1]){ return; }
169170
}
170171
}
171172

0 commit comments

Comments
 (0)