diff --git a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/widgets/options/ViewerOptions.java b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/widgets/options/ViewerOptions.java index 151a87077cde5438f2c8b132fb81acb7cc05cab6..584bf9ac57e1e65b9b0b700200f68559482049c6 100644 --- a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/widgets/options/ViewerOptions.java +++ b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/widgets/options/ViewerOptions.java @@ -176,11 +176,15 @@ public class ViewerOptions { */ @JsProperty public SkyBox skyBox; + @JsProperty(name = "skyBox") + public boolean enableSkyBox; /** * Blue sky, and the glow around the Earth's limb. Set to false to turn it off. */ @JsProperty public SkyAtmosphere skyAtmosphere; + @JsProperty(name = "skyAtmosphere") + public boolean enableSkyAtmosphere; /** * The element or id to be placed into fullscreen mode when the full screen * button is pressed. Default: document.body @@ -241,6 +245,8 @@ public class ViewerOptions { */ @JsProperty public Globe globe; + @JsProperty(name = "globe") + public boolean enableGlobe; /** * If true and the configuration supports it, use order independent * translucency. Default: true 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 302d38e6945ba1a37e42f9fb47863a9ec81cc5f9..8146c88fc5d4f36b4c3a172b60389b7d90bab75d 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 @@ -121,5 +121,6 @@ public class InjectorModule extends AbstractGinModule { bind(CustomShaders3DTiles.class).asEagerSingleton(); bind(CustomShadersModels.class).asEagerSingleton(); bind(Tiles3DNextCDBYemen.class).asEagerSingleton(); + bind(Tiles3DNextS2Globe.class).asEagerSingleton(); } } diff --git a/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextS2Globe.java b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextS2Globe.java new file mode 100644 index 0000000000000000000000000000000000000000..e16fb068ee48281c0c1ea38e631a61efd39ac4dc --- /dev/null +++ b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextS2Globe.java @@ -0,0 +1,228 @@ +/* + * Copyright 2021 iserge, 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.dom.client.DivElement; +import com.google.gwt.dom.client.Style; +import com.google.gwt.user.client.ui.*; +import org.cesiumjs.cs.Cesium; +import org.cesiumjs.cs.core.*; +import org.cesiumjs.cs.core.enums.ScreenSpaceEventType; +import org.cesiumjs.cs.core.events.MouseMoveEvent; +import org.cesiumjs.cs.js.JsObject; +import org.cesiumjs.cs.scene.Cesium3DTileFeature; +import org.cesiumjs.cs.scene.Cesium3DTileStyle; +import org.cesiumjs.cs.scene.Cesium3DTileset; +import org.cesiumjs.cs.scene.Scene; +import org.cesiumjs.cs.scene.experimental.CustomShader; +import org.cesiumjs.cs.scene.experimental.enums.UniformType; +import org.cesiumjs.cs.scene.experimental.options.CustomShaderOptions; +import org.cesiumjs.cs.scene.options.CameraFlyToOptions; +import org.cesiumjs.cs.widgets.Viewer; +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 javax.inject.Inject; + +public class Tiles3DNextS2Globe extends AbstractExample { + private Viewer viewer; + private boolean enablePicking = true; + @Inject + public Tiles3DNextS2Globe(ShowcaseExampleStore store) { + super("3D Tiles Next S2 Globe", + "Load a global scale 3D Tiles Next tileset that uses 3DTILES_bounding_volume_S2", + new String[]{"Showcase", "Cesium", "3d", "Viewer"}, store, "1.87.1"); + } + + @Override + public void buildPanel() { + // One World Terrain Base Globe provided by Maxar + Cesium.ExperimentalFeatures.enableModelExperimental = true; + + ViewerOptions options = new ViewerOptions(); + options.enableGlobe = false; + ViewerPanel csVPanel = new ViewerPanel(options); + viewer = csVPanel.getViewer(); + + Scene scene = csVPanel.getViewer().scene(); + + viewer.camera.flyTo(new CameraFlyToOptions() + .setDuration(0) + .setDestination(new Cartesian3(762079.3157173397, -28363749.882652905, 19814354.842565004)) + .setOrientation(new Cartesian3(-0.022007098944236157, 0.819079900508189, -0.5732571885110), + new Cartesian3(-0.015396759850986286, 0.5730503851893346, 0.8193754913471885)) + .setEasingFunction(EasingFunction.QUADRATIC_IN_OUT())); + + // MAXAR OWT WFF 1.2 Base Globe + Cesium3DTileset tileset = (Cesium3DTileset) scene.primitives().add(Cesium3DTileset.create(IonResource.fromAssetId(666330))); + tileset.maximumScreenSpaceError = 4; + + // --- Style --- + + JsObject jsStyle = JsObject.create(); + jsStyle.setProperty("defines", JsObject.create()); + jsStyle.getJsObject("defines").setProperty("LandCoverColor", "rgb(${color}[0], ${color}[1], ${color}[2])"); + jsStyle.setProperty("color", "${LandCoverColor} === vec4(1.0) ? rgb(254, 254, 254) : ${LandCoverColor}"); + Cesium3DTileStyle style = new Cesium3DTileStyle(jsStyle); + Cesium.log(style); + + // --- Custom Shader --- + + CustomShader customShader = new CustomShader(new CustomShaderOptions() + .addUniform("u_time", UniformType.FLOAT(), 0) + .setFragmentShaderText(String.join("\n", new String[] { + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)", + "{", + " // NOTE: this is exposing internal details of the shader.", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + " // Use cartesian coordinates but scale to be roughly [-1, 1]", + " vec3 positionWC = fsInput.attributes.positionWC / 6.3e6;", + " if (featureId == 60.0)", + " {", + " // Something like FM synthesis to make irregularly spaced waves", + " float wave = sin(14.0 * positionWC.z - u_time);", + " wave = 0.5 + 0.5 * sin(10.0 * wave * positionWC.z - u_time);", + " // mix in an over-saturated version of the diffuse to make shimmering bands of color", + " material.diffuse = mix(material.diffuse, material.diffuse * 3.0, wave);", + " }", + "}", + }))); + + final double startTime = performanceNow(); + scene.postUpdate().addEventListener((Event.Listener) o -> customShaderUpdate(customShader, startTime)); + + // --- Picking --- + + ScreenSpaceEventHandler handler = new ScreenSpaceEventHandler(scene.canvas()); + + DivElement metadataOverlay = RootPanel.get().getElement().getOwnerDocument().createDivElement(); + metadataOverlay.addClassName("backdrop"); + metadataOverlay.getStyle().setDisplay(Style.Display.NONE); + metadataOverlay.getStyle().setPosition(Style.Position.ABSOLUTE); + metadataOverlay.getStyle().setBottom(0., Style.Unit.PX); + metadataOverlay.getStyle().setLeft(0., Style.Unit.PX); +// metadataOverlay.style["pointer-events"] = "none"; + metadataOverlay.getStyle().setPadding(4.0, Style.Unit.PX); + metadataOverlay.getStyle().setBackgroundColor("#303030"); + metadataOverlay.getStyle().setWhiteSpace(Style.WhiteSpace.PRE_LINE); + metadataOverlay.getStyle().setFontSize(16., Style.Unit.PX); + csVPanel.getViewer().container().appendChild(metadataOverlay); + + handler.setInputAction(event -> { + MouseMoveEvent movement = (MouseMoveEvent) event; + if (enablePicking) { + PickedObject feature = scene.pick(movement.endPosition); + if (feature instanceof Cesium3DTileFeature) { + metadataOverlay.getStyle().setDisplay(Style.Display.BLOCK); + metadataOverlay.getStyle().setBottom(viewer.canvas().getClientHeight() - movement.endPosition.y, Style.Unit.PX); + metadataOverlay.getStyle().setLeft(movement.endPosition.x, Style.Unit.PX); + + StringBuilder tableHtmlScratch = new StringBuilder("
Property | Value |
---|---|
").append(propertyName).append(" | ").append(propertyValue).append(" |
Load a global scale 3D Tiles Next tileset that uses 3DTILES_bounding_volume_S2..
")); + contentPanel.add(aPanel); + + initWidget(contentPanel); + } + + @Override + public String[] getSourceCodeURLs() { + String[] sourceCodeURLs = new String[1]; + sourceCodeURLs[0] = GWT.getModuleBaseURL() + "examples/" + "Tiles3DNextS2Globe.txt"; + return sourceCodeURLs; + } + + private native double performanceNow() /*-{ + return performance.now(); + }-*/; + + private void customShaderUpdate(CustomShader customShader, double startTime) { + double elapsedTimeSeconds = (performanceNow() - startTime) / 1000.; + customShader.setUniform("u_time", elapsedTimeSeconds); + } +} diff --git a/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/3D Tiles Next S2 Globe.jpg b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/3D Tiles Next S2 Globe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46f7ea9d2d0e8dd2115595dfdcb553195eb3a7be Binary files /dev/null and b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/3D Tiles Next S2 Globe.jpg differ diff --git a/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextCDBYemen.txt b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextCDBYemen.txt index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..eae65552d5c74d45f892661ea93fa69ae5892b95 100644 --- a/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextCDBYemen.txt +++ b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextCDBYemen.txt @@ -0,0 +1,367 @@ +package org.cleanlogic.cesiumjs4gwt.showcase.examples; + +import com.google.gwt.core.client.*; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Style; +import com.google.gwt.user.client.ui.*; +import org.cesiumjs.cs.Cesium; +import org.cesiumjs.cs.core.*; +import org.cesiumjs.cs.core.Math; +import org.cesiumjs.cs.core.enums.ScreenSpaceEventType; +import org.cesiumjs.cs.core.events.MouseClickEvent; +import org.cesiumjs.cs.core.events.MouseMoveEvent; +import org.cesiumjs.cs.datasources.properties.ConstantProperty; +import org.cesiumjs.cs.js.JsObject; +import org.cesiumjs.cs.scene.*; +import org.cesiumjs.cs.scene.options.CameraFlyToOptions; +import org.cesiumjs.cs.widgets.Viewer; +import org.cesiumjs.cs.widgets.ViewerPanel; +import org.cleanlogic.cesiumjs4gwt.showcase.basic.AbstractExample; +import org.cleanlogic.cesiumjs4gwt.showcase.components.store.ShowcaseExampleStore; + +import javax.inject.Inject; + +public class Tiles3DNextCDBYemen extends AbstractExample { + private Viewer viewer; + + private Cesium3DTileFeature highlightedFeature = null; + private Color highlightedOriginalColor = new Color(); + + private Cesium3DTileFeature selectedFeature = null; + private Color selectedOriginalColor = new Color(); + + private boolean enablePicking = true; + + @Inject + public Tiles3DNextCDBYemen(ShowcaseExampleStore store) { + super("3D Tiles Next CDB Yemen", + "Load a 3D Tile Next tileset converted from CDB", + new String[]{"Showcase", "Cesium", "3d", "Viewer", "experimental"}, store, "1.87.1"); + } + + @Override + public void buildPanel() { + Cesium.ExperimentalFeatures.enableModelExperimental = true; + + ViewerPanel csVPanel = new ViewerPanel(); + viewer = csVPanel.getViewer(); + + viewer.clock().currentTime = JulianDate.fromIso8601("2021-11-09T07:27:37.016064475348684937Z"); + Scene scene = viewer.scene(); + scene.light.intensity = 7.0; + + // 3D Tiles Next converted from CDB of Aden, Yemen (CDB provided by Presagis) + Cesium3DTileset terrainTileset = (Cesium3DTileset) scene.primitives().add(Cesium3DTileset.create(IonResource.fromAssetId(667809))); + + Cesium3DTileset buildingsTileset = (Cesium3DTileset) scene.primitives().add(Cesium3DTileset.create(IonResource.fromAssetId(666747))); + buildingsTileset.maximumScreenSpaceError = 12; + + CameraTransform tileset = new CameraTransform(); + tileset.destination = new Cartesian3(4397999.822774582, 4404502.67774069, 1397782.4709840622); + tileset.direction = new Cartesian3(-0.29335588497705106, -0.6066709587467911, 0.7388454997917905); + tileset.up = new Cartesian3(0.6240972421637774, 0.46391380837591956, 0.6287182283994301); + + CameraTransform airport = new CameraTransform(); + airport.destination = new Cartesian3(4394719.151490939, 4402317.401942875, 1406608.6602404779); + airport.direction = new Cartesian3(0.4146699515908668, -0.8887814163588482, 0.1952342828060377); + airport.up = new Cartesian3(0.8415067525520951, 0.4561872920946922, 0.28941240460723); + + CameraTransform crater = new CameraTransform(); + crater.destination = new Cartesian3(4398179.160380196, 4402518.469409466, 1399161.7612076725); + crater.direction = new Cartesian3(-0.2800903637088597, -0.6348021519070498, 0.7201219452923355); + crater.up = new Cartesian3(0.6319189548885261, 0.4427783126727723, 0.6361020360596605); + + CameraTransform port = new CameraTransform(); + port.destination = new Cartesian3(4399698.85724341, 4399019.639078034, 1405153.7766045567); + port.direction = new Cartesian3(-0.5651458936543287, 0.17696574231117793, -0.8057873447342694); + port.up = new Cartesian3(0.4886488937394081, 0.8587605935024302, -0.15411846642958343); + + buildingsTileset.readyPromise().then(t -> { + Cartesian3 center = Cartesian3.fromDegrees(45.04192, 12.753525, 2000); + double heading = Math.toRadians(50.0); + double pitch = Math.toRadians(-20.0); + double range = 5000.0; + + flyCameraTo(tileset, 0.); + }); + + // --- Style --- + + String[][] conditions = new String[][] { + {"${HGT} !== undefined && ${HGT} < 5", "color('#f5fd2d')"}, + {"${HGT} !== undefined && ${HGT} >= 5 && ${HGT} < 10", "color('#d3a34a')"}, + {"${HGT} !== undefined && ${HGT} >= 10 && ${HGT} < 15", "color('#947e75')"}, + {"${HGT} !== undefined && ${HGT} >= 15 && ${HGT} < 20", "color('#565a9f')"}, + {"${HGT} !== undefined && ${HGT} > 20", "color('#223bc3')"}, + {"true", "color('white')"}, + }; + JsObject style = JsObject.create(); + style.setProperty("color", JsObject.create()); + style.getJsObject("color").setProperty("conditions", stringArrayToJsArrayString(conditions)); + Cesium3DTileStyle buildingStyle = new Cesium3DTileStyle(style); + + conditions = new String[][] { + {"${name} === 'OCEAN'", "color('#436d9d')"}, + {"${name} === 'LAKE'", "color('#3987c9')"}, + {"${name} === 'CALCAREOUS'", "color('#BBB6B1')"}, + {"${name} === 'GRASS'", "color('#567d46')"}, + {"${name} === 'FOREST'", "color('green')"}, + {"${name} === 'CITY'", "color('lightgray')"}, + {"${name} === 'ASPHALTROAD'", "color('#434343')"}, + {"${name} === 'ASPHALT'", "color('#463d39')"}, + {"${name} === 'CONCRETE'", "color('#b9b4ab')"}, + {"${name} === 'DRYGROUND'", "color('#9B7653')"}, + {"${name} === 'WETGROUND'", "color('#5a4332')"}, + {"${name} === 'SAND'", "color('gold')"}, + {"true", "color('#9B7653')"}, + }; + style = JsObject.create(); + style.setProperty("color", JsObject.create()); + style.getJsObject("color").setProperty("conditions", stringArrayToJsArrayString(conditions)); + Cesium3DTileStyle terrainStyle = new Cesium3DTileStyle(style); + + // --- Picking --- + + ScreenSpaceEventHandler handler = new ScreenSpaceEventHandler(scene.canvas()); + + DivElement metadataOverlay = RootPanel.get().getElement().getOwnerDocument().createDivElement(); + metadataOverlay.addClassName("backdrop"); + metadataOverlay.getStyle().setDisplay(Style.Display.NONE); + metadataOverlay.getStyle().setPosition(Style.Position.ABSOLUTE); + metadataOverlay.getStyle().setBottom(0., Style.Unit.PX); + metadataOverlay.getStyle().setLeft(0., Style.Unit.PX); +// nameOverlay.style["pointer-events"] = "none"; + metadataOverlay.getStyle().setPadding(4.0, Style.Unit.PX); + metadataOverlay.getStyle().setBackgroundColor("#303030"); + metadataOverlay.getStyle().setWhiteSpace(Style.WhiteSpace.PRE_LINE); + metadataOverlay.getStyle().setFontSize(16., Style.Unit.PX); + metadataOverlay.getStyle().setBorderStyle(Style.BorderStyle.SOLID); + + csVPanel.getViewer().container().appendChild(metadataOverlay); + + handler.setInputAction(event -> { + MouseMoveEvent movement = (MouseMoveEvent) event; + if (enablePicking) { + // If a feature was previously highlighted, undo the highlight + if (Cesium.defined(highlightedFeature)) { + highlightedFeature.color = highlightedOriginalColor; + highlightedFeature = null; + } + + PickedObject feature = scene.pick(movement.endPosition); + boolean featurePicked = feature instanceof Cesium3DTileFeature; + + boolean isTerrainFeature = featurePicked && ((Cesium3DTileFeature) feature).hasProperty("substrates"); + boolean isBuildingFeature = featurePicked && ((Cesium3DTileFeature) feature).hasProperty("HGT"); + + if (isTerrainFeature) { + metadataOverlay.getStyle().setDisplay(Style.Display.BLOCK); + metadataOverlay.getStyle().setBottom(viewer.canvas().getClientHeight() - movement.endPosition.y, Style.Unit.PX); + metadataOverlay.getStyle().setLeft(movement.endPosition.x, Style.Unit.PX); + + StringBuilder tableHtmlScratch = + new StringBuilder("Material: | " + + ((Cesium3DTileFeature) feature).getProperty("name") + + " |
---|---|
Substrates | |
") + .append(materialsScratch.get(i).substring(3)) + .append(" | ") + .append(weightsScratch.get(i)) + .append("% |
Property Name | ID | Type | Value | |
---|---|---|---|---|
" + + property.getString("name") + + " | ℹ️ | " + + property.getString("id") + + " | " + + property.getString("componentType") + + " | " + + propertyValue + + " |
Load a 3D Tile Next tileset converted from CDB.
")); + contentPanel.add(aPanel); + + initWidget(contentPanel); + } + + @Override + public String[] getSourceCodeURLs() { + String[] sourceCodeURLs = new String[1]; + sourceCodeURLs[0] = GWT.getModuleBaseURL() + "examples/" + "Tiles3DNextCDBYemen.txt"; + return sourceCodeURLs; + } + + private static class CameraTransform { + protected Cartesian3 destination; + protected Cartesian3 direction; + protected Cartesian3 up; + } + + private void flyCameraTo(CameraTransform cameraTransform, double duration) { + // Fly to a nice overview of the city. + viewer.camera.flyTo(new CameraFlyToOptions() + .setDuration(duration) + .setDestination(cameraTransform.destination) + .setOrientation(cameraTransform.direction, cameraTransform.up) + .setEasingFunction(EasingFunction.QUADRATIC_IN_OUT())); + } + + private void resetHighlight() { + if (selectedFeature != null) { + selectedFeature.color = selectedOriginalColor; + selectedFeature = null; + } + if (highlightedFeature != null) { + highlightedFeature.color = highlightedOriginalColor; + highlightedFeature = null; + } + } + + private JsArrayProperty | Value |
---|---|
").append(propertyName).append(" | ").append(propertyValue).append(" |
Load a global scale 3D Tiles Next tileset that uses 3DTILES_bounding_volume_S2..
")); + contentPanel.add(aPanel); + + initWidget(contentPanel); + } + + @Override + public String[] getSourceCodeURLs() { + String[] sourceCodeURLs = new String[1]; + sourceCodeURLs[0] = GWT.getModuleBaseURL() + "examples/" + "Tiles3DNextS2Globe.txt"; + return sourceCodeURLs; + } + + private native double performanceNow() /*-{ + return performance.now(); + }-*/; + + private void customShaderUpdate(CustomShader customShader, double startTime) { + double elapsedTimeSeconds = (performanceNow() - startTime) / 1000.; + customShader.setUniform("u_time", elapsedTimeSeconds); + } +}