Skip to content

Commit

Permalink
Merge pull request #32 from open-pv/feature/smooth-progress-bars
Browse files Browse the repository at this point in the history
Feature/smooth progress bars
  • Loading branch information
khdlr authored Sep 14, 2024
2 parents aa3e702 + a2adb26 commit 3b8dfd5
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 39 deletions.
18 changes: 8 additions & 10 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,23 +190,21 @@ export class ShadingScene {
// Compute unique intensities
console.log('Calling this.rayTrace');

const doDiffuseIntensities = typeof diffuseIrradianceURL === 'string';
const simulationRounds = doDiffuseIntensities ? 2 : 1;

const directIntensities = await this.rayTrace(
midpointsArray,
normalsArray,
meshArray,
numberSimulations,
undefined,
progressCallback,
(i, total) => progressCallback(i, total * simulationRounds),
);
let diffuseIntensities = new Float32Array();
if (typeof diffuseIrradianceURL === 'string') {
diffuseIntensities = await this.rayTrace(
midpointsArray,
normalsArray,
meshArray,
0,
diffuseIrradianceURL,
progressCallback,
if (doDiffuseIntensities) {
diffuseIntensities = await this.rayTrace(midpointsArray, normalsArray, meshArray, 0, diffuseIrradianceURL, (i, total) =>
progressCallback(i + total, total * simulationRounds),
);
}

Expand Down Expand Up @@ -298,7 +296,7 @@ export class ShadingScene {
sun.shadeIrradianceFromElevation(irradiance, shadingElevationAngles);
}
normals = normals.filter((_, index) => index % 9 < 3);
let intensities = rayTracingWebGL(midpoints, normals, meshArray, irradiance, progressCallback);
let intensities = await rayTracingWebGL(midpoints, normals, meshArray, irradiance, progressCallback);

if (intensities === null) {
throw new Error('Error occured when running the Raytracing in WebGL.');
Expand Down
57 changes: 28 additions & 29 deletions src/rayTracingWebGL.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { TypedArray } from 'three';
import { Point, SunVector } from './utils';
import { Point, SunVector, timeoutForLoop } from './utils';

function addToArray(ar1: Float32Array, ar2: Float32Array) {
for (var i = 0; i < ar1.length; i++) {
ar1[i] += ar2[i];
}
}

export function rayTracingWebGL(
export async function rayTracingWebGL(
pointsArray: TypedArray,
normals: TypedArray,
trianglesArray: TypedArray,
irradiance: SunVector[],
progressCallback: (progress: number, total: number) => void,
): Float32Array | null {
): Promise<Float32Array | null> {
const N_TRIANGLES = trianglesArray.length / 9;
const width = pointsArray.length / 3; // Change this to the number of horizontal points in the grid
const N_POINTS = width;
Expand Down Expand Up @@ -181,33 +181,32 @@ export function rayTracingWebGL(
var colorCodedArray = null;
var isShadowedArray = null;

for (var i = 0; i < irradiance.length; i += 1) {
if (irradiance[i].isShadedByElevation) {
continue;
}
progressCallback(i, irradiance.length);

// TODO: Iterate over sunDirection
let sunDirectionUniformLocation = gl.getUniformLocation(program, 'u_sun_direction');
gl.uniform3fv(sunDirectionUniformLocation, [
irradiance[i].vector.cartesian.x,
irradiance[i].vector.cartesian.y,
irradiance[i].vector.cartesian.z,
]);

drawArraysWithTransformFeedback(gl, tf, gl.POINTS, N_POINTS);

if (isShadowedArray == null) {
colorCodedArray = getResults(gl, colorBuffer, N_POINTS);
isShadowedArray = colorCodedArray.filter((_, index) => (index + 1) % 4 === 0);
} else {
colorCodedArray = getResults(gl, colorBuffer, N_POINTS);
addToArray(
isShadowedArray,
colorCodedArray.filter((_, index) => (index + 1) % 4 === 0),
);
await timeoutForLoop(0, irradiance.length, (i) => {
if (!irradiance[i].isShadedByElevation) {
progressCallback(i, irradiance.length);

// TODO: Iterate over sunDirection
let sunDirectionUniformLocation = gl.getUniformLocation(program, 'u_sun_direction');
gl.uniform3fv(sunDirectionUniformLocation, [
irradiance[i].vector.cartesian.x,
irradiance[i].vector.cartesian.y,
irradiance[i].vector.cartesian.z,
]);

drawArraysWithTransformFeedback(gl, tf, gl.POINTS, N_POINTS);

if (isShadowedArray == null) {
colorCodedArray = getResults(gl, colorBuffer, N_POINTS);
isShadowedArray = colorCodedArray.filter((_, index) => (index + 1) % 4 === 0);
} else {
colorCodedArray = getResults(gl, colorBuffer, N_POINTS);
addToArray(
isShadowedArray,
colorCodedArray.filter((_, index) => (index + 1) % 4 === 0),
);
}
}
}
});
gl.deleteTexture(texture);
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
Expand Down
19 changes: 19 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,22 @@ export interface CalculateParams {
urlDiffuseIrrandianceTIF?: string;
progressCallback?: (progress: number, total: number) => void;
}

/**
* Mimics a for-loop but schedules each loop iteration using `setTimeout`, so that
* event handles, react updates, etc. can run in-between
*/
export async function timeoutForLoop(start: number, end: number, body: (i: number) => void) {
return new Promise<void>((resolve) => {
const inner = (i: number) => {
body(i);
i = i + 1;
if (i == end) {
resolve();
} else {
setTimeout(() => inner(i), 0);
}
};
setTimeout(() => inner(0), 0);
});
}

0 comments on commit 3b8dfd5

Please sign in to comment.