Skip to content

Commit

Permalink
Merge pull request #1074 from abwood/issue93
Browse files Browse the repository at this point in the history
Scale billboards based on distance (Issue #93)
  • Loading branch information
pjcozzi committed Aug 30, 2013
2 parents 93d0d70 + fa53705 commit 5bbcaca
Show file tree
Hide file tree
Showing 13 changed files with 639 additions and 20 deletions.
30 changes: 30 additions & 0 deletions Apps/Sandcastle/gallery/Billboards.html
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,26 @@
});
}

function scaleBillboardByDistance(scene, ellipsoid) {
Sandcastle.declare(scaleBillboardByDistance); // For highlighting in Sandcastle.
var image = new Image();
image.onload = function() {
var billboards = new Cesium.BillboardCollection();
var textureAtlas = scene.getContext().createTextureAtlas({
image : image
});
billboards.setTextureAtlas(textureAtlas);

billboards.add({
position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.59777, 40.03883)),
imageIndex : 0,
scaleByDistance : new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5)
});
scene.getPrimitives().add(billboards);
};
image.src = '../images/facility.gif';
}

function addPointBillboards(scene, ellipsoid) {
Sandcastle.declare(addPointBillboards); // For highlighting in Sandcastle.
// A white circle is drawn into a 2D canvas. The canvas is used as
Expand Down Expand Up @@ -400,6 +420,16 @@
};
button.textContent = 'Add billboards in reference frame';
toolbar.appendChild(button);

button = document.createElement('button');
button.className = 'cesium-button';
button.onclick = function() {
primitives.removeAll();
scaleBillboardByDistance(scene, ellipsoid);
Sandcastle.highlight(scaleBillboardByDistance);
};
button.textContent = 'Scale by viewer distance';
toolbar.appendChild(button);
}

