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

drillPick doesn't play well with pickPosition on 3D tilesets #5622

Closed
hpinkos opened this issue Jul 12, 2017 · 10 comments
Closed

drillPick doesn't play well with pickPosition on 3D tilesets #5622

hpinkos opened this issue Jul 12, 2017 · 10 comments

Comments

@hpinkos
Copy link
Contributor

hpinkos commented Jul 12, 2017

In the following code example, I keep getting negative heights when picking tileset features. It doesn't happen all of the time, but if you move the camera around a little bit it happens within a few clicks. This does not seem to happen when i use scene.pick instead of pickPosition. Also, when the camera is more tilted showing the horizon, sometimes picking stops working entirely.

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

viewer.scene.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(-74.01881302800248, 40.69114333714821, 753),
    orientation: new Cesium.HeadingPitchRoll.fromDegrees(21.27879878293835, -21.34390550872461, 0.0716951918898415),
    endTransform: Cesium.Matrix4.IDENTITY
});

var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({
    url: 'https://beta.cesium.com/api/assets/1461?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYWJmM2MzNS02OWM5LTQ3OWItYjEyYS0xZmNlODM5ZDNkMTYiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjFdLCJpYXQiOjE0OTkyNjQ3NDN9.vuR75SqPDKcggvUrG_vpx0Av02jdiAxnnB1fNf-9f7s'
}));

var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(click) {
    var pickedObjects = scene.drillPick(click.position, 10);
    for (var i = 0; i < pickedObjects.length; i++) {
        var pickedObject = pickedObjects[i];
        if (Cesium.defined(pickedObject)) {
            var position = scene.pickPosition(click.position);
            if (Cesium.defined(position)) {
                var cart = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
                console.log('Mouse: ' + Cesium.Math.toDegrees(cart.longitude) + ', ' + Cesium.Math.toDegrees(cart.latitude) + ', ' + cart.height);
            }
        }
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 12, 2017

@lilleyse or @bagnell, do you have any time to look at this?

@lilleyse
Copy link
Contributor

This might be the same issue as #4368. Is it definitely just tilesets having this problem?

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 12, 2017

Not 100% sure, but I've only been able to reproduce it with tilesets

@hpinkos
Copy link
Contributor Author

hpinkos commented Aug 25, 2017

@bagnell to clarify my use case, I have a polyline that follows around the mouse pointer, but I want to click a building in a 3D tileset. Sometimes using scene.pick picks the polyline instead of the building, which is why I want to use drillpick to test if one of the things I clicked was a building before calling pickPosition.

@bagnell
Copy link
Contributor

bagnell commented Aug 25, 2017

The problem here is that pickPosition uses the depth buffer from the last render. The way drillPick works is that it renders, removes what was picked, renders, etc. At the end, there is nothing in the depth buffer for pickPosition to find because it was all removed in the drillPick renders. The negative heights are from the depth plane that we render so primitives behind the globe are hidden. If you had depthTestAgainstTerrain you would get the height from the ellipsoid or from terrain.

A workaround would be to explicitly call render after drillPick.

@hpinkos
Copy link
Contributor Author

hpinkos commented Aug 25, 2017

Is there a reason drillPick doesn't put everything back after it's finished?

@emackey
Copy link
Contributor

emackey commented Aug 28, 2017

We wouldn't want drillPick to always re-render the scene if it wasn't going to be needed. Maybe there could be a flag indicating the depth buffer is dirty after drillPick, and in need of re-rendering before other operations that reuse it?

@bagnell
Copy link
Contributor

bagnell commented Aug 28, 2017

@emackey is right, we could track if it is dirty and re-render before other operations but that is still probably not what you want.

If you render after a drillPick, the pickPosition will always return the position of the closest thing. You want the position under the mouse of everything returned by drillPick right? We could add a function like drillPick that returns every object under the mouse along with the position.

@hpinkos
Copy link
Contributor Author

hpinkos commented Aug 28, 2017

Thanks for the input @bagnell, @emackey! Calling scene.render fixes the problem, and it sounds like we're not going to make any changes in Cesium with regards to this, so I'm going to close this issue.

@hpinkos hpinkos closed this as completed Aug 28, 2017
@fnicollet
Copy link

Just found this issue after getting stuck for a few hours. Calling viewer.scene.render() after "drillPick" does the trick, but it's just impossible to guess.
If that helps anyone, here is a sandcastle example of the issue:

Sandcastle reprod

Click on "use drillPick as well" to see the height of the "pickPosition" change (it gives the height of the ellipsoid instead).
In the code you can uncomment the "viewer.scene.render()" line to "fix the issue. Still, that's probably not good to call render() on each mouseMove() for instance, so a fix would be nice :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants