#bevy_mod_raycast

85 messages Β· Page 1 of 1 (latest)

fallen pawn
midnight star
#

Copying this question from @dusky copper

Hello, I'm using bevy_mod_raycast and it works very good. The problem I have however, is that I cannot get the component of an entity that is hit. I can get the transform with if let Ok(transform_entity) = transform_query.get(intersection.0) {, transform_query being mut transform_query: Query<&Transform>, and intersection.0 being of type Entity . I tried the exact same with a Component of mine. Anybody knows what I am doing wrong? I also tried to add the RaycastMesh::<()>::default(), to my spawn command. Or do I already need the bevy_mod_picking for this use case?

#

If the raycasting system is returning an Entity, that will correspond with the Entity that has the Mesh that was intersected.

#

My best guess is that your component has not been added to the entity with the Mesh, but rather as a child or on some other entity.

#

The RaycastMesh component is only required if you have turned on that setting.

tawny mortar
#

0.12 support soon, yes? πŸ™‚

midnight star
#

Whenever I get the time, yes.

tawny mortar
#

sure! it's just i saw the PR get approved but it wasn't merged so i was wondering

dusky copper
midnight star
#

Both are valid, the second one is maybe more idiomatic.

#

But should be fine either way.

dusky copper
#

Am I maybe doing something wrong here: ```
pub fn strategy_camera_mouse_button_system(
time: Res<Time>,
mut mouse_button_event_reader: EventReader<MouseButtonInput>,
mut zombie_query: Query<&Zombie>,
mut transform_query: Query<&Transform>,
cursor_ray: Res<CursorRay>,
mut raycast: Raycast,
mut gizmos: Gizmos,
) {
for event in mouse_button_event_reader.iter() {
if event.button == MouseButton::Left {
if let Some(cursor_ray) = **cursor_ray {
// raycast.debug_cast_ray(cursor_ray, &default(), &mut gizmos);
let intersections = raycast.cast_ray(cursor_ray, &default());
println!("intersections: {}", intersections.len());
for intersection in intersections {
println!("intersection position: {}", intersection.1.position());
let entity = intersection.0;

                if let Ok(zombie_entity) = zombie_query.get(intersection.0) {
                    println!("zombie intersection position: {}", intersection.1.position());
                }
                if let Ok(transform_entity) = transform_query.get(intersection.0) {
                    println!("transform intersection position: {}", intersection.1.position());
                }
                println!("-------");
            }
        }
    }
}

} ```

midnight star
#

What happens?

dusky copper
#

The transform works fine, like I said earlier and in debug_cast all of my objects are clearly hit

#

This always gets called when I click on my meshes println!("intersection position: {}", intersection.1.position()); and intersections.len() is always 1

midnight star
#

Maybe try spawning a single zombie, and printing it's entity id using let id = spawn(..).id();. Then print out the entity that is being hit with the raycast.

dusky copper
#

good idea, I will try it

#

I print the Id of my component on creation, it is 406. I print the entity id on click it is also 406. Then it seems like it is not related to your plugin

dusky copper
#

I want to do a drag selection where an area of entities is selected. Like for example on a desktop or in a strategy game. I guess I could cast a lot of rays in an area and put all the hit entities in a Set. Is there maybe an built in way to do this or is maybe there is a better approach?

midnight star
#

You'd be better off using a physics engine and colliders.

#

You want a spatial query - "which entities intersect with the selection box?"

#

If you are working on a 2d plane, you could simplify this though, and just look at the entities' translation and check if it is inside the bounds.

dusky copper
#

Okay, thanks for the input πŸ‘

ruby quail
#

hello, the raycasting works great, but when I modify the mesh vertices to new positions, the raycast seems to not hit the new bounds of the mesh, only hitting the old parts. how should I fix this?

#

for context I'm using the CursorRay and the immediate mode Raycast

tawny mortar
#

atm i don't know how to update Aabb manually but there must be a way

ruby quail
#

oh that's weird, thanks tho!

#

this seems like the current workaround

tawny mortar
#

ah, right

#

calculate_bounds system will pick it up automatically afterwards

astral hollow
#

I am messing with the filter attribute of RaycastSettings and I can't for the life of me get the correct result. Here is some context:

I am trying to build a system that places a model (random .glb file) against a plane. The problem is that I want to place the model to where my cursor hits the plane, and the raycast that I use to find the position only detects that of the model that I am placing. Here is some code:

let should_be_picked: &dyn Fn(Entity) -> bool = &(|filter_entity: Entity| -> bool {
    println!("{}, {}", entity.index(), filter_entity.index()); // Numbers never equal eachother
    return entity.index() != filter_entity.index();
});
if let Some(cursor_ray) = **cursor_ray {
    let intersection_array = &raycast.cast_ray(
        cursor_ray,
        &RaycastSettings {
            filter: should_be_picked,
            ..default()
        },
    );
    let intersection_data = &intersection_array[0].1;
    transform.translation = intersection_data.position();
}

Here, I get the entity from a query of the model. For whatever reason, the indexes of the filter_entity and the model entity are never the same, so I can't properly filter them. Thanks for reading!

midnight star
astral hollow
midnight star
#

I also don't understand why you are using !=

#

I assume you want the filter to look like

&RaycastSettings {
    filter: |entity| entity == plane_entity,
    ..default()
},
astral hollow
#

That way I could use it for more than just a plane

midnight star
#

That means it will intersect everything else, and I thought you just want it to check against the plane?

