diff --git a/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/config/InjectorModule.java b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/config/InjectorModule.java
index e0979ccfb898865c1df4987cd35f3096f07fa8dc..965aca9290749f0abd801d0caf4937bc782ccd25 100644
--- a/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/config/InjectorModule.java
+++ b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/config/InjectorModule.java
@@ -126,7 +126,8 @@ public class InjectorModule extends AbstractGinModule {
bind(GPX.class).asEagerSingleton();
bind(Tiles3DCompare.class).asEagerSingleton();
bind(CustomShadersPropertyTextures.class).asEagerSingleton();
-
bind(ManuallyControlledAnimation.class).asEagerSingleton();
+
+ bind(SceneRenderingPerformance.class).asEagerSingleton();
}
}
diff --git a/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/SceneRenderingPerformance.java b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/SceneRenderingPerformance.java
new file mode 100644
index 0000000000000000000000000000000000000000..33b74d64555e358cfdda316b59dc6ac317408925
--- /dev/null
+++ b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/SceneRenderingPerformance.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2022 iSergio, Gis4Fun.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cleanlogic.cesiumjs4gwt.showcase.examples;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.user.client.ui.AbsolutePanel;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.PushButton;
+import org.cesiumjs.cs.Cesium;
+import org.cesiumjs.cs.core.Cartesian3;
+import org.cesiumjs.cs.core.Color;
+import org.cesiumjs.cs.core.Event;
+import org.cesiumjs.cs.core.GregorianDate;
+import org.cesiumjs.cs.core.IonResource;
+import org.cesiumjs.cs.core.JulianDate;
+import org.cesiumjs.cs.core.PickedObject;
+import org.cesiumjs.cs.core.ScreenSpaceEventHandler;
+import org.cesiumjs.cs.core.enums.ScreenSpaceEventType;
+import org.cesiumjs.cs.core.events.MouseMoveEvent;
+import org.cesiumjs.cs.datasources.CzmlDataSource;
+import org.cesiumjs.cs.datasources.Entity;
+import org.cesiumjs.cs.datasources.graphics.BoxGraphics;
+import org.cesiumjs.cs.datasources.graphics.ModelGraphics;
+import org.cesiumjs.cs.datasources.graphics.options.BoxGraphicsOptions;
+import org.cesiumjs.cs.datasources.graphics.options.ModelGraphicsOptions;
+import org.cesiumjs.cs.datasources.options.EntityOptions;
+import org.cesiumjs.cs.datasources.properties.CallbackProperty;
+import org.cesiumjs.cs.datasources.properties.ColorMaterialProperty;
+import org.cesiumjs.cs.datasources.properties.ConstantPositionProperty;
+import org.cesiumjs.cs.datasources.properties.ConstantProperty;
+import org.cesiumjs.cs.js.JsObject;
+import org.cesiumjs.cs.scene.Cesium3DTileset;
+import org.cesiumjs.cs.scene.Scene;
+import org.cesiumjs.cs.widgets.ViewerPanel;
+import org.cesiumjs.cs.widgets.options.ViewerOptions;
+import org.cleanlogic.cesiumjs4gwt.showcase.basic.AbstractExample;
+import org.cleanlogic.cesiumjs4gwt.showcase.components.store.ShowcaseExampleStore;
+import org.cleanlogic.cesiumjs4gwt.showcase.examples.slider.Slider;
+
+import javax.inject.Inject;
+
+public class SceneRenderingPerformance extends AbstractExample {
+ private ViewerPanel csVPanel;
+ private Scene scene;
+ private Cesium3DTileset tileset;
+ private ScreenSpaceEventHandler handler;
+ private CheckBox timeChangeEnabledCBox;
+ private Slider maxDeltaTimeSlider;
+
+ @Inject
+ public SceneRenderingPerformance(ShowcaseExampleStore store) {
+ super("Scene Rendering Performance",
+ "Use explicit rendering to improve app performance",
+ new String[]{"Showcase", "Cesium", "3d", "Viewer", "performance", "render request"}, store);
+ }
+
+ @Override
+ public void buildPanel() {
+ ViewerOptions viewerOptions = new ViewerOptions();
+ viewerOptions.requestRenderMode = true;
+ viewerOptions.maximumRenderTimeChange = Double.POSITIVE_INFINITY;
+ viewerOptions.terrainProvider = Cesium.createWorldTerrain();
+ csVPanel = new ViewerPanel(viewerOptions);
+
+ scene = csVPanel.getViewer().scene();
+ scene.debugShowFramesPerSecond = true;
+
+ PushButton renderButton = new PushButton();
+ renderButton.setHTML("Render new frame");
+ renderButton.addClickHandler(handler -> scene.requestRender());
+
+ CheckBox requestRenderModeCBox = new CheckBox();
+ requestRenderModeCBox.setHTML("requestRenderMode enabled");
+ requestRenderModeCBox.setValue(true);
+ requestRenderModeCBox.addValueChangeHandler(event -> {
+ CheckBox source = (CheckBox) event.getSource();
+ scene.requestRenderMode = source.getValue();
+ });
+
+ ListBox scenariosLBox = new ListBox();
+ scenariosLBox.addItem("Default view", "0");
+ scenariosLBox.addItem("Load a 3D tileset and set the view", "1");
+ scenariosLBox.addItem("Mouseover picking", "2");
+ scenariosLBox.addItem("Load time-dynamic CZML", "3");
+ scenariosLBox.addItem("Animated model", "4");
+ scenariosLBox.addItem("Scene changes with API", "5");
+ scenariosLBox.addChangeHandler(this::setScenario);
+
+ timeChangeEnabledCBox = new CheckBox();
+ timeChangeEnabledCBox.setHTML("Render when simulation time changes");
+ timeChangeEnabledCBox.setEnabled(false);
+
+ maxDeltaTimeSlider = new Slider("maxDeltaTime", 0, 200, 0);
+ maxDeltaTimeSlider.setStep(1);
+
+ FlexTable flexTable = new FlexTable();
+ flexTable.setHTML(1, 0, "");
+ flexTable.setHTML(2, 0, "Simulation time at last render frame");
+ flexTable.setWidget(3, 0, renderButton);
+ flexTable.setWidget(4, 0, requestRenderModeCBox);
+ flexTable.setHTML(5, 0, "When enabled, a new frame is only rendered
when scene updates occur, or a new frame is
explicitly rendered.");
+ flexTable.setWidget(6, 0, scenariosLBox);
+ flexTable.setWidget(7, 0, timeChangeEnabledCBox);
+ flexTable.setHTML(8, 0, "Automatically render when the simulation time
changes by \"Max delta time\". Adjust the
simulation time on the animation widget and
\"Max delta time\" value to see their relationship.");
+ flexTable.setHTML(9, 0, "Max delta time");
+ flexTable.setWidget(10, 0, maxDeltaTimeSlider);
+
+ AbsolutePanel aPanel = new AbsolutePanel();
+ aPanel.add(csVPanel);
+ aPanel.add(flexTable, 20, 20);
+
+ contentPanel.add(new HTML(
+ "
Use explicit rendering to improve app performance.
")); + contentPanel.add(aPanel); + + initWidget(contentPanel); + + scene.postRender().addEventListener((Event.Listener) o -> { + GregorianDate time = JulianDate.toGregorianDate(scene.lastRenderTime()); + String value = time.hour + ":" + time.minute + ":" + time.second + ":" + NumberFormat.getFormat("0").format(time.millisecond); + flexTable.setHTML(1, 0, "" + value + ""); + }); + } + + @Override + public String[] getSourceCodeURLs() { + String[] sourceCodeURLs = new String[1]; + sourceCodeURLs[0] = GWT.getModuleBaseURL() + "examples/" + "SceneRenderingPerformance.txt"; + return sourceCodeURLs; + } + + private void setScenario(ChangeEvent event) { + ListBox source = (ListBox) event.getSource(); + int value = Integer.parseInt(source.getSelectedValue()); + switch (value) { + case 0: resetScene(); break; + case 1: loadTilesetScenario(); break; + case 2: pickingScenario(); break; + case 3: loadCzmlScenario(); break; + case 4: loadModelScenario(); break; + case 5: setScenePropertiesScenario(); break; + default: break; + } + + } + + // Clear scene and set default view. + private void resetScene() { + csVPanel.getViewer().trackedEntity = (Entity) JsObject.undefined(); + csVPanel.getViewer().dataSources().removeAll(); + csVPanel.getViewer().entities().removeAll(); + csVPanel.getViewer().scene().primitives().remove(tileset); + csVPanel.getViewer().clock().shouldAnimate = false; + if (handler != null) { + handler.destroy(); + handler = null; + } + scene.skyBox.show = true; + scene.camera().flyHome(0.0); + scene.requestRender(); + timeChangeEnabledCBox.setEnabled(false); + timeChangeEnabledCBox.setValue(false); + maxDeltaTimeSlider.setValue(0); + } + + // Load a tileset and set the view. + // No need to call scene.requestRender() + private void loadTilesetScenario() { + resetScene(); + + tileset = Cesium3DTileset.create(IonResource.fromAssetId(40866)); + csVPanel.getViewer().scene().primitives().add(tileset); + csVPanel.getViewer().zoomTo(tileset); + } + + // Load an animated model and set the view. + // No need to call scene.requestRender() + // Enable and adjust maximum simulation time change to see + // animations at desired speed. + private void loadModelScenario() { + resetScene(); + timeChangeEnabledCBox.setEnabled(true); + timeChangeEnabledCBox.setValue(true); + + ModelGraphicsOptions modelOptions = new ModelGraphicsOptions(); + modelOptions.uri = new ConstantProperty<>(GWT.getModuleBaseURL() + "SampleData/models/CesiumAir/Cesium_Air.glb"); + modelOptions.minimumPixelSize = new ConstantProperty<>(128); + modelOptions.maximumScale = new ConstantProperty<>(20000); + + EntityOptions entityOptions = new EntityOptions(); + entityOptions.name = "Aircraft"; + entityOptions.position = new ConstantPositionProperty(Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000.0)); + entityOptions.model = new ModelGraphics(modelOptions); + csVPanel.getViewer().trackedEntity = csVPanel.getViewer().entities().add(entityOptions); + csVPanel.getViewer().clock().shouldAnimate = true; + scene.requestRender(); + } + + // Load CZML DataSource with a model and set the trackedEntity. + // No need to call scene.requestRender() + // Enable and adjust maximum simulation time change to see + // animations at desired speed. + private void loadCzmlScenario() { + resetScene(); + timeChangeEnabledCBox.setEnabled(true); + timeChangeEnabledCBox.setValue(true); + maxDeltaTimeSlider.setValue(100); + + scene.maximumRenderTimeChange = 10.; + + csVPanel.getViewer().dataSources().add(CzmlDataSource.load(GWT.getModuleBaseURL() + "SampleData/simple.czml")); + csVPanel.getViewer().clock().shouldAnimate = true; + } + + // Pick an entity, only rendering when needed. + private void pickingScenario() { + resetScene(); + + final Color[] color = {Color.CORNFLOWERBLUE()}; + + CallbackProperty