From 99310cb719addf2c819543613c84856cc88854f1 Mon Sep 17 00:00:00 2001 From: iSergio Date: Wed, 17 Nov 2021 15:58:43 +0300 Subject: [PATCH 1/5] Missed statics --- .../src/main/java/org/cesiumjs/cs/scene/enums/Axis.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/enums/Axis.java b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/enums/Axis.java index 8aaba6a0..c132b28e 100644 --- a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/enums/Axis.java +++ b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/enums/Axis.java @@ -28,15 +28,15 @@ public class Axis { * Denotes the x-axis. */ @JsProperty(name = "X") - public native Number X(); + public static native Number X(); /** * Denotes the y-axis. */ @JsProperty(name = "Y") - public native Number Y(); + public static native Number Y(); /** * Denotes the z-axis. */ @JsProperty(name = "Z") - public native Number Z(); + public static native Number Z(); } -- GitLab From f47a485022bd7f257969952acb94bb3657cddf11 Mon Sep 17 00:00:00 2001 From: iSergio Date: Wed, 17 Nov 2021 16:33:08 +0300 Subject: [PATCH 2/5] Missed statics --- .../scene/experimental/enums/UniformType.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/enums/UniformType.java b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/enums/UniformType.java index df6df0ad..00b8fa4f 100644 --- a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/enums/UniformType.java +++ b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/enums/UniformType.java @@ -29,83 +29,83 @@ public class UniformType { * A single floating point value. */ @JsProperty(name = "FLOAT") - public native String FLOAT(); + public static native String FLOAT(); /** * A vector of 2 floating point values. */ @JsProperty(name = "VEC2") - public native String VEC2(); + public static native String VEC2(); /** * A vector of 3 floating point values. */ @JsProperty(name = "VEC3") - public native String VEC3(); + public static native String VEC3(); /** * A vector of 4 floating point values. */ @JsProperty(name = "VEC4") - public native String VEC4(); + public static native String VEC4(); /** * A single integer value */ @JsProperty(name = "INT") - public native String INT(); + public static native String INT(); /** * A vector of 2 integer values. */ @JsProperty(name = "INT_VEC2") - public native String INT_VEC2(); + public static native String INT_VEC2(); /** * A vector of 3 integer values. */ @JsProperty(name = "INT_VEC3") - public native String INT_VEC3(); + public static native String INT_VEC3(); /** * A vector of 4 integer values. */ @JsProperty(name = "INT_VEC4") - public native String INT_VEC4(); + public static native String INT_VEC4(); /** * A single boolean value. */ @JsProperty(name = "BOOL") - public native String BOOL(); + public static native String BOOL(); /** * A vector of 2 boolean values. */ @JsProperty(name = "BOOL_VEC2") - public native String BOOL_VEC2(); + public static native String BOOL_VEC2(); /** * A vector of 3 boolean values. */ @JsProperty(name = "BOOL_VEC3") - public native String BOOL_VEC3(); + public static native String BOOL_VEC3(); /** * A vector of 4 boolean values. */ @JsProperty(name = "BOOL_VEC4") - public native String BOOL_VEC4(); + public static native String BOOL_VEC4(); /** * A 2x2 matrix of floating point values. */ @JsProperty(name = "MAT2") - public native String MAT2(); + public static native String MAT2(); /** * A 3x3 matrix of floating point values. */ @JsProperty(name = "MAT3") - public native String MAT3(); + public static native String MAT3(); /** * A 3x3 matrix of floating point values. */ @JsProperty(name = "MAT4") - public native String MAT4(); + public static native String MAT4(); /** * A 2D sampled texture. */ @JsProperty(name = "SAMPLER_2D") - public native String SAMPLER_2D(); + public static native String SAMPLER_2D(); @JsProperty(name = "SAMPLER_CUBE") - public native String SAMPLER_CUBE(); + public static native String SAMPLER_CUBE(); } -- GitLab From 72309f0042dd31cef3c8bd61de52aa50c885eafa Mon Sep 17 00:00:00 2001 From: iSergio Date: Wed, 17 Nov 2021 16:33:45 +0300 Subject: [PATCH 3/5] Add functional for pretty use --- .../cs/scene/options/CameraFlyToOptions.java | 89 ++++++++++++++++++- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/options/CameraFlyToOptions.java b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/options/CameraFlyToOptions.java index 01dbeb7b..9cf2fd3e 100644 --- a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/options/CameraFlyToOptions.java +++ b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/options/CameraFlyToOptions.java @@ -16,10 +16,7 @@ package org.cesiumjs.cs.scene.options; -import jsinterop.annotations.JsConstructor; -import jsinterop.annotations.JsPackage; -import jsinterop.annotations.JsProperty; -import jsinterop.annotations.JsType; +import jsinterop.annotations.*; import org.cesiumjs.cs.core.*; import org.cesiumjs.cs.scene.Camera; @@ -116,4 +113,88 @@ public class CameraFlyToOptions { @JsConstructor public CameraFlyToOptions() { } + + @JsOverlay + public final CameraFlyToOptions setDestination(Cartesian3 destination) { + this.destinationPos = destination; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setDestination(Rectangle destination) { + this.destinationRec = destination; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setOrientation(HeadingPitchRoll orientation) { + this.orientation = orientation; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setDuration(double duration) { + this.duration = duration; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setComplete(Camera.FlightCompleteCallback complete) { + this.complete = complete; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setCancel(Camera.FlightCancelledCallback cancel) { + this.cancel = cancel; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setEndTransform(Matrix4 endTransform) { + this.endTransform = endTransform; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setMaximumHeight(double maximumHeight) { + this.maximumHeight = maximumHeight; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setPitchAdjustHeight(double pitchAdjustHeight) { + this.pitchAdjustHeight = pitchAdjustHeight; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setFlyOverLongitude(double flyOverLongitude) { + this.flyOverLongitude = flyOverLongitude; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setFlyOverLongitudeWeight(double flyOverLongitudeWeight) { + this.flyOverLongitudeWeight = flyOverLongitudeWeight; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setEasingFunction(EasingFunction easingFunction) { + this.easingFunction = easingFunction; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setEasingFunctionCallback(EasingFunction.Callback easingFunctionCallback) { + this.easingFunctionCallback = easingFunctionCallback; + return this; + } + + @JsOverlay + public final CameraFlyToOptions setOffset(HeadingPitchRange offset) { + this.offset = offset; + return this; + } } -- GitLab From 65134ef10915397f60d3e0bb3b25dc6245de703c Mon Sep 17 00:00:00 2001 From: iSergio Date: Wed, 17 Nov 2021 16:33:54 +0300 Subject: [PATCH 4/5] Add functional for pretty use --- .../cs/scene/experimental/CustomShader.java | 5 +- .../options/CustomShaderOptions.java | 80 +++++++++++++++++-- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/CustomShader.java b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/CustomShader.java index c0dc5a4c..5ce7ca9f 100644 --- a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/CustomShader.java +++ b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/CustomShader.java @@ -16,9 +16,7 @@ package org.cesiumjs.cs.scene.experimental; -import jsinterop.annotations.JsConstructor; -import jsinterop.annotations.JsMethod; -import jsinterop.annotations.JsType; +import jsinterop.annotations.*; import org.cesiumjs.cs.core.*; import org.cesiumjs.cs.scene.experimental.options.CustomShaderOptions; @@ -27,7 +25,6 @@ import org.cesiumjs.cs.scene.experimental.options.CustomShaderOptions; */ @JsType(isNative = true, namespace = "Cesium", name = "CustomShader") public class CustomShader { - @JsConstructor public CustomShader(CustomShaderOptions options) {} diff --git a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/options/CustomShaderOptions.java b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/options/CustomShaderOptions.java index 0ee17c08..d5f46eab 100644 --- a/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/options/CustomShaderOptions.java +++ b/cesiumjs4gwt-main/src/main/java/org/cesiumjs/cs/scene/experimental/options/CustomShaderOptions.java @@ -16,10 +16,12 @@ package org.cesiumjs.cs.scene.experimental.options; -import jsinterop.annotations.JsConstructor; -import jsinterop.annotations.JsPackage; -import jsinterop.annotations.JsProperty; -import jsinterop.annotations.JsType; +import jsinterop.annotations.*; +import org.cesiumjs.cs.Cesium; +import org.cesiumjs.cs.js.JsObject; +import org.cesiumjs.cs.scene.experimental.CustomShader; +import org.cesiumjs.cs.scene.experimental.enums.CustomShaderMode; +import org.cesiumjs.cs.scene.experimental.enums.LightingModel; @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") public class CustomShaderOptions { @@ -40,8 +42,20 @@ public class CustomShaderOptions { */ @JsProperty public boolean isTranslucent; -// uniforms Object. optional A dictionary for user-defined uniforms. The key is the uniform name that will appear in the GLSL code. The value is an object that describes the uniform type and initial value -// varyings Object. optional A dictionary for declaring additional GLSL varyings used in the shader. The key is the varying name that will appear in the GLSL code. The value is the data type of the varying. For each varying, the declaration will be added to the top of the shader automatically. The caller is responsible for assigning a value in the vertex shader and using the value in the fragment shader. + /** + * A dictionary for user-defined uniforms. The key is the uniform name that will appear in the GLSL code. + * The value is an object that describes the uniform type and initial value + */ + @JsProperty + public JsObject uniforms; + /** + * A dictionary for declaring additional GLSL varyings used in the shader. The key is the varying name that will + * appear in the GLSL code. The value is the data type of the varying. For each varying, the declaration will be + * added to the top of the shader automatically. The caller is responsible for assigning a value in the vertex + * shader and using the value in the fragment shader. + */ + @JsProperty + public JsObject varyings; /** * The custom vertex shader as a string of GLSL code. It must include a GLSL function called vertexMain. See the * example for the expected signature. If not specified, the custom vertex shader step will be skipped in @@ -59,4 +73,58 @@ public class CustomShaderOptions { @JsConstructor public CustomShaderOptions() {} + + @JsOverlay + public final CustomShaderOptions setMode(String mode) { + this.mode = mode; + return this; + } + + @JsOverlay + public final CustomShaderOptions setLightingModel(Number lightingModel) { + this.lightingModel = lightingModel; + return this; + } + + @JsOverlay + public final CustomShaderOptions setTranslucent(boolean isTranslucent) { + this.isTranslucent = isTranslucent; + return this; + } + + @JsOverlay + public final CustomShaderOptions addUniform(String name, String type, Object value) { + if (this.uniforms == JsObject.undefined()) { + this.uniforms = JsObject.create(); + } + JsObject uniform = JsObject.create(); + uniform.setProperty("type", type); + uniform.setProperty("value", value); + + JsObject.setProperty(uniforms, name, uniform); + + return this; + } + + @JsOverlay + public final CustomShaderOptions addVarying(String name, String type) { + if (this.varyings == JsObject.undefined()) { + this.varyings = JsObject.create(); + } + JsObject.setProperty(this.varyings, name, type); + + return this; + } + + @JsOverlay + public final CustomShaderOptions setVertexShaderText(String vertexShaderText) { + this.vertexShaderText = vertexShaderText; + return this; + } + + @JsOverlay + public final CustomShaderOptions setFragmentShaderText(String fragmentShaderText) { + this.fragmentShaderText = fragmentShaderText; + return this; + } } -- GitLab From 572f675340c1141b05f273e3eef1823c13d3d8a1 Mon Sep 17 00:00:00 2001 From: iSergio Date: Wed, 17 Nov 2021 16:35:44 +0300 Subject: [PATCH 5/5] New example - 3D Tiles Next Photogrammetry Classification --- .../showcase/config/InjectorModule.java | 1 + ...les3DNextPhotogrammetryClassification.java | 319 ++++++++++++++++++ ...les Next Photogrammetry Classification.jpg | Bin 0 -> 18122 bytes ...iles3DNextPhotogrammetryClassification.txt | 303 +++++++++++++++++ 4 files changed, 623 insertions(+) create mode 100644 cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextPhotogrammetryClassification.java create mode 100644 cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/3D Tiles Next Photogrammetry Classification.jpg create mode 100644 cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextPhotogrammetryClassification.txt 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 43d1da42..e7ce024f 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 @@ -117,6 +117,7 @@ public class InjectorModule extends AbstractGinModule { bind(Clouds.class).asEagerSingleton(); bind(CloudParameters.class).asEagerSingleton(); + bind(Tiles3DNextPhotogrammetryClassification.class).asEagerSingleton(); bind(CustomShaders3DTiles.class).asEagerSingleton(); } } diff --git a/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextPhotogrammetryClassification.java b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextPhotogrammetryClassification.java new file mode 100644 index 00000000..563f54c0 --- /dev/null +++ b/cesiumjs4gwt-showcase/src/main/java/org/cleanlogic/cesiumjs4gwt/showcase/examples/Tiles3DNextPhotogrammetryClassification.java @@ -0,0 +1,319 @@ +/* + * 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.MouseClickEvent; +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.enums.Cesium3DTileColorBlendMode; +import org.cesiumjs.cs.scene.experimental.CustomShader; +import org.cesiumjs.cs.scene.experimental.enums.LightingModel; +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.ViewerPanel; +import org.cesiumjs.cs.widgets.options.ViewerOptions; +import org.cesiumjs.cs.core.HeadingPitchRoll; +import org.cleanlogic.cesiumjs4gwt.showcase.basic.AbstractExample; +import org.cleanlogic.cesiumjs4gwt.showcase.components.store.ShowcaseExampleStore; + +import javax.inject.Inject; + +public class Tiles3DNextPhotogrammetryClassification extends AbstractExample { + private Cesium3DTileset tileset; + private CustomShader unlitShader; + private Cesium3DTileStyle classificationStyle; + private CustomShader translucentWindowsShader; + private CustomShader materialShader; + private CustomShader selectFeatureShader; + private boolean enablePicking = true; + + @Inject + public Tiles3DNextPhotogrammetryClassification(ShowcaseExampleStore store) { + super("3D Tiles Next Photogrammetry Classification", + "Load a photogrammetry dataset with feature ID textures from EXT_mesh_features", + new String[]{"Showcase", "Cesium", "3d", "Viewer", "experimental"}, store, "1.87.1"); + } + + @Override + public void buildPanel() { + Cesium.ExperimentalFeatures.enableModelExperimental = true; + ViewerOptions options = new ViewerOptions(); + options.terrainProvider = Cesium.createWorldTerrain(); + options.infoBox = false; + options.orderIndependentTranslucency = false; + ViewerPanel csVPanel = new ViewerPanel(options); + + + csVPanel.getViewer().clock().currentTime = JulianDate.fromIso8601("2021-11-09T20:27:37.016064475348684937Z"); + + Scene scene = csVPanel.getViewer().scene(); + + tileset = Cesium3DTileset.create(IonResource.fromAssetId(666297)); + + Cartesian3 translation = new Cartesian3(-1.398521324920626, 0.7823052871729486, 0.7015244410592609); + tileset.modelMatrix = Matrix4.fromTranslation(translation); + + tileset.maximumScreenSpaceError = 8.0; + scene.pickTranslucentDepth = true; + scene.light.intensity = 7.0; + + scene.primitives().add(tileset); + csVPanel.getViewer().zoomTo(tileset); + + // Fly to a nice overview of the city. + csVPanel.getViewer().camera.flyTo(new CameraFlyToOptions() + .setDestination(new Cartesian3(-2703640.80485846, -4261161.990345464, 3887439.511104276)) + .setOrientation(new HeadingPitchRoll(0.22426651143535548, -0.2624145362506527, 0.000006972977223185239))); + + // Styles ============================================================================= + + classificationStyle = new Cesium3DTileStyle(); + JsObject.setProperty(classificationStyle, "color", "color(${color})"); + + // Shaders ============================================================================ + + // Dummy shader that sets the UNLIT lighting mode. For use with the classification style + String emptyFragmentShader = "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {}"; + unlitShader = new CustomShader(new CustomShaderOptions() + .setLightingModel(LightingModel.UNLIT()).setFragmentShaderText(emptyFragmentShader)); + + translucentWindowsShader = new CustomShader(new CustomShaderOptions().setLightingModel(LightingModel.UNLIT()) + .setTranslucent(true).setFragmentShaderText(String.join("\n", new String[] { + "const float WINDOW = 0.0;", + "const float SKYLIGHT = 4.0;", + "const float TOTAL_FEATURES = 12.0;", + "", + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {", + " // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + "", + " if (featureId == WINDOW || featureId == SKYLIGHT) {", + " material.alpha = 0.4;", + " material.roughness = 0.1;", + " }", + "}", + }))); + + materialShader = new CustomShader(new CustomShaderOptions().setLightingModel(LightingModel.PBR()) + .setTranslucent(true).setFragmentShaderText(String.join("\n", new String[] { + "const float WINDOW = 0.0;", + "const float FRAME = 1.0;", + "const float WALL = 2.0;", + "const float ROOF = 3.0;", + "const float SKYLIGHT = 4.0;", + "const float AIR_CONDITIONER_WHITE = 5.0;", + "const float AIR_CONDITIONER_BLACK = 6.0;", + "const float AIR_CONDITIONER_TALL = 7.0;", + "const float CLOCK = 8.0;", + "const float PILLARS = 9.0;", + "const float STREET_LIGHT = 10.0;", + "const float TRAFFIC_LIGHT = 11.0;", + "", + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {", + " // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + "", + " if (featureId == CLOCK) {", + " // Shiny brass", + " material.specular = vec3(0.98, 0.90, 0.59);", + " material.roughness = 0.3;", + " } else if (", + " featureId == STREET_LIGHT ||", + " featureId == AIR_CONDITIONER_BLACK ||", + " featureId == AIR_CONDITIONER_WHITE ||", + " featureId == AIR_CONDITIONER_TALL ||", + " featureId == ROOF", + " ) {", + " // dull aluminum", + " material.specular = vec3(0.91, 0.92, 0.92);", + " material.roughness = 0.5;", + " } else if (featureId == WINDOW || featureId == SKYLIGHT) {", + " // make translucent, but also set an orange emissive color so it looks like", + " // it's lit from inside", + " material.emissive = vec3(1.0, 0.3, 0.0);", + " material.alpha = 0.5;", + " } else if (featureId == WALL || featureId == FRAME || featureId == PILLARS) {", + " // paint the walls and pillars white to contrast the brass clock", + " material.diffuse = mix(material.diffuse, vec3(1.0), 0.8);", + " material.roughness = 0.9;", + " } else {", + " // brighten everything else", + " material.diffuse += 0.05;", + " material.roughness = 0.9;", + " }", + "}", + }))); + + Number NOTHING_SELECTED = 12; + selectFeatureShader = new CustomShader(new CustomShaderOptions() + .setLightingModel(LightingModel.PBR()) + .addUniform("u_selectedFeature", UniformType.FLOAT(), NOTHING_SELECTED) + .setFragmentShaderText(String.join("\n", new String[] { + "const float NOTHING_SELECTED = 12.0;", + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {", + " // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + "", + " if (u_selectedFeature < NOTHING_SELECTED && featureId == u_selectedFeature) {", + " material.specular = vec3(1.00, 0.85, 0.57);", + " material.roughness = 0.3;", + " }", + "}", + }))); + + tileset.style = classificationStyle; + tileset.colorBlendMode = Cesium3DTileColorBlendMode.MIX(); + + DivElement nameOverlay = RootPanel.get().getElement().getOwnerDocument().createDivElement(); + nameOverlay.addClassName("backdrop"); + nameOverlay.getStyle().setDisplay(Style.Display.NONE); + nameOverlay.getStyle().setPosition(Style.Position.ABSOLUTE); + nameOverlay.getStyle().setBottom(0., Style.Unit.PX); + nameOverlay.getStyle().setLeft(0., Style.Unit.PX); +// nameOverlay.style["pointer-events"] = "none"; + nameOverlay.getStyle().setPadding(4.0, Style.Unit.PX); + nameOverlay.getStyle().setBackgroundColor("black"); + nameOverlay.getStyle().setWhiteSpace(Style.WhiteSpace.PRE_LINE); + nameOverlay.getStyle().setFontSize(12., Style.Unit.PX); + csVPanel.getViewer().container().appendChild(nameOverlay); + + this.enablePicking = true; + + csVPanel.getViewer().screenSpaceEventHandler().setInputAction(event -> { + MouseMoveEvent movement = (MouseMoveEvent) event; + if (enablePicking) { + PickedObject pickedObject = scene.pick(movement.endPosition); + if (pickedObject instanceof Cesium3DTileFeature) { + nameOverlay.getStyle().setDisplay(Style.Display.BLOCK); + nameOverlay.getStyle().setBottom(csVPanel.getViewer().canvas().getClientHeight() - movement.endPosition.y, Style.Unit.PX); + nameOverlay.getStyle().setLeft(movement.endPosition.x, Style.Unit.PX); + String message = "Component: " + ((Cesium3DTileFeature) pickedObject).getProperty("component") + + "\nFeature ID: " + ((Cesium3DTileFeature) pickedObject).getProperty("_batchId"); + nameOverlay.setInnerText(message); + } else { + nameOverlay.getStyle().setDisplay(Style.Display.NONE); + } + } else { + nameOverlay.getStyle().setDisplay(Style.Display.NONE); + } + }, ScreenSpaceEventType.MOUSE_MOVE()); + + csVPanel.getViewer().screenSpaceEventHandler().setInputAction(event -> { + MouseClickEvent movement = (MouseClickEvent) event; + if (enablePicking) { + PickedObject pickedObject = scene.pick(movement.position); + Object batchId = JsObject.undefined(); + if (pickedObject != null) { + batchId = JsObject.getObject(pickedObject, "_batchId"); + } + Cesium.log(batchId); + if (Cesium.defined(pickedObject) && Cesium.defined(batchId)) { + selectFeatureShader.setUniform("u_selectedFeature", (Number) batchId); + } else { + selectFeatureShader.setUniform("u_selectedFeature", NOTHING_SELECTED); + } + } + }, ScreenSpaceEventType.LEFT_CLICK()); + + CheckBox enablePickingCBox = new CheckBox("Enable picking"); + enablePickingCBox.getElement().getStyle().setColor("white"); + enablePickingCBox.setWidth("100px"); + enablePickingCBox.setValue(this.enablePicking); + enablePickingCBox.addValueChangeHandler(event -> enablePicking = event.getValue()); + + ListBox listBox = new ListBox(); + listBox.addItem("Photogrammetry"); + listBox.addItem("Show Classification"); + listBox.addItem("Translucent Windows"); + listBox.addItem("Stylized PBR Materials"); + listBox.addItem("Golden Touch"); + listBox.addChangeHandler(event -> { + String value = ((ListBox) event.getSource()).getSelectedItemText(); + switch (value) { + case "Photogrammetry": defaults(); break; + case "Show Classification": showClassification(); break; + case "Translucent Windows": translucentWindows(); break; + case "Stylized PBR Materials": pbrMaterials(); break; + case "Golden Touch": goldenTouch(); break; + default: break; + } + }); + + HorizontalPanel hPanel = new HorizontalPanel(); + hPanel.add(enablePickingCBox); + hPanel.add(listBox); + + AbsolutePanel aPanel = new AbsolutePanel(); + aPanel.add(csVPanel); + aPanel.add(hPanel, 20, 20); + + contentPanel.add(new HTML( + "

Load a photogrammetry dataset with feature ID textures from EXT_mesh_features.

")); + contentPanel.add(aPanel); + + initWidget(contentPanel); + + defaults(); + } + + @Override + public String[] getSourceCodeURLs() { + String[] sourceCodeURLs = new String[1]; + sourceCodeURLs[0] = GWT.getModuleBaseURL() + "examples/" + "Tiles3DNextPhotogrammetryClassification.txt"; + return sourceCodeURLs; + } + + private void defaults() { + tileset.style = (Cesium3DTileStyle) JsObject.undefined(); + tileset.customShader = unlitShader; + tileset.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT(); + tileset.colorBlendAmount = 0.5; + } + + private void showClassification() { + defaults(); + tileset.style = classificationStyle; + tileset.colorBlendMode = Cesium3DTileColorBlendMode.MIX(); + } + + private void translucentWindows() { + defaults(); + tileset.customShader = translucentWindowsShader; + } + + private void pbrMaterials() { + defaults(); + tileset.customShader = materialShader; + } + + private void goldenTouch() { + defaults(); + tileset.customShader = selectFeatureShader; + } +} diff --git a/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/3D Tiles Next Photogrammetry Classification.jpg b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/3D Tiles Next Photogrammetry Classification.jpg new file mode 100644 index 0000000000000000000000000000000000000000..559f54e42076a2a639d04b35250c5a61200ff96a GIT binary patch literal 18122 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 P_czR6|KUhz_y3y!$Pe>z literal 0 HcmV?d00001 diff --git a/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextPhotogrammetryClassification.txt b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextPhotogrammetryClassification.txt new file mode 100644 index 00000000..cfe31a58 --- /dev/null +++ b/cesiumjs4gwt-showcase/src/main/resources/org/cleanlogic/cesiumjs4gwt/public/examples/Tiles3DNextPhotogrammetryClassification.txt @@ -0,0 +1,303 @@ +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.MouseClickEvent; +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.enums.Cesium3DTileColorBlendMode; +import org.cesiumjs.cs.scene.experimental.CustomShader; +import org.cesiumjs.cs.scene.experimental.enums.LightingModel; +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.ViewerPanel; +import org.cesiumjs.cs.widgets.options.ViewerOptions; +import org.cesiumjs.cs.core.HeadingPitchRoll; +import org.cleanlogic.cesiumjs4gwt.showcase.basic.AbstractExample; +import org.cleanlogic.cesiumjs4gwt.showcase.components.store.ShowcaseExampleStore; + +import javax.inject.Inject; + +public class Tiles3DNextPhotogrammetryClassification extends AbstractExample { + private Cesium3DTileset tileset; + private CustomShader unlitShader; + private Cesium3DTileStyle classificationStyle; + private CustomShader translucentWindowsShader; + private CustomShader materialShader; + private CustomShader selectFeatureShader; + private boolean enablePicking = true; + + @Inject + public Tiles3DNextPhotogrammetryClassification(ShowcaseExampleStore store) { + super("3D Tiles Next Photogrammetry Classification", + "Load a photogrammetry dataset with feature ID textures from EXT_mesh_features", + new String[]{"Showcase", "Cesium", "3d", "Viewer", "experimental"}, store, "1.87.1"); + } + + @Override + public void buildPanel() { + Cesium.ExperimentalFeatures.enableModelExperimental = true; + ViewerOptions options = new ViewerOptions(); + options.terrainProvider = Cesium.createWorldTerrain(); + options.infoBox = false; + options.orderIndependentTranslucency = false; + ViewerPanel csVPanel = new ViewerPanel(options); + + + csVPanel.getViewer().clock().currentTime = JulianDate.fromIso8601("2021-11-09T20:27:37.016064475348684937Z"); + + Scene scene = csVPanel.getViewer().scene(); + + tileset = Cesium3DTileset.create(IonResource.fromAssetId(666297)); + + Cartesian3 translation = new Cartesian3(-1.398521324920626, 0.7823052871729486, 0.7015244410592609); + tileset.modelMatrix = Matrix4.fromTranslation(translation); + + tileset.maximumScreenSpaceError = 8.0; + scene.pickTranslucentDepth = true; + scene.light.intensity = 7.0; + + scene.primitives().add(tileset); + csVPanel.getViewer().zoomTo(tileset); + + // Fly to a nice overview of the city. + csVPanel.getViewer().camera.flyTo(new CameraFlyToOptions() + .setDestination(new Cartesian3(-2703640.80485846, -4261161.990345464, 3887439.511104276)) + .setOrientation(new HeadingPitchRoll(0.22426651143535548, -0.2624145362506527, 0.000006972977223185239))); + + // Styles ============================================================================= + + classificationStyle = new Cesium3DTileStyle(); + JsObject.setProperty(classificationStyle, "color", "color(${color})"); + + // Shaders ============================================================================ + + // Dummy shader that sets the UNLIT lighting mode. For use with the classification style + String emptyFragmentShader = "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {}"; + unlitShader = new CustomShader(new CustomShaderOptions() + .setLightingModel(LightingModel.UNLIT()).setFragmentShaderText(emptyFragmentShader)); + + translucentWindowsShader = new CustomShader(new CustomShaderOptions().setLightingModel(LightingModel.UNLIT()) + .setTranslucent(true).setFragmentShaderText(String.join("\n", new String[] { + "const float WINDOW = 0.0;", + "const float SKYLIGHT = 4.0;", + "const float TOTAL_FEATURES = 12.0;", + "", + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {", + " // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + "", + " if (featureId == WINDOW || featureId == SKYLIGHT) {", + " material.alpha = 0.4;", + " material.roughness = 0.1;", + " }", + "}", + }))); + + materialShader = new CustomShader(new CustomShaderOptions().setLightingModel(LightingModel.PBR()) + .setTranslucent(true).setFragmentShaderText(String.join("\n", new String[] { + "const float WINDOW = 0.0;", + "const float FRAME = 1.0;", + "const float WALL = 2.0;", + "const float ROOF = 3.0;", + "const float SKYLIGHT = 4.0;", + "const float AIR_CONDITIONER_WHITE = 5.0;", + "const float AIR_CONDITIONER_BLACK = 6.0;", + "const float AIR_CONDITIONER_TALL = 7.0;", + "const float CLOCK = 8.0;", + "const float PILLARS = 9.0;", + "const float STREET_LIGHT = 10.0;", + "const float TRAFFIC_LIGHT = 11.0;", + "", + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {", + " // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + "", + " if (featureId == CLOCK) {", + " // Shiny brass", + " material.specular = vec3(0.98, 0.90, 0.59);", + " material.roughness = 0.3;", + " } else if (", + " featureId == STREET_LIGHT ||", + " featureId == AIR_CONDITIONER_BLACK ||", + " featureId == AIR_CONDITIONER_WHITE ||", + " featureId == AIR_CONDITIONER_TALL ||", + " featureId == ROOF", + " ) {", + " // dull aluminum", + " material.specular = vec3(0.91, 0.92, 0.92);", + " material.roughness = 0.5;", + " } else if (featureId == WINDOW || featureId == SKYLIGHT) {", + " // make translucent, but also set an orange emissive color so it looks like", + " // it's lit from inside", + " material.emissive = vec3(1.0, 0.3, 0.0);", + " material.alpha = 0.5;", + " } else if (featureId == WALL || featureId == FRAME || featureId == PILLARS) {", + " // paint the walls and pillars white to contrast the brass clock", + " material.diffuse = mix(material.diffuse, vec3(1.0), 0.8);", + " material.roughness = 0.9;", + " } else {", + " // brighten everything else", + " material.diffuse += 0.05;", + " material.roughness = 0.9;", + " }", + "}", + }))); + + Number NOTHING_SELECTED = 12; + selectFeatureShader = new CustomShader(new CustomShaderOptions() + .setLightingModel(LightingModel.PBR()) + .addUniform("u_selectedFeature", UniformType.FLOAT(), NOTHING_SELECTED) + .setFragmentShaderText(String.join("\n", new String[] { + "const float NOTHING_SELECTED = 12.0;", + "void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {", + " // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...", + " float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);", + "", + " if (u_selectedFeature < NOTHING_SELECTED && featureId == u_selectedFeature) {", + " material.specular = vec3(1.00, 0.85, 0.57);", + " material.roughness = 0.3;", + " }", + "}", + }))); + + tileset.style = classificationStyle; + tileset.colorBlendMode = Cesium3DTileColorBlendMode.MIX(); + + DivElement nameOverlay = RootPanel.get().getElement().getOwnerDocument().createDivElement(); + nameOverlay.addClassName("backdrop"); + nameOverlay.getStyle().setDisplay(Style.Display.NONE); + nameOverlay.getStyle().setPosition(Style.Position.ABSOLUTE); + nameOverlay.getStyle().setBottom(0., Style.Unit.PX); + nameOverlay.getStyle().setLeft(0., Style.Unit.PX); +// nameOverlay.style["pointer-events"] = "none"; + nameOverlay.getStyle().setPadding(4.0, Style.Unit.PX); + nameOverlay.getStyle().setBackgroundColor("black"); + nameOverlay.getStyle().setWhiteSpace(Style.WhiteSpace.PRE_LINE); + nameOverlay.getStyle().setFontSize(12., Style.Unit.PX); + csVPanel.getViewer().container().appendChild(nameOverlay); + + this.enablePicking = true; + + csVPanel.getViewer().screenSpaceEventHandler().setInputAction(event -> { + MouseMoveEvent movement = (MouseMoveEvent) event; + if (enablePicking) { + PickedObject pickedObject = scene.pick(movement.endPosition); + if (pickedObject instanceof Cesium3DTileFeature) { + nameOverlay.getStyle().setDisplay(Style.Display.BLOCK); + nameOverlay.getStyle().setBottom(csVPanel.getViewer().canvas().getClientHeight() - movement.endPosition.y, Style.Unit.PX); + nameOverlay.getStyle().setLeft(movement.endPosition.x, Style.Unit.PX); + String message = "Component: " + ((Cesium3DTileFeature) pickedObject).getProperty("component") + + "\nFeature ID: " + ((Cesium3DTileFeature) pickedObject).getProperty("_batchId"); + nameOverlay.setInnerText(message); + } else { + nameOverlay.getStyle().setDisplay(Style.Display.NONE); + } + } else { + nameOverlay.getStyle().setDisplay(Style.Display.NONE); + } + }, ScreenSpaceEventType.MOUSE_MOVE()); + + csVPanel.getViewer().screenSpaceEventHandler().setInputAction(event -> { + MouseClickEvent movement = (MouseClickEvent) event; + if (enablePicking) { + PickedObject pickedObject = scene.pick(movement.position); + Object batchId = JsObject.undefined(); + if (pickedObject != null) { + batchId = JsObject.getObject(pickedObject, "_batchId"); + } + Cesium.log(batchId); + if (Cesium.defined(pickedObject) && Cesium.defined(batchId)) { + selectFeatureShader.setUniform("u_selectedFeature", (Number) batchId); + } else { + selectFeatureShader.setUniform("u_selectedFeature", NOTHING_SELECTED); + } + } + }, ScreenSpaceEventType.LEFT_CLICK()); + + CheckBox enablePickingCBox = new CheckBox("Enable picking"); + enablePickingCBox.getElement().getStyle().setColor("white"); + enablePickingCBox.setWidth("100px"); + enablePickingCBox.setValue(this.enablePicking); + enablePickingCBox.addValueChangeHandler(event -> enablePicking = event.getValue()); + + ListBox listBox = new ListBox(); + listBox.addItem("Photogrammetry"); + listBox.addItem("Show Classification"); + listBox.addItem("Translucent Windows"); + listBox.addItem("Stylized PBR Materials"); + listBox.addItem("Golden Touch"); + listBox.addChangeHandler(event -> { + String value = ((ListBox) event.getSource()).getSelectedItemText(); + switch (value) { + case "Photogrammetry": defaults(); break; + case "Show Classification": showClassification(); break; + case "Translucent Windows": translucentWindows(); break; + case "Stylized PBR Materials": pbrMaterials(); break; + case "Golden Touch": goldenTouch(); break; + default: break; + } + }); + + HorizontalPanel hPanel = new HorizontalPanel(); + hPanel.add(enablePickingCBox); + hPanel.add(listBox); + + AbsolutePanel aPanel = new AbsolutePanel(); + aPanel.add(csVPanel); + aPanel.add(hPanel, 20, 20); + + contentPanel.add(new HTML( + "

Load a photogrammetry dataset with feature ID textures from EXT_mesh_features.

")); + contentPanel.add(aPanel); + + initWidget(contentPanel); + + defaults(); + } + + @Override + public String[] getSourceCodeURLs() { + String[] sourceCodeURLs = new String[1]; + sourceCodeURLs[0] = GWT.getModuleBaseURL() + "examples/" + "Tiles3DNextPhotogrammetryClassification.txt"; + return sourceCodeURLs; + } + + private void defaults() { + tileset.style = (Cesium3DTileStyle) JsObject.undefined(); + tileset.customShader = unlitShader; + tileset.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT(); + tileset.colorBlendAmount = 0.5; + } + + private void showClassification() { + defaults(); + tileset.style = classificationStyle; + tileset.colorBlendMode = Cesium3DTileColorBlendMode.MIX(); + } + + private void translucentWindows() { + defaults(); + tileset.customShader = translucentWindowsShader; + } + + private void pbrMaterials() { + defaults(); + tileset.customShader = materialShader; + } + + private void goldenTouch() { + defaults(); + tileset.customShader = selectFeatureShader; + } +} -- GitLab