#Avian Physics

1 messages ยท Page 11 of 1

dreamy viper
#

I'm not sure what i'm doing wrong, but i'm getting a ray cast hit even when it should not be the case:

INFO server::collision::collider: Ray cast head=Vec2(0.0, 0.0) direction=Up
INFO server::collision::collider: collision! collision=RayHitData { entity: 1v0, time_of_impact: 0.0, normal: Vec2(-1.0, -0.0) } aabb=ColliderAabb(Aabb { mins: [20.0, 10.0], maxs: [100.0, 10.0] })

I alwasy use Position::default()/Rotation::default()

sleek thicket
dreamy viper
#

Thanks i think thats the problem, it was colliding with itself. I thought ray casts didnt affect parallel colliders but apparently they do

full tundra
#

๐Ÿ‘‹ heya, I was wondering of the right way to test if colliding entities have certain components. If the player hits a wall I want it to end the game, but if they hit a "score trigger" I want them to earn a point. The example on colliders has an iterator that loops over every collision event, but it's not clear to me the best way to test if any of those colliders are a player and what they are colliding with

#

for reference my current system which works for colliding walls, but now i want to add in a 'score trigger' seems even worse than when i first wrote it

fn get_collisions(
    mut commands: Commands,
    mut collision_event_reader: EventReader<Collision>,
    mut next_state: ResMut<NextState<GameState>>,
    bird: Query<Entity, With<Gravity>>
) {
    let Ok(bird) = bird.get_single() else {
        println!("get_collisions: expected bird but found none!");
        return;
    };

    for Collision(entity) in collision_event_reader.read() {
        if entity.entity1 == bird {
            commands.entity(entity.entity1).despawn_recursive();
            next_state.set(GameState::GameOver);
        } else if entity.entity2 == bird {
            commands.entity(entity.entity2).despawn_recursive();
            next_state.set(GameState::GameOver);
        }
    }
}
glad abyss
#

@vestal minnow did you do anything re: the pathological performance of the collider transform propagation system with many non-physics entities?

#

can i help in some way?

full tundra
#

for what it's worth i've updated my code to use queries and test. it's still a little ungainly though to have to test each entity individually, is anyone familiar with a neater way of handling it?

fn get_collisions(
    mut commands: Commands,
    mut collision_event_reader: EventReader<Collision>,
    mut next_state: ResMut<NextState<GameState>>,
    bird: Query<Entity, With<Gravity>>,
    score: Query<Entity, With<Score>>,
    mut player_score: ResMut<PlayerScore>
) {
    for Collision(entity) in collision_event_reader.read() {
        // increment player score
        if score.get(entity.entity1).is_ok(){
            commands.entity(entity.entity1).remove::<Collider>();
            player_score.score += 1;
            return;
        } else if score.get(entity.entity2).is_ok() {
            commands.entity(entity.entity2).remove::<Collider>();
            player_score.score += 1;
            return;
        }

        // player has hit a rock, end the game
        if bird.get(entity.entity1).is_ok() {
            commands.entity(entity.entity1).despawn_recursive();
        } else if bird.get(entity.entity2).is_ok() {
            commands.entity(entity.entity2).despawn_recursive();
        }

        next_state.set(GameState::GameOver);
    }
}
cinder summit
#

I just use CollidingEntities everywhere instead ... Tho in theory you could also make some cool stuff with one shot systems that give collision handling per-entity maybe?

full tundra
#

i'll take a look into CollidingEntities - thanks

#

if i understand what you're saying @cinder summit - you have just lots of different systems query for collisions and test what they're concerned about independently?

#

i guess it would be a reversal of what i've got. rather than the main character test if it's collided with a score or a wall, have the score test if it's collider with the main character and the wall test if it's collided with the main character

#

which means that the logic stays the same but instead of one big loop it becomes two separate systems with smaller loops

cinder summit
#

I mostly have sensors that do things when players touch them, but yea the system just checks "Does this thing that have special collision behavior touch a player?"

vestal minnow
#

I guess I can just spawn tens of thousands of children as a simple repro, although a more realistic example would be ideal

glad abyss
#

our game is open-source https://github.com/TheSeekerGame/TheSeeker/
i tried to workaround the issue by changing Option<&mut ColliderTransform> in the collider query to be non-optional. i have no idea if this is correct at all. we haven't really developed the physics in our game yet. In my investigation, the root query only matched 1 entity anyway and the collider and parent queries matched ~60k entities

#

we don't really have actual physics to test if things work yet, i just stumbled upon this perf issue because after upgrading from bevy 0.11 to bevy 0.12 our performance of the game was so awful that we couldn't develop anything else

vestal minnow
glad abyss
#

i completely understand

#

that's why i said "workaround". it's something i did so that we can move on with the development of our game. i know it is not upstreamable

vestal minnow
#

hmm, I think this would make a lot of the propagation redundant

#

since it wouldn't be necessary to do at every substep

#

maybe we could also just yeet ColliderTransform if we can use global positions in a stable way

#

I originally had stability issues without it... but at that time there was also a bug with the way child collider collisions were handled

vestal minnow
vestal minnow
#

Okay I technically got a ContactHook component working, but it's a bit of a pain to use since it requires exclusive World access...

It looks like this currently. This just makes the entity skip collisions against the player

let hook = ContactHook::new(world, |_self_id, contacts, world| {
    let mut players = world.query_filtered::<(), With<Player>>();
    let against_player = players.get(world, contacts.entity1).is_ok()
        || players.get(world, contacts.entity2).is_ok();

    if against_player {
        None
    } else {
        Some(contacts)
    }
});
vestal minnow
#

this is using one-shot systems

cinder summit
#

Why does your one-shot system take &mut World? thonk

vestal minnow
#

to register the system

cinder summit
#

But that closure, which should be the system, also takes world

vestal minnow
#

it's this atm

#[derive(Component)]
pub struct ContactHook(pub SystemId<(Entity, Contacts), Option<Contacts>>);

impl ContactHook {
    pub fn new(
        world: &mut World,
        hook: fn(self_id: Entity, collision: Contacts, world: &mut World) -> Option<Contacts>,
    ) -> Self {
        let hook_id =
            world.register_system(move |input: In<(Entity, Contacts)>, world: &mut World| {
                hook(input.0 .0, input.0 .1, world)
            });
        Self(hook_id)
    }
}
#

and yeah this isn't ideal

cinder summit
#

Don't take an fn, just take a system with the correct In/Out ๐Ÿค”

#

Or even just a SystemId

vestal minnow
#

People would still need to register the system which requires World

cinder summit
#

Yea, but then it's just when registering a system, plenty of things might use the same system, so you just need to grab the SystemId from a resource but have that otherwise be a normal system

#

And not &mut World hell ๐Ÿ˜‚

full tundra
#

do you have a code snippet i can see? might be the tired brain but iโ€™m struggling to visualise this ๐Ÿ˜…

cinder summit
#

A component called Class sounds ... Evil thonk

#

At least with CollidingEntities you can keep things decoupled ...
Like this handler for collisions isn't coupled with anything else:

fn set_teams(query: Query<(&CollidingEntities, &SetTeam)>, mut teams: Query<&mut Team>) {
    for (colliding_with, set_to) in query.iter() {
        for entity in colliding_with.iter() {
            let Ok(mut team) = teams.get_mut(*entity) else {
                continue;
            };
            *team = set_to.0;
        }
    }
}
#

I mean the rest of it also kinda annoys me, but it's definitely enabled by Class ๐Ÿ˜‚

vale thunder
#

a component called object

cinder summit
#

Starting over from scratch with normal components ferris_sob

lavish orbit
frail robin
#

I trying to do a ray cast from cursor.
With rapier I used Ray obtained from camera.viewport_to_world(&global_transform, cursor_pos).
But with bevy_xpbd it results into a wrong ray cast. Do I need to perform additional conversion from global coordinates to local?

vestal minnow
frail robin
#

I.e. RayHits and RayCaster.

vestal minnow
#

I'm pretty sure the result with RayCaster should be the same... I'll verify if the result is in local or global space

#

It seems to be in global space

#

I'll test with cast_ray too

frail robin
#

My camera have a transform offset. Maybe it somehow affects the result?

vestal minnow
vestal minnow
frail robin
#

Hm... Let me try to switch to SpatialQuery. Because I used similar API in Rapier.

vestal minnow
#

i.e. the origin of the raycast is at the entity's global transform, unless you've also offset the origin separately

vestal minnow
frail robin
frail robin
#

The position is just wrong

#

It's like it's with offset.

vestal minnow
#

If the raycaster is on the camera

#

The RayCaster is essentially like Godot's RayCast2D/RayCast3D node

frail robin
vestal minnow
#

The origin you give the caster is like a local transform, i.e. it's added on top of the entity's global transform

#

So the camera's global translation is already added if the raycaster is on the camera

frail robin
#

Got it, then cursor position should be enogh, that's what I thought. I wondering why the result is wrong...
It would be helpful to have a 3D example of ray casting from cursor ๐Ÿ˜…

vestal minnow
#

Yeah, that'd be a good example

#

I have a grabber plugin that I've been meaning to add somewhere in the repo, iirc it uses raycasting

#

This doesn't use RayCaster though

#

just SpatialQuery

frail robin
#

I think I know why. In SpatialQuery I pass the result from viewport_to_world which is in global space.

But for RayCaster I need to supply the local coordinates, right?

frail robin
#

@vestal minnow how can I convert the result from viewport_to_world into compatible with RayCast?

frail robin
#

That's what I used, but look like it returns global coordinates.

#

And RayCast expects local ones

#

It's I think it accepts coordinates relative to the entity.

#

I need to cast a ray from cursor from camera.
I currently use SpatialQuery which works for me, but RayCaster looks a bit more ergonomic.

#

I have a system which updates RayCaster for me.

#

And I use RayHits in other systems.

#

But maybe you are right, it's probably better to use SpatialQuery for something like this

vestal minnow
#

to get the local offset

frail robin
#

I tried it, but for some reason it didn't work correctly...

Will just stick with SpatialQuery. Looks like it's more intended for such use case with cursor.

vestal minnow
#

Yeah I'd probably use SpatialQuery for this. If you want to reuse the hits, you could store them in a resource

fair fractal
#

