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

Picking misses plane at specific angles with orthographic projection #209

Closed
dmlary opened this issue May 18, 2023 · 11 comments
Closed

Picking misses plane at specific angles with orthographic projection #209

dmlary opened this issue May 18, 2023 · 11 comments

Comments

@dmlary
Copy link

dmlary commented May 18, 2023

I'm using a plane centered on the origin to get x/z coords. I discovered that with an orthographic projection, raycasting will miss the bottom edge of the plane if the camera has some rotation. Looking straight (or nearly so) down, and the problem goes away.

Screen.Recording.2023-05-17.at.8.21.44.PM.mov

In this video, the green rectangle is the only Pickable entity. The plane is correctly picked for most of the screen, but when I mouse over it on the lower portion of the screen, it no longer picks the plane.

If I then rotate the camera to look down, picking works correctly.

This doesn't occur when using perspective projection.

@aevyrie
Copy link
Owner

aevyrie commented May 18, 2023

What picking backend are you using? It looks like the mod_raycast backend?

@dmlary
Copy link
Author

dmlary commented May 18, 2023

I believe it is the mod_raycast backend. I'm using the default features for the crate, and DefaultPickingPlugins.

@dmlary
Copy link
Author

dmlary commented Jun 14, 2023

Looking at the implementation of the raycast backend, this does look like it's most likely a bug in bevy_mod_raycast.

I'm planning to dig deeper into it tomorrow. I've confirmed the angle of the camera in reference to the plane does have an impact on where the raycasting stops. It doesn't matter how large the plane is (working with 10,000x10,000 normally) at a 30 degree angle to the plane, the raycast misses the bottom 1/4th of the screen. The plane is absolutely present there.

Do you have any suggestions of where to start looking, or any additional data that you'd like to see to help figure this out? I've started reading the raycast code, but any direction would be appreciated.

@dmlary
Copy link
Author

dmlary commented Jun 14, 2023

Oh, this has something to do with the depth of the hit! I enabled debugging and used the mouse to trace where raycasting stops on the plane. The only thing that stood out is that once depth should go below 0.0 due to mouse movement, the raycast stops hitting the plane.

In this attached video, there is a 10000x10000 (x, z) plane at Y = 0 that is the picking target. It takes up the entire screen when not transparent.

raycast-depth.mov

@dmlary
Copy link
Author

dmlary commented Jun 14, 2023

Digging further, I started dumping the results of Ray3d::from_screenspace and found that it stops detecting the plane once the Ray3d.origin y-value goes negative.

For a moment I thought maybe the problem was that using shape::Plane there is no "back" of the plane. You can see this when you flip to the other side of the plane and it disappears. I added a second pickable plane flipped on the x-axis to give the plane a back to pick from if the ray is cast from y < 0. This did not resolve the problem.

I'm curious now about the calculated Ray3d.origin() value. From an naive perspective, I don't really understand why the Y value for the origin goes negative in this case. Maybe it's because this is an orthographic projection, not perspective?

Note that the problem reproduces with the camera under the plane, but on the top of the screen instead of the bottom.

picking-two-sided.mov

@aevyrie
Copy link
Owner

aevyrie commented Jun 14, 2023

it stops detecting the plane once the Ray3d.origin y-value goes negative.

Is this the input ray? My initial suspicion is that the hit is behind the camera (negative depth), which should be ignored, but orthographic view is rendering objects behind the camera.

@dmlary
Copy link
Author

dmlary commented Jun 14, 2023

That's exactly what is going on. I was just typing up a new issue in bevy_mod_raycast for this.

Should update_raycast() not prune these hits when doing ortho projection?

@dmlary
Copy link
Author

dmlary commented Jun 14, 2023

Here's the simplest demonstration of it I stumbled across. Two xz planes: pink is at y=0, tan is at y=10. The camera is at y=2.5, and pointed at the origin. With ortho projection, that tan plane is visible on a third of the screen, but it's technically behind the camera. Of course picking prunes the hits to the tan plane at Y=10 when I mouse over it, because its behind. Instead the hit is for the pink plane at Y=0

Screen Shot 2023-06-14 at 1 59 32 PM

@dmlary
Copy link
Author

dmlary commented Jun 14, 2023

Resolution

Alright, a couple of the problems I had in my code:

  • The Camera was 5.0 units from the camera focus
  • I had increased projection near to -100 because I was seeing clipping of tiles at the bottom of the screen as a result of the camera being so close

Fix / Workaround

Increase the distance of the camera from the focus. For my case, I increased the distance of the camera to 20, with no change in the on-screen projection. This also stopped my camera from rendering objects behind it.

This will resolve raycast picking issues, and allow a switch to near: 0.

@dmlary dmlary closed this as completed Jun 14, 2023
@aevyrie
Copy link
Owner

aevyrie commented Jun 14, 2023

To add to this - setting the near plane negative resulted in objects behind the camera being rendered. Raycasting does not consider objects behind the camera to be hittable. More precisely, it can raycast against these objects, but will ignore them if the hit is behind the camera.

dmlary added a commit to dmlary/bevy_mod_raycast that referenced this issue Jun 14, 2023
`Ray3d::from_screenspace()` previously was not taking into account the
`near` field for orthographic projections.  When `near` was set to a
negative value, `bevy_mod_raycast` would discard the aabb intersection
of some items on screen as they were behind the camera's location.

In this change I extract the `near` & `far` values from the projection
matrix and use those for origin calculations.  This moves the origin of
the `Ray3d` to be at the `near` location, ensuring everything visibile
on the screen is in front of the raycast `origin`.

Support for perspective projections is maintained by the fact that one
of the fields used for calculating `near` & `far`, `projection.z_axis.z`
is set to zero for perspective projection.  In that case we use the old
values of `(-1, 1)` for the near & far values.

Original research & discussion for this research can be found here:
aevyrie/bevy_mod_picking#209
@dmlary
Copy link
Author

dmlary commented Jul 19, 2023

This is resolved by aevyrie/bevy_mod_raycast#84

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

2 participants