astral hollow
#

Yeah my bad forgot to say that

midnight star
#

Every mesh inside your glb will have its own entity fwiw

astral hollow
midnight star
#

The scene is the parent, and all meshes are child entities

slender cairn
#

(Sorry to dig up this old thread, but)... is it possible to get the SceneBundle when the ray hits one of the child entities? I'm loading a .gltf model of a car (which is made up of multiple meshes) but I'd like to get the data from my SceneBundle when the ray hits one of the child meshes.

midnight star
#

No, you will need to traverse the hierarchy yourself.

#

It's pretty easy to do, but not within the scope of the plugin.

#

You just need to look at the Parent of the entity recursively, until you find the scene at the root.

slender cairn
#

Ah, of course. Thanks! (And thank you for the awesome plugin... having a blast with it!)

slender cairn
#

Not sure if this is a horrible way to do it, but anyone was looking for a quick-n-dirty way to get the root entity (like for a gltf SceneBundle as I described above), this appears to work:

fn raycast(
    mut cmds: Commands,
    mut raycast: Raycast,
    parent: Query<&Parent>
) {
    ... // set up your Ray3d and RaycastSettings
    let hits = raycast.cast_ray(ray, &settings);
    if let Some((e, hit)) = hits.first() {
        let root = match parent.iter_ancestors(*e).last() {
            Some(root) => root,
            None => *e
        };
        cmds.entity(root).insert(SomeHitMarker);
    }
}

Then you can get the entity (and any other of its components) by querying Added<SomeHitMarker>.

midnight star
#

Oh, right, I forgot about iter_ancestors. Back in my day we had to do it manually. Uphill both ways, in the snow.

opal basin
#

Is ray casting a good way to check if an entity is visible to a camera? Or is there a better solution to that problem?

#

(I want to query for the objects a camera can "see", taking into account occlusions and reflections)

midnight star
#

It is automatically updated for you by bevy

#

and it tells you if the entity is visible to any camera, or if it is visible to a camera and in the hierarchy, which is probably what you want

opal basin
#

seems ViewVisibility is what i want, thanks!

midnight star
#

Yeah, it was renamed

opal basin
#

noob here!
can i borrow the Raycast object into a par_iter_mut closure inside my System?
here's a code snippet showing what i'm trying to do:

// Frustum culling and occlusion detection.
pub fn mark_visible_entities(
    mut view_query: Query<(...)>,
    mut aabb_query: Query<(...)>,
    mut raycast: Raycast,
) {
    for (...) in &mut view_query {
        aabb_query.par_iter_mut().for_each(|query_item| {
            ...
            let hits = raycast.cast_ray(ray, &raycast_settings);
            ...

The error I get:

33  |           visible_aabb_query.par_iter_mut().for_each(|query_item| {
    = note: `Clone` is implemented for `&bevy_mod_raycast::immediate::Raycast<'_, '_>`, but not for `&mut bevy_mod_raycast::immediate::Raycast<'_, '_>`
midnight star
#

It looks like you are trying to clone a mutable reference

#

That is not allowed.

#

From what I can tell, you are trying to running raycasts in parallel, this is not possible, because reaycasting requires a mutable reference to data. You can not have multiple mutable references to the same data.

#

Raycasts are already run in parallel, you would be better off running each raycast serially.

opal basin
#

Ah, i wasn't aware i couldn't run them in parallel. What's the mutable reference needed for? Index updates?

opal basin
#

any convenient way to visualize/debug raycasts?

#

i have xpbd debug wireframes enabled but i guess raycasts aren't going to get rendered that wayunless i add placeholder entities for all the raycasts i'm doing

opal basin
#

nm, this worked: gizmos.ray(origin, direction, Color::BLUE);

midnight star
#

There is a builtin for debugging raycasts

midnight star
#

It will show a debug ray and point at the ray source and on any hits, including normals

opal basin
#

please ignore me - i was confused by the debug normals

obtuse tide
#

hi just switched to new version and trying to update my code - what's the new version of intersect_primitive?

#

(the method that was on RayCastSource)

indigo widget
#

Is it possible to mark some meshes to be ignored without using filters ? The same way NoBackfaceCulling work

midnight star
#

Are you using the immediate or deferred raycasting?

indigo widget
indigo widget
sudden glacier
#

Is this addon still being maintained? There seems to be MRs to get it running on Bevy 0.15 have been open for a while https://github.com/aevyrie/bevy_mod_raycast/pull/127 https://github.com/aevyrie/bevy_mod_raycast/pull/128

GitHub

Update to Bevy 0.15, see change-log for details.

GitHub

Did additional work on top of #127 to pass tests and fix bug mentioned in the comments. Should now be ready to crate

midnight star
#

Not really. The mesh raycasting has been upstreamed, but I haven't gotten around to tidying things up.

sudden glacier
#

I see, the only dependency I have for this crate is bevy_transform_gizmo.

$ cargo tree -i bevy_mod_raycast --depth 1
bevy_mod_raycast v0.18.0
β”œβ”€β”€ bevy_picking_raycast v0.20.0
└── bevy_transform_gizmo v0.12.1
$ cargo tree -p bevy_transform_gizmo --depth 1
bevy_transform_gizmo v0.12.1
β”œβ”€β”€ bevy v0.14.0
β”œβ”€β”€ bevy_mod_picking v0.20.1
└── bevy_mod_raycast v0.18.0

Has this crate been replaced by another for Bevy 0.15 as well?