Skip to content

Commit

Permalink
Fix SceneTransforms.wgs84ToWindowCoordinates in 2D
Browse files Browse the repository at this point in the history
  • Loading branch information
bagnell committed Mar 23, 2016
1 parent 1063c83 commit dae0242
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 55 deletions.
11 changes: 9 additions & 2 deletions Source/Scene/Billboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,15 @@ define([
positionEC.z += zEyeOffset.z;

var positionCC = Matrix4.multiplyByVector(projection, positionEC, scratchCartesian4); // clip coordinates
var positionWC = SceneTransforms.clipToGLWindowCoordinates(scene, positionCC, result);

var canvas = scene.canvas;
var viewport = new BoundingRectangle();
viewport.x = 0;
viewport.y = 0;
viewport.width = canvas.clientWidth;
viewport.height = canvas.clientHeight;

var positionWC = SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, result);

// Apply pixel offset
pixelOffset = Cartesian2.clone(pixelOffset, scratchComputePixelOffset);
Expand All @@ -1131,7 +1139,6 @@ define([
*
* @exception {DeveloperError} Billboard must be in a collection.
*
*
* @example
* console.log(b.computeScreenSpacePosition(scene).toString());
*
Expand Down
16 changes: 4 additions & 12 deletions Source/Scene/PointPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,21 +388,13 @@ define([
return SceneTransforms.computeActualWgs84Position(frameState, tempCartesian3);
};

var scratchMatrix4 = new Matrix4();
var scratchCartesian4 = new Cartesian4();

// This function is basically a stripped-down JavaScript version of PointPrimitiveCollectionVS.glsl
PointPrimitive._computeScreenSpacePosition = function(modelMatrix, position, scene, result) {
// This function is basically a stripped-down JavaScript version of PointPrimitiveCollectionVS.glsl
var camera = scene.camera;
var view = camera.viewMatrix;
var projection = camera.frustum.projectionMatrix;

// Model to eye coordinates
var mv = Matrix4.multiplyTransformation(view, modelMatrix, scratchMatrix4);
var positionEC = Matrix4.multiplyByVector(mv, Cartesian4.fromElements(position.x, position.y, position.z, 1, scratchCartesian4), scratchCartesian4);
var positionCC = Matrix4.multiplyByVector(projection, positionEC, scratchCartesian4); // clip coordinates
var positionWC = SceneTransforms.clipToGLWindowCoordinates(scene, positionCC, result);

// Model to world coordinates
var positionWorld = Matrix4.multiplyByVector(modelMatrix, Cartesian4.fromElements(position.x, position.y, position.z, 1, scratchCartesian4), scratchCartesian4);
var positionWC = SceneTransforms.wgs84ToWindowCoordinates(scene, positionWorld, result);
return positionWC;
};

Expand Down
142 changes: 101 additions & 41 deletions Source/Scene/SceneTransforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ define([
'../Core/DeveloperError',
'../Core/Math',
'../Core/Matrix4',
'../Core/Transforms',
'./SceneMode'
], function(
BoundingRectangle,
Expand All @@ -20,6 +21,7 @@ define([
DeveloperError,
CesiumMath,
Matrix4,
Transforms,
SceneMode) {
'use strict';

Expand All @@ -35,6 +37,9 @@ define([
var viewProjectionScratch = new Matrix4();
var scratchViewport = new BoundingRectangle();

var scratchWindowCoord0 = new Cartesian2();
var scratchWindowCoord1 = new Cartesian2();

/**
* 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.
Expand Down Expand Up @@ -72,15 +77,6 @@ define([
return undefined;
}

// View-projection matrix to transform from world coordinates to clip coordinates
var camera = scene.camera;
var viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjectionScratch);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);

if ((positionCC.z < 0) && (scene.mode !== SceneMode.SCENE2D)) {
return undefined;
}

// Assuming viewport takes up the entire canvas...
var canvas = scene.canvas;
var viewport = scratchViewport;
Expand All @@ -89,9 +85,101 @@ define([
viewport.width = canvas.clientWidth;
viewport.height = canvas.clientHeight;

result = SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, result);
result.y = canvas.clientHeight - result.y;
var camera = scene.camera;
var viewProjection = viewProjectionScratch;

var cameraCentered = false;

if (frameState.mode === SceneMode.SCENE2D) {
var projection = scene.mapProjection;
var maxCartographic = new Cartographic(Math.PI, CesiumMath.PI_OVER_TWO);
var maxCoord = projection.project(maxCartographic, maxCoord);

var cameraPosition = Cartesian3.clone(camera.position);
var frustum = camera.frustum.clone();

var viewportTransformation = Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, new Matrix4());
var projectionMatrix = camera.frustum.projectionMatrix;

var x = camera.positionWC.y;
var eyePoint = Cartesian3.fromElements(Math.sign(x) * maxCoord.x - x, 0.0, -camera.positionWC.x);
var windowCoordinates = Transforms.pointToGLWindowCoordinates(projectionMatrix, viewportTransformation, eyePoint);

var viewportX = viewport.x;
var viewportWidth = viewport.width;

if (x === 0.0 || windowCoordinates.x <= 0.0 || windowCoordinates.x >= canvas.clientWidth) {
cameraCentered = true;
} else {
if (windowCoordinates.x > canvas.clientWidth * 0.5) {
viewport.width = windowCoordinates.x;

camera.frustum.right = maxCoord.x - x;

viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjection);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord0);

viewport.x += windowCoordinates.x;

camera.position.x = -camera.position.x;

var right = camera.frustum.right;
camera.frustum.right = -camera.frustum.left;
camera.frustum.left = -right;

viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjection);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord1);
} else {
viewport.x += windowCoordinates.x;
viewport.width -= windowCoordinates.x;

camera.frustum.left = -maxCoord.x - x;

viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjection);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord0);

viewport.x = viewport.x - viewport.width;

camera.position.x = -camera.position.x;

var left = camera.frustum.left;
camera.frustum.left = -camera.frustum.right;
camera.frustum.right = -left;

viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjection);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord1);
}

Cartesian3.clone(cameraPosition, camera.position);
camera.frustum = frustum.clone();

viewport.x = viewportX;
viewport.width = viewportWidth;

Cartesian2.clone(scratchWindowCoord0, result);
if (result.x < 0.0 || result.x > canvas.clientWidth) {
result.x = scratchWindowCoord1.x;
}
}
}

if (frameState.mode !== SceneMode.SCENE2D || cameraCentered) {
// View-projection matrix to transform from world coordinates to clip coordinates
viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjection);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);

if (positionCC.z < 0 && frameState.mode !== SceneMode.SCENE2D) {
return undefined;
}

result = SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, result);
}

result.y = canvas.clientHeight - result.y;
return result;
};

Expand All @@ -115,36 +203,8 @@ define([
* }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
*/
SceneTransforms.wgs84ToDrawingBufferCoordinates = function(scene, position, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
throw new DeveloperError('scene is required.');
}

if (!defined(position)) {
throw new DeveloperError('position is required.');
}
//>>includeEnd('debug');

// Transform for 3D, 2D, or Columbus view
var actualPosition = SceneTransforms.computeActualWgs84Position(scene.frameState, position, actualPositionScratch);

if (!defined(actualPosition)) {
return undefined;
}

// View-projection matrix to transform from world coordinates to clip coordinates
var camera = scene.camera;
var viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjectionScratch);
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);

if ((positionCC.z < 0) && (scene.mode !== SceneMode.SCENE2D)) {
return undefined;
}

// Assuming viewport takes up the entire canvas...
var viewport = BoundingRectangle.clone(scene._passState.viewport, scratchViewport);

return SceneTransforms.clipToDrawingBufferCoordinates(viewport, positionCC, result);
SceneTransforms.wgs84ToWindowCoordinates(scene, position, result);
return SceneTransforms.transformWindowToDrawingBuffer(scene, result, result);
};

var projectedPosition = new Cartesian3();
Expand Down

0 comments on commit dae0242

Please sign in to comment.