is there a way to get the exit points of a ray or shapecast?

#

I know I could just shapecast in the opposite direction but that seems problematic for a lot of reasons, namely because I will have to iterate through each hit to get to the last one, which would correspond to the first entry point

vestal minnow
#

For raycasts, I think you could maybe do another raycast starting from the entry point (or slightly inside the shape) with solid set to false. This way it'd essentially continue the raycast and hit the boundary of the shape on the other side

#

the caveat is that the normal would be pointing towards the inside of the shape (I think), but you can negate that to get the outside normal

#

For shapecasts, I don't think the same approach would really work, and the only way would be to do a shapecast in the opposite direction

#

Shapecasts are mostly just "time of impact" queries, and you can't really get the "time of exit" afaik

fair fractal
#

yeah that makes sense

#

I don't see solid as an option for shapecasts but yeah that probably wouldn't work anyway for cases where the shape doesn't enter all the way into the shape it's being cast against

#

good idea for raycasting though, didn't think of that

#

also another unrelated question, what would be the best way to calculate the force of an impact? right now I just have a component set up that stores velocity and angular velocity before PhysicsSet::Prepare, and then another system that runs after sync and compares the change in velocity from the initial velocity and calculates force from the difference in those properties, but I'm wondering if theres somehwere it's exposed internally in the resolver step where I could just intercept it?

vestal minnow
#

There is no nice way, no... The constraints in the PenetrationConstraints resource do technically have contact forces, but (1) they have to be accessed in a pretty specific part of the schedule, (2) they are per substep so individual forces are quite small, and (3) I'm not entirely sure how accurate they are

#

XPBD doesn't really use forces or impulses, so they're not needed in contact data or constraints unlike with impulse-based simulation methods

fair fractal
#

yeah that's what I was afraid of, I don't know much about xpbd but I thought something like that was the case

#

I might check out the Penetration Constraints if m current method falls apart, but for now I think I'll just stick to doing that

vestal minnow
#

Yeah it can compute the constraint forces, but they're not actually needed or used anywhere

fair fractal
#

thanks for the info!

vestal minnow
#

I could maybe try exposing the total force accumulated over a physics frame somehow

#

iirc I tried this at some point and had some issues, but I think it should be doable

fair fractal
#

you mean as an accumulation of the penetration constraints over all the substeps?

vestal minnow
#

yea

fair fractal
#

I feel like that should be relatively easy for a user to implement. there is a substep schedule isnt there?

vestal minnow
#

yes

fair fractal
#

well I guess it'd definitely be more convenient

vestal minnow
#

I think a user could have a system for this in the SubstepSchedule in e.g. SubstepSet::SolveUserConstraints

#

Oh and one caveat with the forces here is that it doesn't consider restitution or dynamic/kinetic friction since they're handled separately

#

XPBD handles resolving the actual overlap using a position-based constraint and then applies velocity corrections based on restitution and friction in another phase

#

so it might be difficult to get the accurate total force since you'd need to consider both parts of contact solving

fair fractal
#

don't you need to know the pressure or contact force to properly simulate friction?

vestal minnow
#

yesn't

fair fractal
#

lol

#

fair, I guess 100% realism isn't always necessary in these types of simulation

vestal minnow
#

XPBD has these things called "Lagrange multipliers" which in this context are similar to the signed magnitude of the force

fair fractal
#

oo interesting

vestal minnow
#

and the normal Lagrange can be used instead of the normal force

#

kinda

#

But I believe the friction with XPBD might not be quite as accurate/robust as friction with impulse-based methods

#

or at least it's not as trivial

#

at least Erin Catto had lots of friction issues with XPBD in his solver comparison test
https://www.youtube.com/watch?v=sKHf_o_UCzI

In this video I go over Solver2D results in detail.
Find the blog post here: https://box2d.org/posts/
Github repo: https://github.com/erincatto/solver2d

00:00 - Intro
00:31 - Parabolic Arch
03:56 - Confined Circles
07:44 - Double Domino Effect
09:41 - Friction Ramp
13:13 - High Mass Ratio 1
17:34 - High Mass Ratio 2
20:18 - Overlap Recovery
24:...

โ–ถ Play video
#

but I haven't done comparisons like this myself, and haven't noticed any major issues with friction in the current bevy_xpbd

#

(an older version did have some issues because of an error in the XPBD paper, lol)

fair fractal
#

that was really interesting to watch

#

kind of seems like he just didn't put as much love into xpbd as he did with his other solvers though

#

I feel like xpbd should have done really well with the chain test and the cloth test but it did significantly worse than some of the other ones

#

and wiht the ragdoll one he didn't even test xpbd

vestal minnow
#

Yeah, especially the cloth and chain test results were a bit surprising

#

I'd like to recreate them to compare

#

That's what I'm mostly looking into implementing now

#

Also here's the blog post for Solver2D, it goes into more detail and has some interesting insights
https://box2d.org/posts/2024/02/solver2d/

cinder summit
vestal minnow
#

Yeah, XPBD can have some pretty aggressive explosions in edge cases

cinder summit
#

XPBD popularized the substepping vs iterating right?

vestal minnow
#

Substepping was originally in another paper but it probably popularized it, yeah

#

I feel like substepping has been the main thing that has made XPBD seem more stable than impulse-based methods... people just haven't used substepping outside of XPBD much :P

vestal minnow
cinder summit
#

Godot 4's amazing physics engine always goes like "Oh look a penetration of 0.3m, better apply 59258912501285190 units of force" thonk

vestal minnow
#

but that has worse convergence overall so it's not ideal

cinder summit
#

It's nice to see other people are experimenting with physics stuff too tho

#

It kinda felt like no one was doing any of it but now suddenly everyone is like "Look at these shiny substeps" ๐Ÿ˜‚

vestal minnow
#

everyone switching to the same solver lol

#

Box2D, Rapier, maybe Bepu (I think it uses it?) and maybe bevy_xpbd

#

...bevy_xpbd_but_actually_not

cinder summit
#

I mean it makes sense tho

#

TGS Soft looks good ... And probably doesn't have the patent trolling liability ๐Ÿค”

vestal minnow
#

Yeah unless NVIDIA patented advancing simulations in smaller steps, I think it should be fine ๐Ÿ˜‚

#

TGS is a garbage name though, it's just a substepped impulse-based solver

#

"Temporal Gauss Seidel" is so unnecessary and somewhat inaccurate

cinder summit
#

Also is it not possible for a TGS Soft NGS to exist?

vestal minnow
#

I'm not sure... the article says that "NGS looks like Baumgarte Stabilization with the relative normal velocity and the time step removed" and soft constraints are already an alternative / better version of Baumgarte Stabilization

cinder summit
#

Ah ... in the constrained example it sounded fairly different since it doesn't apply velocity to solve penetration, yet it doesn't explode either ... It doesn't seem meaningfully better in any other cases tho

#

At least TGS Soft still behave sort of fine in that case, if you open the box it's gonna explode tho ๐Ÿ‘€

vestal minnow
#

It'd probably still be a more controlled explosion

#

and a case like that would be explosive irl too because of pressure

cinder summit
#

Yea that's true, I'd just imagine it isn't what you'd want in a game

#

The PGS and XPBD behavior there would just be outright undesirable for any game tho ... They'll never go to sleep and if you open it they all fly off to some +/- Infinty coordinate ๐Ÿ˜‚

vestal minnow
#

without CCD they'll just phase through the walls even before opening the box

#

I think Rapier has now basically evolved like PGS NGS -> PGS (soft?) -> TGS soft

#

IIRC it used to have a velocity solve followed by a position solve (NGS), then moved to a two-phase velocity solve, and now adopted substepping

cinder summit
#

The High Mass Ratio 2 one is ... Concerning ๐Ÿ‘€

vestal minnow
#

TGS soft carrying again

#

btw I've already kinda implemented it ๐Ÿ˜… but without warm-starting atm, and collisions are way too "squishy"/soft currently

cinder summit
#

TGS Soft carries on all examples ... Are we sure this isn't a rigged test by big TGS Soft? ๐Ÿ˜‚

#

Or maybe it's funded by AMD to make XPBD look really bad ... Well still better than PGS or TGS Sticky ... Those do bad on almost every test

fair fractal
vestal minnow
#

poor PGS, it's trying it's best...

cinder summit
vestal minnow
#

upstream yes

fair fractal
#

lol

cinder summit
#

Do we know what solver godot's physics uses? (not the popular jolt plugin or 3.x's bullet integration)

#

The overlap recovery test shows why that warning exists ... I've suprisingly never seen this behavior tho ... When I spawn enemies inside a wall, they just stay there thonk

vestal minnow
#

the repo is a pain to navigate though

#

Godot has a BVH and pathfinding algorithms in a math directory... time to scope-creep those into bevy_math

cinder summit
#

Make all of ploc-bvh a PR on bevy_math, then get it tagged S-Controversial because I didn't implement the P of PLOC ๐Ÿ˜‚

vestal minnow
#

I like that there's a crypto folder, I assume it's the cryptography kind and not the scam kind

cinder summit
#

I found a paper earlier today that had a name that was very funny if put in the context of the scam kind ๐Ÿ˜‚

vestal minnow
#

lmao

#

why is physics in a servers directory, that's very confusing

#

I guess servers in Godot are different from what I associate them with

#

why does almost every file need to be prefixed with godot_

#

the code doesn't really have any docs

cinder summit
vestal minnow
#

Okay what the hell is this formatting

cinder summit
#

Not a physics engine, but a physics server. Not a rendering engine, but a rendering server ... And it's of course not regular code because the node structure would be performance hell for actual physics/rendering/whatever ๐Ÿ˜‚

vestal minnow
#

This is some of the most unreadable code I've ever seen

cinder summit
vestal minnow
#

No but seriously how did this happen

#

It's a weird mix of zero whitespace and way too much whitespace

#

and weird alignment

#

also tabs for indentation ๐Ÿฅฒ

cinder summit
vestal minnow
#

The solver code is weird enough that I can't find the actual contact constraint, but it doesn't look substepped to me

cinder summit
#

Maybe they use their own proprietary bad code iteration solver thonk

vestal minnow
#

but I can't find how solve works for contacts

#

Also... does it not do relaxation after position integration? I think that can cause stability issues

#

or at least overshooting issues

