Skip to content

Commit

Permalink
Added mode to render only when needed
Browse files Browse the repository at this point in the history
  • Loading branch information
mkkellogg committed Mar 11, 2024
1 parent 6298b67 commit d67297b
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 11 deletions.
5 changes: 5 additions & 0 deletions src/RenderMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const RenderMode = {
Always: 0,
OnChange: 1,
Never: 2
};
4 changes: 4 additions & 0 deletions src/SceneHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ export class SceneHelper {
this.meshCursor.visible = visible;
}

getMeschCursorVisibility() {
return this.meshCursor.visible;
}

setMeshCursorPosition(position) {
this.meshCursor.position.copy(position);
}
Expand Down
2 changes: 2 additions & 0 deletions src/SplatMesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class SplatMesh extends THREE.Mesh {
this.maxRadius = 0;
this.visibleRegionRadius = 0;
this.visibleRegionFadeStartRadius = 0;
this.visibleRegionChanging = false;

this.disposed = false;
}
Expand Down Expand Up @@ -921,6 +922,7 @@ export class SplatMesh extends THREE.Mesh {
this.material.uniforms.currentTime.value = performance.now();
this.material.uniforms.fadeInComplete.value = fadeInComplete;
this.material.uniformsNeedUpdate = true;
this.visibleRegionChanging = !fadeInComplete;
}

