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

2D mode issues #73

Closed
djone010 opened this issue Jun 21, 2012 · 27 comments
Closed

2D mode issues #73

djone010 opened this issue Jun 21, 2012 · 27 comments
Assignees

Comments

@djone010
Copy link

Hey guys, I am trying to get some things working in 2D mode that work fine in 3D.

If you paste this into the top of the sandbox example for "show cartographic position on mouse over", you'll see my problem.

transitioner = new Cesium.SceneTransitioner(scene);
transitioner.to2D();

First you'll notice that the sun shines only in the center. I can fix this by using the "affectedByLighting" flag in CentralBody which was added a couple of weeks ago, but the 2D map will be darker than it was in 3D.

My main problem is that scene.getCamera().pickEllipsoid no longer works. How do I get the cartographic position when in 2D?

@ghost ghost assigned bagnell Jun 22, 2012
@pjcozzi
Copy link
Contributor

pjcozzi commented Jun 22, 2012

@jktaylor - for the sun light, use affectedByLighting for now. We are working on proper lighting as part of materials, but probably won't be done until the end of the summer.

pickEllipsoid probably shots a ray through the WGS84 ellipsoid, not the 2D map, so I would not expect it to be right. @bagnell - can you take a look?

@djone010
Copy link
Author

Since this is kind of related, I also wanted to ask if there is a way to get a screen pixel location from a globe coordinate?

@pjcozzi
Copy link
Contributor

pjcozzi commented Jun 27, 2012

@jktaylor There is not a function to do so, but we welcome such a contribution. Convert from cartographic to cartesian, then create a function on the CentralBody, computeScreenSpacePosition that transforms it from model to window coordinates using code similar to Billboard.prototype.computeScreenSpacePosition. It will actually be less code since we will not need to consider eye and pixel offsets used by billboards, and we can use the model-view-projection matrix to go right to clip coordinates, instead of going to eye coordinates first. @bagnell can provide further guidance.

@bagnell
Copy link
Contributor

bagnell commented Jun 27, 2012

@jktaylor You could use the function Transforms.pointToWindowCoordinates that takes the model-view-projection matrix, viewport matrix and the point in model coordinates to get the point in window coordinates.

Also, @pjcozzi is right about pickEllipsoid only working in 3D mode, but I'm working on adding picking the maps in 2D and Columbus View.

@djone010
Copy link
Author

@bagnell I tried what you suggested in the sandbox "Show cartographic position on mouse-over", and it is not giving the correct answer.

function(movement) {
var p = scene.getCamera().pickEllipsoid(ellipsoid, movement.endPosition);
if (p) {
var d = Cesium.Math.cartographic2ToDegrees(ellipsoid.toCartographic2(p));
label.setShow(true);
label.setText("(" + d.longitude.toFixed(2) + ", " + d.latitude.toFixed(2) + ")");
label.setPosition(p);
var px = Cesium.Transforms.pointToWindowCoordinates(scene.getUniformState().getModelViewProjection(),scene.getUniformState().getViewProjection(),ellipsoid.cartographicDegreesToCartesian(d));
console.log("pToWindow: "+px);
console.log("orig: "+movement.endPosition);
} else {
label.setText("");
}
}, Cesium.MouseEventType.MOVE);

I'm seeing in console

pToWindow: (-0.028427104913234247, 0.1603221355997794)
orig: (813, 574)

What am I doing wrong?

@djone010 djone010 reopened this Jun 27, 2012
@djone010
Copy link
Author

Nevermind, I should have read the API more closely. It should have been getViewportTransformation()

Cesium.Transforms.pointToWindowCoordinates(scene.getUniformState().getModelViewProjection(),scene.getUniformState().getViewportTransformation(),ellipsoid.cartographicDegreesToCartesian(d))

Thanks a lot for your help!

@djone010
Copy link
Author

@bagnell pointToWindowCoordinates doesn't exactly give me what I expected, but I can easily fix it. In my example above, you can see that the y screen coordinate that I get back is not the same as the y that was passed in from the mouse event. I think it is because cesium considers y=0 to be at the bottom of the screen and the mouse event considers y=0 the top of the screen.

@bagnell
Copy link
Contributor

bagnell commented Jun 29, 2012

@jktaylor The changes for picking the ellipsoid have been merged into master. You should use Scene.pickEllipsoid instead of Camera.pickEllipsoid.

The origin in window coordinates is the bottom left for WebGL and the top left for the browser. I'm going to submit another issue to change public functions to use the top left because that is what most people are expecting.

@djone010
Copy link
Author

djone010 commented Jul 5, 2012