cinder summit
#

Does a similar comparison to the solver2d thing exist for iteration vs substep vs ccd?

cinder summit
vestal minnow
#

I haven't seen a comparison like that. Substeps are just straight up better than iterations based on what I've seen and read, but for tunneling specifically CCD is still needed for cases where very thin/small objects collide against each other

#

substepping can help a bit ofc

vestal minnow
#

(except joints had changes 5 months ago)

#

I read that they are/were considering switching to Jolt physics for 3D... I can see that that could be an improvement ๐Ÿ˜‚

#

I wonder what solver Jolt uses

#

It looks like a pretty basic PGS solver based on the website's description

#

nvm

#

might be NGS?

cinder summit
#

If we can reuse collisions for the whole step ... I wonder if we can do some trickery too where we can skip rechecking everything that we know is gonna be too far away anyway ๐Ÿค”

fiery mortar
#

is it be possible to load a collider from a file?

#

the best thing i have found is bevy_rapier_collider_gen but it is for rapier and i cant really figure out how to convert it to a bevy xpbd collider

cinder summit
fiery mortar
#

well i am making a 2d game and i dont think theres any asset types that support it right now

cinder summit
#

Hmmm, yea might need some custom asset type then, it's not too hard to make a loader for it, but I'm not sure what the assets would be like ๐Ÿค”

vestal minnow
fiery mortar
#

how could i do that tho?

vestal minnow
#

It's just three modules, and you'd just need to switch bevy_rapier to bevy_xpbd for this module (I think)

#

some method APIs might be slightly different

#

but very similar

cinder summit
#

If you only need specific methods it might be even simpler ... The convex hulls could be generated by passing pixels to a function that makes a convex hull from a point cloud ๐Ÿค”

vestal minnow
#

I think that's what bevy_rapier_collider_gen does, at least for some methods

cinder summit
vestal minnow
#

yeah

fiery mortar
#

im not sure if i can do all this, im not very good at such things yet

#

well it seems theres no other option so i guess im gonna have to do it then

vestal minnow
#

I can port it real quick too

vestal minnow
#

so your module structure will be roughly like

src/
    collider_gen/
        collider.rs
        edge.rs
        mod.rs
    ...
    lib.rs

edit: remember to include licenses, or just clone the actual crate so it's already included

cinder summit
#

And copy over the license notice ๐Ÿ‘€

vestal minnow
#

or just fork bevy_rapier_collider_gen so it's already included

#

and make a PR to support bevy_xpbd ๐Ÿ‘€

#

there's an issue for that

fiery mortar
#

or i can just make a new crate for it ยฏ_(ใƒ„)_/ยฏ

vestal minnow
#

yep

fiery mortar
#

or you can do it actually, since you are the creator of it

vestal minnow
#

I'd just make a PR to make bevy_rapier_collider_gen agnostic over the collision backend

#

and provide xpbd and rapier backends behind feature flags

cinder summit
fiery mortar
#

well the whole project is named specifically for rapier

cinder summit
#

bevy_rapier_collider_gen/Cargo.toml

[features]
default = ["xpbd"]
xpbd = []
rapier = []

๐Ÿ˜‚

vestal minnow
#

The crate's owner made an issue where they specifically want to rename the crate and support xpbd

fiery mortar
#

oh i didnt notice it was from the owner

cinder summit
vestal minnow
#

I don't remember getting one...

#

I should probably respond / make a PR now

fiery mortar
#

would it actually be possible to use a gtlf for 2d assets?

#

it seems theoretically possible

trail sparrow
#

Does xpbd use shaders for ray/shape casting?

cinder summit
cinder summit
#

SVGs for the most part are just 2D meshes (tho there's a few other features in there that you wouldn't want to use)
I think there might be a few other vector formats too

trail sparrow
#

I'm loading a splash screen from GLTF

fiery mortar
#

its really hard to decide what to use, im just trying to load some 2d models ๐Ÿ˜ข

trail sparrow
#

You can see some example code I use here โ˜๏ธ

#

You can totally load 2d assets from a gltf. But, you'll need to check the rotation/scale

#

Upvote the issue tho

fiery mortar
#

i also need to load a collider for a model

#

and that doesnt really support it i think

trail sparrow
#

Umm, I think you could set custom properties onto your 2D meshes to create colliders

fiery mortar
#

maybe that would work

#

idk ill try tomorrow

#

this is quite complex just for loading a physics object which has an image

trail sparrow
#

I want it to be simpler as well

fiery mortar
#

possible opportunity for making a library which simplifies this process?

trail sparrow
#

I'm hoping the bevy devs decide to support my idea for a Scene2dBundle to make loading 2d scenes easier

#

But, XPBD has the ability to create convex hull colliders or directly from a trimesh, so I think that's done.

cinder summit
#

I think it was kaosat, you can find posts about it in #showcase

frail robin
#

If I don't add a RigidBody to an object, how it will behave? The same as RigidBidy::Static?
Should I always add RigidBody if in my game I interested only in collision events? I know about Sensor, but I see that in the documentation it showcased with RigidBody::Static.

cinder summit
#

Not adding RigidBody makes it behave like Sensor

#

If you just want to receive collision events and not integrate any forces, Sensor is the way to go ... If you do want to integrate forces, but not be stopped by collisions it would be kinematic

frail robin
# cinder summit If you just want to receive collision events and not integrate any forces, Senso...

Thanks!

So if I don't plan to move an object and only interested in collision events, I can add a collider and it will work like Sensor.
But If I also plan to move an object by changing its transform (while still interested only in collision events), I need to use RigidBody::Kinematic in combination with Sensor, right? Otherwise it triggers end collision events even if the object still collides after I stop moving it.

sleek thicket
#

doesn't it just add RB automatically

frail robin
bleak gust
#

Does anyone know how to fix camera jitter with bevy xpbd? The FAQ system ordering solution just shifts the problem from the IdealCameraPosition to the rest of the world.

#

Added bevy_framepace

#

and turned the lerp factor down. Not sure if the frame spikes are a problem with bevy_framepace or if theyre indicative of the real issue. This is how my systems are currently ordered:

app.add_systems(Update, move_hovering_players
  .after(InputManagerSystem::Update)
  .after(InputManagerSystem::ManualControl)
);

app.add_systems(PostUpdate, (
  (compute_ideal_camera_position, position_camera)
    .chain()
    .before(TransformSystem::TransformPropagate)
    .after(PhysicsSet::Sync),
));

also: https://discord.com/channels/691052431525675048/1205352875937636453

dusty knot
#

What solutions are people using to serialize colliders given that reflection isn't supported?

cinder summit
cinder summit
vestal minnow
#

I believe in 0.13 we could theoretically implement Reflect for colliders since self-referential reflection will be supported iirc. But I'm not sure how we can reflect SharedShape from bevy_xpbd's side since it's a Parry type

dusty knot
#

Is there any other way to export coliders to scene files?

dusty knot
cinder summit
#

Probably the most awful usecase for the blueprint pattern ๐Ÿ˜‚

dusty knot
#

yeah...

dusty knot
#

Does CollidingEntities only work when an entity it is moving?

#

I'm trying to detect collisions between entities held on the mouse cursor, and background entities

vestal minnow
#

If it doesn't work when entities stay still, it might be a bug in 0.3 that has since been fixed on the main branch

frail robin
vestal minnow
#

it affects all rigid bodies

frail robin
#

That's what I thought, thanks

#

@vestal minnow could you confirm that my assumptions are correct?

If I don't plan to move an object and only interested in collision events, I can add a collider and it will work like Sensor.
But If I also plan to move an object by changing its transform (while still interested only in collision events), I need to use RigidBody::Kinematic in combination with Sensor, right? Otherwise it triggers end collision events even if the object still collides after I stop moving it.

dusty knot
frail robin
#

And works as you described with RigidBody::Static and without RigidBody at all.

dusty knot
cinder summit
vestal minnow
#

But a kinematic body allows you to use velocity

vestal minnow
#

(not in 0.3)

frail robin
#

Thank you a lot for the explanations!

vestal minnow
dusty knot
#

In case it matters, I'm adding collider to an entity that didn't have one previously

#

(the "spawn" behaviour is actually done by replacing the spawner entity with the waymark being spawned, and spawning a new spawner in its place)

vestal minnow
#

Some logic around component initialization was changed so it could maybe be related

dusty knot
#

I can verify that Position and Rotation get added

vestal minnow
#

hmm

dusty knot
#

