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

Rigorous recursive raycast #488

Open
kpreid opened this issue Apr 23, 2024 · 2 comments
Open

Rigorous recursive raycast #488

kpreid opened this issue Apr 23, 2024 · 2 comments
Labels
area: data Things related to the data structures underlying the world, and the functions that manipulate them. kind: incomplete A feature is partially implemented; the current state of the code is inconsistent

Comments

@kpreid
Copy link
Owner

kpreid commented Apr 23, 2024

We have a function called recursive_ray, which is used by the raytracer and cursor to descend into a block's voxels. It is just implemented as:

pub(crate) fn recursive_ray(ray: Ray, cube: Cube, resolution: Resolution) -> Ray {
    Ray {
        origin: ((ray.origin - cube.lower_bounds().map(FreeCoordinate::from))
            * FreeCoordinate::from(resolution))
        .to_point(),
        direction: ray.direction,
    }
}

However, this approach is subject to floating-point error (I think; a test case proving that would be good). Instead, we should build it directly into RaycastStep so that it can generate a child Raycaster with exactly the right state, guaranteeing that it will step through at least one voxel that lies on the surface of the relevant block (as opposed to, say, entirely missing the block by passing diagonally through an edge of its bounds).

@kpreid kpreid added kind: incomplete A feature is partially implemented; the current state of the code is inconsistent area: data Things related to the data structures underlying the world, and the functions that manipulate them. labels Apr 23, 2024
@kpreid
Copy link
Owner Author

kpreid commented Jun 1, 2024

Commit 0f34c9a replaces block::recursive_ray() with raycast::RaycastStep::recursive_raycast(). I also added a basic test. None of the actual improvements have been done yet.

I wanted to add a Raycaster::ray() method that conveniently returns the ray, but that turned out to be difficult because Raycaster modifies its ray field for its own purposes. Something to revisit later.

@kpreid
Copy link
Owner Author

kpreid commented Jun 20, 2024

On further consideration of the problem, I'm thinking that the current impl Iterator for Raycaster design isn't the best way to proceed — we want to be able to fetch more pieces of the raycaster's internal state, which is inconsistent with having a single, non-borrowing step (iterator item) type.

Also, here's an interesting question about recursive raycasts: we've been thinking about cube-containment consistency when entering voxels, but what about exiting? What if numerical error in the recursive cast leads to the recursive ray changing direction a little? This could result in a similar diagonal crack from the ray passing through a gap. Suppose we have half-blocks A and B arranged like this (+s mark the outer level block grid):

+AAA+   +
AAAA
    BBBB
    BBBB
+   +   +

Then it might be possible for a ray exiting A to miss the solid part of B and render as a crack.

In order to avoid this, we would want to not just have a special procedure for recursive-enter but one for recursive-exit too — the inner Raycaster writing some of its state back to the outer one. Possibly the API would be a single integrated TwoLevelRaycaster of some sort.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: data Things related to the data structures underlying the world, and the functions that manipulate them. kind: incomplete A feature is partially implemented; the current state of the code is inconsistent
Projects
None yet
Development

No branches or pull requests

1 participant