var widget = new Cesium.CesiumWidget('cesiumContainer');
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ var geometry = BoxGeometry.createGeometry(box);
* Fixed `EllipsoidPrimitive` rendering for some oblate ellipsoids. [#1067](https://github.com/AnalyticalGraphicsInc/cesium/pull/1067).
* Upgraded Knockout from version 2.2.1 to 2.3.0.
* Added `CorridorGeometry`.
* Added `Billboard.scaleByDistance` and `NearFarScalar` to control Billboard minimum/maximum scale based on Camera distance to Billboard.

### b19 - 2013-08-01

Expand Down
97 changes: 97 additions & 0 deletions Source/Core/NearFarScalar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*global define*/
define([
'./defaultValue',
'./defined',
'./DeveloperError'
], function(
defaultValue,
defined,
DeveloperError) {
"use strict";

/**
* Represents a scalar value's lower and upper bound at a near distance and far distance in eye space.
* @alias NearFarScalar
* @constructor
*
* @param {Number} [near=0.0] The lower bound of the camera range.
* @param {Number} [nearValue=0.0] The value at the lower bound of the camera range.
* @param {Number} [far=1.0] The upper bound of the camera range.
* @param {Number} [farValue=0.0] The value at the upper bound of the camera range.
*/
var NearFarScalar = function(near, nearValue, far, farValue) {
/**
* The lower bound of the camera range.
* @type {Number}
* @default 0.0
*/
this.near = defaultValue(near, 0.0);
/**
* The value at the lower bound of the camera range.
* @type {Number}
* @default 0.0
*/
this.nearValue = defaultValue(nearValue, 0.0);
/**
* The upper bound of the camera range.
* @type {Number}
* @default 1.0
*/
this.far = defaultValue(far, 1.0);
/**
* The value at the upper bound of the camera range.
* @type {Number}
* @default 0.0
*/
this.farValue = defaultValue(farValue, 0.0);
};

/**
* Duplicates a NearFarScalar instance.
* @memberof NearFarScalar
*
* @param {NearFarScalar} nearFarScalar The NearFarScalar to duplicate.
* @param {NearFarScalar} [result] The object onto which to store the result.
* @returns {NearFarScalar} The modified result parameter or a new NearFarScalar instance if one was not provided. (Returns undefined if nearFarScalar is undefined)
*/
NearFarScalar.clone = function(nearFarScalar, result) {
if (!defined(nearFarScalar)) {
return undefined;
}

if (!defined(result)) {
return new NearFarScalar(nearFarScalar.near,
nearFarScalar.nearValue,
nearFarScalar.far,
nearFarScalar.farValue);
}

result.near = nearFarScalar.near;
result.nearValue = nearFarScalar.nearValue;
result.far = nearFarScalar.far;
result.farValue = nearFarScalar.farValue;
return result;
};

/**
* Compares the provided NearFarScalar and returns <code>true</code> if they are equal,
* <code>false</code> otherwise.
* @memberof NearFarScalar
*
* @param {NearFarScalar} [left] The first NearFarScalar.
* @param {NearFarScalar} [right] The second NearFarScalar.
*
* @returns {Boolean} <code>true</code> if left and right are equal; otherwise <code>false</code>.
*/
NearFarScalar.equals = function(left, right) {
return (left === right) ||
((defined(left)) &&
(defined(right)) &&
(left.near === right.near) &&
(left.nearValue === right.nearValue) &&
(left.far === right.far) &&
(left.farValue === right.farValue));
};

return NearFarScalar;
});
14 changes: 14 additions & 0 deletions Source/DynamicScene/DynamicBillboardVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ define([
'../Core/Color',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Ellipsoid',
'../Core/NearFarScalar',
'../Scene/BillboardCollection',
'../Scene/HorizontalOrigin',
'../Scene/VerticalOrigin',
Expand All @@ -17,6 +19,8 @@ define([
Color,
Cartesian2,
Cartesian3,
Ellipsoid,
NearFarScalar,
BillboardCollection,
HorizontalOrigin,
VerticalOrigin,
Expand Down Expand Up @@ -196,6 +200,7 @@ define([
};

var position;
var lla;
var color;
var eyeOffset;
var pixelOffset;
Expand Down Expand Up @@ -256,6 +261,15 @@ define([
billboard.setScale(1.0);
billboard.setHorizontalOrigin(HorizontalOrigin.CENTER);
billboard.setVerticalOrigin(VerticalOrigin.CENTER);

// set default Billboard scaleByDistance based on altitude
position = positionProperty.getValue(time, position);
lla = Ellipsoid.WGS84.cartesianToCartographic(position);
if (lla.height < 8.0e5) {
billboard.setScaleByDistance(new NearFarScalar(1.5e2, 1.0, 8.0e6, 0.2));
} else {
billboard.setScaleByDistance(new NearFarScalar(1.0e2, 2.0, 3.2e7, 0.2));
}
} else {
billboard = dynamicBillboardVisualizer._billboardCollection.get(billboardVisualizerIndex);
}
Expand Down
67 changes: 67 additions & 0 deletions Source/Renderer/ShaderProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,33 @@ define([
}
},

/**
* An automatic GLSL uniform containing height (<code>x</code>) and height squared (<code>y</code>)
* of the eye (camera) in the 2D scene in meters.
* <br /><br />
* Like all automatic uniforms, <code>czm_eyeHeight2D</code> does not need to be explicitly declared.
* However, it can be explicitly declared when a shader is also used by other applications such
* as a third-party authoring tool.
*
* @alias czm_eyeHeight2D
* @glslUniform
*
* @see UniformState#getEyeHeight2D
*/
czm_eyeHeight2D : {
getSize : function() {
return 1;
},

getDatatype : function() {
return UniformDatatype.FLOAT_VECTOR2;
},

getValue : function(uniformState) {
return uniformState.getEyeHeight2D();
}
},

/**
* An automatic GLSL uniform containing the near distance (<code>x</code>) and the far distance (<code>y</code>)
* of the frustum defined by the camera. This is the individual
Expand Down Expand Up @@ -1686,6 +1713,46 @@ define([
}
},

/**
* An automatic GLSL uniform representing the current {@link SceneMode} enumeration, expressed
* as a float.
* <br /><br />
* Like all automatic uniforms, <code>czm_sceneMode</code> does not need to be explicitly declared.
* However, it can be explicitly declared when a shader is also used by other applications such
* as a third-party authoring tool.
*
* @alias czm_sceneMode
* @glslUniform
*
* @see czm_sceneMode2D
* @see czm_sceneModeColumbusView
* @see czm_sceneMode3D
* @see czm_sceneModeMorphing
*
* @example
* // GLSL declaration
* uniform float czm_sceneMode;
*
* // Example
* if (czm_sceneMode == czm_sceneMode2D)
* {
* eyeHeightSq = czm_eyeHeight2D.y;
* }
*/
czm_sceneMode : {
getSize : function() {
return 1;
},

getDatatype : function() {
return UniformDatatype.FLOAT;
},

getValue : function(uniformState) {
return uniformState.getFrameState().mode.value;
}
},

/**
* An automatic GLSL uniform representing a 3x3 rotation matrix that transforms
* from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.
Expand Down
20 changes: 20 additions & 0 deletions Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ define([
this._cameraRight = new Cartesian3();
this._cameraUp = new Cartesian3();
this._frustum2DWidth = 0.0;
this._eyeHeight2D = new Cartesian2();
};

function setView(uniformState, matrix) {
Expand Down Expand Up @@ -244,8 +245,12 @@ define([

if (frameState.mode === SceneMode.SCENE2D) {
this._frustum2DWidth = camera.frustum.right - camera.frustum.left;
this._eyeHeight2D.x = this._frustum2DWidth * 0.5;
this._eyeHeight2D.y = this._eyeHeight2D.x * this._eyeHeight2D.x;
} else {
this._frustum2DWidth = 0.0;
this._eyeHeight2D.x = 0.0;
this._eyeHeight2D.y = 0.0;
}

setSunAndMoonDirections(this, frameState);
Expand Down Expand Up @@ -916,6 +921,21 @@ define([
return this._currentFrustum;
};

/**
* Returns the the height (<code>x</code>) and the height squared (<code>y</code>)
* in meters of the camera above the 2D world plane. This uniform is only valid
* when the {@link SceneMode} equal to <code>SCENE2D</code>.
*
* @memberof UniformState
*
* @returns {Cartesian2} Height and height squared above the 2D world plane for SCENE2D {@link SceneMode}.
*
* @see czm_eyeHeight2D
*/
UniformState.prototype.getEyeHeight2D = function() {
return this._eyeHeight2D;
};

/**
* Returns the size of a pixel in meters at a distance of one meter from the camera.
*
Expand Down
Loading

0 comments on commit 5bbcaca

Please sign in to comment.