I honestly may just abandon this integration and do what little physicsy stuff I need on top of parry. (Doesn't solve the reflection problem though!)

vestal minnow
#

i.e. RigidBody::Static or something else

dusty knot
#

None

vestal minnow
#

huh, I'll try to reproduce this

frail robin
# dusty knot None

Try adding RigidBody::Kinematic, it should temporarely solve your problem.

#

On 0.3.3

dusty knot
#

To which entity?

#

ah, the docs answer that question

#

I tried adding RigidBody::Kinematic and it didn't help. I also added RigidBody::Static to the background and it didn't help either.

frail robin
#

It solved the problem for me.

dusty knot
#

oh wait I did it wrong

#

yeah that works

#

but if I put the spawner over the background I get a warning about overlapping at spawn

#

which isn't really required here since there's no physics logic relevant to these entities

vestal minnow
#

okay I can repro non-rigidbody colliders being broken on main

#

I'll try to debug

vestal minnow
dusty knot
#

Rigidbody seems to fix it, so I'll just use that for now. Thanks.

#

Also is there an easy way to disable all the systems that run dynamics?

#

I don't currently have any entities that make use of dynamics and I don't know if I'll ever add any

#

Ok, one last q for now: it appears to me that the entities collide even when they aren't actually touching

vestal minnow
dusty knot
#

Is there a way to disable it?

vestal minnow
#

Workaround is to set the prediction_distance to 0

dusty knot
#

You're fantastic, thank you!

#

I'll think on the parry reflection problem

vestal minnow
dusty knot
#

It's also wrapping a &dyn Shape which means it won't work if the shape isn't reflectable

vestal minnow
#

Yeah

dusty knot
#

It would probably be possible to manually implement reflection traits for the Collider and forward but the proper of the shapes not being reflectable is a bigger one...

#

The most straightforward way I guess would be to implement a suite of custom shape types that all implement Shape and forward to parry's implementation

#

the new math primitives in Bevy would be a great candidate except that they can't implement Shape ๐Ÿ˜ฆ

vestal minnow
#

they can, I'm doing / trying to do it for 0.4

#

or not Shape directly yet

#

but conversion to/from Parry shapes for the primitives

#

And I have a fork of Parry (Barry) where I'm trying to replace Parry's shapes with the primitives

cinder summit
vestal minnow
#

yeah for the boxed polyline and polygon

dusty knot
#

It could be done dynamically to start, erroring when it encounters an unreflectable shape.

#

Maybe not ideal, but it would also help migrate code using custom Shapes that may not support reflection

vestal minnow
dusty knot
#

Is there any reason I should take out the RigidBody code?

#

or can I just leave it?

vestal minnow
#

no, you can leave it

dusty knot
#

thanks for all the help! sylheart

vestal minnow
#

np!

dusty knot
#

Let me know if you want help with the math on the circular arc code. I feel responsible for that ๐Ÿ™‚

#

(not to imply that you can't do it yourself... just that it's things I've added to your no doubt long todo list)

vestal minnow
dusty knot
#

oh good call

cinder summit
#

It's cause I just replaced all my enum variants with types ๐Ÿ™ƒ

vestal minnow
#

Hmm, it's specifically a CircularArc so it could also be called that

#

It'd also be consistent with CircularSector and CircularSegment

#

but Arc2d is kinda nice too... not sure

vestal minnow
dusty knot
#

but CircularSegment could also be ArcSegment ๐Ÿซ 

vestal minnow
#

Not necessarily, I don't think that's a geometry term for it

#

I can only find "circular segment" and "disk segment"

frail robin
#

I have an object which consists of multiple children colliders. Is there a way to treat it as a single physics object?

vestal minnow
#

Collider::compound makes a single collider from multiple shapes

frail robin
#

Thanks!

frail robin
vestal minnow
#

I think it means you can't have e.g. Collider::compound(vec![(pos, rot, Collider::compound(...))])

#

Parry doesn't know anything about Bevy hierarchies

frail robin
vestal minnow
#

Yeah, I think internally it's a compound collider

frail robin
#

Got it, so I probably need to merge all my meshes first.

vestal minnow
#

Yeah, somehow flatten them to be a single trimesh... I don't remember if Parry has a helper for that

#

I have a PR that would add mesh merging to Bevy though

frail robin
dusty knot
#

also re: #224: you said here that the default is pixels in 2d but that doesn't seem to be the case. 1.0 world units seems much more in line with what I was seeing.

GitHub

Objective
I tripped up on collisions, because I considered the units as meters, but the default value for prediction distance is 1 (presumably pixels)
Solution
Most of the documentation links to th...

#

I'd be okay with one pixel, but that's not the case?

vestal minnow
#

Is your camera scaled? 1 px is basically 1 world unit in 2D

dusty knot
#

yeah, it's scaled

vestal minnow
#

Well then your "pixels" are just larger

#

By pixel I meant one world unit

dusty knot
#

ahh

#

I'm working with an external scale so pixels and world units are very differnent. And I'll probably offer zoom, too

frail robin
#

Noticed one small catch when you merge meshes. If you create an empty mesh like this Mesh::new(PrimitiveTopology::TriangleList) and try to merge something into it - it will silently doesn't do anything.
To make it work I had to initialize the mesh like this:

Mesh::new(PrimitiveTopology::TriangleList)
  .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, Vec::<Vec3>::new())
  .with_indices(Some(Indices::U32(Vec::new())));
vestal minnow
#

and an empty mesh doesn't have attributes I think

frail robin
#

One last question for today. Can I somehow ignore collisions for specific entity for sensors?

vestal minnow
#

Not right now. I might add something like CollisionFlags for this, but for now you need collision layers for it

#

Or you could do filtering manually with a custom system in the PostProcessCollisions schedule, but that can be more expensive

frail robin
#

Got it, thanks!

vestal minnow
#

np!

dusty knot
vestal minnow
dusty knot
#

Awesome! Ty!

vestal minnow
#

A minimal repro could be useful

bleak gust
#

I can do that

valid fog
#

HMMM okay so i'm having a weird issue

#

So i'm trying to avoid transform propogation issues

#

So if i just do commands.entity(*bone_entity).remove_parent(); that works fine

#

But i want to maintain things like the visibility heireichy

#
let intermediate_child = commands.spawn_empty().id();
commands.entity(parent).add_child(intermediate_child);
commands.entity(intermediate_child).add_child(*bone_entity);

So i do this instead

#

And then, for some reason, all the physics just stops working on the bone_entities

#

They show up in the debug plugin as moving around but they aren't actually moving around

bleak gust
vestal minnow
#

thanks, I'll try to look into it when I have time

#

need to go sleep now :)

bleak gust
#

ok gn ThumbsQ

slim ledge
#

Hi, I'm trying to build a simple vehicle: a box with 4 wheels attached, each with a revolute joint.
I made it kinda work with no rotation but when I rotate the wheels (because they are cylinders and the round part is along the XZ plane), the joints are not correctly aligned. Here's some reduced code with only 1 wheel:

let chassis = commands
    .spawn((
        SpatialBundle {
            // chassis is not rotated
            transform: Transform::from_xyz(0.0, 4.0, 0.0),
            ..default()
        },
        RigidBody::Dynamic,
        Collider::cuboid(1.0, 1.0, 1.0),
    ))
    .id();
let wheel_fl = commands
    .spawn((
        SpatialBundle {
            // wheel_fl is rotated
            transform: Transform::from_xyz(-2.0, 4.0, -1.0)
                .with_rotation(Quat::from_rotation_z(-FRAC_PI_2)),
            ..default()
        },
        RigidBody::Dynamic,
        Collider::cylinder(0.2, 0.5),
    ))
    .id();
commands.spawn(
    RevoluteJoint::new(chassis, wheel_fl)
        .with_local_anchor_1(vec3(-1.0, 0.0, -1.0))
        .with_local_anchor_2(vec3(0.0, 1.0, 0.0)) // anchor2 uses wheel_fl transform
        .with_aligned_axis(Vec3::X) // which axis?
);

I tried to set the aligned axis to X, Y, Z, whatever, it doesn't work.
How does the aligned axis work when anchor 2 is rotated but not anchor 1? What is the reference?

Left/right is without/with wheel rotation.

vestal minnow
#

and the joint will always try to keep this axis aligned, so if one body is rotated and the other one isn't (in a way that makes them unaligned on the common axis), it'll try to snap them to be aligned again

slim ledge
#

I understand the words but I'm confused, what should I do? ๐Ÿ˜€ Is there some simple vehicle code anywhere?

#

I guess I should either rotate the chassis too, or build a cylinder collider that is aligned on the YZ plane ... or find another approach. ๐Ÿค”

mossy flume
#

is there a way i can sum up the current total forces being experienced by a rigidbody?

#

well, total normal forces

#

i tried looking through the contact event struct but couldn't find anything that actually relays forces, just contact points and normals (not the force kind)

mossy flume
#

additional info if it helps, i'm trying to make objects break if there is a powerful collision (but i don't want it to happen if the collision is not very strong). just trying to detect the "strength" of collisions. i'm also not necessarily looking for sudden impacts, ideally ongoing collisions would have a similar effect (eg slowly crushing)

mossy flume
#

huh? i don't think so...

#

if the body is moving at a constant rate then there's no force being applied

#

or forces are being cancelled out

sleek thicket
#

ok you're right... i think i saw debugger for that but i'm not sure if it was xpbd or not

mossy flume
#

hmm, i dunno

sleek thicket
#

nah i think it was from box2d video

#

i'm not sure if xpbd even has something like it, since it's position-based

#

but only @vestal minnow knows

vestal minnow
#

forces can be computed for constraints (like contact constraints) but they're currently not exposed nicely in the API

#

XPBD itself doesn't need to compute forces

mossy flume
#

oh, interesting, looks like i need to read up more on how position based physics works

#

in any case, do u have any recommendation for detecting strong forces?

#

or just fast collisions i guess

vestal minnow
#

You could store the previous frame's velocity, and use the velocity delta to approximate the contact force/impulse

mossy flume
#

ok, fair enough. was hoping there would be something built in but that should work fine. thanks!

vestal minnow
#

Yeah I might try again if I can expose contact forces or impulses nicely

#

IIRC there was some issue when I previously tried that but we'll see

mossy flume
#

what was the approach you tried/considered in the past?

vestal minnow
#

The forces used for solving overlap are already computed for PenetrationConstraints since there's a basic formula for that (it uses the constraint "Lagrange multipliers"), and I was just using that. But restitution and friction are handled separately from overlap in XPBD, so the "true" impulse will be different

#

Basically, overlap is solved at a position-level, and afterwards the velocity is corrected based on the restitution (i.e. bounciness) and friction at a velocity-level. And these would need to be combined into a single force or impulse

mossy flume
#

hmm i see

#

i think even just being able to access the restitution by itself would be great, at least for me

#

although i'm not sure how overlap contributes to the final impulse

#

also, it would be great to be able to access individual "bounces" one by one, after thinking about it, because one rigidbody being squeezed between two others wouldn't change velocity but would still technically be experiencing a strong force

#

for that reason just storing last frame velocity might not actually work for the thing i'm trying to do

vestal minnow
mossy flume
#

do u mean just applying the restitution coefficient by "closer to what you'd expect"? or is there something more going on?

#

sorry i could probably ask 100 questions about this i should probably just do some reading lol

vestal minnow
#

(and the relative velocities of the bodies)

mossy flume
#

ah ok makes sense

#

yeah i guess that does have to be combined then lol

#

that's very interesting

vestal minnow
mossy flume
#

oh cool i'll have a read

#

bookmarked

#

hmm i might have to try rapier and see if they support getting this data

vestal minnow
#

It does, it might be a bit easier with impulse-based dynamics. But I'll try to expose it too rn

mossy flume
#

that would be awesome i'd appreciate it!

#

either way i'll definitely be following this project, seems really cool

#

i like others am very interested in bevy native physics

#

gotta get to bed now but thanks for the chat! i'll probably be around : )

vestal minnow
#

alright, good night!

sleek thicket
#