/**
Expand Down
84 changes: 74 additions & 10 deletions src/Viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ import { VRButton } from './webxr/VRButton.js';
import { ARButton } from './webxr/ARButton.js';
import { delayedExecute } from './Util.js';
import { LoaderStatus } from './loaders/LoaderStatus.js';

import { RenderMode } from './RenderMode.js';

const THREE_CAMERA_FOV = 50;
const MINIMUM_DISTANCE_TO_NEW_FOCAL_POINT = .75;
const MIN_SPLAT_COUNT_TO_SHOW_SPLAT_TREE_LOADING_SPINNER = 1500000;
const FOCUS_MARKER_FADE_IN_SPEED = 10.0;
const FOCUS_MARKER_FADE_OUT_SPEED = 2.5;
const CONSECUTIVE_RENDERED_FRAMES_FOR_FPS_CALCULATION = 60;

/**
* Viewer: Manages the rendering of splat scenes. Manages an instance of SplatMesh as well as a web worker
Expand Down Expand Up @@ -121,6 +122,8 @@ export class Viewer {
this.gpuAcceleratedSort = false;
}

this.renderMode = options.renderMode || RenderMode.Always;

this.controls = null;

this.showMeshCursor = false;
Expand All @@ -147,6 +150,7 @@ export class Viewer {

this.currentFPS = 0;
this.lastSortTime = 0;
this.consecutiveRenderFrames = 0;

this.previousCameraTarget = new THREE.Vector3();
this.nextCameraTarget = new THREE.Vector3();
Expand Down Expand Up @@ -283,6 +287,10 @@ export class Viewer {
}
}

setRenderMode(renderMode) {
this.renderMode = renderMode;
}

onKeyDown = function() {

const forward = new THREE.Vector3();
Expand Down Expand Up @@ -941,6 +949,7 @@ export class Viewer {
this.sortPromiseResolver();
this.sortPromise = null;
this.sortPromiseResolver = null;
this.forceRenderNextFrame();
if (sortCount === 0) {
this.runAfterFirstSort.forEach((func) => {
func();
Expand Down Expand Up @@ -1088,13 +1097,60 @@ export class Viewer {
this.requestFrameId = requestAnimationFrame(this.selfDrivenUpdateFunc);
}
this.update();
this.render();
if (this.shouldRender()) {
this.render();
this.consecutiveRenderFrames++;
} else {
this.consecutiveRenderFrames = 0;
}
this.renderNextFrame = false;
}

forceRenderNextFrame() {
this.renderNextFrame = true;
}

shouldRender = function() {

let renderCount = 0;
const lastCameraPosition = new THREE.Vector3();
const lastCameraOrientation = new THREE.Quaternion();
const changeEpsilon = 0.0001;

return function() {
let shouldRender = false;
let cameraChanged = false;
if (this.camera) {
const cp = this.camera.position;
const co = this.camera.quaternion;
cameraChanged = Math.abs(cp.x - lastCameraPosition.x) > changeEpsilon ||
Math.abs(cp.y - lastCameraPosition.y) > changeEpsilon ||
Math.abs(cp.z - lastCameraPosition.z) > changeEpsilon ||
Math.abs(co.x - lastCameraOrientation.x) > changeEpsilon ||
Math.abs(co.y - lastCameraOrientation.y) > changeEpsilon ||
Math.abs(co.z - lastCameraOrientation.z) > changeEpsilon ||
Math.abs(co.w - lastCameraOrientation.w) > changeEpsilon;
}

shouldRender = this.renderMode !== RenderMode.Never && (renderCount === 0 || this.splatMesh.visibleRegionChanging ||
cameraChanged || this.renderMode === RenderMode.Always || this.dynamicMode === true || this.renderNextFrame);

if (this.camera) {
lastCameraPosition.copy(this.camera.position);
lastCameraOrientation.copy(this.camera.quaternion);
}

renderCount++;
return shouldRender;
};

}();

render = function() {

return function() {
if (!this.initialized || !this.splatRenderingInitialized) return;

const hasRenderables = (threeScene) => {
for (let child of threeScene.children) {
if (child.visible) return true;
Expand Down Expand Up @@ -1141,14 +1197,18 @@ export class Viewer {
let frameCount = 0;

return function() {
const currentTime = getCurrentTime();
const calcDelta = currentTime - lastCalcTime;
if (calcDelta >= 1.0) {
this.currentFPS = frameCount;
frameCount = 0;
lastCalcTime = currentTime;
if (this.consecutiveRenderFrames > CONSECUTIVE_RENDERED_FRAMES_FOR_FPS_CALCULATION) {
const currentTime = getCurrentTime();
const calcDelta = currentTime - lastCalcTime;
if (calcDelta >= 1.0) {
this.currentFPS = frameCount;
frameCount = 0;
lastCalcTime = currentTime;
} else {
frameCount++;
}
} else {
frameCount++;
this.currentFPS = null;
}
};

Expand Down Expand Up @@ -1227,6 +1287,7 @@ export class Viewer {
this.sceneHelper.setFocusMarkerOpacity(newFocusMarkerOpacity);
this.sceneHelper.updateFocusMarker(this.nextCameraTarget, this.camera, renderDimensions);
wasTransitioning = true;
this.forceRenderNextFrame();
} else {
let currentFocusMarkerOpacity;
if (wasTransitioning) currentFocusMarkerOpacity = 1.0;
Expand All @@ -1237,6 +1298,7 @@ export class Viewer {
this.sceneHelper.setFocusMarkerOpacity(newFocusMarkerOpacity);
if (newFocusMarkerOpacity === 0.0) this.sceneHelper.setFocusMarkerVisibility(false);
}
if (currentFocusMarkerOpacity > 0.0) this.forceRenderNextFrame();
wasTransitioning = false;
}
};
Expand All @@ -1250,6 +1312,7 @@ export class Viewer {

return function() {
if (this.showMeshCursor) {
this.forceRenderNextFrame();
this.getRenderDimensions(renderDimensions);
outHits.length = 0;
this.raycaster.setFromCameraAndScreenPosition(this.camera, this.mousePosition, renderDimensions);
Expand All @@ -1261,6 +1324,7 @@ export class Viewer {
this.sceneHelper.setMeshCursorVisibility(false);
}
} else {
if (this.sceneHelper.getMeschCursorVisibility()) this.forceRenderNextFrame();
this.sceneHelper.setMeshCursorVisibility(false);
}
};
Expand All @@ -1279,7 +1343,7 @@ export class Viewer {
const meshCursorPosition = this.showMeshCursor ? this.sceneHelper.meshCursor.position : null;
const splatRenderCountPct = this.splatRenderCount / splatCount * 100;
this.infoPanel.update(renderDimensions, this.camera.position, cameraLookAtPosition,
this.camera.up, meshCursorPosition, this.currentFPS, splatCount,
this.camera.up, meshCursorPosition, this.currentFPS || 'N/A', splatCount,
this.splatRenderCount, splatRenderCountPct, this.lastSortTime);
};

Expand Down
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { OrbitControls } from './OrbitControls.js';
import { AbortablePromise } from './AbortablePromise.js';
import { SceneFormat } from './loaders/SceneFormat.js';
import { WebXRMode } from './webxr/WebXRMode.js';
import { RenderMode } from './RenderMode.js';

export {
PlyParser,
Expand All @@ -29,5 +30,6 @@ export {
OrbitControls,
AbortablePromise,
SceneFormat,
WebXRMode
WebXRMode,
RenderMode
};

0 comments on commit d67297b

Please sign in to comment.