Skip to content

Commit d698876

Browse files
committed
Rendering/Update events
1 parent a99bc64 commit d698876

File tree

5 files changed

+148
-40
lines changed

5 files changed

+148
-40
lines changed

CHANGES.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ Change Log
33

44
### 1.42 - 2017-02-01
55

6-
* Added optional scene request render mode to reduce CPU usage
7-
* `scene.requestRenderMode` enables a mode which will only request new render frames on changes to the scene, or when the simulation time change exceeds `scene.maximumRenderTimeChange`.
6+
* Breaking changes
7+
* `scene.preRender` and `scene.postRender` events are called immediately before and after scene rendering only if the scene renders a frame. See `scene.requestRenderMode`. Use `scene.preUpdate` and `scene.postUpdate` for task that require regular updates.
8+
* Added optional scene request render mode to reduce CPU usage. [#6065](https://github.com/AnalyticalGraphicsInc/cesium/pull/6065)
9+
* `scene.requestRenderMode` enables a mode which will only request new render frames on changes to the scene, or when the simulation time change exceeds `scene.maximumRenderTimeChange`.
810
* `scene.requestRender` will explicitly request a new render frame when in request render mode.
11+
* Added `scene.preUpdate` and `scene.postUpdate` events that are raised before and after the scene updates respectively. The scene is always updated before executing a potential render.
912

1013
### 1.41 - 2017-01-02
1114

Source/Scene/FrameRateMonitor.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ define([
9898
this._pauseCount = 0;
9999

100100
var that = this;
101-
this._preRenderRemoveListener = this._scene.preRender.addEventListener(function(scene, time) {
101+
this._preUpdateRemoveListener = this._scene.preUpdate.addEventListener(function(scene, time) {
102102
update(that, time);
103103
});
104104

@@ -274,7 +274,7 @@ define([
274274
* @see FrameRateMonitor#isDestroyed
275275
*/
276276
FrameRateMonitor.prototype.destroy = function() {
277-
this._preRenderRemoveListener();
277+
this._preUpdateRemoveListener();
278278

279279
if (defined(this._visibilityChangeRemoveListener)) {
280280
this._visibilityChangeRemoveListener();

Source/Scene/Scene.js

+84-32
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@ define([
339339

340340
this._transitioner = new SceneTransitioner(this);
341341

342+
this._preUpdate = new Event();
343+
this._postUpdate = new Event();
344+
342345
this._renderError = new Event();
343346
this._preRender = new Event();
344347
this._postRender = new Event();
@@ -1024,6 +1027,45 @@ define([
10241027
}
10251028
},
10261029

1030+
/**
1031+
* Gets the event that will be raised before the scene is updated or rendered. Subscribers to the event
1032+
* receive the Scene instance as the first parameter and the current time as the second parameter.
1033+
* @memberof Scene.prototype
1034+
*
1035+
* @see scene#postUpdate
1036+
* @see scene#preRender
1037+
* @see scene#postRender
1038+
* @see scene#render
1039+
*
1040+
* @type {Event}
1041+
* @readonly
1042+
*/
1043+
preUpdate : {
1044+
get : function() {
1045+
return this._preUpdate;
1046+
}
1047+
},
1048+
1049+
/**
1050+
* Gets the event that will be raised immediately after the scene is updated and before the scene is rendered.
1051+
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
1052+
* parameter.
1053+
* @memberof Scene.prototype
1054+
*
1055+
* @see scene#preUpdate
1056+
* @see scene#preRender
1057+
* @see scene#postRender
1058+
* @see scene#render
1059+
*
1060+
* @type {Event}
1061+
* @readonly
1062+
*/
1063+
postUpdate : {
1064+
get : function() {
1065+
return this._postUpdate;
1066+
}
1067+
},
1068+
10271069
/**
10281070
* Gets the event that will be raised when an error is thrown inside the <code>render</code> function.
10291071
* The Scene instance and the thrown error are the only two parameters passed to the event handler.
@@ -1041,10 +1083,16 @@ define([
10411083
},
10421084

10431085
/**
1044-
* Gets the event that will be raised at the start of each call to <code>render</code>. Subscribers to the event
1045-
* receive the Scene instance as the first parameter and the current time as the second parameter.
1086+
* Gets the event that will be raised after the scene is updated and immediately before the scene is rendered.
1087+
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
1088+
* parameter.
10461089
* @memberof Scene.prototype
10471090
*
1091+
* @see scene#preUpdate
1092+
* @see scene#postUpdate
1093+
* @see scene#postRender
1094+
* @see scene#render
1095+
*
10481096
* @type {Event}
10491097
* @readonly
10501098
*/
@@ -1055,10 +1103,15 @@ define([
10551103
},
10561104

10571105
/**
1058-
* Gets the event that will be raised at the end of each call to <code>render</code>. Subscribers to the event
1106+
* Gets the event that will be raised immediately after the scene is rendered. Subscribers to the event
10591107
* receive the Scene instance as the first parameter and the current time as the second parameter.
10601108
* @memberof Scene.prototype
10611109
*
1110+
* @see scene#preUpdate
1111+
* @see scene#postUpdate
1112+
* @see scene#postRender
1113+
* @see scene#render
1114+
*
10621115
* @type {Event}
10631116
* @readonly
10641117
*/
@@ -2787,7 +2840,7 @@ define([
27872840
}
27882841
}
27892842

2790-
function callAfterRenderFunctions(frameState) {
2843+
function callAfterRenderCycleFunctions(frameState) {
27912844
// Functions are queued up during primitive update and executed here in case
27922845
// the function modifies scene state that should remain constant over the frame.
27932846
var functions = frameState.afterRender;
@@ -2860,14 +2913,7 @@ define([
28602913
}
28612914

28622915
function update(scene, time) {
2863-
var frameState = scene._frameState;
2864-
2865-
scene._groundPrimitives.update(frameState);
2866-
scene._primitives.update(frameState);
2867-
2868-
if (defined(scene.globe)) {
2869-
scene.globe.update(frameState);
2870-
}
2916+
// TODO: Update primitives, including globe
28712917
}
28722918

28732919
function render(scene, time) {
@@ -2922,6 +2968,18 @@ define([
29222968
context.endFrame();
29232969
}
29242970

2971+
function tryAndCatchError(scene, time, functionToExecute) {
2972+
try {
2973+
functionToExecute(scene, time);
2974+
} catch (error) {
2975+
scene._renderError.raiseEvent(scene, error);
2976+
2977+
if (scene.rethrowRenderErrors) {
2978+
throw error;
2979+
}
2980+
}
2981+
}
2982+
29252983
/**
29262984
* @private
29272985
*/
@@ -2930,39 +2988,33 @@ define([
29302988
time = JulianDate.now();
29312989
}
29322990

2933-
this._preRender.raiseEvent(this, time);
29342991
this._jobScheduler.resetBudgets();
29352992

2936-
var cameraChanged = checkForCameraUpdates(this);
2993+
// Update
2994+
this._preUpdate.raiseEvent(this, time);
2995+
tryAndCatchError(this, time, update);
2996+
this._postUpdate.raiseEvent(this, time);
29372997

2998+
var cameraChanged = checkForCameraUpdates(this);
29382999
var shouldRender = !this.requestRenderMode || this._renderRequested || cameraChanged || (this.mode === SceneMode.MORPHING);
2939-
29403000
if (!shouldRender && defined(this.maximumRenderTimeChange) && defined(this._lastRenderTime)) {
29413001
var difference = Math.abs(JulianDate.secondsDifference(this._lastRenderTime, time));
29423002
shouldRender = shouldRender || difference >= this.maximumRenderTimeChange;
29433003
}
29443004

2945-
try {
2946-
if (shouldRender) {
2947-
this._lastRenderTime = JulianDate.clone(time, this._lastRenderTime);
2948-
this._renderRequested = false;
3005+
if (shouldRender) {
3006+
this._lastRenderTime = JulianDate.clone(time, this._lastRenderTime);
3007+
this._renderRequested = false;
29493008

2950-
render(this, time);
2951-
} else {
2952-
update(this, time);
2953-
}
2954-
} catch (error) {
2955-
this._renderError.raiseEvent(this, error);
2956-
2957-
if (this.rethrowRenderErrors) {
2958-
throw error;
2959-
}
3009+
// Render
3010+
this._preRender.raiseEvent(this, time);
3011+
tryAndCatchError(this, time, render);
3012+
this._postRender.raiseEvent(this, time);
29603013
}
29613014

29623015
updateDebugShowFramesPerSecond(this, shouldRender);
29633016
RequestScheduler.update();
2964-
callAfterRenderFunctions(this._frameState);
2965-
this._postRender.raiseEvent(this, time);
3017+
callAfterRenderCycleFunctions(this._frameState);
29663018
};
29673019

29683020
/**
@@ -3143,7 +3195,7 @@ define([
31433195

31443196
var object = this._pickFramebuffer.end(scratchRectangle);
31453197
context.endFrame();
3146-
callAfterRenderFunctions(frameState);
3198+
callAfterRenderCycleFunctions(frameState);
31473199
return object;
31483200
};
31493201

Source/Widgets/Viewer/Viewer.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to
705705
eventHelper.add(dataSourceCollection.dataSourceRemoved, Viewer.prototype._onDataSourceRemoved, this);
706706

707707
// Prior to each render, check if anything needs to be resized.
708-
eventHelper.add(cesiumWidget.scene.preRender, Viewer.prototype.resize, this);
708+
eventHelper.add(cesiumWidget.scene.postUpdate, Viewer.prototype.resize, this);
709709
eventHelper.add(cesiumWidget.scene.postRender, Viewer.prototype._postRender, this);
710710

711711
// We need to subscribe to the data sources and collections so that we can clear the

Specs/Scene/SceneSpec.js

+56-3
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,47 @@ defineSuite([
983983
s.destroyForSpecs();
984984
});
985985

986-
it('raises the preRender event prior to rendering', function() {
986+
it('alwayas raises preUpdate event prior to updating', function() {
987+
var s = createScene();
988+
989+
var spyListener = jasmine.createSpy('listener');
990+
s.preUpdate.addEventListener(spyListener);
991+
992+
s.render();
993+
994+
expect(spyListener.calls.count()).toBe(1);
995+
996+
s.requestRenderMode = true;
997+
s.maximumRenderTimeChange = undefined;
998+
999+
s.render();
1000+
1001+
expect(spyListener.calls.count()).toBe(2);
1002+
1003+
s.destroyForSpecs();
1004+
});
1005+
1006+
it('always raises preUpdate event after updating', function() {
1007+
var s = createScene();
1008+
1009+
var spyListener = jasmine.createSpy('listener');
1010+
s.preUpdate.addEventListener(spyListener);
1011+
1012+
s.render();
1013+
1014+
expect(spyListener.calls.count()).toBe(1);
1015+
1016+
s.requestRenderMode = true;
1017+
s.maximumRenderTimeChange = undefined;
1018+
1019+
s.render();
1020+
1021+
expect(spyListener.calls.count()).toBe(2);
1022+
1023+
s.destroyForSpecs();
1024+
});
1025+
1026+
it('raises the preRender event prior to rendering only if the scene renders', function() {
9871027
var s = createScene();
9881028

9891029
var spyListener = jasmine.createSpy('listener');
@@ -993,10 +1033,17 @@ defineSuite([
9931033

9941034
expect(spyListener.calls.count()).toBe(1);
9951035

1036+
s.requestRenderMode = true;
1037+
s.maximumRenderTimeChange = undefined;
1038+
1039+
s.render();
1040+
1041+
expect(spyListener.calls.count()).toBe(1);
1042+
9961043
s.destroyForSpecs();
9971044
});
9981045

999-
it('raises the postRender event after rendering', function() {
1046+
it('raises the postRender event after rendering if the scene rendered', function() {
10001047
var s = createScene();
10011048

10021049
var spyListener = jasmine.createSpy('listener');
@@ -1006,6 +1053,13 @@ defineSuite([
10061053

10071054
expect(spyListener.calls.count()).toBe(1);
10081055

1056+
s.requestRenderMode = true;
1057+
s.maximumRenderTimeChange = undefined;
1058+
1059+
s.render();
1060+
1061+
expect(spyListener.calls.count()).toBe(1);
1062+
10091063
s.destroyForSpecs();
10101064
});
10111065

@@ -1245,7 +1299,6 @@ defineSuite([
12451299
scene.destroyForSpecs();
12461300
});
12471301

1248-
12491302
it('Sets material', function() {
12501303
var scene = createScene();
12511304
var globe = scene.globe = new Globe(Ellipsoid.UNIT_SPHERE);

0 commit comments

Comments
 (0)