Cartesian to Screen Coordinates

Is there a quick way to translate from a Cartesian3 (or Cartographic) point to the screen (Cartesian2) coordinates for the current camera view, returning undefined if the point is not currently visible? CameraController.pickEllipsoid(...) does the inverse of this.

Thanks,
Jon

Hi Jon,

Check out Transforms.pointToWindowCoordinates.

Patrick

Patrick,

We wrote the following code to get the screen coordinates for a cartesian point in order to open up an “info bubble” for a point on the globe (think google earth functionality):

getScreenCoordinates: function(cartesian3Point)

{

var uniformState = this.scene.getUniformState(),

modelViewProjectionMatrix = uniformState.getModelViewProjection(),

viewportTransformation = uniformState.getViewportTransformation();

return Transforms.pointToWindowCoordinates(modelViewProjectionMatrix, viewportTransformation, cartesian3Point);

}

Once the mouse moves, we call this same function to update the position of the bubble. The bubble initially opens up in the correct place, but once the mouse moves or the render loop of the CesiumViewWidget gets called, the bubble moves to the bottom left corner of the screen. I did some debugging and found that the value returned by uniformState.getViewportTransformation() is changing after the bubble is initially opened, which causes the movement to the bottom left corner. If, instead, I grab a copy of viewportTransformation right when the bubble opens and don’t update it in the function, like so:

getScreenCoordinates: function(cartesian3Point,viewportTransformation)

{

var uniformState = this.scene.getUniformState(),

modelViewProjectionMatrix = uniformState.getModelViewProjection();

return Transforms.pointToWindowCoordinates(modelViewProjectionMatrix, viewportTransformation, cartesian3Point);

}

the screen coordinates are returned correctly and the bubble stays attached to the globe. This is workable, but seems like strange behavior.

Thanks again,
Jon

Hi Jon,

Thanks for the detailed info. I’m glad you have a workaround. When I use the following code in Cesium Viewer I get the same matrix every time I click:

var handler = new ScreenSpaceEventHandler(scene.getCanvas());

handler.setInputAction(

function (e) {

console.log(scene.getUniformState().getViewportTransformation());

},

ScreenSpaceEventType.LEFT_CLICK

);

Perhaps there is an issue in your app or, perhaps more likely, your app is exposing an issue in Cesium with multiple canvases or canvas resizing.

Regards,

Patrick

Patrick,

Thanks for taking a look at this again. It could definitely be an issue with out application, but another thing we noticed is that the strange behavior only occurs with streaming imagery, and not on the default SingleTileImageryProvider. I’ll try creating a simple example with your code and see if I still see the issue.

Jon

Hi Jon,

We made the viewport part of the render state so the viewport transformation of the uniform state will be for the viewport of the last primitive rendered. It makes sense that you would see the problem with streaming imagery because ViewportQuads are used to draw the credits. ViewportQuads modify the viewport and are the last thing drawn. I suggest that you use Matrix4.computeViewportTransformation instead of the viewport transformation of the UniformState.

Regards,

Dan

Dan,

We were able to get this working with Matrix4.computeViewportTransformation as you suggested, just passing it a viewport that is the size of the canvas. But we’re still seeing an issue with modelViewProjectionMatrix = uniformState.getModelViewProjection() when rendering CZML at the same as we’re calculating this window position. I was able to get the following code working in 3D mode, but not in 2D or Columbus:

var canvas = this.scene.getCanvas(),

camera = this.scene.getCamera(),

frustum = camera.frustum,

view = camera.getViewMatrix(),

model = Matrix4.IDENTITY,

modelView,

projection = frustum.getProjectionMatrix(),

modelViewProjectionMatrix,

viewportTransformation;

modelView = Matrix4.multiply(view, model);

modelViewProjectionMatrix = Matrix4.multiply(projection, modelView);

viewportTransformation = Matrix4.computeViewportTransformation({ x : 0,

y : 0,

width : canvas.clientWidth,

height : canvas.clientHeight });

return Transforms.pointToWindowCoordinates(modelViewProjectionMatrix, viewportTransformation, cartesian3Point);

I imagine it’s something to do with the fact that I’m passing an identity matrix for model or with how I’m grabbing the projection matrix from the camera view frustum, although, hopefully there’s an easier way to accomplish this task.

Thanks,
Jon

Hi Jon,

I ran into a similar issue recently. Have you tried using the function SceneTransforms.wgs84ToWindowCoordinates? The uniform state isn’t always reliable because it changes as different primitives are being rendered.

-Hannah

Hannah,

Just what I was looking for–thank you!

Jon