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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 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