i was thinking, doesn't "getting crushed" need a response fairly often in games?
e.g. something falls on top of a player, how do you know how much damage to deal?
would exposing the "force" applied be the only/best solution?

vestal minnow
#

yeah it's probably the best solution

vestal minnow
#

To go from an impulse to a force, you'd just divide by delta time

#

For each ContactData, the impulse is the impulse from one substep, but Contacts (the thing returned by collision events) also has a total impulse accumulated over the entire frame

#

(also this isn't on the main branch yet, but I'll make a PR)

#

One issue here is that the contact data is specifically the contact from the last substep, and at that point the contact should be mostly solved anyway... this is why you can see the arrows jitter a lot or even seemingly miss contacts

#

A part of the solution would probably be to run the narrow phase outside the substepping loop (which we should do anyway) and persist the contact points

#

But we'd need Continuous Collision Detection to avoid increased tunneling for the cases where that's an issue (substepped collision detection has worked as a hacky workaround for now)

sleek thicket
mossy flume
#

this is super cool! thanks for taking the time to investigate!

#

i'll try it out today!

vestal minnow
mossy flume
#

ah ok, in that case, whenever it is lol

vestal minnow
#

There's a slight issue where the reported forces are roughly 2x the expected value for a basic 1 kg cube test... I'm trying to figure out if the XPBD paper means that the force is the total force applied to both bodies (i.e. 2x the force applied to one) or if I just have something wrong

mossy flume
#

ah. if it's 2x then that would make sense. but my words mean nothing on this subject haha

vestal minnow
#

Yeah it's unclear since it varies a bit, like if I use a 2 kg cube, the force is bit less than 2x

mossy flume
#

inchresting

vestal minnow
#

In practise, people would probably mainly use the forces to detect stuff like "was this impact hard enough for X to happen", so we might not need super accurate forces, but it would still be nice

mossy flume
#

true. definitely would be ideal to match expectations though

mossy flume
vestal minnow
#

each contact point has a separate force that can be accessed, yeah

mossy flume
#

nicee

mossy flume
#

oh right true

finite blaze
#

I would be interested in exposed forces to simulate object collisions and derive damage on a sim

mossy flume
#

^ same use case here :)

#

glad to see there is interest

finite blaze
#

@mossy flume may I ask what kind of sim? Thinking of combat flight sim here

mossy flume
#

i'm working on making a particle-based world. the reason i want to see forces is to break particles into smaller pieces when they're getting crushed under their own weight or impacted by another object

#

particles can merge together if they're in a liquid-like state to reduce the complexity of the simulation

vestal minnow
#

I...

#

wow

#

I had restitution commented out for whatever reason ๐Ÿคฆ

#

Now I get a pretty stable 9.81 N force which is exactly the expected value

#

I haven't felt this dumb in a while

#

lmao

mossy flume
#

hahahaha well that is a good find!

vestal minnow
#

It needed some other minor refactors too, so it's maybe a bit bigger than anticipated

#

I'll test more tomorrow

vestal minnow
#

Then I'll do the rest of the Bevy 0.13 migration and maybe start writing a blog post for 0.4 :P

#

not yet, I can make something basic for that as well

#

it is in the FAQ though

#

yeah, true

#

