Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add label scale by distance #5019

Merged
merged 3 commits into from
Feb 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Apps/Sandcastle/gallery/Labels.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@
});
}

function scaleByDistance() {
Sandcastle.declare(scaleByDistance);

viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Philadelphia',
scaleByDistance : new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5)
}
});
}

Sandcastle.addToolbarMenu([{
text : 'Add label',
onselect : function() {
Expand Down Expand Up @@ -139,6 +151,12 @@
fadeByDistance();
Sandcastle.highlight(fadeByDistance);
}
}, {
text : 'Scale label by distance',
onselect : function() {
scaleByDistance();
Sandcastle.highlight(scaleByDistance);
}
}]);

Sandcastle.reset = function() {
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Change Log
* Fixed exception in 2D in certain cases with polylines when rotating the map. [#4619](https://github.com/AnalyticalGraphicsInc/cesium/issues/4619)
* Fixed an issue with constant `VertexArray` attributes not being set correctly. [#4995](https://github.com/AnalyticalGraphicsInc/cesium/pull/4995)
* Add support for `Scene.pickPosition` in Columbus view and 2D. [#4990](https://github.com/AnalyticalGraphicsInc/cesium/pull/4990)
* Added `Label.scaleByDistance` to control minimum/maximum label size based on distance from the camera. [#5019](https://github.com/AnalyticalGraphicsInc/cesium/pull/5019)

### 1.30 - 2017-02-01

Expand Down
17 changes: 17 additions & 0 deletions Source/DataSources/LabelGraphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ define([
* @param {Property} [options.pixelOffset=Cartesian2.ZERO] A {@link Cartesian2} Property specifying the pixel offset.
* @param {Property} [options.translucencyByDistance] A {@link NearFarScalar} Property used to set translucency based on distance from the camera.
* @param {Property} [options.pixelOffsetScaleByDistance] A {@link NearFarScalar} Property used to set pixelOffset based on distance from the camera.
* @param {Property} [options.scaleByDistance] A {@link NearFarScalar} Property used to set scale based on distance from the camera.
* @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to.
* @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this label will be displayed.
*
Expand Down Expand Up @@ -87,6 +88,8 @@ define([
this._translucencyByDistanceSubscription = undefined;
this._pixelOffsetScaleByDistance = undefined;
this._pixelOffsetScaleByDistanceSubscription = undefined;
this._scaleByDistance = undefined;
this._scaleByDistanceSubscription = undefined;
this._distanceDisplayCondition = undefined;
this._distanceDisplayConditionSubscription = undefined;
this._definitionChanged = new Event();
Expand Down Expand Up @@ -289,6 +292,18 @@ define([
*/
pixelOffsetScaleByDistance : createPropertyDescriptor('pixelOffsetScaleByDistance'),

/**
* Gets or sets near and far scaling properties of a Label based on the label's distance from the camera.
* A label's scale will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined,
* scaleByDistance will be disabled.
* @memberof LabelGraphics.prototype
* @type {Property}
*/
scaleByDistance : createPropertyDescriptor('scaleByDistance'),

/**
* Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this label will be displayed.
* @memberof LabelGraphics.prototype
Expand Down Expand Up @@ -325,6 +340,7 @@ define([
result.pixelOffset = this.pixelOffset;
result.translucencyByDistance = this.translucencyByDistance;
result.pixelOffsetScaleByDistance = this.pixelOffsetScaleByDistance;
result.scaleByDistance = this.scaleByDistance;
result.distanceDisplayCondition = this.distanceDisplayCondition;
return result;
};
Expand Down Expand Up @@ -360,6 +376,7 @@ define([
this.pixelOffset = defaultValue(this.pixelOffset, source.pixelOffset);
this.translucencyByDistance = defaultValue(this._translucencyByDistance, source.translucencyByDistance);
this.pixelOffsetScaleByDistance = defaultValue(this._pixelOffsetScaleByDistance, source.pixelOffsetScaleByDistance);
this.scaleByDistance = defaultValue(this._scaleByDistance, source.scaleByDistance);
this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition);
};

Expand Down
2 changes: 2 additions & 0 deletions Source/DataSources/LabelVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ define([
var pixelOffset = new Cartesian2();
var translucencyByDistance = new NearFarScalar();
var pixelOffsetScaleByDistance = new NearFarScalar();
var scaleByDistance = new NearFarScalar();
var distanceDisplayCondition = new DistanceDisplayCondition();

function EntityData(entity) {
Expand Down Expand Up @@ -161,6 +162,7 @@ define([
label.verticalOrigin = Property.getValueOrDefault(labelGraphics._verticalOrigin, time, defaultVerticalOrigin);
label.translucencyByDistance = Property.getValueOrUndefined(labelGraphics._translucencyByDistance, time, translucencyByDistance);
label.pixelOffsetScaleByDistance = Property.getValueOrUndefined(labelGraphics._pixelOffsetScaleByDistance, time, pixelOffsetScaleByDistance);
label.scaleByDistance = Property.getValueOrUndefined(labelGraphics._scaleByDistance, time, scaleByDistance);
label.distanceDisplayCondition = Property.getValueOrUndefined(labelGraphics._distanceDisplayCondition, time, distanceDisplayCondition);
}
return true;
Expand Down
57 changes: 57 additions & 0 deletions Source/Scene/Label.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ define([
if (defined(options.pixelOffsetScaleByDistance) && options.pixelOffsetScaleByDistance.far <= options.pixelOffsetScaleByDistance.near) {
throw new DeveloperError('pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.');
}
if (defined(options.scaleByDistance) && options.scaleByDistance.far <= options.scaleByDistance.near) {
throw new DeveloperError('scaleByDistance.far must be greater than scaleByDistance.near.');
}
if (defined(options.distanceDisplayCondition) && options.distanceDisplayCondition.far <= options.distanceDisplayCondition.near) {
throw new DeveloperError('distanceDisplayCondition.far must be greater than distanceDisplayCondition.near');
}
Expand All @@ -99,6 +102,7 @@ define([
this._id = options.id;
this._translucencyByDistance = options.translucencyByDistance;
this._pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance;
this._scaleByDistance = options.scaleByDistance;
this._heightReference = defaultValue(options.heightReference, HeightReference.NONE);
this._distanceDisplayCondition = options.distanceDisplayCondition;

Expand Down Expand Up @@ -613,6 +617,58 @@ define([
}
},

/**
* Gets or sets near and far scaling properties of a Label based on the label's distance from the camera.
* A label's scale will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined,
* scaleByDistance will be disabled.
* @memberof Label.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a label's scaleByDistance to scale by 1.5 when the
* // camera is 1500 meters from the label and disappear as
* // the camera distance approaches 8.0e6 meters.
* label.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable scaling by distance
* label.scaleByDistance = undefined;
*/
scaleByDistance : {
get : function() {
return this._scaleByDistance;
},
set : function(value) {
//>>includeStart('debug', pragmas.debug);
if (defined(value) && value.far <= value.near) {
throw new DeveloperError('far distance must be greater than near distance.');
}
//>>includeEnd('debug');

var scaleByDistance = this._scaleByDistance;
if (!NearFarScalar.equals(scaleByDistance, value)) {
this._scaleByDistance = NearFarScalar.clone(value, scaleByDistance);

var glyphs = this._glyphs;
for (var i = 0, len = glyphs.length; i < len; i++) {
var glyph = glyphs[i];
if (defined(glyph.billboard)) {
glyph.billboard.scaleByDistance = value;
}
}
var backgroundBillboard = this._backgroundBillboard;
if (defined(backgroundBillboard)) {
backgroundBillboard.scaleByDistance = value;
}
}
}
},

/**
* Gets and sets the 3D Cartesian offset applied to this label in eye coordinates. Eye coordinates is a left-handed
* coordinate system, where <code>x</code> points towards the viewer's right, <code>y</code> points up, and
Expand Down Expand Up @@ -1066,6 +1122,7 @@ define([
Cartesian3.equals(this._eyeOffset, other._eyeOffset) &&
NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance) &&
NearFarScalar.equals(this._pixelOffsetScaleByDistance, other._pixelOffsetScaleByDistance) &&
NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) &&
DistanceDisplayCondition.equals(this._distanceDisplayCondition, other._distanceDisplayCondition) &&
this._id === other._id;
};
Expand Down
2 changes: 2 additions & 0 deletions Source/Scene/LabelCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ define([
backgroundBillboard.id = label._id;
backgroundBillboard.translucencyByDistance = label._translucencyByDistance;
backgroundBillboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance;
backgroundBillboard.scaleByDistance = label._scaleByDistance;
backgroundBillboard.distanceDisplayCondition = label._distanceDisplayCondition;
}

Expand Down Expand Up @@ -263,6 +264,7 @@ define([
billboard.image = id;
billboard.translucencyByDistance = label._translucencyByDistance;
billboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance;
billboard.scaleByDistance = label._scaleByDistance;
billboard.distanceDisplayCondition = label._distanceDisplayCondition;
}
}
Expand Down
60 changes: 31 additions & 29 deletions Source/Shaders/BillboardCollectionVS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
attribute vec2 direction;
#endif
attribute vec4 positionHighAndScale;
attribute vec4 positionLowAndRotation;
attribute vec4 positionLowAndRotation;
attribute vec4 compressedAttribute0; // pixel offset, translate, horizontal origin, vertical origin, show, direction, texture coordinates (texture offset)
attribute vec4 compressedAttribute1; // aligned axis, translucency by distance, image width
attribute vec4 compressedAttribute2; // image height, color, pick color, size in meters, valid aligned axis, 13 bits free
Expand Down Expand Up @@ -44,7 +44,7 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca
halfSize *= ((direction * 2.0) - 1.0);

vec2 originTranslate = origin * abs(halfSize);

#if defined(ROTATION) || defined(ALIGNED_AXIS)
if (validAlignedAxis || rotation != 0.0)
{
Expand All @@ -57,7 +57,7 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca
tangent = czm_modelViewProjection * tangent;
angle += sign(-tangent.x) * acos(tangent.y / length(tangent.xy));
}

float cosTheta = cos(angle);
float sinTheta = sin(angle);
mat2 rotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);
Expand All @@ -82,44 +82,44 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca
{
positionWC.xy += halfSize;
}

positionWC.xy += translate;
positionWC.xy += (pixelOffset * czm_resolutionScale);

return positionWC;
}

void main()
void main()
{
// Modifying this shader may also require modifications to Billboard._computeScreenSpacePosition

// unpack attributes
vec3 positionHigh = positionHighAndScale.xyz;
vec3 positionLow = positionLowAndRotation.xyz;
float scale = positionHighAndScale.w;

#if defined(ROTATION) || defined(ALIGNED_AXIS)
float rotation = positionLowAndRotation.w;
#else
float rotation = 0.0;
#endif

float compressed = compressedAttribute0.x;

vec2 pixelOffset;
pixelOffset.x = floor(compressed * SHIFT_RIGHT7);
compressed -= pixelOffset.x * SHIFT_LEFT7;
pixelOffset.x -= UPPER_BOUND;

vec2 origin;
origin.x = floor(compressed * SHIFT_RIGHT5);
compressed -= origin.x * SHIFT_LEFT5;

origin.y = floor(compressed * SHIFT_RIGHT3);
compressed -= origin.y * SHIFT_LEFT3;

origin -= vec2(1.0);

float show = floor(compressed * SHIFT_RIGHT2);
compressed -= show * SHIFT_LEFT2;

Expand All @@ -134,30 +134,30 @@ void main()

vec2 textureCoordinates = czm_decompressTextureCoordinates(compressedAttribute0.w);
#endif

float temp = compressedAttribute0.y * SHIFT_RIGHT8;
pixelOffset.y = -(floor(temp) - UPPER_BOUND);

vec2 translate;
translate.y = (temp - floor(temp)) * SHIFT_LEFT16;

temp = compressedAttribute0.z * SHIFT_RIGHT8;
translate.x = floor(temp) - UPPER_BOUND;

translate.y += (temp - floor(temp)) * SHIFT_LEFT8;
translate.y -= UPPER_BOUND;

temp = compressedAttribute1.x * SHIFT_RIGHT8;

vec2 imageSize = vec2(floor(temp), compressedAttribute2.w);

#ifdef EYE_DISTANCE_TRANSLUCENCY
vec4 translucencyByDistance;
translucencyByDistance.x = compressedAttribute1.z;
translucencyByDistance.z = compressedAttribute1.w;

translucencyByDistance.y = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;

temp = compressedAttribute1.y * SHIFT_RIGHT8;
translucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;
#endif
Expand All @@ -170,7 +170,7 @@ void main()
vec3 alignedAxis = vec3(0.0);
bool validAlignedAxis = false;
#endif

#ifdef RENDER_FOR_PICK
temp = compressedAttribute2.y;
#else
Expand All @@ -183,27 +183,27 @@ void main()
temp = floor(temp) * SHIFT_RIGHT8;
color.g = (temp - floor(temp)) * SHIFT_LEFT8;
color.r = floor(temp);

temp = compressedAttribute2.z * SHIFT_RIGHT8;
bool sizeInMeters = floor((temp - floor(temp)) * SHIFT_LEFT7) > 0.0;
temp = floor(temp) * SHIFT_RIGHT8;

#ifdef RENDER_FOR_PICK
color.a = (temp - floor(temp)) * SHIFT_LEFT8;
vec4 pickColor = color / 255.0;
#else
color.a = floor(temp);
color /= 255.0;
#endif

///////////////////////////////////////////////////////////////////////////

vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
vec4 positionEC = czm_modelViewRelativeToEye * p;
positionEC = czm_eyeOffset(positionEC, eyeOffset.xyz);
positionEC.xyz *= show;
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////

#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(EYE_DISTANCE_PIXEL_OFFSET) || defined(DISTANCE_DISPLAY_CONDITION)
float lengthSq;
Expand All @@ -220,7 +220,9 @@ void main()
#endif

#ifdef EYE_DISTANCE_SCALING
scale *= czm_nearFarScalar(scaleByDistance, lengthSq);
float distanceScale = czm_nearFarScalar(scaleByDistance, lengthSq);
scale *= distanceScale;
translate *= distanceScale;
// push vertex behind near plane for clipping
if (scale == 0.0)
{
Expand Down
Loading