@bagnell we are still seeing an issue in 2D mode where the cartographic degrees for longitude is about 110 degrees east of where it should be. You can easily reproduce this in the sandbox example for "show cartographic position on mouse over" by pasting this at the top.

transitioner = new Cesium.SceneTransitioner(scene);
transitioner.to2D();

@bagnell
Copy link
Contributor

bagnell commented Jul 5, 2012

@jktaylor The issue was in creating a pick ray with an orthographic frustum. I pushed the fix to master.

@djone010
Copy link
Author

djone010 commented Jul 5, 2012

@bagnell Looks good, Thanks for the quick fix!

There is also a problem with the Camera class viewextent function when in 2D mode. The map flips sideways very strangely. See what I mean in the Sandbox Camera "View an extent" example:

transitioner = new Cesium.SceneTransitioner(scene);
transitioner.to2D();

@bagnell bagnell mentioned this issue Jul 23, 2012
@bagnell
Copy link
Contributor

bagnell commented Jul 25, 2012

@jktaylor I added new functions to the camera to view extents in 2D and Columbus view; however, you should now use Scene.viewExtent which will call the correct function depending on which mode the scene is in. The changes have been merged into master.

@djone010
Copy link
Author

djone010 commented Aug 7, 2012

@bagnell I finally got a chance to check out these enhancements that you have made, and I still have a few issues.

Not a major problem at the moment, but flyto does not work in 2D mode as in the fly to Los Angeles example in the sandbox.

ViewExtent works in 2D mode, however we are removing the camera in order to let the user mouse drag a rectangle to create the extent in which to zoom to. When we add the camera back, the camera is "glued" to this extent and always returns to it after trying to move away. You can easily reproduce this in the sandbox with the following code snippet.

var transitioner = new Cesium.SceneTransitioner(scene, ellipsoid);

var west = Cesium.Math.toRadians(-77.0);
var south = Cesium.Math.toRadians(38.0);
var east = Cesium.Math.toRadians(-72.0);
var north = Cesium.Math.toRadians(42.0);

var extent = new Cesium.Extent(west, south, east, north);
transitioner.to2D();
scene.getCamera().getControllers().removeAll();
scene.viewExtent(extent, ellipsoid);
scene.getCamera().getControllers().add2D(scene.scene2D.projection);

Is there a better way that we can temporarily deactivate the camera controls without removing them altogether?

@djone010
Copy link
Author

djone010 commented Aug 7, 2012

Also, before this change we could zoom to a full view over the globe centered at point x,y by adding a 45 degree buffer around the point, but that no longer works. The resulting camera view is no longer centered at point x,y. Is there a better way we could center the globe at a given point that would be compatible with all view modes?

@bagnell
Copy link
Contributor

bagnell commented Aug 8, 2012

@jktaylor I fixed the problem with adding the 2D mouse control after calling viewExtent in branch "camera-2d". It should be in master soon. Unfortunately, there isn't a better way to temporarily deactivate a camera control, but in the future we want to redo how to add/remove/configure the camera controls.

I'm not sure I understand your second post. You have a point in 2D and you want to set the camera position/direction/up with that point in all modes?

@djone010
Copy link
Author

djone010 commented Aug 8, 2012

@bagnell What I mean is, we were using the viewextent function to show a full view of the globe with the camera centered at a given longitude, latitude. We did this by creating a 45 degree window around the position and calling viewextent with those bounds. Now that does not work anymore except for nice cases like longitude:0, latitude:0. I wish there was a centerAt(position) function that would pan the camera to the given position without changing zoom level and work for all view modes.

@djone010
Copy link
Author

djone010 commented Aug 8, 2012

Or better yet, a function like the flyto that goes to a x,y,z without the animation.

@djone010
Copy link
Author

djone010 commented Aug 8, 2012

Another issue with 2D mode (and Columbus view as well) Transforms.pointToWindowCoordinates doesn't give the correct answer. Maybe I'm not using it correctly, but it works fine in 3D mode. Paste this into the _handleMouseMove of CesiumViewerWidget and try the other modes.