@sleek thicket So, for the layers, is this what we landed on for now?

  • memberships instead of groups (but there's a doc alias)
  • filters instead of masks (but there's a doc alias)
  • Remove methods like add_groups/add_masks, and instead access the properties directly
let layers = CollisionLayers::new(0b0010, 0b0101);

layers.memberships.add(0b0001);
layers.filters.remove(0b0100);
// Bitwise ops also work:
layers.memberships |= 0b0001;
layers.filters &= !0b0100;

The memberships and filters use the LayerMask(u32) type, which allows you to also use the enum-based approach for layers, and to pass arrays of layers to the methods

#

yeah I can do that

vestal minnow
#

nah, I believe that's just a higher level thing for grouping collision shapes

vestal minnow
#

No component == all layers

vestal minnow
#

It is Line2d and Line3d though

#

Oh you mean the methods

#

Yeah there it's just line

cinder summit
#

Easy solution to that one. Use primitive_2d/3d with Line2d/Line3d ๐Ÿ˜‚

vestal minnow
#

I believe the gizmo line method is actually a line segment :P

#

unlike the primitive line

cinder summit
#

Oh right ... LineSegment2d/3d

vestal minnow
#

Btw you probably want me to add that feature to disable parry and nalgebra now that generic colliders are merged

#

I'm not sure if the feature should enable or disable them... It makes sense for features to be additive, but 99% of apps probably use built-in collision detection

#

Unless you don't need collision detection at all

#

I guess it can be additive but just be a default feature

vestal minnow
#

yeah

#

but we should at least try to make good decisions early where possible :P

#

yeah I agree

cinder summit
#

Yea parry would be a feature that enables it, but part of default-features

vestal minnow
#

We could call it something like default-collider too, for when we'll probably yeet Parry

cinder summit
#

"recommended-collider" ๐Ÿ˜‚

#

Setting defualt-features=false on crates has kind of become the norm for me too ๐Ÿ‘€

#

On some of them I also barely re-enable anything ...

bevy = {version = "0.12", default-features=false, features = [
    "bevy_asset", "file_watcher",
]}
bevy_hanabi = { version = "0.9.0-dev", default-features = false, features = ["3d"]}
bevy_xpbd_3d = {version = "0.3", default-features=false, features = ["3d", "f32"]}
leafwing-input-manager = { version = "0.11", default-features = false }
renet = {version = "0.0.14", default-features=false, features = [ "bevy" ]}
bevy_renet = {version = "0.0.10", default-features=false}
tokio = {version = "1.33", default-features=false, features=["rt-multi-thread", "macros"]}
vestal minnow
cinder summit
vestal minnow
#

I was confused for a sec lol

cinder summit
#

Yea no reason to ever set it to true, it's on by default anyway ๐Ÿ˜‚

#

But yea I even already have xpbd set to default-features=false

vestal minnow
#

If only cargo supported disabling individual default features instead of all or nothing...

cinder summit
#

My code will definitely break when I port to 0.4 tho ... It has been broken for a while on main so I just use the last commit that does work thonk

vestal minnow
#

broken how?

cinder summit
#

Collisions just don't work at all ๐Ÿ˜‚

vestal minnow
#

I'd assume/hope that it should work with the generic collider stuff now

#

without custom narrow phase plugins and stuff

cinder summit
#

I still need to try that ... I'd imagine it would probably work tho ... I think it just broke because the narrow phase changed and I didn't update my narrow phase copy paste ๐Ÿค”

#

Maybe it'll also fix that funny issue where sometimes my server starts and doesn't have collisions at all thonk

#

Definitely a system ordering thing

#

@vestal minnow Is the plan to merge the open PRs into main, then finish up the 0.13 migration?

vestal minnow
#

There's only one open PR I plan on merging right now, i.e. the layer rework (updating the PR description atm...) but yeah, that's the plan

#

I might also try to add joint breakage since I had that basically done already

#

we'll see

cinder summit
#

Nice ... Then I'll port my project to xpbd main first, before migrating to 0.13 ... Should make the 0.13 migration less stressful

vestal minnow
#

I added some more docs as well, like a quick example of how you could use constants and bitwise ops

#

This is like the third major iteration of this rework lol

#

Layers V4 if we include the original

#

that has never been const because of the excluded_entities HashSet

#

it's not really related to this layer rework

#

yeah

cinder summit
#

Funnily enough HashSet can't be const because of the hasher, and not because it's an alloc type ๐Ÿ˜‚

#

Meanwhile Vec::new is const

vestal minnow
#

HashSet::with_hasher is const, but I don't think DefaultHashBuilder can be constructed in a const way

#

I do wonder if I could make a cursed custom hash builder though...

#

hehe, maybe it was

#

I've seen some people take examples way too literally though

#

but maybe that comment is unnecessary lol

cinder summit
vestal minnow
#

because &mut self

#

even if self was a u32, you'd need the deref there

#

if you assigned to self directly, I think the right side value would need to be a &mut Self too

#

*I think

#

I don't really understand the borrow checker either for stuff like this tbh

#

but no it doesn't copy from what I understand

#

and if it wasn't mutating the value, the doc tests and stuff would be failing

cinder summit
vestal minnow
#

yep

cinder summit
#

Also this is less borrow checker and more pointers ... Pointers suck but not having them is even worse

#

It definitely does give nice suggestions sometimes ... Tho whenever I do something it doesn't like it will just suggest things that create an error suggesting to revert the change ๐Ÿ˜‚

vestal minnow
#

Could have it for both

#

most people will probably mainly look at CollisionLayers

vestal minnow
#

So I'd be forcing everyone to use my custom HashSet for this ๐Ÿ˜‚

#

technically yes, but the SpatialQueryFilter still wouldn't be const (because of the HashSet) and directly coupling layers with spatial queries like that would be weird imo

#

Spatial queries use layers, not the other way around

cinder summit
#

I don't like that name but some function to turn a layermask into a spatialfilter could be usefull ... Until SpatialQueryFilter changes ๐Ÿค”

vestal minnow
#

impl From<LayerMask> for SpatialQueryFilter so you can just pass layers as filters to spatial queries

#

instead of needing SpatialQueryFilter::from_mask every time :P

cinder summit
#

const.into().with_excluded_entities().with_future_filter_thing() would actually be fairly nice if rust gets that .into right ๐Ÿค”

vestal minnow
#

the Into impl would still create the hashset

#

Btw you can't combine LayerMasks directly in a const way because stable rust doesn't support const operator overloads, you need to use the u32 values directly

#

so you can do this

pub const FIRST_LAYER: LayerMask = LayerMask(1 << 0);
pub const LAST_LAYER: LayerMask = LayerMask(1 << 31);
pub const COMBINED: LayerMask = LayerMask(FIRST_LAYER.0 | LAST_LAYER.0);

but for the operation, you need .0 to do it on u32

cinder summit
vestal minnow
#

and tbh you could just use u32 anyway since the APIs should handle the conversion for you

vestal minnow
cinder summit
#

Doesn't it just ::new()?

#

That already does 0 capacity

vestal minnow
#

probably yes

cinder summit
#

Me wondering how I handle it currently with my projectile system which has this field:
ignore: Vec<Entity>,
The answer is ... I don't use excluded_entities at all ... For some reason thonk

#

I mean I guess checking an extra collision or two is a lot faster than the alloc of actually passing in the entities ... I could just reuse the filter or something tho

cinder summit
#

And I guess we can't even have Intos and stuff either ... If only const support was better ferris_sob

vestal minnow
#

we can't impl BitOr in a const way because trait methods can't be const

cinder summit
#

My favorite is when I need to make a pub const fn or because I can't tell std::ops::BitOr to just be const

vestal minnow
#

improved LayerMask docs

#

(also removed the rather redundant comment)

#

I'll probably merge in a bit if it looks fine now

#

edit what?

#

yeah

#

I'll merge the layer rework stuff now (when CI passes), and we can figure out if and how we want to change the spatial query filter stuff later

cinder summit
#

SQF
I read SDF ๐Ÿ‘€

vestal minnow
#

Same ๐Ÿ˜‚

#

I read SDF, then SQL, then finally SQF

#

*for now

night granite
#

Hello,
In my game, the character can throw fireballs. I'd like to make them disappear when they come into contact with a wall. My first attempt was to use events but that didn't work well.

pub fn fireball_collisions(
    mut commands: Commands,
    mut collision_event_reader: EventReader<CollisionStarted>,
    wall_query: Query<With<Wall>>,
) {
    // Wrong. 
    for CollisionStarted(entity1, entity2) in collision_event_reader.read() {
        if let Ok(_) = wall_query.get(*entity2) {
            commands.entity(*entity1).despawn_recursive();
        }
    }
}

In the code, the fireball entity can be entity1 and entity2. What's more, I'd like to manage these collisions in the future:

NB: The gif preview is glitchy, open it in browser

pulsar bone
#

Using CollidingEntities for this is a good idea.
If you're sticking with the event though I'd write something like this:

pub fn fireball_collisions(
    mut commands: Commands,
    mut collision_event_reader: EventReader<CollisionStarted>,
    wall_query: Query<With<Wall>>,
    projectile_query: Query<With<Projectile>>,
) {
    for &CollisionStarted(entity1, entity2) in collision_event_reader.read() {
        for (entity1, entity2) in [(entity1, entity2), (entity2, entity1)] {
            if projectile_query.contains(entity1) && wall_query.contains(entity2) {
                commands.entity(entity1).despawn_recursive();
            }
        }
    }
}
#

The inner for loop should make it less of a hassle to add more checks.

#

The nice thing about CollidingEntities though is that you can split things into separate systems with less boilerplate.

#

Though with CollidingEntities you don't get to know whether the other entity was already colliding or just started

night granite
#

Dear @pulsar bone,
Thank you for your reply. Your solution works very well. The fireballs are correctly removed when they collide with a wall, contrary to what happens in the example.

The solution with CollidingEntities seems to be cleaner. I'll change to it when the code becomes too complex

sleek thicket
#

pub fn system
(   mut csER: EventReader<CollisionStarted>,
        tagQ: Query<&Tag>,
    mut hdEW: EventWriter<damage::hit_damage_event>,
    mut htEW: EventWriter<damage::hit_target_event>,
    mut hoEW: EventWriter<damage::hit_obstacle_event>,
    mut hpEW: EventWriter<hit_player_event>,
)
{   for CollisionStarted(e1, e2) in csER.read()
    {   let tag1 = tagQ.get(*e1).unwrap_or(&Tag::None);
        let tag2 = tagQ.get(*e2).unwrap_or(&Tag::None);

        match (tag1, *e1, *e2, tag2)
        {   (Tag::None, _, _, Tag::None) =>
            {   error!("collision tag component is missing on both entities."); }

            (Tag::damage, damage_a, damage_b, Tag::damage) =>
            {   hdEW.send(damage::hit_damage_event(damage_a, damage_b)); }

            (Tag::damage, damage, target, Tag::target) |
            (Tag::target, target, damage, Tag::damage) => 
            {   htEW.send(damage::hit_target_event(damage, target)); }

            (Tag::damage, damage, target, Tag::None) |
            (Tag::None,   target, damage, Tag::damage) => 
            {   hoEW.send(damage::hit_obstacle_event(damage, target)); }

            (Tag::damage, _, _, _) | (_, _, _, Tag::damage) => 
            {   error!("damage hit something unexpected."); }

            (Tag::player_sensor, player_sensor, presumably_player, Tag::target) |
            (Tag::target, presumably_player, player_sensor, Tag::player_sensor) =>
            {   hpEW.send(hit_player_event(player_sensor, presumably_player)); }
        }

pub fn player_system
(   mut    hpER: EventReader<hit_player_event>,
    mut playerQ: Query<&mut Player::component>,
)
{   for hit_player_event(player_sensor, presumably_player) in hpER.read()
    {   let Ok(mut player) = playerQ.get_mut(*presumably_player)
        else { error!("non-player has triggered a player sensor."); continue; };
        // ...
}   }
#

^

night granite
#

Collision sorting is quite cursed. One of the advantages of your solution is that collision event management is handled in a single place in the code

sleek thicket
#

it's still less cursed than dealing with unity/godot's race conditions

vestal minnow
cinder summit
#

If you have default-features enabled, f32 would be enabled too no?

vestal minnow
#

if it was one crate and used just feature flags for the precision, we could do optional feature enabling like f64 = ["parry3d?/f64"]

#

wait

cinder summit
#

That sounds like it would still work ๐Ÿค”

vestal minnow
#

can I

#

hmm

cinder summit
#

Oh wait the problem is that parry3d set up like that?

vestal minnow
#

I guess I could technically disable parry's default features and enable f64 even from the f32 version of the crate thonk

#

since the source lib is the same

cinder summit
#

You can disable 3d on bevy_xpbd_3d too thonk

vestal minnow
#

yeah

#

this is so hacky but it might work ๐Ÿ˜‚

#

Parry:

[features]
default = ["required-features", "std"]
required-features = ["dim3", "f32"]
#

I'll just disable the required features real quick...

cinder summit
#

Hmmm ... Rust doesn't want me to have SDF collisions apparantly .... Pretty sure a file right next to lib.rs should be able to implement the trait thonk

error: implementation is not supported in `trait`s or `impl`s
  --> core/sdf_peck/src/xpbd.rs:24:1
   |
24 | impl AnyCollider for SdfCollider {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: consider moving the implementation out to a nearby module scope
cinder summit
#

Oh ... Would be nice if Rust just told me there was an unclosed bracket somewhere ferris_sob

vestal minnow
#

noo cargo why ๐Ÿ˜ญ

the package `bevy_xpbd_2d` depends on `parry2d`, with features: `f64` but `parry2d` does not have these features
#

the code does, but not the Cargo.toml...

#

I wonder if parry would accept a PR that adds the features to support this cursed use case

cinder summit
#

Worst case you can just make parry-f32 and parry-f64 the collider features

#

And make those enable f32 and f64

#

Also what is up with this index stuff everywhere? ๐Ÿ‘€

vestal minnow
#

needed for contact impulses

#

since the constraints need to know where the contact came from

#

to update the contact data after the solve

#

(I'm pretty sure rapier and Box2D have similar stuff)

cinder summit
#

The ugliest aabb-related thing in my whole repo ferris_sob

let aabb = self.sdf.aabb(position, *rotation.into());
bevy_xpbd_3d::prelude::ColliderAabb(bevy_xpbd_3d::parry::bounding_volume::Aabb {
    mins: aabb.min.into(),
    maxs: aabb.max.into(),
})
vestal minnow
#

yeah another motivator to make bevy_peck

#

or barry

#

or both

sleek thicket
#

berry

cinder summit
#

I used to make my manifolds like this, but now I'm wondering it that's even the right approach thonk

ContactManifold {
    normal1: m.normal1,
    normal2: m.normal2,
    contacts: vec![ContactData {
        point1: m.point1,
        point2: m.point2,
        normal1: m.normal1,
        normal2: m.normal2,
        penetration: m.penetration,
    }],
}
vestal minnow
# cinder summit I used to make my manifolds like this, but now I'm wondering it that's even the ...

the built-in collider uses this

let manifold = ContactManifold {
    normal1,
    normal2,
    contacts: manifold
        .contacts()
        .iter()
        .enumerate()
        .map(|(contact_index, contact)| {
            ContactData::new(
                subpos1.transform_point(&contact.local_p1).into(),
                subpos2.transform_point(&contact.local_p2).into(),
                normal1,
                normal2,
                -contact.dist,
                contact_index,
            )
        })
        .collect(),
    index: manifold_index,
};

you only have one contact and don't have subshapes so it's simpler

cinder summit
#

No it's the stage where we have multiple entirely separate approaches

cinder summit
vestal minnow
cinder summit
#

At least my collision detection works ... If at least one of the shapes is a sphere or capsule (or rounded cone if I ever implement that in my sdf crate)

#

I mean sure if you only have circles and axis-aligned boxes it's pretty simple

#

It's even built into bevy at this point ๐Ÿ˜‚

vestal minnow
#

yeah I did see that, but iirc it seemed like they didn't even entirely know what an AABB was, so they probably meant something very basic

#

yep

#

school lmao

#

for about a month (with light dev stuff on the side)

#

afterwards I'll be free to work on things

#

for a pretty long time

#

The most important things would be

  • CCD
  • Optimize (CCD will help, since we could maybe move the narrow phase out of the substepping loop while having an answer for tunneling)
  • Glam-based collision detection
  • Try alternative solvers properly (and add better examples and samples)
  • Improve joints (this was meant to be the focus of 0.4)
cinder summit
#

Perfect! ๐Ÿ™ˆ

impl ScalableCollider for SdfCollider {
    fn scale(&self) -> bevy_xpbd_3d::math::Vector {
        bevy::math::Vec3::ONE
    }
    fn set_scale(&mut self, _: bevy_xpbd_3d::math::Vector, _: u32) {}
    fn scale_by(&mut self, _: bevy_xpbd_3d::math::Vector, _: u32) {}
}
vestal minnow
#

it's just a way to do collision detection without tunneling

cinder summit
vestal minnow
vestal minnow
#

but people really want better performance atm

#

idk, I'd end up spending too much time on it and being distracted from school things

#

solving smaller issues that I'm less likely to spend ages on would be better for that

#

there's 50 issues on the repo now ๐Ÿ‘€

#

yeah I've mentioned it a few times but it's not very relevant built-in yet since we don't have any official physics

#

and it requires some relatively complex stuff like an eigensolver

#

(which I do have implemented in glam, but probably not in the most numerically stable way)

#

@cinder summit would like mass props for primitives tho

cinder summit
#

Yes please

#

Give mass props

#

Would be a lot better than uh ...

    fn mass_properties(
        &self,
        _: bevy_xpbd_3d::math::Scalar,
    ) -> bevy_xpbd_3d::prelude::ColliderMassProperties {
        bevy_xpbd_3d::prelude::ColliderMassProperties::ZERO
    }
vestal minnow
#

you'll end up depending on bevy_peck just for mass props

#

lol

#

maybe I should make bevy_heavy

#

sounds nice

#

logo is a fat bird ๐Ÿ˜‚

cinder summit
#

Oof ... It neither works nor gives me any errors ferris_sob

sleek thicket
vestal minnow
#

I'm so good at naming things, bevy_peck, barry, and now bevy_heavy

#

barry is just bevy parry

#

it uses bevy_math

#

for primitives, direction types, bounding types, etc.

#

(or currently it still uses parry's shapes, but I'll get there... eventually)

#

it's a parry fork

cinder summit
#

Ah yes, adding a narrow phase might be ... Useful thonk

vestal minnow
#

might be...

cinder summit
#

And also disabling the parry one

#

Because who even wants a parry narrow phase?

#

And checking if either self or other can detect SDFs, rather than just checking self twice might also help (how tf did I not get a warning for that???)

#

SDF collisions working on xpbd main ๐Ÿ‘€

vestal minnow
#

omg first try

#

whoa

#

now things like child colliders also should work in theory

cinder summit
#

Kinda crazy how it JustWorksTM despite the fact that scaling functions don't do anything, and that mass properties just returns zero values ๐Ÿ˜‚

#

Online RPG

#

It's like and MMORPG but less massive

vestal minnow
#

not massively multiplayer yet

#

yea

cinder summit
#

I hope it's not just yet tbh ๐Ÿ˜‚

#

Imagine trying to get both bevy_xpbd and sdf collisions to perform wel at MMO scales

vestal minnow
#

we must experience the glorious SDF collisions in a massively multiplayer environment

cinder summit
#

I actually had this idea for a while of making a ballpit MMO for a bevy jam thonk

vestal minnow
#

Pac Man? Agar.io? The suika game thing?

cinder summit
#

Realized it doesn't look very SDF if it's just spheres on a box so here are arcs

vestal minnow
#

I'm guessing they can't be dynamic currently

cinder summit
#

I haven't tried tbh

#

I think I could in theory animate the arcs for example

#

Let me just ... Try that thonk

vestal minnow
#

Animated collider shapes thonk

#

like marble marcher

#

oh yeah ColliderAabb uses Parry's AABB... if only we had another AABB ๐Ÿค”

#

it'll just have to convert between Parry's AABB and Bevy's AABB but that should be a pretty negligible cost

#

but I'll need 0.13 for that and I've been working on the main branch for this ๐Ÿ˜ญ

#

I'll just have to migrate it for that...

#

or just make a temporary AABB for main, and replace it with the 0.13 AABBs once I merge that

cinder summit
vestal minnow
#

That's pretty cool ๐Ÿ‘€

#

Could post in #showcase for fun

cinder summit
#

Why are some of the spheres even stuck ๐Ÿ˜‚

#

I guess xpbd doesn't take nearby changing colliders into account for waking rigid bodies ๐Ÿ˜‚

vestal minnow
#

oh yea I didn't even notice lol

#

it should

#

those also don't look like sleeping I think, since the gizmo color isn't dimmer

#

@cinder summit Do you use any spatial query types? Like SQF or RayCaster

cinder summit
#

I use SpatialQueryFilter in my sdf spatial query stuff

#

Hmmm, I think we're gonna need a solver that doesn't hate overlap before changing colliders like this becomes a viable idea ๐Ÿค”

vestal minnow
#

(RayCaster just does nothing)

#

(except get positioned normally)

cinder summit
#

Doesn't RayCaster have a collider? ๐Ÿค”

vestal minnow
#

it's just a ray

#

so no

cinder summit
#

Oh right it's ShapeCaster that has a shape ... Obviously ๐Ÿ™ƒ

cinder summit
#
Update bevy_xpbd
 25 files changed, 239 insertions(+), 336 deletions(-)

Less LoC! ๐Ÿ‘€

vestal minnow
#

Nice!

#

+97 points

cinder summit
#

Doesn't even make a dent in my -21418 points ๐Ÿ˜‚

vestal minnow
#

I think I've managed to fix all errors that making Parry and Nalgebra optional cause... PR soon

#

I went for this in terms of features

default-collider = ["dep:nalgebra"]
# We unfortunately can't reuse the f32 and f64 features for this,
# because Parry uses separate crates for f32 and f64.
parry-f32 = ["f32", "dep:parry2d", "default-collider"]
parry-f64 = ["f64", "dep:parry2d-f64", "default-collider"]
vestal minnow
vestal minnow
mossy flume
#

is negative impulse from ContactData intended?

vestal minnow
#

Btw I'm renaming Collider::ball to Collider::circle in 2D and Collider::sphere in 3D to match Bevy, so at least that'll be more consistent

#

And Collider::cuboid to Collider::rectangle in 2D

vestal minnow
#

Actually it does make sense with the way the normals are set up I think

#

The normal is pointing "out of the body", so the applied impulse will be opposite

#

So impulse1 * normal1 should still return the expected impulse vector I'm pretty sure

sleek thicket
#

they actually make sense
line/line2d vs vec2/vec3 vs camera2d/camera3d just feel like they're all over the place

vestal minnow
#

yeah I agree it's weird that the gizmo methods don't specify the dimension for 3D

#

but every type that comes from Bevy itself has the "d" for types like Camera2d/Camera3d

sleek thicket
#

also i can imagine sphere2d being reasonable if you add normals to it

vestal minnow
#

Vec2 and Vec3 come from glam, and imo it kinda makes sense to leave out the "d" there

sleek thicket
#

doesn't it make sense to cut off the d for everything

vestal minnow
#

I feel like that could be more confusing for some types, like you could think that Camera2 means "the second camera"

sleek thicket
#

but there's no camera1

vestal minnow
#

yeah but the name can still be confusing

#

and there is Camera

sleek thicket
#

there's just as much confusion with that and 2d/3d though

vestal minnow
#

2D/3D at least makes it explicit that it's a type for a specific dimension

#

and also most other engines and tools (that I know of) have the d, like Godot's RigidBody2D, Ray3D and so on

#

while for math types, leaving it out is common

#

like glam Vec2, nalgebra Vector2

sleek thicket
#

vec2/3 methods are used explicitly for specific dimensions but don't specify it

vestal minnow
#

vectors are essentially matrices, which aren't just for spatial dimensions

sleek thicket
#

vectors themselves yeah, but then you have methods like distance, which implies a dimension

vestal minnow
#

yeah you can have helpers for things like Euclidean distance but the type itself isn't necessarily tied to Euclidean space

#

and either way it's just nicer to write Vec2/Vec3 than Vec2d/Vec3d, especially since they're used so much all over the place

#

and in a vector context it's very clear what the number signifies

sleek thicket
#

so making line2/line3, cam2/cam3, vec2/vec3 would align everything

vestal minnow
#

people congratulated for 10k just a few days ago lol

sleek thicket
#

i'll take responsibility for half of it.

#

and nise for the other one.

cinder summit
#

Yea half of it must've been about SDFs and the other half is about layers thonk

sleek thicket
#

and a little bit of bevy heavy

#

not even layers but bikeshedding about layer names

#

bevy heavy and 2/3 also apply

vestal minnow
#

and then the gizmo methods are a weird outlier

sleek thicket
#

yeah gizmos definitely need to be fixed

vestal minnow
#

it's not purely arbitrary

sleek thicket
#

yeah, both unity and godot drop the d for them too, but dropping d for everything else would make sense to me too

vestal minnow
#

Both Unity and Godot have the d for non-math types

sleek thicket
#

it doesn't really have any real consequences because of autocompletion though

vestal minnow
#

like Object3D in unity

sleek thicket
#

line vs line2d tripped me up though

#

when converting from 2d to 3d i was like "what, there's no line3d?"

#

"is there a different name for a 3d line?"

vestal minnow
#

I'll maybe make a PR after I've released xpbd 0.4

cinder summit
sleek thicket
#

nah i like it

#

z in 2d does exactly the thing i expect it to

vestal minnow
#

but quats tho

#

and having to truncate Vec3 everywhere

cinder summit
#

Yea get those quats out of my 2D code ๐Ÿ˜‚

sleek thicket
#

quats are quats, you're gonna have a bad time with them either way

cinder summit
#

Which is exactly why you don't want Quat in 2D ๐Ÿ˜‚

#

It can't be a float because it's the same type as 3D

vestal minnow
#

Transform2d wouldn't have a quat if that's what you mean

sleek thicket
#

or was it my custom methods doing all the job to the point i forgot about it exists ๐Ÿ˜‚

cinder summit
#

Maybe you're using bevy_xpbd's Position and Rotation

sleek thicket
#

oh it had rotate_z

#

and yeah, the rest was custom methods

#

custom methods definitely have a lot of truncate and extend.

trail sparrow
#

I'm not sure if I'm doing something wrong. I'm trying to use collision layers to make a one way exit in my game. Once the object has left the exit, I don't want it to come back in, so I add the ExitLayer group to the object. If I initialize CollisionLayers, such that both layer group/mask are assigned, then the objects can't exit. However, if I call add_mask /add_group in a system it has no effect.

                    CollisionLayers::new([InteractionLayer::Maze,InteractionLayer::Exit], 
                     [InteractionLayer::Maze, InteractionLayer::Exit])

fn add_col_layer(
    gate_objs: Query<
        (
            Entity,
            &mut CollisionLayers,
        ),
        With<ParticleId>,
    >,
    
) {
  for (_e, c ) in gate_objs.iter_mut() {
     c.add_mask(InteractionLayer::Exit);
     c.add_group(InteractionLayer::Exit);
  }
}

Also, I just confirmed. I can .remove CollisionLayers and then .insert it and then it works.

dusty knot
#

*c = c.add_group(...)

trail sparrow
dusty knot
#

It's not an in-place modification

#

I think Jondolf's renamed it though or planning to

vestal minnow
#

Yeah layers have been reworked for 0.4, which solves this footgun

trail sparrow
#

Brutal ๐Ÿ˜„

#

Ok that's great to hear

vestal minnow
#

In 0.4 this would be

fn add_col_layer(
    gate_objs: Query<
        (
            Entity,
            &mut CollisionLayers,
        ),
        With<ParticleId>,
    >,
    
) {
  for (_e, c ) in gate_objs.iter_mut() {
     c.filters.add(InteractionLayer::Exit);
     c.memberships.add(InteractionLayer::Exit);
  }
}
sleek thicket
#

Once the object has left the exit, I don't want it to come back in
did you make sure that when object enters collision, it can't exit by backing out of it?

trail sparrow
#
1100 | ...   *collision_layers = collision_layers.add_group(InteractionLayer::Gate);
     |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `collision_layers` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*collision_layers`, which is behind a `&` reference
 
vestal minnow
trail sparrow
sleek thicket
trail sparrow
sleek thicket
#

i had the same thing and ran into that problem, solved by making the door way behind the trigger

vestal minnow
sleek thicket
#

you might also need to check that there's no enemy/object stuck inside door when you're locking it, otherwise it might go ballistic

vestal minnow
trail sparrow
trail sparrow
vestal minnow
#

#1124043933886976171 message

trail sparrow
sleek thicket
#

btw that would make a really nice example for how sensors, spatialquery, and turning collider or changing layer work

vestal minnow
trail sparrow
#

I think what I "needed" was for the sensor to still work, but no physical interaction

trail sparrow
#

As is, I have one Sensor without any masks and one Kinematic rigid body with a CollisionLayer

trail sparrow
#

So only one by one as the objects exit I turn on the interaction between the gate and the object.

sleek thicket
#

ah ok

#

yeah that does sound like one-way thing more than gate then

vestal minnow
#

0.13 migration for bevy_xpbd ๐Ÿ’€

sleek thicket
#

just need to make the gate behind trigger and it should be fine then

trail sparrow
sleek thicket
#

xpbd didn't though

trail sparrow
#

I mean I'm using bevy_xbpd with Bevy 0.13

sleek thicket
#

upgrading xpbd will probably break some stuff

vestal minnow
#

need to wait for seb to update Parry before I can release 0.4

sleek thicket
#

oof

vestal minnow
#

the classic wait

sleek thicket
#

bevy heavy nudge nudge

vestal minnow
#

parry is blocking both bevy_rapier and bevy_xpbd

sleek thicket
#

last time xpbd was updated a couple weeks earlier than rapier though

#

did parry just have no breaking changes?

vestal minnow
#

not many (previous commit a month ago) but the primary issue is that it needs to update nalgebra to support the new glam version used by Bevy

#

(for conversion between nalgebra and glam)

#

so ultimately the issue is Parry's dependence on Nalgebra

#

I made the PR to update Nalgebra to support glam 0.25 and that was merged, but they haven't released new versions yet

trail sparrow
#

Oh, that's why I could update locally?

parry2d = { git = "https://github.com/Jondolf/parry.git", branch = "update-nalgebra", optional = true }
parry2d-f64 = { git = "https://github.com/Jondolf/parry.git", branch = "update-nalgebra", optional = true }
nalgebra = { git = "https://github.com/Jondolf/nalgebra.git", features = [
    "convert-glam025",
], branch = "glam025" }
vestal minnow
#

yeah

#

I think I deleted that glam025 branch though since it's in upstream nalgebra already

#

cargo update will probably break a bunch of things :)

trail sparrow
#

Still compiles for me, so maybe you didn't delete it. ๐Ÿ˜„

vestal minnow
#

the new layer stuff should also be on the bevy-main branch of bevy_xpbd already

#

so you probably have an older version cached

trail sparrow
trail sparrow
trail sparrow
#

@vestal minnow something to think about: I'm currently using ExternalForce::apply_force to apply a vector field dependent on (x,y). It might be helpful to have some kind of function/query based way of doing this same operation. For example, right now Gravity is a vector, but I would like to specify gravity as a function in x,y,[z] (My game is 2D).

Also, translating from Force to Acceleration obv requires dividing by mass, it'd be great to have an additional function apply_acceleration , perhaps on the RigidBody::Dynamic component.

vestal minnow
# trail sparrow <@545959292281552928> something to think about: I'm currently using `ExternalFor...

Well, RigidBody::Dynamic definitely can't have that (what data does it mutate??) but there could maybe be an Acceleration component.

That would be a very strange component though, since it'd probably have to be updated to match the current acceleration (using current and previous velocity?) but also respond to users changing the acceleration. Forces already cause acceleration, so I'm not sure if we need this complexity. I have this vague memory of bevy_rapier also having (or considering having) an Acceleration component at some point, but it had issues and was removed (if it was merged in the first place)

#

I might be misremembering though ๐Ÿค” Can't find acceleration issues in the repo

trail sparrow
#

Maybe it's all just too specific and there are ways of doing it without adding an API.

#

The Gravity resource is basically an Acceleration component applied to everything though

cinder summit
#

Acceleration is always pretty easy to apply from your own code at least. You rarely want to apply some acceleration that just lingers around after all ๐Ÿค”

trail sparrow
#

Yeah, I'm just applying environmental forces that depend on x,y. It's all good I just found the API a bit awkward, but maybe the problem only exists in my brain.

vestal minnow
trail sparrow
#

Is apply_force an update or does it sum across calls?

trail sparrow
# vestal minnow I'm not sure if I fully understood what you meant by applying a vector field dep...

Yeah, my code looks like this:

            let p = t.translation.xy() / 100.0;

            let mag_p = p.length();

            /// Orbit
            let orbit = Vec2::new( p.y / mag_p,
                               -p.x / mag_p
                );
            /// Push out from center
            let push = Vec2::new( p.x / mag_p,
                               p.y / mag_p
                );
            /// Push into center
            let pull = Vec2::new( -p.x, -p.y );

            f.apply_force( ( orbit * 20. ) * gravity.get_intensity() + ( push + pull ) * gravity.get_intensity().abs() * 10.0 );

vestal minnow
trail sparrow
#

At some point, push and pull balance out, then the 'orbit' forces push the objects around in a circle

vestal minnow
#

iirc there's something like set_force too though

trail sparrow
#

I guess I'm just thinking users might find it helpful if, for example, a body could have, for example, a point source gravity field.

#

Or, whatever other force fields they might have. It's totally doable through ExternalForce though.

sleek thicket
#

maybe as a feature

vestal minnow
#

Yeah something like ForceField could be fine to add

#

or PointAttractor

sleek thicket
#

i think right now replacing parry for the sake of instant updates is way more important

trail sparrow
#

Maybe point attractor with iteraction layers?

vestal minnow
#

they'd probably be limited to a specific area, which could be a sensor collider

#

like Godot's Area and Area2D

sleek thicket
#

while inside sensor, apply force based on distance and pull strength

trail sparrow
trail sparrow
sleek thicket
#

parry is the collision detection library from rapier

#

xpbd won't be able to update to bevy 0.13 until parry updates

#

among other problems only jondolf knows

vestal minnow
#

and NiseVoid

trail sparrow
#

Got it. Actually, I was playing with bevy_hanabi and wondering if a shader based collision detection backend would be useful/possible.

sleek thicket
#

probably, to somebody, somewhere.

trail sparrow
#

lol

sleek thicket
#

shader rain collisions would be cool

#

no idea if it's actually better than a sim on cpu though

trail sparrow
#

I was just thinking you could maybe model a lot more collisions per frame with shaders and a rendering pipeline

sleek thicket
#

not sure how that'd work though

vestal minnow
sleek thicket
#

you're probably thinking of something like noita, but even noita does it on CPU

cinder summit
trail sparrow
sleek thicket
vestal minnow
#

collision detection already is backend-agnostic with the new generic collider stuff, but you'd probably need to switch collider types

sleek thicket
sleek thicket
vestal minnow
#

yea

cinder summit
trail sparrow
#

Isn't there a collider from_trimesh?

sleek thicket
vestal minnow
# trail sparrow Got it. Actually, I was playing with bevy_hanabi and wondering if a shader based...

but yeah collision detection on the GPU would get very complex very quickly, here's an article on why GPU physics generally isn't a good idea unless you're NVIDIA
https://www.bepuentertainment.com/blog/2019/1/16/-but-gpus-arent-always-the-right-choice

#

for particles it might be more viable maybe

sleek thicket
#

rain and snow are really common but end up being mostly faked

cinder summit
cinder summit
sleek thicket
#

i did a test in unity with gpu particles and collisions, it couldn't use physics engine and had to replicate the environment inside the system

#

it was pretty cool though

vestal minnow
trail sparrow
# sleek thicket all i know about shader physics is that they're basically faked, no idea how GPU...

My thought was just that there should be a way to detect the hull intersections, then toss those back to CPU for the rest of the modeling. Maybe there's no point.

My game has a bunch of square-2d-voxels for the map. I can join them into larger rectanglular sections, but I'm talking only about a couple hundreds of RigidBody::Kinematic colliders interacting with RigidBody::Dynamic colliders. When I scale the map I'm finding the frame rates drop pretty dramatically.

cinder summit
vestal minnow
cinder summit
#

Give torus gradients and I'll do it ๐Ÿ‘€

#

I have marching along straight lines how hard could marching along circles be?!

vestal minnow
sleek thicket
trail sparrow
sleek thicket
#

@vestal minnow

vestal minnow
#

uh

cinder summit
vestal minnow
#

lmao

#

I'm a low hanging fruit

trail sparrow
sleek thicket
#

rewriting parry starting with learning how collision detection libs work at all would probably end up helping

trail sparrow
#

I messed around with collision detection in college... like, 2004

sleek thicket
vestal minnow
trail sparrow
#

I was doing some path planning for a radiation therapy machine and the idea was to avoid squishing the patient.

sleek thicket
#

it doesn't hurt to read the code at least