Skip to content

Commit

Permalink
Merge pull request #747 from AnalyticalGraphicsInc/issue746
Browse files Browse the repository at this point in the history
ComputeScreenSpacePosition for polygon. Temporary fix for issue #746.
  • Loading branch information
bagnell committed May 21, 2013
2 parents e7404b6 + 6f28c76 commit 1a58385
Show file tree
Hide file tree
Showing 10 changed files with 321 additions and 48 deletions.
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ Beta Releases
* Renamed `Widgets/Fullscreen` folder to `Widgets/FullscreenButton` along with associated objects/files.
* `FullscreenWidget` -> `FullscreenButton`
* `FullscreenViewModel` -> `FullscreenButtonViewModel`
* Added `SceneTransforms.wgs84ToWindowCoordinates`. [#746](https://github.com/AnalyticalGraphicsInc/cesium/issues/746).
* Added `fromElements` to `Cartesian2`, `Cartesian3`, and `Cartesian4`.
* Added `DrawCommand.cull` to avoid redundant visibility checks.
* Added `czm_morphTime` automatic GLSL uniform.
* Added support for floating-point textures.
* Fixed polyline clipping artifact. [#728](https://github.com/AnalyticalGraphicsInc/cesium/issues/728).
* Added `IntersectionTests.trianglePlaneIntersection`.
* Fixed polygon crossing international date line for 2D and Columbus view.
* Fixed polygon crossing International Date Line for 2D and Columbus view. [#99](https://github.com/AnalyticalGraphicsInc/cesium/issues/99).
* Added `computeHorizonCullingPoint`, `computeHorizonCullingPointFromVertices`, and `computeHorizonCullingPointFromExtent` methods to `EllipsoidalOccluder` and used them to build a more accurate horizon occlusion test for terrain rendering.
* Added sun visualization. See `Sun` and `Scene.sun`.
* Added a new `HomeButton` widget for returning to the default view of the current scene mode.
Expand Down
19 changes: 19 additions & 0 deletions Source/Core/Cartesian2.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ define([
return result;
};

/**
* Creates a Cartesian2 instance from x and y coordinates.
* @memberof Cartesian2
*
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Cartesian2} [result] The object onto which to store the result.
* @return {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
*/
Cartesian2.fromElements = function(x, y, result) {
if (typeof result === 'undefined') {
return new Cartesian2(x, y);
}

result.x = x;
result.y = y;
return result;
};

/**
* Duplicates a Cartesian2 instance.
* @memberof Cartesian2
Expand Down
21 changes: 21 additions & 0 deletions Source/Core/Cartesian3.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,27 @@ define([
return result;
};

/**
* Creates a Cartesian3 instance from x, y and z coordinates.
* @memberof Cartesian3
*
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
* @param {Cartesian3} [result] The object onto which to store the result.
* @return {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
*/
Cartesian3.fromElements = function(x, y, z, result) {
if (typeof result === 'undefined') {
return new Cartesian3(x, y, z);
}

result.x = x;
result.y = y;
result.z = z;
return result;
};

/**
* Duplicates a Cartesian3 instance.
* @memberof Cartesian3
Expand Down
23 changes: 23 additions & 0 deletions Source/Core/Cartesian4.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,29 @@ define([
return result;
};

/**
* Creates a Cartesian4 instance from x, y, z and w coordinates.
* @memberof Cartesian4
*
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
* @param {Number} w The w coordinate.
* @param {Cartesian4} [result] The object onto which to store the result.
* @return {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
*/
Cartesian4.fromElements = function(x, y, z, w, result) {
if (typeof result === 'undefined') {
return new Cartesian4(x, y, z, w);
}

result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
};

/**
* Duplicates a Cartesian4 instance.
* @memberof Cartesian4
Expand Down
55 changes: 8 additions & 47 deletions Source/Scene/Billboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,29 @@
define([
'../Core/defaultValue',
'../Core/DeveloperError',
'../Core/BoundingRectangle',
'../Core/Color',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Cartesian4',
'../Core/Cartographic',
'../Core/Math',
'../Core/Matrix4',
'./HorizontalOrigin',
'./VerticalOrigin',
'./SceneMode'
'./SceneMode',
'./SceneTransforms'
], function(
defaultValue,
DeveloperError,
BoundingRectangle,
Color,
Cartesian2,
Cartesian3,
Cartesian4,
Cartographic,
CesiumMath,
Matrix4,
HorizontalOrigin,
VerticalOrigin,
SceneMode) {
SceneMode,
SceneTransforms) {
"use strict";

var EMPTY_OBJECT = {};
Expand Down Expand Up @@ -559,54 +557,21 @@ define([
};

var tempCartesian4 = new Cartesian4();
var tempCartographic = new Cartographic();
Billboard._computeActualPosition = function(position, frameState, modelMatrix) {
var mode = frameState.mode;

if (mode === SceneMode.SCENE3D) {
if (frameState.mode === SceneMode.SCENE3D) {
return position;
}

modelMatrix.multiplyByPoint(position, tempCartesian4);

var projection = frameState.scene2D.projection;
var cartographic = projection.getEllipsoid().cartesianToCartographic(tempCartesian4, tempCartographic);
if (typeof cartographic === 'undefined') {
return undefined;
}

var projectedPosition = projection.project(cartographic);
if (mode === SceneMode.MORPHING) {
var morphTime = frameState.morphTime;
var x = CesiumMath.lerp(projectedPosition.z, tempCartesian4.x, morphTime);
var y = CesiumMath.lerp(projectedPosition.x, tempCartesian4.y, morphTime);
var z = CesiumMath.lerp(projectedPosition.y, tempCartesian4.z, morphTime);
return new Cartesian3(x, y, z);
}
if (mode === SceneMode.SCENE2D) {
return new Cartesian3(0.0, projectedPosition.x, projectedPosition.y);
}
if (mode === SceneMode.COLUMBUS_VIEW) {
return new Cartesian3(projectedPosition.z, projectedPosition.x, projectedPosition.y);
}
return undefined;
return SceneTransforms.computeActualWgs84Position(frameState, tempCartesian4);
};

var scratchViewport = new BoundingRectangle();
var scratchViewportTransform = new Matrix4();
Billboard._computeScreenSpacePosition = function(modelMatrix, position, eyeOffset, pixelOffset, context, frameState) {
// This function is basically a stripped-down JavaScript version of BillboardCollectionVS.glsl

var camera = frameState.camera;
var view = camera.getViewMatrix();
var projection = camera.frustum.getProjectionMatrix();

// Assuming viewport takes up the entire canvas...
var canvas = context.getCanvas();
scratchViewport.width = canvas.clientWidth;
scratchViewport.height = canvas.clientHeight;
var viewportTransformation = Matrix4.computeViewportTransformation(scratchViewport, 0.0, 1.0, scratchViewportTransform);

// Model to eye coordinates
var mv = view.multiply(modelMatrix);
var positionEC = mv.multiplyByPoint(position);
Expand All @@ -617,12 +582,8 @@ define([
positionEC.y += eyeOffset.y + zEyeOffset.y;
positionEC.z += zEyeOffset.z;

// Eye to window coordinates, e.g., czm_eyeToWindowCoordinates
var q = projection.multiplyByVector(positionEC); // clip coordinates
q.x /= q.w; // normalized device coordinates
q.y /= q.w;
q.z /= q.w;
var positionWC = viewportTransformation.multiplyByPoint(q); // window coordinates
var positionCC = projection.multiplyByVector(positionEC); // clip coordinates
var positionWC = SceneTransforms.clipToWindowCoordinates(context.getCanvas(), positionCC);

// Apply pixel offset
var uniformState = context.getUniformState();
Expand Down
151 changes: 151 additions & 0 deletions Source/Scene/SceneTransforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*global define*/
define([
'../Core/defaultValue',
'../Core/DeveloperError',
'../Core/Cartographic',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Cartesian4',
'../Core/Matrix4',
'../Core/BoundingRectangle',
'../Core/Math',
'./SceneMode'
],
function(
defaultValue,
DeveloperError,
Cartographic,
Cartesian2,
Cartesian3,
Cartesian4,
Matrix4,
BoundingRectangle,
CesiumMath,
SceneMode) {
"use strict";

/**
* Functions that do scene-dependent transforms between rendering-related coordinate systems.
*
* @exports SceneTransforms
*/
var SceneTransforms = {};

var actualPosition = new Cartesian3();
var positionCC = new Cartesian4();

/**
* Transforms a position in WGS84 coordinates to window coordinates. This is commonly used to place an
* HTML element at the same screen position as an object in the scene.
*
* @memberof SceneTransforms
*
* @param {Scene} scene The scene.
* @param {Cartesian3} position The position in WGS84 (world) coordinates.
* @param {Cartesian2} [result=undefined] An optional object to return the input position transformed to window coordinates.
*
* @return {Cartesian2} The modified result parameter or a new Cartesian3 instance if one was not provided. This may be <code>undefined</code> if the input position is near the center of the ellipsoid.
*
* @exception {DeveloperError} scene is required.
* @exception {DeveloperError} position is required.
*
* @example
* // Output the window position of longitude/latitude (0, 0) every time the mouse moves.
* var scene = widget.scene;
* var ellipsoid = widget.centralBody.getEllipsoid();
* var position = ellipsoid.cartographicToCartesian(new Cartographic(0.0, 0.0));
* var handler = new Cesium.ScreenSpaceEventHandler(scene.getCanvas());
* handler.setInputAction(function(movement) {
* console.log(Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position));
* }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
*/
SceneTransforms.wgs84ToWindowCoordinates = function(scene, position, result) {
if (typeof scene === 'undefined') {
throw new DeveloperError('scene is required.');
}

if (typeof position === 'undefined') {
throw new DeveloperError('position is required.');
}

// Transform for 3D, 2D, or Columbus view
SceneTransforms.computeActualWgs84Position(scene.getFrameState(), position, actualPosition);

if (typeof actualPosition === 'undefined') {
result = undefined;
return undefined;
}

// View-projection matrix to transform from world coordinates to clip coordinates
var viewProjection = scene.getUniformState().getViewProjection();
viewProjection.multiplyByPoint(actualPosition, positionCC);

return SceneTransforms.clipToWindowCoordinates(scene.getCanvas(), positionCC, result);
};

var projectedPosition = new Cartesian3();
var positionInCartographic = new Cartographic();

/**
* @private
*/
SceneTransforms.computeActualWgs84Position = function(frameState, position, result) {
var mode = frameState.mode;

if (mode === SceneMode.SCENE3D) {
return Cartesian3.clone(position, result);
}

var projection = frameState.scene2D.projection;
projection.getEllipsoid().cartesianToCartographic(position, positionInCartographic);
if (typeof positionInCartographic === 'undefined') {
result = undefined;
return result;
}

projection.project(positionInCartographic, projectedPosition);

if (mode === SceneMode.COLUMBUS_VIEW) {
return Cartesian3.fromElements(projectedPosition.z, projectedPosition.x, projectedPosition.y, result);
}

if (mode === SceneMode.SCENE2D) {
return Cartesian3.fromElements(0.0, projectedPosition.x, projectedPosition.y, result);
}

// mode === SceneMode.MORPHING
var morphTime = frameState.morphTime;
return Cartesian3.fromElements(
CesiumMath.lerp(projectedPosition.z, position.x, morphTime),
CesiumMath.lerp(projectedPosition.x, position.y, morphTime),
CesiumMath.lerp(projectedPosition.y, position.z, morphTime),
result);
};

var positionNDC = new Cartesian3();
var positionWC = new Cartesian4();
var viewport = new BoundingRectangle();
var viewportTransform = new Matrix4();

/**
* @private
*/
SceneTransforms.clipToWindowCoordinates = function(canvas, position, result) {
// Perspective divide to transform from clip coordinates to normalized device coordinates
positionNDC.x = position.x / position.w;
positionNDC.y = position.y / position.w;
positionNDC.z = position.z / position.w;

// Assuming viewport takes up the entire canvas...
viewport.width = canvas.clientWidth;
viewport.height = canvas.clientHeight;
Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);

// Viewport transform to transform from clip coordinates to window coordinates
viewportTransform.multiplyByPoint(positionNDC, positionWC);

return Cartesian2.fromCartesian4(positionWC, result);
};

return SceneTransforms;
});
13 changes: 13 additions & 0 deletions Specs/Core/Cartesian2Spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -618,4 +618,17 @@ defineSuite([
Cartesian2.equalsEpsilon(new Cartesian2(), new Cartesian2(), undefined);
}).toThrow();
});

it('fromElements returns a cartesian2 with corrrect coordinates', function(){
var cartesian2 = Cartesian2.fromElements(2, 2);
var expectedResult = new Cartesian2(2, 2);
expect(cartesian2).toEqual(expectedResult);
});

it('fromElements result param returns cartesian2 with correct coordinates', function(){
var cartesian2 = new Cartesian2();
Cartesian2.fromElements(2, 2, cartesian2);
var expectedResult = new Cartesian2(2, 2);
expect(cartesian2).toEqual(expectedResult);
});
});
13 changes: 13 additions & 0 deletions Specs/Core/Cartesian3Spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -702,4 +702,17 @@ defineSuite([
Cartesian3.cross(left, undefined);
}).toThrow();
});

it('fromElements returns a cartesian3 with corrrect coordinates', function(){
var cartesian2 = Cartesian3.fromElements(2, 2, 4);
var expectedResult = new Cartesian3(2, 2, 4);
expect(cartesian2).toEqual(expectedResult);
});

it('fromElements result param returns cartesian3 with correct coordinates', function(){
var cartesian3 = new Cartesian3();
Cartesian3.fromElements(2, 2, 4, cartesian3);
var expectedResult = new Cartesian3(2, 2, 4);
expect(cartesian3).toEqual(expectedResult);
});
});
Loading

0 comments on commit 1a58385

Please sign in to comment.