_handleMouseMove : function(movement) {
var p = this.scene.pickEllipsoid(movement.endPosition,this.ellipsoid);
if (p) {
var d = this.ellipsoid.cartesianToCartographic(p);
var px = Transforms.pointToWindowCoordinates(this.scene.getUniformState().getModelViewProjection(),this.scene.getUniformState().getViewportTransformation(),this.ellipsoid.cartographicToCartesian(d));
px.y=this.canvas.clientHeight-px.y;
console.log("pToWindow: "+px);
console.log("orig: "+movement.endPosition);
}

.....

@bagnell
Copy link
Contributor

bagnell commented Aug 9, 2012

pickEllipsoid returns a cartesian in world coordinates that is a point on the surface of the ellipsoid centered at the origin in 3D. That is why converting to/from a cartographic works, but it isn't the point you want to use for finding the window coordinates. So what you need to do is project it to 2D and transform it to the yz-plane. Paste this code into the Skeleton Example:

handler.setMouseAction(function(movement) {
    var p = scene.pickEllipsoid(movement.endPosition,ellipsoid);
    if (p) {
        if (scene.mode !== Cesium.SceneMode.SCENE3D) {
            p = scene.scene2D.projection.project(ellipsoid.cartesianToCartographic(p));
            p = new Cesium.Cartesian3(p.z, p.x, p.y);
        }
        var px = Cesium.Transforms.pointToWindowCoordinates(scene.getUniformState().getViewProjection(), scene.getUniformState().getViewportTransformation(), p);
        px.y=canvas.clientHeight-px.y;
        console.log("pToWindow: "+px);
        console.log("orig: "+movement.endPosition);
    }
}, Cesium.MouseEventType.MOVE);

You can press "1", "2", and "3" to transition to 2D, Columbus view and 3D.

@bagnell
Copy link
Contributor

bagnell commented Aug 9, 2012

I forgot to mention that there's another issue for setting camera orientation over a flight path. It'll be easier to get the camera flight into 2D/CV once that is finished.

@djone010
Copy link
Author

djone010 commented Aug 9, 2012

Thanks for clearing that up Dan. That works great now!

@djone010
Copy link
Author

djone010 commented Aug 9, 2012

@bagnell I am seeing a very strange issue with the same code snippet inside of the cesium viewer. When you drag dynamic data into the viewer, the pointToWindowCoordinates function is totally off in 3D mode, but is fine in the other views. Paste this inside _handleMouseMove of CesiumViewerWidget and drop in the simple.czml.

var p = this.scene.pickEllipsoid(movement.endPosition,this.ellipsoid);
if (p) {
if (this.scene.mode !== SceneMode.SCENE3D) {
p = this.scene.scene2D.projection.project(this.ellipsoid.cartesianToCartographic(p));
p = new Cartesian3(p.z, p.x, p.y);
}
var d = this.ellipsoid.cartesianToCartographic(p);
var px = Transforms.pointToWindowCoordinates(this.scene.getUniformState().getModelViewProjection(),this.scene.getUniformState().getViewportTransformation(),this.ellipsoid.cartographicToCartesian(d));
px.y=this.canvas.clientHeight-px.y;
console.log("pToWindow: "+px);
console.log("orig: "+movement.endPosition);
}

@djone010
Copy link
Author

djone010 commented Aug 9, 2012

Oh, I also had to add SceneMode into the imports by the way.

@bagnell
Copy link
Contributor

bagnell commented Aug 9, 2012

In the call to pointToWindowCoordinates, use this.scene.getUniformState().getViewProjection() instead of this.scene.getUniformState().getModelViewProjection() like in the code I posted above :). The model matrix gets set to the model matrix of the primitive before rendering each primitive (in this case probably the satellite marker) but doesn't get reset to the identity. The model matrix transforms a point from model coordinates to world coordinates. But this doesn't matter in your case because you already have a point in world coordinates so you just need the view-projection matrix.

@djone010
Copy link
Author

djone010 commented Aug 9, 2012

Oh sorry, I did not notice that difference. Works great now! Thanks again for your help and patience.

@bagnell
Copy link
Contributor

bagnell commented Aug 9, 2012

Thank you for posting the bugs you find, especially with code that demonstrates it. I find it difficult to test all of the camera features across all of the view modes for consistency and I appreciate the help.

For the view extent problem you are having, I plan to add an optional height parameter to the function. Would that fix your problem? But I'm not sure when I can get to it. I have to spend some time working on another project.

@djone010
Copy link
Author

djone010 commented Aug 9, 2012

I know how hard it can be to reproduce or understand an issue someone is seeing, so I try to provide clear examples. Then you don't have to waste your time trying to figure out what my issue even is.

I'm just needing something like a scene.view(position) where x and y are positions on the globe's surface and z is the altitude. The flyto does this, but I would like to do it without the animation. Using the flyto with a very short animation time looks ok, but an instant switch would be nicer. I would try to contribute this, but I don't quite understand all of the 3D math logic.

I think I will close this now because the main 2D viewing issues that I brought up seem to be resolved now.

@djone010 djone010 closed this as completed Aug 9, 2012
mramato added a commit that referenced this issue Oct 22, 2015
Fixed Issue66 caused by undefined render state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants