Skip to content

Commit

Permalink
Merge pull request #12141 from timeichfeld-msa/main
Browse files Browse the repository at this point in the history
Fix #11940 : add VerticalExaggeration option to models
  • Loading branch information
ggetz committed Sep 9, 2024
2 parents 009a66d + c0fa214 commit 2cf09cb
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 9 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change Log

### 1.122 - 2024-10-01

#### @cesium/engine

##### Additions :tada:

- Added `enableVerticalExaggeration` option to models. Set this value to `false` to prevent model exaggeration when `Scene.verticalExaggeration` is set to a value other than `1.0`. [#12141](https://github.com/CesiumGS/cesium/pull/12141)

### 1.121.1 - 2024-09-04

This is an npm-only release to extra source maps included in 1.121
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
- [T2 Software](http://t2.com.tr/)
- [Hüseyin ATEŞ](https://github.com/ateshuseyin)
- [İbrahim Furkan Aygar](https://github.com/furkanaygar)
- MSA
- [Timothy Eichfeld](https://github.com/timeichfeld-msa)
- [EMapGis](http://emapgis.com)
- [IKangXu](https://github.com/IKangXu)
- [EMapGIS](https://github.com/EMapGIS)
Expand Down
20 changes: 20 additions & 0 deletions packages/engine/Source/DataSources/ModelGraphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function createArticulationStagePropertyBag(value) {
* @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the model.
* @property {Property | string | Resource} [uri] A string or Resource Property specifying the URI of the glTF asset.
* @property {Property | number} [scale=1.0] A numeric Property specifying a uniform linear scale.
* @property {Property | boolean} [enableVerticalExaggeration=true] A boolean Property specifying if the model is exaggerated along the ellipsoid normal when {@link Scene.verticalExaggeration} is set to a value other than <code>1.0</code>.
* @property {Property | number} [minimumPixelSize=0.0] A numeric Property specifying the approximate minimum pixel size of the model regardless of zoom.
* @property {Property | number} [maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.
* @property {Property | boolean} [incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded.
Expand Down Expand Up @@ -70,6 +71,10 @@ function ModelGraphics(options) {
this._uriSubscription = undefined;
this._scale = undefined;
this._scaleSubscription = undefined;
this._hasVerticalExaggeration = undefined;
this._hasVerticalExaggerationSubscription = undefined;
this._enableVerticalExaggeration = undefined;
this._enableVerticalExaggerationSubscription = undefined;
this._minimumPixelSize = undefined;
this._minimumPixelSizeSubscription = undefined;
this._maximumScale = undefined;
Expand Down Expand Up @@ -150,6 +155,16 @@ Object.defineProperties(ModelGraphics.prototype, {
*/
scale: createPropertyDescriptor("scale"),

/**
* Gets or sets the boolean Property specifying if the model is exaggerated along the ellipsoid normal when {@link Scene.verticalExaggeration} is set to a value other than <code>1.0</code>.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default true
*/
enableVerticalExaggeration: createPropertyDescriptor(
"enableVerticalExaggeration"
),

/**
* Gets or sets the numeric Property specifying the approximate minimum
* pixel size of the model regardless of zoom. This can be used to ensure that
Expand Down Expand Up @@ -333,6 +348,7 @@ ModelGraphics.prototype.clone = function (result) {
result.show = this.show;
result.uri = this.uri;
result.scale = this.scale;
result.enableVerticalExaggeration = this.enableVerticalExaggeration;
result.minimumPixelSize = this.minimumPixelSize;
result.maximumScale = this.maximumScale;
result.incrementallyLoadTextures = this.incrementallyLoadTextures;
Expand Down Expand Up @@ -370,6 +386,10 @@ ModelGraphics.prototype.merge = function (source) {
this.show = defaultValue(this.show, source.show);
this.uri = defaultValue(this.uri, source.uri);
this.scale = defaultValue(this.scale, source.scale);
this.enableVerticalExaggeration = defaultValue(
this.enableVerticalExaggeration,
source.enableVerticalExaggeration
);
this.minimumPixelSize = defaultValue(
this.minimumPixelSize,
source.minimumPixelSize
Expand Down
8 changes: 8 additions & 0 deletions packages/engine/Source/DataSources/ModelVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Property from "./Property.js";
import Cartographic from "../Core/Cartographic.js";

const defaultScale = 1.0;
const defaultEnableVerticalExaggeration = true;
const defaultMinimumPixelSize = 0.0;
const defaultIncrementallyLoadTextures = true;
const defaultClampAnimations = true;
Expand Down Expand Up @@ -198,6 +199,13 @@ ModelVisualizer.prototype.update = function (time) {
time,
defaultScale
);

model.enableVerticalExaggeration = Property.getValueOrDefault(
modelGraphics._enableVerticalExaggeration,
time,
defaultEnableVerticalExaggeration
);

model.minimumPixelSize = Property.getValueOrDefault(
modelGraphics._minimumPixelSize,
time,
Expand Down
63 changes: 57 additions & 6 deletions packages/engine/Source/Scene/Model/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ import pickModel from "./pickModel.js";
* @privateParam {boolean} [options.show=true] Whether or not to render the model.
* @privateParam {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms the model from model to world coordinates.
* @privateParam {number} [options.scale=1.0] A uniform scale applied to this model.
* @privateParam {boolean} [options.enableVerticalExaggeration=true] If <code>true</code>, the model is exaggerated along the ellipsoid normal when {@link Scene.verticalExaggeration} is set to a value other than <code>1.0</code>.
* @privateParam {number} [options.minimumPixelSize=0.0] The approximate minimum pixel size of the model regardless of zoom.
* @privateParam {number} [options.maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.
* @privateParam {object} [options.id] A user-defined object to return when the model is picked with {@link Scene#pick}.
Expand Down Expand Up @@ -161,7 +162,7 @@ import pickModel from "./pickModel.js";
* @privateParam {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.
* @privateParam {object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
* @privateParam {ClassificationType} [options.classificationType] Determines whether terrain, 3D Tiles or both will be classified by this model. This cannot be set after the model has loaded.
*
*
* @see Model.fromGltfAsync
*
Expand Down Expand Up @@ -340,7 +341,11 @@ function Model(options) {
this._heightDirty = this._heightReference !== HeightReference.NONE;
this._removeUpdateHeightCallback = undefined;

this._verticalExaggerationOn = false;
this._enableVerticalExaggeration = defaultValue(
options.enableVerticalExaggeration,
true
);
this._hasVerticalExaggeration = false;

this._clampedModelMatrix = undefined; // For use with height reference

Expand Down Expand Up @@ -1339,6 +1344,45 @@ Object.defineProperties(Model.prototype, {
},
},

/**
* If <code>true</code>, the model is exaggerated along the ellipsoid normal when {@link Scene.verticalExaggeration} is set to a value other than <code>1.0</code>.
*
* @memberof Model.prototype
* @type {boolean}
* @default true
*
* @example
* // Exaggerate terrain by a factor of 2, but prevent model exaggeration
* scene.verticalExaggeration = 2.0;
* model.enableVerticalExaggeration = false;
*/
enableVerticalExaggeration: {
get: function () {
return this._enableVerticalExaggeration;
},
set: function (value) {
if (value !== this._enableVerticalExaggeration) {
this.resetDrawCommands();
}
this._enableVerticalExaggeration = value;
},
},

/**
* If <code>true</code>, the model is vertically exaggerated along the ellipsoid normal.
*
* @memberof Model.prototype
* @type {boolean}
* @default true
* @readonly
* @private
*/
hasVerticalExaggeration: {
get: function () {
return this._hasVerticalExaggeration;
},
},

/**
* The light color when shading the model. When <code>undefined</code> the scene's light color is used instead.
* <p>
Expand Down Expand Up @@ -2062,10 +2106,15 @@ function updateFog(model, frameState) {
}

function updateVerticalExaggeration(model, frameState) {
const verticalExaggerationNeeded = frameState.verticalExaggeration !== 1.0;
if (model._verticalExaggerationOn !== verticalExaggerationNeeded) {
model.resetDrawCommands();
model._verticalExaggerationOn = verticalExaggerationNeeded;
if (model.enableVerticalExaggeration) {
const verticalExaggerationNeeded = frameState.verticalExaggeration !== 1.0;
if (model.hasVerticalExaggeration !== verticalExaggerationNeeded) {
model.resetDrawCommands();
model._hasVerticalExaggeration = verticalExaggerationNeeded;
}
} else if (model.hasVerticalExaggeration) {
model.resetDrawCommands(); //if verticalExaggeration was on, reset.
model._hasVerticalExaggeration = false;
}
}

Expand Down Expand Up @@ -2748,6 +2797,7 @@ Model.prototype.destroyModelResources = function () {
* @param {boolean} [options.show=true] Whether or not to render the model.
* @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms the model from model to world coordinates.
* @param {number} [options.scale=1.0] A uniform scale applied to this model.
* @param {boolean} [options.enableVerticalExaggeration=true] If <code>true</code>, the model is exaggerated along the ellipsoid normal when {@link Scene.verticalExaggeration} is set to a value other than <code>1.0</code>.
* @param {number} [options.minimumPixelSize=0.0] The approximate minimum pixel size of the model regardless of zoom.
* @param {number} [options.maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.
* @param {object} [options.id] A user-defined object to return when the model is picked with {@link Scene#pick}.
Expand Down Expand Up @@ -3116,6 +3166,7 @@ function makeModelOptions(loader, modelType, options) {
show: options.show,
modelMatrix: options.modelMatrix,
scale: options.scale,
enableVerticalExaggeration: options.enableVerticalExaggeration,
minimumPixelSize: options.minimumPixelSize,
maximumScale: options.maximumScale,
id: options.id,
Expand Down
5 changes: 3 additions & 2 deletions packages/engine/Source/Scene/Model/ModelRuntimePrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ ModelRuntimePrimitive.prototype.configurePipeline = function (frameState) {
const mode = frameState.mode;
const use2D =
mode !== SceneMode.SCENE3D && !frameState.scene3DOnly && model._projectTo2D;
const exaggerateTerrain = frameState.verticalExaggeration !== 1.0;
const hasVerticalExaggeration =
frameState.verticalExaggeration !== 1.0 && model.hasVerticalExaggeration;

const hasMorphTargets =
defined(primitive.morphTargets) && primitive.morphTargets.length > 0;
Expand Down Expand Up @@ -283,7 +284,7 @@ ModelRuntimePrimitive.prototype.configurePipeline = function (frameState) {
pipelineStages.push(CPUStylingPipelineStage);
}

if (exaggerateTerrain) {
if (hasVerticalExaggeration) {
pipelineStages.push(VerticalExaggerationPipelineStage);
}

Expand Down
28 changes: 28 additions & 0 deletions packages/engine/Specs/Scene/Model/ModelRuntimePrimitiveSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe("Scene/Model/ModelRuntimePrimitive", function () {
type: ModelType.GLTF,
allowPicking: true,
featureIdLabel: "featureId_0",
hasVerticalExaggeration: true,
};
const mockWebgl1Context = {
webgl2: false,
Expand Down Expand Up @@ -992,4 +993,31 @@ describe("Scene/Model/ModelRuntimePrimitive", function () {
primitive.configurePipeline(frameState);
verifyExpectedStages(primitive.pipelineStages, expectedStages);
});

it("configures pipeline stages for vertical exaggeration when enableVerticalExaggeration is false", function () {
const primitive = new ModelRuntimePrimitive({
primitive: mockPrimitive,
node: mockNode,
model: {
...mockModel,
hasVerticalExaggeration: false,
},
});
const frameState = createFrameState(mockWebgl2Context);
frameState.verticalExaggeration = 2.0;

const expectedStages = [
GeometryPipelineStage,
MaterialPipelineStage,
FeatureIdPipelineStage,
MetadataPipelineStage,
LightingPipelineStage,
PickingPipelineStage,
AlphaPipelineStage,
PrimitiveStatisticsPipelineStage,
];

primitive.configurePipeline(frameState);
verifyExpectedStages(primitive.pipelineStages, expectedStages);
});
});
25 changes: 24 additions & 1 deletion packages/engine/Specs/Scene/Model/ModelSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ describe(
expect(model.id).toBeUndefined();
expect(model.allowPicking).toEqual(true);

expect(model.enableVerticalExaggeration).toEqual(true);

expect(model.activeAnimations).toBeDefined();
expect(model.clampAnimations).toEqual(true);

Expand Down Expand Up @@ -3769,7 +3771,28 @@ describe(
scene.verticalExaggeration = 2.0;
scene.renderForSpecs();
expect(resetDrawCommands).toHaveBeenCalled();
scene.verticalExaggeration = 1.0;
});

it("resets draw commands when enableVerticalExaggeration changes", async function () {
scene.verticalExaggeration = 2.0;
const model = await loadAndZoomToModelAsync(
{
gltf: boxTexturedGltfUrl,
},
scene
);
const resetDrawCommands = spyOn(
model,
"resetDrawCommands"
).and.callThrough();
expect(model.ready).toBe(true);
expect(model.hasVerticalExaggeration).toBe(true);

model.enableVerticalExaggeration = false;

scene.renderForSpecs();
expect(resetDrawCommands).toHaveBeenCalled();
expect(model.hasVerticalExaggeration).toBe(false);
});

it("does not issue draw commands when ignoreCommands is true", async function () {
Expand Down

0 comments on commit 2cf09cb

Please sign in to comment.