Skip to content

Commit cfa3042

Browse files
authored
Merge pull request #10481 from CesiumGS/model-experimental-distance-display-condition
Add `distanceDisplayCondition` to `ModelExperimental`
2 parents 5b9baaf + ded5160 commit cfa3042

File tree

4 files changed

+183
-11
lines changed

4 files changed

+183
-11
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- Added `modelUpAxis` and `modelForwardAxis` constructor options to `Cesium3DTileset` [#10439](https://github.com/CesiumGS/cesium/pull/10439)
1616
- Added `heightReference` to `ModelExperimental`. [#10448](https://github.com/CesiumGS/cesium/pull/10448)
1717
- Added `silhouetteSize` and `silhouetteColor` to `ModelExperimental`. [#10457](https://github.com/CesiumGS/cesium/pull/10457)
18+
- Added `distanceDisplayCondition` to `ModelExperimental`. [#10481](https://github.com/CesiumGS/cesium/pull/10481)
1819
- Added support for `AGI_articulations` to `ModelExperimental`. [#10479](https://github.com/CesiumGS/cesium/pull/10479)
1920

2021
##### Fixes :wrench:

Source/Scene/ModelExperimental/ModelExperimental.js

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ClippingPlaneCollection from "../ClippingPlaneCollection.js";
77
import defined from "../../Core/defined.js";
88
import defaultValue from "../../Core/defaultValue.js";
99
import DeveloperError from "../../Core/DeveloperError.js";
10+
import DistanceDisplayCondition from "../../Core/DistanceDisplayCondition.js";
1011
import GltfLoader from "../GltfLoader.js";
1112
import HeightReference from "../HeightReference.js";
1213
import ImageBasedLighting from "../ImageBasedLighting.js";
@@ -49,33 +50,34 @@ import SplitDirection from "../SplitDirection.js";
4950
* @param {Number} [options.scale=1.0] A uniform scale applied to this model.
5051
* @param {Number} [options.minimumPixelSize=0.0] The approximate minimum pixel size of the model regardless of zoom.
5152
* @param {Number} [options.maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.
53+
* @param {Boolean} [options.allowPicking=true] When <code>true</code>, each primitive is pickable with {@link Scene#pick}.
5254
* @param {Boolean} [options.clampAnimations=true] Determines if the model's animations should hold a pose over frames where no keyframes are specified.
55+
* @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from light sources.
5356
* @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model.
5457
* @param {Boolean} [options.enableDebugWireframe=false] For debugging only. This must be set to true for debugWireframe to work in WebGL1. This cannot be set after the model has loaded.
5558
* @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe. Will only work for WebGL1 if enableDebugWireframe is set to true.
5659
* @param {Boolean} [options.cull=true] Whether or not to cull the model using frustum/horizon culling. If the model is part of a 3D Tiles tileset, this property will always be false, since the 3D Tiles culling system is used.
5760
* @param {Boolean} [options.opaquePass=Pass.OPAQUE] The pass to use in the {@link DrawCommand} for the opaque portions of the model.
58-
* @param {Boolean} [options.allowPicking=true] When <code>true</code>, each primitive is pickable with {@link Scene#pick}.
5961
* @param {CustomShader} [options.customShader] A custom shader. This will add user-defined GLSL code to the vertex and fragment shaders. Using custom shaders with a {@link Cesium3DTileStyle} may lead to undefined behavior.
6062
* @param {Cesium3DTileContent} [options.content] The tile content this model belongs to. This property will be undefined if model is not loaded as part of a tileset.
6163
* @param {HeightReference} [options.heightReference=HeightReference.NONE] Determines how the model is drawn relative to terrain.
6264
* @param {Scene} [options.scene] Must be passed in for models that use the height reference property.
65+
* @param {DistanceDisplayCondition} [options.distanceDisplayCondition] The condition specifying at what distance from the camera that this model will be displayed.
6366
* @param {Color} [options.color] A color that blends with the model's rendered color.
6467
* @param {ColorBlendMode} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] Defines how the color blends with the model.
6568
* @param {Number} [options.colorBlendAmount=0.5] Value used to determine the color strength when the <code>colorBlendMode</code> is <code>MIX</code>. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.
6669
* @param {Color} [options.silhouetteColor=Color.RED] The silhouette color. If more than 256 models have silhouettes enabled, there is a small chance that overlapping models will have minor artifacts.
6770
* @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels.
68-
* @param {String|Number} [options.featureIdLabel="featureId_0"] Label of the feature ID set to use for picking and styling. For EXT_mesh_features, this is the feature ID's label property, or "featureId_N" (where N is the index in the featureIds array) when not specified. EXT_feature_metadata did not have a label field, so such feature ID sets are always labeled "featureId_N" where N is the index in the list of all feature Ids, where feature ID attributes are listed before feature ID textures. If featureIdLabel is an integer N, it is converted to the string "featureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
69-
* @param {String|Number} [options.instanceFeatureIdLabel="instanceFeatureId_0"] Label of the instance feature ID set used for picking and styling. If instanceFeatureIdLabel is set to an integer N, it is converted to the string "instanceFeatureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
70-
* @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
7171
* @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model.
7272
* @param {Cartesian3} [options.lightColor] The light color when shading the model. When <code>undefined</code> the scene's light color is used instead.
7373
* @param {ImageBasedLighting} [options.imageBasedLighting] The properties for managing image-based lighting on this model.
7474
* @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the material's doubleSided property; when false, back face culling is disabled. Back faces are not culled if the model's color is translucent.
75-
* @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from light sources.
7675
* @param {Boolean} [options.showCreditsOnScreen=false] Whether to display the credits of this model on screen.
7776
* @param {SplitDirection} [options.splitDirection=SplitDirection.NONE] The {@link SplitDirection} split to apply to this model.
7877
* @param {Boolean} [options.projectTo2D=false] Whether to accurately project the model's positions in 2D. If this is true, the model will be projected accurately to 2D, but it will use more memory to do so. If this is false, the model will use less memory and will still render in 2D / CV mode, but its positions may be inaccurate. This disables minimumPixelSize and prevents future modification to the model matrix. This also cannot be set after the model has loaded.
78+
* @param {String|Number} [options.featureIdLabel="featureId_0"] Label of the feature ID set to use for picking and styling. For EXT_mesh_features, this is the feature ID's label property, or "featureId_N" (where N is the index in the featureIds array) when not specified. EXT_feature_metadata did not have a label field, so such feature ID sets are always labeled "featureId_N" where N is the index in the list of all feature Ids, where feature ID attributes are listed before feature ID textures. If featureIdLabel is an integer N, it is converted to the string "featureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
79+
* @param {String|Number} [options.instanceFeatureIdLabel="instanceFeatureId_0"] Label of the instance feature ID set used for picking and styling. If instanceFeatureIdLabel is set to an integer N, it is converted to the string "instanceFeatureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
80+
* @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
7981
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
8082
*/
8183
export default function ModelExperimental(options) {
@@ -248,6 +250,8 @@ export default function ModelExperimental(options) {
248250
}
249251
this._scene = scene;
250252

253+
this._distanceDisplayCondition = options.distanceDisplayCondition;
254+
251255
const pointCloudShading = new PointCloudShading(options.pointCloudShading);
252256
this._attenuation = pointCloudShading.attenuation;
253257
this._pointCloudShading = pointCloudShading;
@@ -685,6 +689,33 @@ Object.defineProperties(ModelExperimental.prototype, {
685689
},
686690
},
687691

692+
/**
693+
* Gets or sets the distance display condition, which specifies at what distance
694+
* from the camera this model will be displayed.
695+
*
696+
* @memberof ModelExperimental.prototype
697+
*
698+
* @type {DistanceDisplayCondition}
699+
* @default undefined
700+
*
701+
*/
702+
distanceDisplayCondition: {
703+
get: function () {
704+
return this._distanceDisplayCondition;
705+
},
706+
set: function (value) {
707+
//>>includeStart('debug', pragmas.debug);
708+
if (defined(value) && value.far <= value.near) {
709+
throw new DeveloperError("far must be greater than near");
710+
}
711+
//>>includeEnd('debug');
712+
this._distanceDisplayCondition = DistanceDisplayCondition.clone(
713+
value,
714+
this._distanceDisplayCondition
715+
);
716+
},
717+
},
718+
688719
/**
689720
* The structural metadata from the EXT_structural_metadata extension
690721
*
@@ -1723,13 +1754,22 @@ function submitDrawCommands(model, frameState) {
17231754
// we want the user to be able to instantly see the model
17241755
// when show is set to true.
17251756

1757+
const displayConditionPassed = passesDistanceDisplayCondition(
1758+
model,
1759+
frameState
1760+
);
1761+
17261762
const invisible = model.isInvisible();
17271763
const silhouette = model.hasSilhouette(frameState);
1764+
17281765
// If the model is invisible but has a silhouette, it still
17291766
// needs to draw in order to write to the stencil buffer and
17301767
// render the silhouette.
17311768
const showModel =
1732-
model._show && model._computedScale !== 0 && (!invisible || silhouette);
1769+
model._show &&
1770+
model._computedScale !== 0 &&
1771+
displayConditionPassed &&
1772+
(!invisible || silhouette);
17331773

17341774
if (showModel) {
17351775
const asset = model._sceneGraph.components.asset;
@@ -1827,6 +1867,43 @@ function getUpdateHeightCallback(model, ellipsoid, cartoPosition) {
18271867
};
18281868
}
18291869

1870+
const scratchDisplayConditionCartesian = new Cartesian3();
1871+
1872+
function passesDistanceDisplayCondition(model, frameState) {
1873+
const condition = model.distanceDisplayCondition;
1874+
if (!defined(condition)) {
1875+
return true;
1876+
}
1877+
1878+
const nearSquared = condition.near * condition.near;
1879+
const farSquared = condition.far * condition.far;
1880+
let distanceSquared;
1881+
1882+
if (frameState.mode === SceneMode.SCENE2D) {
1883+
const frustum2DWidth =
1884+
frameState.camera.frustum.right - frameState.camera.frustum.left;
1885+
const distance = frustum2DWidth * 0.5;
1886+
distanceSquared = distance * distance;
1887+
} else {
1888+
// Distance to center of primitive's reference frame
1889+
const position = Matrix4.getTranslation(
1890+
model.modelMatrix,
1891+
scratchDisplayConditionCartesian
1892+
);
1893+
1894+
// This will project the position if the scene is in Columbus View,
1895+
// but leave the position as-is in 3D mode.
1896+
SceneTransforms.computeActualWgs84Position(frameState, position, position);
1897+
1898+
distanceSquared = Cartesian3.distanceSquared(
1899+
position,
1900+
frameState.camera.positionWC
1901+
);
1902+
}
1903+
1904+
return distanceSquared >= nearSquared && distanceSquared <= farSquared;
1905+
}
1906+
18301907
/**
18311908
* Gets whether or not the model is translucent based on its assigned model color.
18321909
* If the model color's alpha is equal to zero, then it is considered invisible,
@@ -2010,6 +2087,9 @@ ModelExperimental.prototype.destroyModelResources = function () {
20102087
* @param {Number} [options.minimumPixelSize=0.0] The approximate minimum pixel size of the model regardless of zoom.
20112088
* @param {Number} [options.maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.
20122089
* @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded.
2090+
* @param {Boolean} [options.allowPicking=true] When <code>true</code>, each primitive is pickable with {@link Scene#pick}.
2091+
* @param {Boolean} [options.clampAnimations=true] Determines if the model's animations should hold a pose over frames where no keyframes are specified.
2092+
* @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from light sources.
20132093
* @param {Boolean} [options.releaseGltfJson=false] When true, the glTF JSON is released once the glTF is loaded. This is is especially useful for cases like 3D Tiles, where each .gltf model is unique and caching the glTF JSON is not effective.
20142094
* @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model.
20152095
* @param {Boolean} [options.enableDebugWireframe=false] For debugging only. This must be set to true for debugWireframe to work in WebGL1. This cannot be set after the model has loaded.
@@ -2018,27 +2098,26 @@ ModelExperimental.prototype.destroyModelResources = function () {
20182098
* @param {Boolean} [options.opaquePass=Pass.OPAQUE] The pass to use in the {@link DrawCommand} for the opaque portions of the model.
20192099
* @param {Axis} [options.upAxis=Axis.Y] The up-axis of the glTF model.
20202100
* @param {Axis} [options.forwardAxis=Axis.Z] The forward-axis of the glTF model.
2021-
* @param {Boolean} [options.allowPicking=true] When <code>true</code>, each primitive is pickable with {@link Scene#pick}.
20222101
* @param {CustomShader} [options.customShader] A custom shader. This will add user-defined GLSL code to the vertex and fragment shaders. Using custom shaders with a {@link Cesium3DTileStyle} may lead to undefined behavior.
20232102
* @param {Cesium3DTileContent} [options.content] The tile content this model belongs to. This property will be undefined if model is not loaded as part of a tileset.
20242103
* @param {HeightReference} [options.heightReference=HeightReference.NONE] Determines how the model is drawn relative to terrain.
20252104
* @param {Scene} [options.scene] Must be passed in for models that use the height reference property.
2105+
* @param {DistanceDisplayCondition} [options.distanceDisplayCondition] The condition specifying at what distance from the camera that this model will be displayed.
20262106
* @param {Color} [options.color] A color that blends with the model's rendered color.
20272107
* @param {ColorBlendMode} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] Defines how the color blends with the model.
20282108
* @param {Number} [options.colorBlendAmount=0.5] Value used to determine the color strength when the <code>colorBlendMode</code> is <code>MIX</code>. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.
20292109
* @param {Color} [options.silhouetteColor=Color.RED] The silhouette color. If more than 256 models have silhouettes enabled, there is a small chance that overlapping models will have minor artifacts.
20302110
* @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels.
2031-
* @param {String|Number} [options.featureIdLabel="featureId_0"] Label of the feature ID set to use for picking and styling. For EXT_mesh_features, this is the feature ID's label property, or "featureId_N" (where N is the index in the featureIds array) when not specified. EXT_feature_metadata did not have a label field, so such feature ID sets are always labeled "featureId_N" where N is the index in the list of all feature Ids, where feature ID attributes are listed before feature ID textures. If featureIdLabel is an integer N, it is converted to the string "featureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
2032-
* @param {String|Number} [options.instanceFeatureIdLabel="instanceFeatureId_0"] Label of the instance feature ID set used for picking and styling. If instanceFeatureIdLabel is set to an integer N, it is converted to the string "instanceFeatureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
2033-
* @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation and lighting.
20342111
* @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model.
20352112
* @param {Cartesian3} [options.lightColor] The light color when shading the model. When <code>undefined</code> the scene's light color is used instead.
20362113
* @param {ImageBasedLighting} [options.imageBasedLighting] The properties for managing image-based lighting on this model.
20372114
* @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the material's doubleSided property; when false, back face culling is disabled. Back faces are not culled if the model's color is translucent.
2038-
* @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from light sources.
20392115
* @param {Boolean} [options.showCreditsOnScreen=false] Whether to display the credits of this model on screen.
20402116
* @param {SplitDirection} [options.splitDirection=SplitDirection.NONE] The {@link SplitDirection} split to apply to this model.
20412117
* @param {Boolean} [options.projectTo2D=false] Whether to accurately project the model's positions in 2D. If this is true, the model will be projected accurately to 2D, but it will use more memory to do so. If this is false, the model will use less memory and will still render in 2D / CV mode, but its positions may be inaccurate. This disables minimumPixelSize and prevents future modification to the model matrix. This also cannot be set after the model has loaded.
2118+
* @param {String|Number} [options.featureIdLabel="featureId_0"] Label of the feature ID set to use for picking and styling. For EXT_mesh_features, this is the feature ID's label property, or "featureId_N" (where N is the index in the featureIds array) when not specified. EXT_feature_metadata did not have a label field, so such feature ID sets are always labeled "featureId_N" where N is the index in the list of all feature Ids, where feature ID attributes are listed before feature ID textures. If featureIdLabel is an integer N, it is converted to the string "featureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
2119+
* @param {String|Number} [options.instanceFeatureIdLabel="instanceFeatureId_0"] Label of the instance feature ID set used for picking and styling. If instanceFeatureIdLabel is set to an integer N, it is converted to the string "instanceFeatureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
2120+
* @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation and lighting.
20422121
* @returns {ModelExperimental} The newly created model.
20432122
*/
20442123
ModelExperimental.fromGltf = function (options) {
@@ -2251,5 +2330,6 @@ function makeModelOptions(loader, modelType, options) {
22512330
showCreditsOnScreen: options.showCreditsOnScreen,
22522331
splitDirection: options.splitDirection,
22532332
projectTo2D: options.projectTo2D,
2333+
distanceDisplayCondition: options.distanceDisplayCondition,
22542334
};
22552335
}

0 commit comments

Comments
 (0)