#Avian Physics

1 messages · Page 2 of 1

warm gulch
#

OK; so I actually managed to rotate the kinematic body using the Rotation component, there has to be something wrong with my code for the mouse angle stuff.

warm gulch
#

About the rotations, what I want to do is take some arbitrary angle (the angle between player and mouse pointer) and just set the Rotation to that angle. I know the rotations work because I can do add_assign and add some degrees per second, but there is something I am not getting here. So, how would I most conveniently do that?

#

Basically, how do I do a "rotate_to"?

vestal minnow
#

2.0 doesn't have that functionality, only the main branch does

warm gulch
#

Ah, I get it. Gotta get on that main branch, ASAP

#

Don't worry about the rotations, unless you've got a really good idiomatic example on how to do it; I managed to figure it out.

vestal minnow
#

Transform::look_at would probably work

#

If you want an entity to just "look at" the mouse position

warm gulch
#

Yeah, I think so, but I screwed up what forward(), up() etc actually were... So I did it using rotation and some lerping.

vestal minnow
#

Yeah up should generally be just Vec3::Y but that works as well

vestal minnow
#

I can try if a full update instead of update_incremental would fix it when I have time, although I would expect it to be slower in general

cinder summit
#

Ofc it's a known bug 🙃 ... Only workarounds I can imagine are full update or doing a full update every Xth update

#

I'm not sure how much difference full makes compared to incremental when everything is always moving and there's those weird issues with rebalance 🤔

drifting marsh
#

where can I schedule moving the camera? normally, I would put it in Update but I need to put it in PostUpdate so it can run after physics. I tried this but it causes jitter:

.add_systems(
    PostUpdate,
    transform_camera
        .after(TransformSystem::TransformPropagate)
        .before(CameraUpdateSystem),
);
severe urchin
#

i have a serialization/float accuracy question about bevy_xpbd's Rotation component..
my Position x,y stuff is syncing up fine - deterministically. since the full precision f32 values of x and y are sent over the wire.
When it comes to Rotation, the sin and cos fields of the struct are private, so i'm sending using Rotation::from_radians and Rotation::to_radians.. but this is giving me slight discrepencies between server and client, because i'm losing precision. (sending radians: f32 instead of cos: f32 and sin: f32)

One solution is to add Rotation::from_sin_cos() constructor. Then i could serialize and deserialize with full precision. Is that something you'd accept a patch for jondolf?

    /// Creates a [`Rotation`] from sine and cosine
    pub fn from_sin_cos(sin: Scalar, cos: Scalar) -> Self {
        Self { sin, cos }
    }

However, alternatively perhaps there's a way to quantize my simulation on both server and client so float accuracy isn't an issue.. anyone tried this? would probably cause other bugs in the physics code i guess

Welcome any suggestions!

#

if i patch in that constructor i can send rot.sin() and rot.cos() over the wire and reconstruct accurately, will give that a try.

#

yeah that works fine.. quantizing is premature i suppose, i can spare the few extra bytes to send position accurately heh

vestal minnow
#

You can make a PR if you have time, I probably can't today at least

severe urchin
#

i sent a pr against main

#

although i'm still using 0.2 which i've patched locally

vestal minnow
#

Oh didn't notice, thanks :)

undone oyster
#

Hello ! I' m trying to replicate the behavior of the gear train of a watch and I have a weird behavior at some point :

#

In this video you can see that I have some extreme jittering when there too many gears connected. At some point, I remove the last gear collider and everything runs extremely smoothly.

#

Do you know what could cause these jittering ? My guess was the last gears rotate too fast, so I should increase the substeps (in the video, there are at 30) , but it actually make the simulation worse

#

On the plot you can see the actual evolution of the rotation for the two first gear of the wheel train, and without the last gear, it is a perfect straight line which is quite impressive !

vestal minnow
#

@undone oyster Looks really cool! It's hard to tell what the problem is based on the video, but it could maybe be related to numerical imprecision at high speeds, or it could be related to collision instability https://github.com/Jondolf/bevy_xpbd/issues/93.
If the centers of masses are offset (not zero), it could also be https://github.com/Jondolf/bevy_xpbd/issues/108.

You could maybe try with the f64 feature (no default features) and with many substeps to see if it's a number precision issue. You might have to change some types to e.g. DVec3 instead of Vec3 though

undone oyster
#

thanks a lot, will try to switch to f64 and increase the substep. I'll keep you posted!

#

All the colliders are convex colliders, i generate a convex hull for each tooth of each gear at setup and then use the compound feature to join them

#

Again it is remarkably stable until the last gear, much better than any other simulation engine I've tested.

vestal minnow
drifting marsh
#

It can run at any time in PostUpdate. Wouldn't CameraUpdateSystem run after physics because I run my system after TransformPropagate?

#

I don't think I actually need to run it before CameraUpdateSystem. It just appears to update the camera's projection when the viewport size changes.

drifting marsh
undone oyster
#

Hello again, just a follow up from my previous question, I'm still having instability issues and I managed to isolate the problem with the last two gears. If I zoom in at the contact zone, I have an explosive reaction on the small pinion as shown in the video.

#

I've tried to play with the restitution parameter but couldn't see any visible difference. Also I switched to f64 precision but again, no visible difference.

vestal minnow
#

Hmm, hard to say what's causing it without a local repro. Did you try setting both restitution and friction to zero, either for all cogs or just for the small one using CoefficientCombine::Min? I doubt it's that though

#

*pinions

#

I suppose I could also experiment locally a bit if you're fine sharing the project via DM or something

undone oyster
#

Thanks ! Sending you a DM 🙂

severe urchin
#

i switched from using 0.2 (with a couple of patches) to main for my 2d thing, and now my triangle collider passes through my wall (a rectangle collider). it behaved correctly with 0.2.. i don't think i changed anything else. any ideas what might be going on?

warm gulch
#

OK, so say I have a bunch of entities, with some components defining "what" they are, players, enemies, bullets. Players shoot bullets at enemies and vice-versa. I have some collision layers to illustrate this as well, of course. So I then set up my little collision event-listening system where I can get a nice little iterator over all the collisions. Every contact has two entities. I need to figure out which is which of all of these. No problem, I could just have some queries for that, including their health components, score components and other necessary stuff, buuuut this is just three different types of entities, right now. I see a horrible mess of if let Ok(c1, c2, c3) = query_for_player(entity1) type of queries to figure out which entity is which and what type each entity is. What would be the "most conventient" way of doing this? I'm very new to Rust and Bevy so maybe there is something here I'm missing.

warm gulch
#

Oh, I kind of like rust - I can do this: let (bullet_entity, other_entity) = if bullet_query.contains(contact.entity1) { (&contact.entity1, &contact.entity2) } else { (&contact.entity1, &contact.entity2) };

#

I realize the code is wrong, but still - this makes it easier to do what I wanted. I will now stop spamming this channel, no one seems to be awake anyways.

severe urchin
#

quite common to filter queries for specific marker components (ie components that don't really have data), eg: Query<(&Whatever,..), With<Player>> or With<Bullet> etc

#
    asteroids_q: Query<Entity, With<Asteroid>>,
    bullets_q: Query<(Entity, &Geid), With<Bullet>>,
warm gulch
#

OK, I am sorry for the poorly formatted code.

#

And then I did if bullet_query.contains(*entity1) || bullet_query.contains(*entity2) {

#

to check if this was indeed a collision with a bullet and worked from there... I don't think I have grasped the query system 100% yet.

#

I'll probably get back to that snippet of code again later.

vestal minnow
#

Instead of using an Option<Something> and .is_none(), it can be nicer to use Has<Something> which returns a boolean directly

severe urchin
#

i mean, doesn't seem unreasonable as a first version. i do that sort of thing in various places. i wouldn't try and get too fancy unless you have evidence it's a bottleneck 🤷‍♂️

#

ah yes Has is better if you don't need the component value

warm gulch
#

OK, neat, I'll check that out in the docs. Thx!

#

But how do I use that when I have two given entities, already?

severe urchin
#

you'll need to do query.get(entity1) and .get(entity2) i believe, to check them both. either could be a bullet or whatever

#

so you might have

q: Query<(Has<Boid>, Has<Projectile>, Has<Wall>)>, 
...
if let Ok((is_boid, is_projectile, is_wall)) = q.get(contact.entity1) {} ... // same for entity2
vestal minnow
#

Oops referenced wrong message lmao

severe urchin
#

ah yes get_many i should use that.. i'm still fairly new to all this too heh

vestal minnow
#

I'm pretty busy with school for quite a while so I might not have much time but if I do, I can test if I can repro

vestal minnow
severe urchin
crystal cosmos
#

is there a way to get the velocity at a point of a rigid body? i had a look on rigidbody and linearvelocity but didn't see any methods there

royal helm
#

point velocity = linear velocity + angular velocity.cross(point - center of mass)

#

but I don't know if there is a specific method for it

#

@crystal cosmos ^

vestal minnow
#

There's no method currently but it should be very easy to add

#

LinearVelocity and AngularVelocity are separate components though so users would have to manually pass the angular velocity and center of mass

severe urchin
#

is there a specific way to run the tests to avoid them failing with left = 9.700001 right = 9.7 and related floating point issues? i just ran cargo test (on mac m1) after making a seemingly innocent change.

royal helm
vestal minnow
#

Yeah assert_relative_eq! from approx should be used for tests with floating point issues, most of our tests should use it already but I might've missed some

#

I don't have a Mac so the tests work for me

severe urchin
#

ah, thanks. will swap any you missed until it passes on m1

royal helm
crystal cosmos
#

Am I using cast_ray wrong 😅

spatial_query.cast_ray(
    p.translation + w,
    p.down() * 1.0,
    0.5,
    true,
    SpatialQueryFilter::default().without_entities([e]),
)
thread 'main' panicked at 'Matrix index out of bounds.', /Users/choc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/parry3d-0.13.5/src/query/clip/clip_aabb_line.rs:141:13
  14: bevy_xpbd_3d::plugins::spatial_query::system_param::SpatialQuery::cast_ray
             at /Users/choc/.cargo/git/checkouts/bevy_xpbd-87d8ac3552aaa63b/d9d50bc/crates/bevy_xpbd_3d/../../src/plugins/spatial_query/system_param.rs:149:9
crystal cosmos
#

Thanks for your help aceeri ^_^ worked

cinder summit
crystal cosmos
#

Nah didn't find it, something to do with adding forces in certain directions 🤷

#

Just want to make sure it's evaluated properly

cinder summit
#

Hmmm, all I can think of is either of the values becoming NaN or p.down() being 0, otherwise you shouldn't get an out of bounds 🤔

severe urchin
#

(i'm having a go at changing parry so that SharedShape implements PartialEq btw)

#

there are a couple of shape types i'm not sure what to do with, like heightfields

cinder summit
#

I mean you can compare heightfields, but that's not the most efficient operation 🤔

vestal minnow
#

I guess you could compare all the heights (not very efficient) and leave it up to sebcrozet to decide if that's fine or if it should just always return false or something

#

for TypedShape::Custom I think it's fine to always return false since you just can't know the shape in advance

#

I'm guessing that shapes like these are the reason SharedShape already doesn't impl PartialEq though so idk if it'll get accepted

#

could add a note on comparison performance of some shapes in the docs I suppose

severe urchin
#

yeah i'm not sure if it will either. i think with custom you'll know if you're using custom shapes, and can do a separate equality check

#

i think the other eq implementations are correct, none of them seem inefficient except heightfield, which i've left alone for now

vestal minnow
#

For TriMesh, is it enough to compare indices? Shouldn't it iter and compare trimesh.triangles()?

severe urchin
#

hmm, yes it should probably compare triangles. will change it. i've only ever done 2d stuff so a bit clueless

cinder summit
#

You need to check both yea

vestal minnow
#

or yeah TriMesh seems to have .vertices() so you can use that as well

severe urchin
#
impl PartialEq for TriMesh {
    fn eq(&self, other: &Self) -> bool {
        let triangles = self.triangles();
        let other_triangles = other.triangles();
        if triangles.len() != other_triangles.len() {
            return false;
        }
        for (t1, t2) in triangles.zip(other_triangles) {
            if t1 != t2 {
                return false;
            }
        }
        true
    }
}
#

oh wait yes can't i just check if indices and vertices match

vestal minnow
#

with .triangles() idk if it guarantees that indices match

#

if yes, you can use that, but otherwise check separately

cinder summit
#

They would technically be different if they didn't match ... But the same triangles in the same order could be considered the same shape 🤔

severe urchin
#

i've pushed the comparing triangles version for now

vestal minnow
#

I think they'd be different because Triangle is this

#[derive(PartialEq, Debug, Copy, Clone, Default)]
#[repr(C)]
pub struct Triangle {
    /// The triangle first point.
    pub a: Point<Real>,
    /// The triangle second point.
    pub b: Point<Real>,
    /// The triangle third point.
    pub c: Point<Real>,
}
#

and the points are given by indexing into vertices

#

but yeah thanks for making the PR, we'll just have to wait and see if it gets accepted

#

I would probably be fine with adding it for bevy_xpbd regardless

severe urchin
#

cool, well it would be neater to push it down into parry so let's see..

#

i can progress with my patch locally that adds it to bevy_xpbd for now

broken crystal
#

Hello, I am trying to add bevy_xpdb to my project. I am testing on two cubioid entities, one static, one kinematic and both have collider component. I have added PhysicsPlugins, but I get no collision responses, only collision events. Is there something more that I need to do?

shell ermine
#
Dynamic bodies are similar to real life objects and are affected by forces and contacts.

Kinematic bodies can only be moved programmatically, which is useful for things like character controllers and moving platforms.
Static bodies can not move, so they can be good for objects in the environment like the ground and walls.

broken crystal
drifting marsh
#

does anyone know if it would be possible to implement the collide and slide algorithm for kinematic bodies or do you need to use shape casting?

vestal minnow
#

bevy_xpbd doesn't have a built-in character controller yet, but yeah it should definitely be possible to implement collide and slide for kinematic bodies. Afaik collide and slide uses shape casts, which we do support

#

this is a pretty good video on collide and slide
https://youtu.be/YR6Q7dUz2uk?si=krv4akOiD5vuPkSq

How to make actually decent collision for your custom character controller. Hopefully you find this helpful and people will finally stop saying "jUsT uSe DyNaMiC rIgIdBoDy!!!1!!11!!"

Chapters:
00:00 - Intro
01:09 - Algorithm
05:11 - Implementation

Improved Collision detection and Response (Fauerby Paper):
https://www.peroxide.dk/papers/collisi...

▶ Play video
drifting marsh
#

I saw that, I was just wondering if it was possible to implement a similar quality character controller without shapecasts

#

I'll go with shape casts for now though

vestal minnow
#

so I suppose you could test that

#

it's not quite "collide and slide" in the same way though

crystal cosmos
#

Is there a way to get more accurate colliders from a mesh than via convex_decomposition_from_bevy_mesh

vestal minnow
#

it's not exposed in the API yet but parry has VHACDParameters which controls the quality of the convex decomposition

#

you could make an extension trait to add this for Collider:

pub fn convex_decomposition_from_bevy_mesh_with_params(mesh: &Mesh, params: parry::VHACDParameters) -> Option<Self> {
    let vertices_indices = extract_mesh_vertices_indices(mesh);
    vertices_indices.map(|(v, i)| SharedShape::convex_decomposition_with_params(&v, &i, &params).into())
}
#

the name is so long that I'll probably end up making a from_mesh method that takes in e.g. ComputedColliderType that determines if it's a trimesh, convex decomp or convex hull and has the extra parameters

crystal cosmos
#

What if the mesh is supposed to be the collision shape, is there a way to use the mesh itself as opposed to a decomposition

vestal minnow
#

probably a convex hull but I don't have generation from mesh implemented for them yet

#

or a trimesh, but they're more prone to clipping issues since they don't have insides

crystal cosmos
#

Oh building a trimesh from the vertices & indices of the mesh worked perfectly

vestal minnow
#

zoom zoom 🏎️

#

wroom wroom

#

is the track hand made or do you have some system that generates it from e.g. a list of points and track widths?

#

a year ago I was experimenting with a track system that used interpolation to make smooth tracks from some points

crystal cosmos
#

I made it in blender in 30 seconds, it's atrocious. I would like to try generate a track but I'm trying not to get caught in that rabbit hole for now xD

vestal minnow
#

yeah 😆
a modular track system like in Trackmania would be pretty cool as well

#

if you don't need it to be fully organic

crystal cosmos
#

Yea.. the dream. It there was some blocks I could make as a blender file people could snap them together and just load the gltf into the game. budget track builder 😄

#

I also don't know how to use blender, all I know how to do is extrude and rotate
I'm sure there's a better way to proportionally rotate things along some axis to achieve this effect for real

severe urchin
#

is one of the existing bevy_xpbd_2d joints suitable for what i want? i'd like to fire a grappling line between my 2d ship and an asteroid. i want to be able to rotate and fly my ship around to drag the asteroid. i have a spatial_query doing a cast_ray to identify an asteroid behind the ship within range. not sure if any of the joint types are suitable.

vestal minnow
#

compliance is the inverse of stiffness that controls how hard or springy the joint is, 0 is perfectly stiff

severe urchin
#

i see joints::DistanceLimit, but that's not a component so can't insert it directly. i'm on 0.2 atm

#

ah main only?

vestal minnow
#

Ah, it's on main. But you can copy the file and add the joint locally, I'll pull up links

severe urchin
#

maybe time to switch back to main.. looks like there are a slight differences in the Joint trait too

vestal minnow
cinder summit
severe urchin
#

method local_anchor_1 is not a member of trait Joint .. i'll just switch to main. i have a few patches locally need to make sure i have them on my main fork too

#

thinkgs like randomly adding derive(Reflect) to stuff because i want to use the egui inspector to twiddle settings for testing etc

vestal minnow
severe urchin
#

would be nice to get a 0.3 yeah, even if you have to omit certain things

cinder summit
#

Tracking main on bevy_xpbd has luckily been pretty easy. I only use main on two crates, bevy_xpbd and bevy_hanabi. Both tend to get really big features/fixes shortly after any release

#

Watch 0.3 release and then the next day we have a PR to fix determinism 😂

vestal minnow
#

note: there are probably other determinism issues

cinder summit
#

Since it's not deterministic on the same platform yet there's definitely more stuff yea

#

We kinda need to figure out a repro for that tho 🤔

vestal minnow
#

yeah I'm working a bit with Johan on it since he has desyncs as noted here #showcase message

#

I have desyncs reproing when simulating lag using a program called clumsy

#

hard to tell if it's the physics or issues with rollback tho

cinder summit
#

I think in my game I at some point I ironed out all the issues from the prediction, but it still desynced after a long time

#

I wonder if it's cause in my case the deviations tend to cancel out, instead of add up and drift over time

severe urchin
#

is there a way to have the local_anchor rotate with the entity? i want the grapple to come out the back of the ship. i can add a system to do that i suppose

vestal minnow
#

Does it not rotate? It's in local space

#

should show up in debug renderer

severe urchin
#

ah, now i'm on main i will switch to the debug renderer. i was rendering it myself

vestal minnow
#

or do you mean that the entire joint (both "anchors") should be in line with the body, i.e. the attached asteroid will rotate with the ship

severe urchin
#

i'm doing .with_local_anchor_1(Vec2::Y * -20.0) to account for the size of the ship, so the line attaches 20px below it

#

maybe i'm just rendering wrong, will switch to debug renderer

vestal minnow
#

hard to tell the colors but pink is from center of mass to anchor and red is from anchor to anchor

cinder summit
#

Why does that simulation look so weird? It almost looks like the bottom one is also anchored at the edge 🤔

#

No wait are they both at the edge?

vestal minnow
#

the bottom one is attached from the corner

severe urchin
vestal minnow
#

yep

severe urchin
#

yeah with debug renderer the anchor point looks fine

vestal minnow
#

it looks a bit wobbly because in the initial state both bodies are upright but the bottom one is attached from the corner so it wobbles

cinder summit
cinder summit
vestal minnow
#

no

cinder summit
#

Then it being wobbly makes sense right? 🤔

vestal minnow
#

yes

#

and the stiffness is low

severe urchin
#

can i get the point on the surface of where i cast_ray'ed to, to attach to my asteroid on the exterior? i don't see something like that in RayHitData

vestal minnow
#

ray_origin + hit.time_of_impact * ray_direction to get global coords

severe urchin
#

ah, thanks

#

so need to do that then translate to relative coords of the target to be able to set local_anchor

vestal minnow
#

yeah

cinder summit
vestal minnow
#

I think Rapier gives it in local space

#

like point1 is local point on entity 1

#

idk

#

parry's ray casts don't give the point directly so we'd have to compute it, which is easy but maybe unnecessary memory since it's easy to compute

#

could add a compute_point method that takes the ray origin tho

#

...or just mention how to get global/local point in docs

cinder summit
vestal minnow
#

yeah dir and origin aren't in RayHitData so the helper would be kinda pointless

severe urchin
#

cool, that's working nicely. need to fiddle with the damping etc..

#

are rope or chain joints normally implemented as just a bunch of short distance fixed joints connected together?

#

i suppose the parts between the links would need to have colliders 🤔

vestal minnow
#

A bunch of DistanceJoints should work. You can also use RevoluteJoints if you want to limit the relative angle to make the rope bend less

#

I'm not sure what the best way to handle collision would be, but you could just connect a bunch of small circles

severe urchin
#

if i wanted the chain to wrap around the asteroid, yeah small circle colliders between links maybe

vestal minnow
#

there will be small gaps, but if you don't have very thin objects then they won't pass through

severe urchin
#

i may experiment with that before i go back to the netcode stuff..

cinder summit
#

BTW @vestal minnow, what happened to the soft body physics showcase from ages ago? 🤔

vestal minnow
#

I probably have it stashed away somewhere but it was very unfinished and required some modifications to constraints and had poor performance

#

I'll return to it later tho, I really want soft bois

#

I had mostly the implementation from the first few vids (distance constraints + global volume constraints) working but it needs bending constraints and a tetrahedralizer

#

Making a tetrahedralizer (and triangulator for 2D) is another rabbit hole, so much so that they ended up using TetGen which is written in C so I'd prefer not to use it

#

and there aren't nice tetrahedralizers in Rust yet afaik

#

could at least try it though

severe urchin
#

very different behaviour to 0.2

vestal minnow
#

how are you initializing it?

severe urchin
#
    // triangle ship, pointing up the screen
    let points = vec![
        Vec2::new(0.0, SHIP_LENGTH / 2.),
        Vec2::new(SHIP_WIDTH / 2., -SHIP_LENGTH / 2.),
        Vec2::new(-SHIP_WIDTH / 2., -SHIP_LENGTH / 2.),
    ];

    let collider = Collider::triangle(points[0], points[1], points[2]);
    cmd.insert((collider, ....
#

SHIP_LEN is 32, WIDTH is 19

#

(asteroids are using Collider::convex_hull)

vestal minnow
#

the many_shapes example has triangle colliders and they're working normally


    let delta_rotation = Rotation::from_degrees(120.0);
    let triangle_points = [
        Vector::Y * 10.0,
        delta_rotation.rotate(Vector::Y * 10.0),
        delta_rotation.inverse().rotate(Vector::Y * 10.0),
    ];
    let triangle = (
        Collider::triangle(triangle_points[0], triangle_points[1], triangle_points[2]),
        ...
#

does the point order matter?

severe urchin
#

i'll try changing the point order

#
let collider = Collider::triangle(points[2], points[1], points[0]);

hm, this order seems to work

vestal minnow
#

does it work with any counterclockwise order?

#

your original code had clockwise

severe urchin
#

1,0,2 kinda works but looks like the front of the ship doesnt quite touch the asteroid when it collides. definitelty some weirdness. will make some recordings to show

#

actually no 1,0,2 the ship just went half over an asteroid

vestal minnow
#

yeah I can repro weirdness with different orders

#

weird that it would change from 0.2 though since I haven't touched triangle colliders

severe urchin
#

odd, yeah. glad i'm not hallucinating anyway. off to bed, but happy to help debug (in the coming days) if you need me to do anything

vestal minnow
#

yeah I need to sleep too, good night

junior flower
#

Hi! First of all, thank you for this crate!
I’ve spent a couple of days poking around and found it very easy to follow what's going on so far!

I forked main a little while ago because I’ve been thinking of having a go at implementing collision filtering, which is the one feature I wanted from Rapier that XPBD didn’t have yet.

The major issue I had with Rapier’s collision filtering is that as far as I could figure out you had to pass the query you want for the filter as the generic arg when adding the plugin, so it seemed as though it was only possible to set up one SystemParams for all of your physics. I’ve been hoping to making something a little more flexible.

Has there been any discussion yet about how collision filtering should be implemented?

What I’ve got so far is extremely simplistic but it almost feels like it's enough to get things off the ground: I’ve added a new Substep after NarrowPhase that is blank by default, with the expectation that users would add their own systems to filter through the Collisions resource.

vestal minnow
#

1. Global physics hooks that iterate through all contacts like Rapier and your proposed solution

Something similar to your solution would be nice, but just adding an empty set doesn't feel very user-friendly in the sense that people would need to make sure they're running the systems in SubstepSchedule and e.g. SubstepSet::ContactFilter, and I consider substeps to generally be more of an internal thing.

One way to do this could be to abstract this out with an extension trait that implements .add_contact_filters(my_system_configuration) for App. This would add the systems in the correct schedule and system set. Alternatively, we could add e.g. a ContactFilterSchedule that is run automatically in the appropriate place.

We could also have something like a ContactHook resource, but that feels more limited.

#

2. Entity-level filters with a component like ContactFilter

What I had in mind is to just have a ContactFilter or CollisionFilter component that allows you to exclude things like entities and RigidBody variants and supports a custom predicate for contact filtering and modification.

Something like this:

commands.spawn((
    Collider::ball(0.5),
    ContactFilter::new()
        .with_excluded_entities([...])
        .with_predicate(|mut contact: ContactData| {
            // Modify contact (optional)
            contact.penetration = 0.1;
            // Return the contact or use None to ignore contact
            Some(contact)
        }),
));

You can pass the colliding entities to the closure, so the user could handle collisions between specific entity pairs differently. The two main issues here are:

  1. How to deal with cases where both entities have their own predicates? (maybe a priority property)
  2. The filter can't use Query or otherwise have proper access to the world, so it's not very flexible.

2 could maybe be done using something like Bevy's (future) one-shot systems passed as the predicate similarly to callbacks, but I'm not sure if this would actually be possible.

#

I'm open to any other solutions or APIs though, these are just what I originally had in mind :)

vestal minnow
#

2 could maybe be done using something like Bevy's (future) one-shot systems passed as the predicate similarly to callbacks, but I'm not sure if this would actually be possible.

Btw what I meant by this is that it would be cool if one-shot systems could be used to do something like this: (not sure if this would work, just an API idea)

fn setup(mut commands: Commands, contact_hook_pipeline: ContactHookPipeline) {
    commands.spawn((
        ContactHook::new(
            &contact_hook_pipeline,
            |In(mut contact): In<ContactData>, query: Query<&MyBundle>| {
                // Modify contact, query for entities, do whatever
                // Return new contact data to narrow phase; if None, skip contact
                Some(contact)
            }
        ),
    ));
}

Here, ContactHook is a component storing a callback system, and ContactHookPipeline is a system param giving access to the SystemRegistry.

ContactHook::new registers the callback, which is a normal system, so we can use normal queries, and the contact data can be given as an input (provided when running the callback system in the narrow phase)

cinder summit
#

The one shot PR is almost done, but it doesn't yet allow passing in input, so that wouldn't really work. There is however also a run_system_with api on World on bevy main, which could support it. Systems there are however not cached so I assume it would have a bunch of overhead

vestal minnow
#

Yeah run_system_with is what I was referring to with "running the callback system in the narrow phase"

#

and overhead might be an issue as you said

cinder summit
#

Yea, generally that would be the only thing that would work anyway, oneshot systems wouldn't actually be able to take a reference to something I think

vestal minnow
#

Could be interesting to see if it even technically works though and see how bad the overhead is

cinder summit
#

Yea it would be interesting to test. It might perform about the same as just doing stuff manually on &World

vestal minnow
#

I doubt people will have tons of entities with their own entity-specific contact hooks anyway (just use the "global" hooks in that case) so it generally wouldn't be an outrageous amount of one-shot system calls

#

ooh systems called using world.run_system_with can apparently return data, so we could get rid of the mutable reference and return Option<ContactData> like in my earlier simpler predicate example

#

and if it's None, we ignore the contact

#

updated the code to reflect this

junior flower
#

Thanks for getting back to me. I figured you'd at least have some thoughts on it so I'm glad I reached out.
It's pre-coffee morning for me so I apologise if the below doesn't make much sense.

I agree that just adding an empty set isn't very user-friendly.
I'm not super well-versed with Bevy, but does extension trait preclude being able to apply ordering to the systems you add?
If it does, an extra schedule like you suggested may be more flexible.

One reason I didn't start with the predicate approach was that I was aiming for was to avoid dynamic dispatch. I can see that having it as a possible option would definitely be useful, though.

Re your suggestion of being able to return Option<ContactData> in the predicate-style ones, that would open up the way to editing a contact in a very obvious way.
I'm sure there must be some valid use-case, but I'm unsure whether or not that is desirable as it would allow influencing the simulation.
(Edit: Having mutable access to Collisions in the schedule-based approach does the same anyway, so perhaps the point is moot.)

This is mostly a curiosity question, and I've really not looked into the solver at all because it mostly goes over my head, but:
I see that currently, contacts are all stored in a resource and then eventually copied onto the component during the send events step. Is there a reason they're not all on entity1 from the get-go? Is there something about storing them in a resource that makes the solver more efficient?

crystal cosmos
#

I'm struggling to figure out where my camera update logic should go to follow a dynamic rigid body. I've tried in FixedUpdate, Update, and PhysicsSchedule but there's jarring jitter in all of them. eg

.add_systems(
    FixedUpdate, // PhysicsSchedule
    parent_camera_to_car
        .after(PhysicsSet::Sync)
        .after(PhysicsStepSet::Substeps),
)
pulsar flower
#

Noob here. How do I turn off bevy_xpbd mid game?
do I need to make a state with all it's default systems, or there is another way?
I guess I only need to disable collisions and motion integration

pulsar flower
vestal minnow
vestal minnow
#

These could be somewhat related:

  • #1143726581362204672 message
  • #1147121135285174303 message
vestal minnow
# junior flower Thanks for getting back to me. I figured you'd at least have some thoughts on it...

I'm not super well-versed with Bevy, but does extension trait preclude being able to apply ordering to the systems you add?

I think you could still apply ordering. The input would be similar to add_systems and allow multiple systems and ordering, but it would just add .in_set(...) and the appropriate schedule automatically.

That being said, a separate extension trait might be unnecessary for how simple it is. An easier and more explicit way would probably be just to have a custom schedule.

I'm sure there must be some valid use-case [for contact modification], but I'm unsure whether or not that is desirable as it would allow influencing the simulation.

Rapier supports this, and there's several potential use cases like conveyor belts, non-uniform friction/restitution, modifying contact normals to simulate "randomness" in surface contacts etc.

I see that currently, contacts are all stored in a resource and then eventually copied onto the component during the send events step. Is there a reason they're not all on entity1 from the get-go? Is there something about storing them in a resource that makes the solver more efficient?

Contacts are stored in the Collisions resource (on main). The data is copied for the Collision event currently so that people can conveniently listen to collisions, but the same data is not copied for entities. Entities only have CollidingEntities for conveniency, but it's not used by the engine itself.

Contacts are between two entities, so it wouldn't make sense to have the data on just one of them. We could copy the same data for both entities, but it would waste memory, queries would have duplicate data, and you would have to do potential contact modifications for both entities individually.

Having a "single source of truth" like Collisions is easier and more efficient to work with, and it allows us to add optimizations or custom methods like collisions_with_entity.

#

Once/if we eventually get entity relations 🌈 in Bevy, we could maybe describe collisions as relationships and have efficient queries like (Body1, CollidesWith(Contacts), Body2) (heavily simplified)

#

I have no idea if this would work in practise though, I haven't looked into relations that much

cinder summit
#

BTW @vestal minnow did you ever look into that thing of trying update instead of update_incremental? I've been keeping my game's server offline because it keeps going to 100%, which is probably a sign I should test some solutions 😂

vestal minnow
#

You can ask me again at the end of the month when I have a lot more time haha

cinder summit
#

Ah no problem, I can probably test this myself too, I'll just have to get some baseline first ... I should probably set up some case that tests it, I guess if it breaks from updating having many colliders that constantly move should trigger this behavior fast 🤔

#

Logically if it takes ~24 hours to hit 100% load with 25 moving entities at 60 ticks/s it should speed up at either more ticks or more entities

junior flower
crystal cosmos
#

Does it sound reasonable to use something like a distance joint to position a camera relative to the target

vestal minnow
#

You can control the stiffness to get some kind of smoothing I suppose haha

#

With custom following logic you'll still have more control though

shell ermine
#

most 3rd person games use a spring arm to attach the camera to the player

#

so the camera doesn't clip through walls

crystal cosmos
#

Yea, was wondering how to get the 3rd person race car camera, so the car accelerates "away" from the camera initially to give you the feeling of speed, and it "catches up" as you brake

shell ermine
#

no idea

#

a fancy spring arm that stretches/squashes depending on speed?

royal helm
#

What most do is more so a ray or shape cast back from the player to position the camera

royal helm
severe urchin
#

when i spawn 10k almost identical entities (save for minor differences in collider shape and velocity) i end up with a few of them seemingly not having mass properly, despite a MassPropertiesBundle being in my spawn function:

 Dynamic rigid body 2017v0 has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.

that message repeats for 5 entities after a 10k spawns. anyone else noticed this?

vestal minnow
#

Not sure why you're getting the warning, but it's printed if mass <= 0.0, inertia <= 0.0, or either mass or inertia isn't finite (i.e. it's +/- infinite or NaN)

#

The message might be a bit misleading in that it doesn't mean that any components are missing, but rather the values are invalid which essentially means that the body has no mass

severe urchin
#

looks like my colliders for those entities are preposterously small, whoops. that'll do it.

warm gulch
#

I just posted a question I'm the wrong thread, it's just nonsensical there...

#

Anyways, here goes

#

OK, so I just switched to 3D instead of fiddling with the 2D stuff and... say I have a very very simple gltf model, basically a box. I can load this box from file and display it, got a little camera and a little light, and I want to create a collider for it. Now, the parry stuff has Collider::convex_decomposition_from_bevy_mesh - but when loading the model I get some GltfMesh resources... Anyways, what is the most obvious way of doing this? I'm going to check out the fox example, haven't been able to figure this one out myself...

fervent pond
#

I appreciate there's probably a million things going on, but how far do you think you are from implementing "On-demand simulation stepping" - I realised I need it so have been using rapier for now. Really excited to get back to using xpbd though in future

vestal minnow
#

Depends on how you interpret "on-demand simulation stepping". If you want to advance the simulation by some time dt, that's already easy to do in a custom system

fervent pond
#

well right now I have a system that manually does (amongst other things) one or more steps of the rapier physics engine (I'm not using bevy_rapier). Sometimes I might want to go and revert some objects then run a few more steps. I manually extract out the collision data to do stuff with it on the network

#

so I'd like to literally call a .step function on xpbd

vestal minnow
#

and .step would just take a (positive) dt and advance the sim accordingly?

fervent pond
#

yes, ideally allowing me to then get all the collision data back for that step. I have no idea if this would work with how xpbd ties in with the ECS

#

but it's how I'm manually using rapier, I am having to sync certain bits of data back ot the ECS for rendering etc

#

I appreciate it won't work with the events system (from my limited understanding of bevy so far) as it's not running on the normal Update flow

vestal minnow
#

That should be as simple as setting DeltaTime to something and doing world.run_schedule(PhysicsSchedule) as I mentioned. On the main branch, collisions are stored in a Collisions resource, so you should be able to access them even if you can't listen to events

fervent pond
#

if I run world.run_schedule(PhysicsSchedule) can I wait for it, get the positions of certain entities, and then run it again?

#

i.e. if I need to do 5 steps and get the position of the entites as I go, to send off somewhere else

vestal minnow
#

I would expect something like this to work

fn my_system(world: &mut World) {
    // Set delta time to 60 Hz
    world.resource::<DeltaTime>().0 = 1.0 / 60.0;

    // Do 5 steps, printing positions each time
    for i in 0..5 {
        world.run_schedule(PhysicsSchedule);
        let query = world.query::<&Position>();
        for position in &query {
            println!("Position at step {}: {:?}", i, position.0);
        }
    }
}
#

(could have errors, wrote it in discord directly lol)

fervent pond
#

amazing thank you, I will give it a try

vestal minnow
#

The main thing here is that because the engine is ECS-based, we need exclusive world access to run the schedule. Otherwise we could have conflicts with data access

#

We could maybe add some system parameter like PhysicsRunner with utils like step, but it would still be doing essentially the same thing

warm gulch
#

@vestal minnow : is there a convenient way to create colliders from gltf-meshes using xpbd?

#

Cheers

crystal cosmos
# warm gulch Cheers

Could either use Collider::convex_decomposition_from_bevy_mesh or something like this

let pos = mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
if let VertexAttributeValues::Float32x3(vertices) = pos {
    let vertices = vertices.iter().map(|v| Vec3::from(*v)).collect::<Vec<_>>();

    let indices = mesh
        .indices()
        .unwrap()
        .iter()
        .map(|v| v as u32)
        .collect::<Vec<_>>();
    let indices = indices
        .chunks_exact(3)
        .map(|v| [v[0], v[1], v[2]])
        .collect::<Vec<_>>();
    // println!("{:?}", pos);
    let c = Collider::trimesh(vertices, indices);
    
    // if let Some(c) = Collider::convex_decomposition_from_bevy_mesh(mesh) {
    commands.entity(e).insert((c, RigidBody::Static));
    // }
}
terse burrow
#

im having this issue server side

crystal cosmos
# terse burrow did u ever fix this?

sort of.. I changed some other things in the surrounding code and it stopped happening :/ it only happened occationally and I wasn't sure if I'd just gotten lucky for a while or I'd actually fixed it until I'd forgotten about it

terse burrow
#

it was workign completely fine for me till i networked it

#

and now it occasionally works

terse burrow
crystal cosmos
#

It stopped happening a little while back sorry, I'll try and have a look at the code a bit later and see if I can remember what I changed

terse burrow
#

im gonna keep looking at the docs just incase im missing something

#

here is my code just incase

#
                let x = (fastrand::f32() - 0.5) * 40.;
                let z = (fastrand::f32() - 0.5) * 40.;
                // Spawn new player
                let transform = Transform::from_xyz(
                    x.clone(),
                    0.51,
                    z.clone(),
                );
                let ground_entity = commands
                    .spawn(
                        RayCaster::new(
                            Vec3::new(x.clone(), -1.0, z.clone()), 
                            Vec3::new(0.0, -1.0, 0.0)
                        ).with_max_time_of_impact(0.1)
                    )
                    .id();
                let player_entity = commands
                    .spawn((
                        PbrBundle {
                            mesh: meshes.add(Mesh::from(shape::Capsule::default())),
                            material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
                            transform,
                            ..Default::default()
                        },
                        RigidBody::Dynamic,
                        LockedAxes::new().lock_rotation_x().lock_rotation_z(),
                        Position(Vec3::Y * 1.0),
                        LinearVelocity(Vec3::ZERO),
                        Collider::capsule(1.0, 0.5),
                        Player {
                            id: *client_id,
                            is_grounded: false,
                        },
                        PlayerInput::default(),
                    ))
                    .add_child(ground_entity)
                    .id();
crystal cosmos
#

It was something to do with my car's steering angle or wheel raycast properties somehow. Like it was something to do with the current state of the world and the interaction with the day cast 🤣 but it was very vague, hard to describe

terse burrow
#

i think i know what u mean

#

the cases where it worked was when the player was closer to the x:0 z:0

cinder summit
#

Wait it breaks when you go further from 0, 0, 0? How far?

terse burrow
#

good question

#

going to check now

terse burrow
#

mighta just been a coincidence

#

its not looking good 😭

cinder summit
#

Wait, so it happens due to empty colliders? 🤔

#

Or maybe rigid bodies without colliders?

terse burrow
#

rigidbody has a collider

#

the ground has a collider too

#
pub fn setup_level(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    commands.spawn((
        PbrBundle {
            mesh: meshes.add(Mesh::from(shape::Plane::from_size(100.0))),
            material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
            ..default()
        },
        RigidBody::Static,
        Collider::cuboid(100.0, 0.002, 100.0),
        Friction::new(5.0),
    ));
    commands.spawn(PointLightBundle {
        point_light: PointLight {
            intensity: 1500.0,
            shadows_enabled: true,
            ..default()
        },
        transform: Transform::from_xyz(4.0, 8.0, 4.0),
        ..default()
    });
}
crystal cosmos
#

gosh I'm having trouble with the camera jittering out of sync with the simulation again 😅
might try using Position instead of Transform.

.add_systems(
    PostUpdate,
    move_camera_to_car
        .after(PhysicsSet::Sync)
        .before(bevy::transform::TransformSystem::TransformPropagate),
)
cinder summit
#

Huh, it is scheduled correctly so that's definitely interesting

crystal cosmos
#

I moved it to PhysicsSchedule and it's much better, now instead of jittering the whole world 🤢 only the car jitters 🤔

.add_systems(
    PhysicsSchedule,
    move_camera_to_car.before(car_update),                                       
)
cinder summit
#

Shouldn't it run after the car update?

crystal cosmos
#

heh you'd think so, but it doesn't matter, car_update just mutates ExternalForce, it doesn't move anything

terse burrow
#

not sure if you already doing it but i recommend you make the camera a child of the car

crystal cosmos
#

Hmm. Maybe I can combine that with camera movement. I don't want a static camera

terse burrow
terse burrow
crystal cosmos
#

hmm now I need to figure out if Position is local or global xD

cinder summit
#

Position is always global iirc

terse burrow
#

ok well i somehow fixed the raycast issue i just changed -1.0 to -0.9 and TOI to 0.2

lament matrix
#

any idea on improving the performance of this? I used rigidbodies to demo it but I don't think I need rigidbodies. currently I'm spawning new ones inside others so it pushes those but that's not a feature I'm going for. so I need 2 things:

  • prevent entities from moving into eachother
  • collisions for hit detection

would kinematic body approach with shapecast better in this case? or some sort of custom implementation. any ideas?

cinder summit
#

Shape casting is not really gonna get you any big gains here. Either we'd need to speed up collisions, or you can do something to avoid collisions entirely, by using something like boids

lament matrix
#

(forgot to post this, sorry)
this is the profiling data btw, substeps are the most time consuming stuff. so I assumed it is not possible to handle this much entities with usual physics implementation

cinder summit
#

Oh and, you can reduce the number of substeps

#

The default is 12 iirc, I use 6

#

I remember jondolf saying the lower bound is probably 3

#

And yea that looks exactly like I'd expect, every step is mostly just penetration_constraint, which means it's solving collisions

lament matrix
lament matrix
cinder summit
#

And I assume all of these are already just circle colliders?

lament matrix
#

yup

#

I wonder how factorio handles so many biter entities

#

it uses grids I suppose

cinder summit
#

There's definitely room to speed up collision, but I think the key to making it run fast is for things to not actually touch

#

If it doesn't pass the broad phase, it won't take up many cpu cycles

lament matrix
cinder summit
#

The collision avoidance would be similar to boids yea, depending on other AI behavior other steps might be unnecessary. Potentially you could use large shape intersections as a way to handle the spatial acceleration, but parry has some broken behavior so something like bevy_spatial might work better right now

shell ermine
#

also I previously found just rolling my own simple spatial hash grid (literally just a hashmap) was faster than bevy_spatial

lament matrix
#

thanks!

shell ermine
#

I want to do something other than the hashmap, I'm just not sure what yet

lament matrix
shell ermine
#

yeah I just set it to a pretty coarse grid

#

like 20x20 or something

#

and just do (position / grid_cell_size).floor()

#

to get the grid cell

lament matrix
#

still thinking about hashmap, do you want to use something else because it could perform better or something else?

shell ermine
#

yeah I'm pretty sure a decent quadtree would be faster

#

(i'm assuming you only need a 2d grid for the spatial stuff?)

#

the hashmap is super cheap to update and not super slow for queries, but I think someting else could be faster for queries

#

though to be fair it only really gets bad at ~50k units

#

but I'm not doing a lot of the queries i'll need to do, so it could probably handle ~10-20k units?

lament matrix
#

I might spitting nonsense at this hour but what about using a plain vector? with a known worldsize it shouldn't have too much memory overhead while granting fast access

#

especially for my usecase, I might despawn far away entities (2 times the screen resolution for example), so I could use a smaller grid for way bigger area I think

shell ermine
#

wdym a plain vector

#

my grid is a hashmap of vecs

lament matrix
#

let's talk in #general if you don't mind this became a little out of context I think
(here is the link if anyone wants to follow up #1150296798062198887 message)

shell ermine
#

kk

cinder summit
#

@vestal minnow Can you guess what the difference between these two apps is?

vestal minnow
cinder summit
#

Qbvh update stuff yea. I basically stole rapier's update and adapted it to bevy_xpbd. It had lower CPU load from frame one 🙃

vestal minnow
#

does it fix add with overflow errors as well?

cinder summit
#

Haven't tried it but I don't think that code path even gets hit anymore 🤔

vestal minnow
#

yeah true, if it doesn't do any incremental updates then it probably doesn't

#

if it works and doesn't seem to break anything, a PR would be nice

cinder summit
#

Yea I can clean up some of the code and make a PR ... Tho I'd imagine in the longer term a bvh that actually works would perform better. Can't see why recreating the bvh would perform better than incremental updates 😂

vestal minnow
#

yeah, it'd be ideal to have it working properly with incremental

#

but having it not crash and burn is even better

#

also I think you mentioned gltf physics at some point so #math-and-physics might be interesting rn if you haven't seen it

cinder summit
vestal minnow
#

Thanks, I'll review and test when I have time

#

It probably also fixes #110 because there's no unwrap anymore and it doesn't need removed colliders 👀

cinder summit
#

Fixing 2 crashes and improving performance by doing something that should've been slower, nice 😂

vestal minnow
#

Lmao yeah 😂 I love parry

#

tbf #110 was probably our issue but still

cinder summit
#

Someone should make a more stable collision library ... And while at it ... Without dyn Shapes

#

Yea it might be something like "it was removed but not detected because the wrong field was removed"

vestal minnow
#

but then I look at how much stuff parry has and how little I currently know about GJK, EPA and other stuff...

#

for now I guess it would be best to just help improve parry

cinder summit
#

I mean fwiw you only need the features bevy_xpbd actually uses

cinder summit
vestal minnow
cinder summit
#

And that right there is my #1 reason for not making PRs on some crates

#

My PR on bevy_rapier got merged after I switched to bevy_xpbd, iirc like 2-3 days later

#

Also I really should've made this PR earlier, I've been keeping my game's server down for over a month because of it 😂

#

Well not like I made any interesting updates in the meantime anyway

vestal minnow
#

@cinder summit I took a look at the PR and left a comment; looks good, but RemovedColliders could be removed since it's pointless now

crystal cosmos
#

could my jitteryness be due to the use of ExternalForce::ZERO.with_persistence(false) ?

#

if i'm not applying force every update or something

vestal minnow
#

I doubt it since forces just increase velocity (or acceleration to be more precise) in some direction, so if you skip a frame, it's not going to suddenly slow you down in a jittery way

#

unless you have some massive damping/friction

cinder summit
crystal cosmos
#

At a loss of how to proceed 😅
I've tried moving my logic that does things based off physics positions into the Last schedule and I'm still getting jitter which seems impossible
I've tried referencing &Position of the rigid body, tried &Transform, tried in Update, PostUpdate, PhysicsSchedule, Last.

Going to try in a minimal reproduction in a new project as a last ditch haha, I wonder what I've done wrong

cinder summit
#

I think a propperly functioning spatial acceleration structure could be the easiest optimization for xbpd at this point. The broadphase currently also functions in an n choose n way iirc, tho maybe that could be optimized even further by only searching nearby enties from the perspective of a non-sleeping dynamic body 🤔

vestal minnow
#

Yeah, but a simple spatial grid generally isn't ideal because it requires some uniform cell size that users would need to manually specify. Even then, it doesn't work well when there are many large and many small objects in the same world.
This is why Rapier has "Hierarchical-SAP" for the broad phase, which is a combination of a multi-layered spatial grid, and sweep and prune (which we use) #game-development message

#

there's also some other sweep and prune hybrids/variants, I think one does it on several axes or chooses the ideal axis for each iteration and uses quicksort or smth

cinder summit
#

I wonder what bepu physics uses, iirc it's the fastest opensource option

vestal minnow
#

I think they have some kind of bvh, I can try to find it

#

their narrow phase is the more unorthodox one, the "tootbird"

cinder summit
#

Oh and I removed the RemovedComponents, CI seems to be struggling with the tests tho 😂

vestal minnow
#

yeah the tests are really slow, it does a fresh recompile every time I think

#

I should optimize the CI

cinder summit
#

So many things to optimize 😂

vestal minnow
#

yeah bepu seems to have a bvh judging from how the broad phase code has leaves, trees and bounding boxes

#

maybe check the Update/Update2 code for fixing parry's qbvh lol

#

"dynamically updated binary tree"

#

but yeah it's still a bvh, just a slightly different representation

crystal cosmos
#

so... this is what is causing the jitter

[profile.dev.package."*"]
opt-level = 3
#

going to try release mode and see what that does, Edit: also jitters in release

vestal minnow
#

are you printing logs by chance?

crystal cosmos
#

nope, at least nothing that is being shown by bevys default log filter

#

no user code level logging happening

vestal minnow
#

hmm yeah, weird if the opt-level has an effect 🤔

cinder summit
#

If opt-level has effect that suggests it's something that it's impacted by how long things are running, which is usually system ordering

crystal cosmos
vestal minnow
#

for me, release doesn't jitter

crystal cosmos
#

🙃 ...
what platform are you on? im on mac m1

vestal minnow
#

windows

crystal cosmos
#

I will boot up my windows computer in the morning and try.

vestal minnow
#

MacOS is just 6 min tho

upbeat marsh
#

Hey guys, moving my question here from the physics channel. I'm having issues hitting a collider on origin using the SpatialQuery.shape_hits_callback with ignore_origin_penetration set to true. I'm wondering if the system is being placed in the wrong part of the whole pipeline. I'm also working on a collide and slide character controller

drifting marsh
#

I had issues with this as well. I think you might be hitting your player entity, so you can try filtering it.

upbeat marsh
#

I know it's hitting the player entity. Maybe the ignore_origin_penetration isn't doing what the name implies or I'm misunderstanding what it means or I'm completely using the spatial api incorrectly (system order or other issues). Just trying to see which one it is.

#

It's just strange that certain directions hit the player and others do not (in the example)

#

On my computer, A and S do not hit the origin (player collider) but W and D does

tall talon
#

Guys, there is a way to change the color of just one material in a object exported by blender?? I have to change just one part of my texture in bevy:

drifting marsh
#

Did you mean to send that in a different channel?

tall talon
#

Idk. I have one object in blender that have 5 materials, okay? But I need to change one of these materials in bevy. How can I do this??

#

I need to change a color of a part of my object. Ex: My object is a wall and I need to change a color of just one side.

vestal minnow
#

ignore_origin_penetration is a bit fiddly, I'm not 100% sure how parry even handles it under the hood

upbeat marsh
#

No worries. As long as I’m not using it incorrectly I’m happy to work around it. Any suggestions on where to put the system that does the collision test for character movement?

vestal minnow
upbeat marsh
#

Well long story short I’m using leafwing input to gather inputs and plan on using my implementation of collide and slide, then applying the effects on xpbd components. If it all doesn’t matter much then I’ll just explicitly order these

#

In your examples you put the movement before the BroadPhase

vestal minnow
#

For movement (and maybe spatial query) things, somewhere in the PhysicsSchedule is probably ideal to make things frame-rate independent

#

either at the start of the schedule (before BroadPhase) or the end (after SpatialQuery)

#

idk if it matters that much though, I haven't actually made a game with my own engine yet so I might not be aware of scheduling issues with input, movement etc. 😅

upbeat marsh
#

Best guess is good enough for me. I’m happy to be the lab rat here haha

carmine sluice
crystal cosmos
carmine sluice
#

Differences in compilation maybe? Have you checked for ambiguities?

crystal cosmos
cinder summit
#

Wouldn't you need to set that on each schedule rather than just Main?

crystal cosmos
#

lol... I attached tracy profiler and the stutter stops 🤦

cinder summit
#

Usually when I can't figure out order issues I use bevy_mod_debugdump

low jacinth
#

there is this feature which is quite interesting: "bevy/trace_chrome"

low jacinth
#

oh ok

crystal cosmos
#

I'm looking at the output of debugdump but I honestly have no idea what I would be looking for xD there's a lot of nodes in the graph pointing all over the place, and PostUpdate is a separate schedule to PhysicsSchedule so I don't know how to see if there's overlap

cinder summit
#

Somewhere in PostUpdate would be a system that runs PhysicsSchedule, so if your system is there you can just use that as a reference point for where physics runs

#

The system causing issues for you involved moving the camera right?

crystal cosmos
carmine sluice
#

Is PhysicsSchedule running in FixedUpdate maybe?

cinder summit
#

Are you sure it's the camera moving jittery, and not the car updates getting jittery? What FPS ar you running at with opt-level 0 and opt-level 1?

cinder summit
#

If your FPS is over (or equal to) the update rate of physics at opt-level 1, and lower at opt-level 0 this could be because you use inputs inside the PhysicsSchedule. You could test to see if it's "solved" if you use variable physic updates instead of Fixed (the default)

royal helm
#

otherwise it will still return it I think

vestal minnow
royal helm
#

or well, I believe it is mostly just direction here

crystal cosmos
merry tide
#

Hello! It is me, your friend. I have a problem that I think is not really an xpbd-problem, but more of a general Bevy-issue and I hope it is OK that I ask it here. When reading collision events, the structure has entity1 and entity2. What is the best way to see what components are on that entity? All my Google queries seem to favor using the Query-interface, but inside a system, is there a canonical way of doing it? Or some example code that shows it off. Sorry, I am new at both Bevy and xpbd, but I am making good time.

carmine sluice
merry tide
#

Because let's say I have a Player-component attached to an entity and a Crystal-component attached to another, I want to despawn the Crystal-component, if that makes sense.

#

They do not show up deterministically as entity1 and entity2, and that seems a little dubious to rely on anyway.

#

My Player-component is basically just pub struct Player; derived from Component, so it is a marker/tag. Keep in mind I am a noob so sorry if I am butchering the terminology.

carmine sluice
#

Right, so you want to handle collisions differently based on which entities are colliding right?

merry tide
#

I guess the short version would be, given this data: Entity Contact { entity1: 6v0, entity2: 5v0, point1: Vec2(0.0, 14.098724), point2: Vec2(0.0, 14.142136), normal: Vec2(0.0, -1.0), penetration: 0.04341221 } how do I know which entity is a Player and which one is a Crystal without knowing the IDs.

#

Yes. I would love to be able to consistently handle the case where a player collides with a crystal by despawning the crystal. And ideally without propagating magic IDs through the system.

#

I might be missing the point altogether, is there perhaps a way to tell the EventReader to filter this before I get the data?

carmine sluice
#

So, when working with parry or other collision detection libraries directly, my strategy has been to add another system that looks for the player, and then checks its collisions to see if its colliding with an object of the correct type

#

I'm unsure about how exactly you'd want to do that with bevy_xpbd: maybe there's a per entity event list of collisions that you could then check against?

#
if crystal_query.contains(candidate)

is a useful snippet though

merry tide
#

Ah, OK. So you basically query for all the crystals, see if it contains the entity in the collision structure. That makes a lot of sense to me. It is probably exactly what I am looking for.

#

Thank you so much, I will test that. Sounds very sound.

cinder summit
#

The way I handle my collisions is with the component that gets a list of collisions for that entity

merry tide
#

Is there example code and/or documentation for that feature? I still have some issues reading typical Rust docs.

#

I would be happy to contribute an example for it if that is helpful and I can wrap my head around it.

cinder summit
merry tide
cinder summit
#

Yea, you can just make systems that handle collisions for certain things. Like this system I have to set the team of a player if they step in it:

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;
        }
    }
}
merry tide
#

This is very convenient.

#

What is SetTeam in this context? Is that a Component you added to your entities?

cinder summit
#

Yea it's a component I made and added to the entities, it just holds which team the entities need to be added to

merry tide
#

That looks just about what I wanted, thanks for sharing.

upbeat marsh
merry tide
#

I am super impressed by this physics engine. Sorry, I got lost and forgot where I just chatted. The input you guys gave me yesterday allowed me to fix mostly all my issues. The approach you have @cinder summit seems to only actually give information when objects come to rest, but that is super helpful in a lot of situations also. So, I just wanted to say thanks.

#

I was hoping I would paste my code here to see if you saw anything wrong with it, but I am learning Helix at the same time.

#

This is what I ended up doing. It seems a little naive, I am sure.

merry tide
#

Would you write this differently?

#

It works. And I love that it is captured in a system. ECS is a gift that keeps giving.

merry tide
#

It seems clunky to me, the way I approached it.

drifting marsh
#

Has anyone manged to get bevy_xpbd and bevy_ggrs working together?

vestal minnow
#

There are occasional desyncs in that example though, we haven't verified yet if there's indeterminism from the engine or if it's maybe not rolling back enough data

drifting marsh
drifting marsh
#

Why is it necessary to create a PhysicsSchedule and run it manually instead of doing: PhysicsPlugins::new(GgrsSchedule)?

merry tide
#

What construct would I use to model an attractor? Let's say sort of a black hole.

vestal minnow
#

I would do two queries:

  1. Query<&Transform, With<Attractor>>
  2. Query<&mut ExternalForce, With<RigidBody>>
    and for each attractor, apply a force to each rigid body
merry tide
#

Ah, OK, so you sort of have to "roll your own", but it isn't that hard. That works for me.

vestal minnow
#

you can make it more efficient by only applying forces to bodies in some radius with e.g. bevy_spatial

merry tide
#

I am really looking for a simple use-case where it is only active on the player in the very beginning of the level, but I might want to expand it later so this is useful. This is probably great for me, thanks. Just wanted to see if it was something built-in.

#

Would it be possible to make a general abstraction for it? Unfortunately, I am a very weak visionary. I don't see what a game should really look like until I see the building blocks. But if I have the building blocks I try to assemble them. And now it feels like at some point I would like this as a general feature in some levels.

#

In my context I would probably want something where the attractors have no influence on the physics system, so to me it seems like just making a collider around the attractor could work.

#

Like "fall-off" turns into no influence, if that makes sense.

vestal minnow
#

Like the attractor only works in some area or only affects specific entities?

merry tide
#

I guess both, there are collision layers, but yeah, just a large collider to activate the attractor on a collision layer in, say, a circular collider shape.

#

Just curious if it seems like a viable level of abstraction.

vestal minnow
#

You could give the attractor a Collider with a Sensor component (to make objects not bump into it) and give it optional CollisionLayers to choose which layers it affects. This could be wrapped in an AttractorBundle.
Then, you can make a system like the one I suggested, but use CollidingEntities to only get the entities in the collider's area, and apply forces to just those bodies

merry tide
#

Ah great. I was actually going to ask about that, I didn't know about the difference between Collider and Sensor and while what I am currently doing works, I was thinking of a power-up or something that would turn the Collider into a Sensor.

#

But, yes, that sounds great.

vestal minnow
#

But yeah I guess this could be made built-in (I think Godot has an attractor?) but I feel like it's high-level enough that it would make more sense as a third-party plugin than a physics engine feature

merry tide
#

Sure. I am just trying to wrap my head around stuff, seeing what's there and how it fits in. I agree.

severe urchin
#

is there a convenient way to create a 2d bevy_xpbd collider from a sprite? (eg a png with transparency)

vestal minnow
#

@severe urchin ^

kind lava
#

Could xpbd get a feature to adopt serde for its components? I’m trying to build a game with bevy_replicon, and they switched from using reflect to serde in their latest release.

severe urchin
vestal minnow
drifting marsh
#

Is there a way to exclude entities that belong to a specific collision group using SpatialQueryFilter?

vestal minnow
junior flower
#

@vestal minnow I've just sent in a small pull request that exposes filtering (+ editing, since collisions is mut) and adds a one-way-platform example. I've had some stuff come up so I've not been able to put much time in recently, so it's just a small change for now, I'm afraid

junior flower
#

One question I do have: is there a reason that xpbd only exposes the first normal that the backend returns? As you can see in the example I added to go with, it's jumping through some hoops to calculate normal2, and it would have be nice to have access to it. I considered exposing it, but it was out-of-scope of the target so I didn't think it right to.

vestal minnow
vestal minnow
junior flower
#

It looks like the child colliders code is building the collision manifolds is pretty close so it's probably going to conflict, but I can make a pull request to expose it if you like

vestal minnow
#

even though it's not strictly related

junior flower
#

Coolio. Once that is merged I'll update the one-way-platform example in #150, so I'll return it to draft state for now

drifting marsh
#

I don't actually need it anymore, but I do think it would be a useful feature.

tawny comet
#

Probably a silly question, but what is the correct way to enable debug-plugin on command line with cargo run?

When I do cargo run --features "debug-plugin", I get error: none of the selected packages contains these features: debug-plugin. But the debug view works fine when I set it in the cargo.toml. Just curious how to do it the command line way.

vestal minnow
#

(or 3d)

tawny comet
#

oh yep that did it. thank you!

vestal minnow
#

yeah if you use just debug-plugin, it'll look for the feature in your own Cargo.toml, not bevy_xpbd's Cargo.toml

tawny comet
#

ahh makes sense. figured it would be something small haha

crystal crag
#

Hi,

I looked at the example (https://github.com/Jondolf/bevy_xpbd/blob/main/crates/bevy_xpbd_2d/examples/move_marbles.rs) which seemed to be the simplest one from the 2D examples (but it's easier to guess with a name like "hello_world" or "cube")
And I was wondering, you spawn circles with :

            commands.spawn((
                marble_mesh.clone(),
                RigidBody::Dynamic,
                Position(position),
                Collider::ball(marble_radius),
                Marble,
            ));

but where is the LinearVelocity component added ? Is it something automatic ? (I didn't test Bevy since 0.9 I think)

vestal minnow
#

bevy_rapier also does this

crystal crag
#

Oh nice thx, I didn't know it was possible
I would have thought it would work with things like Bundle

vestal minnow
#

Yeah we used to have a RigidBodyBundle, and a ColliderBundle, but being able to add RigidBody::Dynamic and having it Just work™ is pretty ergonomic and also what bevy_rapier does

#

We just have systems that query for Added<RigidBody> and insert the missing components

#

I do think that bundles are more explicit though, so I'm open to revisiting the idea of having them

severe urchin
#

is it safe (for bevy_xpbd) to add a child entity to a regular physics entity, and the child has a big sensor collider? or do i need to move a separate sensor entity manually to keep it at the same pos?

vestal minnow
#

(WIP PR)

severe urchin
#

lmk if you want a 2d tester for the pr in future. i'm on main branch of xpbd now, mostly

#

btw with absolutely no attempt to optimize or profile it, seems like I can get to around 15,000 circle-collider bullets before things start to lag: https://www.youtube.com/watch?v=86NVuT0xRQI

RJ

No Audio. Running in local sandbox mode, so no networking or rollback.

disabled bullet expiry, curious when it would lag.. each bullet is a small rigidbody circle collider. went up to 15,000 or so. you can see the entity counter in the bottom right. I've not bothered profiling this scenario, but something in physics systems is hard at work.

N...

▶ Play video
#

i don't know if that's good or not, but it's sufficient for my needs at the mo 🙂

#

(i will probably make it so bullets don't collide with bullets anyway, but they do for now)

vestal minnow
#

A better broad phase along with a parallel solver would probably speed this up substantially though

severe urchin
#

makes sense yeah. certainly fun to see so much physics happening 😄

crystal crag
#

Is it normal if the debug-plugin draw ball shape as rectangle ?
It's written : debug-plugin enables the PhysicsDebugPlugin used for rendering physics objects and events like AABBs and contacts. in the doc
Nor is it mentioned in the README.md as "Future features"

vestal minnow
crystal crag
#

Ok I'll try with it so

terse burrow
#

can you set a collider to be a trigger? or do you have to use spherecast or whateve

cinder summit
#

Like Sensor or something different?

terse burrow
#

dont know 🤷

#

in unity you can have a collider be a trigger or not

#

if its a trigger it wont collide but will let you make function calls

#

like onTriggerEnter and yada yada

#

but i imagine you can just shapecast

cinder summit
#

Sensor causes it to register collision events but not function as a physical object otherwise

terse burrow
#

yeah might just be that

#

also im still gettin that error with raycaster

#

but it happens randomly

potent plume
#

spawning a monster every frame, xpbd doesn't even fill up half the screen before it starts to chug (rapier never impacted framerate as far as I could tell). am I doing something wrong, or is this expected given the algorithm? (It was more correct in terms of nonoverlapping then rapier for a lot longer)

junior flower
#

I'm pretty sure bevy_xpbd hasn't been hugely optimized yet, and the broad-phase is checking all combinations (i.e. N*N-1 combinations).
I think I read somewhere that Rapier is using some form of spatial lookup table to minimize the number of combinations it has to check, which would explain the difference

crystal cosmos
#

I'm a bit confused by how Mass works, I changed the mass of my car from 1 up to 1 million and it seemed to have very little impact

potent plume
#

at least thats what I would assume

#

like if the 1 million mass car hits a 1 mass postbox, it will send the postbox flying without slowing down almost at all, while the 1 mass car would bounce back

crystal cosmos
#

I would also expect it to influence gravity, but it doesn't seem to

potent plume
#

hah

#

(hint, thats not how gravity works in real life, but thats how people since time immemorial thought it would intuitively work til like around Galileo)

#

mass increases the force of gravity linearly, but also decreases the impact of that force linearly due to making the object harder to move, which cancels out and thus the affect is identical acceleration independent of mass

#

F = G * (m1 * m2) / r^2 where r is distance (in the case of a flat physics world, that part is considered to be constant)

#

F = m * a

#

m1 * a = G * m1 * m2 / r^2
a = G * m2 / r^2
a = (some constant not dependant on the mass of the object, only on the mass of the other object and distance to it)

crystal cosmos
#

so all forces are also relative?

potent plume
#

I'm not sure what you mean my that question

crystal cosmos
#

I'm applying Transform.forward (normalized) to a rigidbody every tick, but the object still behaves the same with mass 1 or 1million. So I have to assume the force is multiplied by mass or something inside the physics sim

potent plume
#

applying a transform isnt applying a force, its just teleporting the object

#

there is an ExternalForce that lets you apply a force

crystal cosmos
#

I'm calling apply_force_at_point on the ExternalForce

potent plume
#

oh, ok then yeah

crystal cosmos
#

With a constant force. So I'm only changing mass

potent plume
#

that should be scaled by mass yeah

#

afaik, I havent really used the lib much yet

#

but from physics, I would expect the change in velocity to be force / mass

#

so yeah, affected by mass

terse burrow
#

do you mind sharing your code?

vestal minnow
#

We currently have to do a lot of query.get_many_mut([...]) in the solver, which is slow according to Tracy, and the solver is currently single-threaded. I have plans for optimizing this in the future though

vestal minnow
#

(using ExternalForce)

terse burrow
#

Also i got a question why isnt the physics world seperated?

#

would it not making controlling it easier? for example settings the physics world at 30 fps and the normal word 144 or whatever

vestal minnow
#

You can change the physics frame rate freely with PhysicsTimestep and the substep count with SubstepCount

#

or run physics in a custom way by just setting DeltaTime to whatever you want and calling world.run_schedule(PhysicsSchedule)

#

As for having a fully separate physics world (i.e. data not in ECS), that's the main thing bevy_xpbd tries to avoid and does differently from bevy_rapier to see if it's a better approach for Bevy's physics. It makes things feel much more integrated and native, although in specific places (like the solver) it might currently be slower due to the additional querying

potent plume
vestal minnow
#

Also have you lowered the substep count from the default of 12 to something more reasonable for your use case?

potent plume
#

no, I wasn't really sure what to try

vestal minnow
#

It can improve performance significantly, for you just a few should be enough

#

Like SubstepCount(3)

#

for example

cinder summit
#

Didn't @lament matrix also have performance issues with the closely bunched up enemies for a survivors clone? They went for making it more boids-like rather than making them all circle colliders

lament matrix
#

yup

#

I recall we talked about it with kazagistar 😅

potent plume
#

yeah. I just decided to test this way out. thing is, rapier manages to hold up reasonably well, without switching to boids

#

gimme like 20 min, ill test the lower substeps, push the comparable branches of code

cinder summit
#

Rapier definitely has more optimization, tho you really need some specific cases for rapier to not perform poorly due to various other issues

#

My game runs better now with xpbd, but it's heavily bottlenecked by those stupid trimesh colliders 🙃

potent plume
#

I tested SubstepCount(3) and it does make it so the entity count is approaching what would be fine for a VS-style game (almost the entire screen completely full of enemies, but I dont actually have a precise count sorry) and close the the point at which rapier starts to slow down as well. The biggest problem I have left I think is that once it does suffer, it goes off a cliff (my guess would be a quadratic time complexity somewhere) while rapier degrades linearly

terse burrow
#

interesting

crystal cosmos
#

Argh, re-reading the docs I can see why, collider is changing Mass

#

Are there any more convenient way to work with ColliderMassProperties without using density? I want to keep Mass stable while I experiment with the size/shape of the collider

knotty furnace
#

What do I need for an entity to register a collision? I have a collider on it, but I seem to be messing something up, and it isn't working for me.
I have this system for checking the collision events

pub fn handle_bomb_collisions(
    mut commands: Commands,
    enemy_query: Query<&Enemy>,
    explosion_query: Query<&Explosion>,
    mut collision_event_reader: EventReader<Collision>
) {
    for Collision(contact) in collision_event_reader.iter() {
        println!("{:?} and {:?} are colliding", contact.entity1, contact.entity2);
        if (enemy_query.contains(contact.entity1)) && (explosion_query.contains(contact.entity2)) {
            commands.entity(contact.entity1).despawn();
        }
        
        if (enemy_query.contains(contact.entity2)) && (explosion_query.contains(contact.entity1)) {
            commands.entity(contact.entity2).despawn();
        }
    }
}

And I add the collider simply like this:

commands.spawn((
    enemy_sprite,
    Enemy {
        direction: Vec2::new(random_point.x, random_point.y).normalize(),
    },
    Collider::ball(ENEMY_SIZE)
));
#

The explosion is also an entity that is basically the same as the enemy spawn code

#

I also tried shape intersections

severe urchin
#

let mass = MassPropertiesBundle::new_computed(&collider, 10.0).mass.0; and then instert a Mass component using that value, or just hardcode it. you might need to insert all of ColliderMassProperties to avoid it being recomputed when changing colliders, not sure.

crystal cosmos
fossil pendant
#

can I use bevy_xpbd just for collision detection without all the physics stuff?

cinder summit
#

What level of collision detection without physics do you expect?

fossil pendant
#

just something simple for hit detection

cinder summit
#

It's possible to use sensors or just have colliders and use ray/shape casts or shape intersections

fossil pendant
#

what would be the minimum required plugins to make that work?

cinder summit
#

But for some usecases it makes more sense to have the full physics and just not ever apply any physics forces. That way it also handles cases like not being able to move trough walls

vestal minnow
fossil pendant
#

thanks!

severe urchin
#

if i want to keep track of which entities are touching (in contact) should i just write a system to aggregate the collision started and ended events myself, or is that already maintained inside bevy_xpbd that I can get at for no extra cost?

vestal minnow
#

CollidingEntities

severe urchin
#

oh, nice. so ican just filter that to detect what i need

knotty furnace
vestal minnow
#

might be remembering wrong tho

knotty furnace
# vestal minnow In 0.2 yes, but I think on the main branch it's not needed

Ok thanks. I'm using 0.2

I'm gonna need to figure something out, because when I add a RigidBody::Static to the explosion (which is what I'm testing against, and it doesn't move), it now spawns in the bottom left corner of the window instead of where the bomb was dropped. I'll figure it out though, now at least I know I'm heading in the right direction!

Thanks

cinder summit
#

Isn't the normal approach to have the rest of the game be rigid bodies, and handle an explosion with a one time shape intersection test?

knotty furnace
# cinder summit Isn't the normal approach to have the rest of the game be rigid bodies, and hand...

Yeah, that was my first thing I tried.

let intersections = spatial_query.shape_intersections(
    &Collider::ball(BOMB_DET_RADIUS),                // Shape
    bomb_transform.translation.truncate(),  // Shape position
    f32::default(),                         // Shape rotation
    SpatialQueryFilter::default(),            // Query filter
);

for entity in intersections.iter() {
    println!("Entity: {:?}", entity);
    if enemy_query.contains(*entity) {
        commands.entity(*entity).despawn();
    }
}
#

Nothing had rigidbodies when I wrote that though, so that's probably the issue.

I can't seem to get my enemies to spawn or move correctly with rigidbodies as the code is written now
I'm doing the bevy-ball-game tutorial and it didn't use any physics (rapier nor xpbd), so just dropping this in was over-hopeful haha.

I'll be rewriting the movement and trying to add rigidbodies to the enemies and player

junior flower
knotty furnace
drifting marsh
#

I've been looking for the source of non-determinism and one thing I found is that the accumulator in run_physics_schedule will vary because of delta time. I think this can be fixed by moving your PhysicsSchedule to FixedUpdate. I'm guessing this is the reason that bevy_gaff isn't deterministic.

#

I think bevy_ggrs would have to update the Time resource if that's possible.

#

@lime hatch

drifting marsh
#

You set the time in that schedule?

lime hatch
#

hmm.. maybe not

#

that could explain it

drifting marsh
#

bevy_xpbd is using the client's frame rate delta time because it's not scheduled in FixedUpdate

lime hatch
#

I though bevy_xpbd had a fixed step mode, that i set it in, but maybe i forgot/made that up

drifting marsh
#

It does, but it accumulates time with the Time resource

lime hatch
#

that would be a huge 🤦 on my part

#

i do this:

.insert_resource(PhysicsTimestep::FixedOnce(1. / FPS as f32))
#

But I haven't actually looked into what it does

#

just assumed that should make it ignore the time resource

drifting marsh
#

ooh, that might work actually. I use Fixed, let me test that

#

Yeah, that got rid of my desyncs. That's my bad, I thought bevy_gaff used PhysicsTimestep::Fixed.

lime hatch
#

oh, that's nice. so you're running bevy_xpbd without desyncs now?

drifting marsh
#

Yeah, I haven't had a desync yet

#

I'm not using a ton of features though, I have rotation disabled, and I'm using dynamic rigid bodies rn

merry tide
#

Hello! I am at the point where I am seeing some odd behavior in the physics engine, and I am pretty sure it is me, like 99% sure. Does anyone here do paid work? Sorry if this is the wrong forum for this. I am not talking about consistent and/or long term, just trading some moolah for eyeballs.

#

It just has to do with despawning on collision and it makes the objects sometimes bounce back and sometimes just pass through.

#

And I need it to be deterministic.

vestal minnow
merry tide
#

Sorry, I am using Helix so copy/paste doesn't work reasonably for me.

#

If anyone would be willing to give it a quick glance that would be great. Also I understand if that is a tall order.

#

Again, I am pretty certain this is just me fumbling things.

cinder vapor
#

Hmmm..... it seems for a frame there is an overlap of colliders.

vestal minnow
# cinder vapor

Yep, in 0.1 and 0.2 this is an issue, but it's fixed on the main branch.

Previously we only used one contact point per collision, and for numerical reasons / implementation reasons it could be at the corner. In your case all of the initial contact force is applied at the bottom right corner, which causes the rotation.

We now use multiple contact points per contact, in this case one for each corner, which makes the collision much more stable and even.

cinder vapor
#

Thanks! I will check it out.

vestal minnow
# cinder vapor

Also I think this should be fixed now as well. There was previously a one-frame delay in the instantiation, but iirc we fixed this

cinder vapor
#

Sounds sweet. I will verify.

#

It works 🎉

severe urchin
#

i know it's a bit of a crap error report, but i'm occasionally seeing things not correctly being removed from CollidingEntities. i haven't figured out how to reporoduce it or why it happens yet.

#

anything known?

#

eg my player entity moves far away from a sensor collider, but still has it in it's CollidingEntities

#

i need to check the inverse too, and see if it got removed from the sensor collider

vestal minnow
#

It just has a collision stability regression that I still need to fix

severe urchin
#

ah ok. so if i disabled the sleeping plugin that would "fix" it for the time being?

vestal minnow
#

No, I think sleeping is unrelated for that issue

severe urchin
#

ok

#

i can't seem to get CollidingEntities to show in egui world inspector, despite registering the types

vestal minnow
#

Yeah it's saying that HashSet<Entity> needs to be registered but it doesn't seem to work

#

maybe it needs some manual impl or something

#

But ya I'll revisit the sleeping + collision event + CollidingEntities PR in a few days hopefully

merry tide
#

I am making something that is made for speed-running, and I love the idea of having a ghost to play against. Tracking the position of a "ghost" seems almost trivial, but how would you account for frame-time issues doing it like that? Does this make sense? Imagine super-meat boy, or a racing game where you see your previous deaths.

potent plume
#

what kind of issues are you imagining?

#

if I were to come up with a design off the top of my head, I would just record every position and animation at a fixed update, and set velocity of each ghost towards the next one in their list. you can easily fit a hundred recordings in under a Mb, and linear approximation should be fine for the handful of frames that might render between the fixed ticks?

#

(though I know that the normal method for this is to record inputs and replay them, but that seems risky, and not like that much of a memory savings, and you could also time travel more easily if you wanted that)

fallen citrus
#

How viable would it be to piggyback off of bevy query filters for SpatialQuery instead of using CollisionLayers? Basically, SpatialQuery could have a generic ROWorldQuery parameter so you could do SpatialQuery<(With<Solid>, Without<Player>)> in your system param. Instead of having each layer be declared as variants of a single enum, you would just make them as marker components. Aside from simplification, this would have two useful benefits: one is that it would make it less of a pain to use SpatialQuery in any system that needs to mutate position by excluding them from the filter, the other is making it easier for other systems to make use of these flags without needing to sync marker components with flags. It may be necessary though to implement a flag trait on the components you want to do this for though, as I imagine many bevy projects will use more than 32 different components especially if they have any generic components.

It would still be necessary to have a filter for excluded entities, but instead of being a SpatialQueryFilter type it could just be any entity iterator so [] would work as an empty filter.

vestal minnow
# fallen citrus How viable would it be to piggyback off of bevy query filters for SpatialQuery i...

Yeah I had the idea of allowing Query filters for spatial queries, just never tried if it would work. I think it would definitely be the most natural and flexible approach for Bevy and its ECS, so we should definitely try.

One issue here is that the spatial query pipeline currently maintains a collider HashMap that maps the collider entity indices with some data that we need to give to Parry and the spatial query filters (the collider's shape, position and collision layers). This means that we can't just apply Bevy's Query filters for that, since it's just a HashMap. IIRC this was for performance reasons or something, but I might be misremembering

But I do think it can be refactored to work

fallen citrus
#

Here's a quick n' dirty implementation as a wrapper in case you want to see

#[derive(SystemParam)]
pub struct SuperSpatialQuery<'w, 's, F: Filter> {
    spatial_query: SpatialQuery<'w, 's>,
    filter: Query<'w, 's, (), F>
}

impl<'w, 's, F: Filter> SuperSpatialQuery<'w, 's, F> {
    fn cast_ray(
        &self,
        mut origin: V3,
        direction: V3,
        mut max_time_of_impact: Real,
        solid: bool,
        mut exclude: Vec<Entity>
    ) -> Option<RayHitData> {
        while let Some(hit) = self.spatial_query.cast_ray(
            origin, 
            direction, 
            max_time_of_impact, 
            solid, 
            SpatialQueryFilter::new().without_entities(exclude.clone()) 
        ) {
            if self.filter.contains(hit.entity) { return Some(hit) }
            origin += direction * hit.time_of_impact;
            max_time_of_impact -= hit.time_of_impact;
            exclude.push(hit.entity);
        }
        None
    }
}
vestal minnow
#

It would still be necessary to have a filter for excluded entities
If we keep the excluded entities thing, then yes; however we could also just allow users to do this manually through predicates/callbacks

fallen citrus
#

Yeah that would be good too, would be compatible with the same loop structure I implemented there

vestal minnow
#

But that's slightly trickier, because the pipeline currently doesn't have access to the ECS unlike SpatialQuery

fallen citrus
#

My thinking there was to move the origin forward to each erroneous hit and reducing the max_toi accordingly, but I don't know how qbvh works so it may not be that helpful

vestal minnow
#

Ohh, I didn't read the code properly mb

#

That could work though 🤔

fallen citrus
#

And you have to readjust the toi at the end, which I didn't do there, but it should return this:
Some( RayHitData { entity, normal, time_of_impact: max_time_of_impact - time_of_impact})

#

and instead of mutating the max_toi, make a copy to mutate

vestal minnow
#

Yeah it's definitely worth testing and benchmarking, I think it'd be a great usability improvement and make things more flexible

#

I don't personally have time to do it for 0.3 (coming in a couple of weeks probably) but I can try after that, or if you have time then you could make a PR as well

fallen citrus
#

Awesome, I will first see how this lazy wrapper fares and if it fits in convenient enough I'll try implementing it properly and see the performance.

junior flower
fallen citrus
junior flower
#

We actually gave up in the end

We were trying to recreate a feature from a future version of Unity which didn’t exist in the version of Unity we had, but did in the next LTS. We were trying to avoid updating because we were so far in, but ended up updating just to get this feature

fallen citrus
#

I see, thanks!

junior flower
#

Now that I'm not on mobile I can see the code properly.
If I understand the code correctly, it looks as though -- as you suggested -- moving the origin only 99% of the way forward (give or take some float inaccuracies) would probably work fine here since you're pushing onto the exclude vec.

vestal minnow
#

@fallen citrus hmm, another potential issue is that people will still probably want to filter by collision layers as well. Collisions would still have to use CollisionLayers, so it'd be useful to reuse those instead of having to add both a collision layer and a separate marker component, like Layer::Ground and a Ground component.

Not sure if this is actually an issue though, since we could just allow users to manually handle layers in callbacks, and RayCaster and ShapeCaster could maybe still store masks as an optional property or component

cinder summit
#

Replacing CollisionLayers honestly doesn't seem like it would be all that much of a gain in terms of DX. Also you should be careful with moving things to a callback, if that can't get inlined somehow you might end up with a bunch of extra function call overhead

crystal cosmos
severe urchin
#

nice

vestal minnow
# cinder summit Replacing CollisionLayers honestly doesn't seem like it would be all that much o...

Yeah, I think I agree overall, and I'm not planning to replace CollisionLayers as of now.

However, if it can be done efficiently, I do think it could be very powerful and perhaps more ECS-like to be able to e.g. "cast ray against every collider with component X" or even "cast ray against everything that moved" instead of having to manage collision layers and masks everywhere. With the current setup, you also need to do some extra work; for example, you probably have a Player or Enemy component anyways, but for spatial queries you would still need to manually define and add separate collision layers for them.

I think an ideal ECS-like API could be to replace CollisionLayers with some other component that uses plain query filters like With<T> for collision masks (no idea how this would be done tho), and spatial queries would also just use query filters like suggested here. I feel like this is difficult to do efficiently though, so I don't know how viable this is.

This might not be a perfectly fair comparison, but I do think I like the API without CollisionLayers a bit more:

With CollisionLayers:

#[derive(PhysicsLayer)]
enum Layer {
    Ground,
    // ...
}

fn setup(mut commands: Commands) {
    commands.spawn((
        Collider::cuboid(5.0, 1.0, 5.0),
        CollisionLayers::all_masks::<Layer>().add_group(Layer::Ground),
    ));
}

fn raycast(spatial_query: SpatialQuery) {
    let query_filter = SpatialQueryFilter::new().with_masks([Layer::Ground]);
    spatial_query.cast_ray(Vec3::ZERO, Vec3::NEG_Y, 1000.0, true, query_filter);
}

Without CollisionLayers:

#[derive(Component)]
struct Ground;

fn setup(mut commands: Commands) {
    commands.spawn((Collider::cuboid(5.0, 1.0, 5.0), Ground));
}

fn raycast(spatial_query: SpatialQuery<With<Ground>>) {
    spatial_query.cast_ray(Vec3::ZERO, Vec3::NEG_Y, 1000.0, true);
}
#

Wow that became long 😅

severe urchin
#

i like that. in my code my collision layers are basically just copying names of marker components that everythign has anyway, and i expect that's fairly common. if it can be done efficiently i think it would feel more ECSy

#

but being able to do spatial queries against Added<Something> would be cool

#

"what spawned near to my player" -> SpatialQuery<(Added<Powerup>)> ...

vestal minnow
#

Yeah that's another benefit, things like Added<Powerup> or Changed<Transform> should "just work" for spatial queries (and collisions if we implemented it there as well)

#

The main concern would probably be performance, so it should definitely be compared to the current approach tho

#

But it would also only affect the entities/queries that do have these filters, for everything else it wouldn't have any cost I think

quartz heart
#

Is there a way to define the orientation (rotation) for fixed joints?

quartz heart
carmine dove
#

Looking for some debugging pointers; I've got a 2d game set up where there's a ball; it has a rigidbody::dynamic, restitution of 1.0 and ball:collider; when it runs into various other colliders that i have in the scene it doesn't actually "bounce" at all, i have set the combination mode thing to "max" and i'm using the main branch currently. any pro tips on where to go figuring out what ive screwed up?

vestal minnow
carmine dove
#

lol; happy to test if you have a commit somewhere 🙂

#

wouldn't happen to also manifest as possibly making collision events be "laggy" would it? sensor variant seemed to fire immediately 😄

vestal minnow
#

Shouldn't affect collision events, there's just an incorrect condition that causes restitution to always be 0

#

But I know of some issues with collision events that should be fixed by #112 once I have time to finish it

carmine dove
#

cool; will follow along there; thanks so much for this library btw been great for the most part

vestal minnow
carmine dove
#

things are bouncing! now to see if i can do some work arounds on the sleepy colliders 🙂

devout imp
#

Hello! Very neat library, I have a tiny, probably very stupid question but is there a way to see the collision normal in the CollisionStarted & CollisionEnded events? I'm trying to figure out if I need to look at the Collision events instead since they have contact points, but I'm not sure. Basically what I'm trying to do is to check if my player is standing "on the ground" like this:

fn collision_events(
    mut movables: Query<&mut Movable>,
    mut collisions: EventReader<Collision>,
) {
    for collision in collisions.iter() {
        if let Ok(mut movable) = movables.get_mut(collision.0.entity1) {
            movable.on_ground |= collision.0.normal.y >= 0.9;
        }

        if let Ok(mut movable) = movables.get_mut(collision.0.entity2) {
            movable.on_ground |= collision.0.normal.y >= 0.9;
        }
    }
}

But this is kind of messy and I will never detect if the collision ends like this. Is there a better way perhaps? 😅

#

(Trying to do the catlikecoding unity tutorials in bevy)

quartz heart
#

I tried to create my own joint, It seems I would need to add it to the solve_contraint and joint_damping systems.

But those are not exposed in the API.

How can I add my custom joint that its contraints are resolved.

vestal minnow
#

joint_damping is now public, but it requires a bit more manual scheduling than solve_constraint since there isn't a separate system set for user joint damping. To avoid conflicts, it's probably best to use .after(SubstepSet::SolveVelocities)

#

I think we could maybe add an extension trait to add methods like .add_xpbd_constraint::<Constraint>() and .add_xpbd_joint::<Joint>() to App so that you wouldn't have to manually schedule these things

vestal minnow
# devout imp Hello! Very neat library, I have a tiny, probably very stupid question but is th...

Yeah CollisionStarted and CollisionEnded only give access to the entities, so you need to use Collision events. You could maybe do something like this, although it's not exactly optimal:

fn collision_events(
    mut collisions: EventReader<Collision>,
    mut started_collisions: EventReader<CollisionStarted>,
    mut ended_collisions: EventReader<CollisionEnded>,
) {
    for collision in collisions.iter() {
        let entity1 = collision.0.entity1;
        let entity2 = collision.0.entity2;
        if started_collisions
            .iter()
            .any(|ev| ev.0 == entity1 && ev.1 == entity2)
        {
            // respond to started collision
        } else if ended_collisions
            .iter()
            .any(|ev| ev.0 == entity1 && ev.1 == entity2)
        {
            // respond to ended collision
        }
    }
}

On the main branch there is also a new Collisions resource (name TBD since it's so close to the event name) which would allow you to iterate e.g. CollisionStarted events normally and get the collision data easily like collisions.get(entity1, entity2)

quartz heart
vestal minnow
devout imp
vestal minnow
devout imp
#

I see! Good to know, I can probably just schedule my ground checking system to run in the PhysicsSchedule with a bit of luck 😄

#

I'll give it a go, thanks!

devout imp
#

Not sure if this is optimal but it works:

fn collision_events(
    mut movables: Query<(Entity, &mut Movable)>,
    collisions: Res<Collisions>,
) {
    for (entity, mut movable) in movables.iter_mut() {
        let mut on_ground = false;
        for collision in collisions.collisions_with_entity(entity) {
            on_ground |= collision.manifolds.iter().any(|m| m.normal1.y >= 0.9 || m.normal2.y >= 0.9 );
        }
        movable.on_ground = on_ground;
    }
}
#

Added it here:

.add_systems(SubstepSchedule, collision_events.after(SubstepSet::ApplyTranslation))
#

Well, it works until it starts sleeping, of course 😅

#

I'll go for the Started/Ended events.

quartz heart
#

It seems fixed joints can lead to some strange behaviors, is there a good way to prevent it to happen with adjusting some of the values?

carmine sluice
quartz heart
# carmine sluice Looks like maybe you put it into an impossible-to-satisfy setup?

I just spawn them and add a fixed joint with 1.5 on the anchor:

    let box_gltf = asset_server.load("models/box-small.glb#Scene0");
    let size = 0.25;

    let cube_1_entity = commands
        .spawn((
            SpatialBundle {
                transform: Transform::from_translation(SPAWN_POINT),
                ..Default::default()
            },
            // Collider::cuboid(size, size, size),
            RigidBody::Kinematic,
            Name::new("little_cube"),
            Thing1,
        ))
        .with_children(|commands| {
            commands.spawn(SceneBundle {
                scene: box_gltf.clone_weak(),
                transform: Transform::from_xyz(0.0, -0.25, 0.0),
                ..default()
            });
        })
        .id();

    let cube_2_entity = commands
        .spawn((
            SpatialBundle {
                transform: Transform::from_translation(Vec3::new(2.0, 2.0, 2.0)),
                ..Default::default()
            },
            Collider::cuboid(size, size, size),
            RigidBody::Dynamic,
            Name::new("little_cube"),
        ))
        .with_children(|commands| {
            commands.spawn(SceneBundle {
                scene: box_gltf,
                transform: Transform::from_xyz(0.0, -0.25, 0.0),
                ..default()
            });
        })
        .id();

    commands.spawn(
        FixedJoint::new(cube_1_entity, cube_2_entity).with_local_anchor_1(Vec3::new(1.5, 0.0, 0.0)),
    );
#

and there is a simple system that rotates the kinematic cube:

pub fn rotate_thing_1(mut thing1_query: Query<&mut Transform, With<Thing1>>, time: Res<Time>) {
    for mut t in thing1_query.iter_mut() {
        let position = SPAWN_POINT + Vec3::X * 1.0;
        let rotation = Quat::from_rotation_y(time.delta_seconds() / 5.2);
        t.rotate_around(position, rotation);
    }
}
vestal minnow
#

I wouldn't expect that kind of problems to be possible in such simple cases, I've mostly seen it for very long chains of bodies where the masses are very small, which can cause numerical issues with f32

quartz heart
#

I can share the repo if that helps?

vestal minnow
#

Yeah that'd be useful, thanks

quartz heart
#

its on the bevy_xpbd_test branch

#

(you can press L to lock the mouse, and editor_pls is available too.

#

You can also "equip" an object by pulling it towards you with the left mouse button, but when you rotate left and right, it sometimes deforms (like stretches)

vestal minnow
#

Yeah this is really weird 🤔 I have the issue in your project as well, but when I do a one-to-one copy of spawn_experiment and rotate_thing_1 and the assets into a separate example, it works

vestal minnow
#

@quartz heart it's this box 😅

// main.rs lines 94-97
spawn_blaster(Vec3::splat(3.0), &mut commands, asset_server.as_ref());
spawn_small_box(Vec3::splat(1.0), &mut commands, asset_server.as_ref());
// THIS
spawn_small_box(Vec3::splat(2.0), &mut commands, asset_server.as_ref());

Removing it fixes the joint issue. There's a box that goes flying so I think the box is clipping into the rotating dynamic box which causes it to get a massive angular velocity that takes a long time to converge

#

Doesn't solve the jitters/stretching when equipping objects though; it seems to happen at very specific angles only so it could be some numerical issue or something

drifting marsh
#

I'm trying to solve a source of non-determinism. I printed the PreviousPosition in the integrate_pos system. In the picture, before I run the PhysicsSchedule I print the PreviousPosition. You can see though, while the frame 1s start at the same position, the first time it's printed in integrate_pos it's different. Is there a system that would change PreviousPosition that runs before integrate_pos?

drifting marsh
#

I print PreviousPosition after it's set to Position so the issue would actually be with Position

#

It looks like the position is different even in update_aabb, is there anything that even runs before that?

drifting marsh
#

According to bevy_mod_debugdump there isn't. I don't understand how the position is changing.

drifting marsh
#

It's happening sometime between Prepare and the beginning of BroadPhase

#

oh, is it because of PreviousGlobalTransform. That isn't pub so I can't register it as a rollback component.

#

yeah, I tried that with a fork and now I don't get any desyncs!

vestal minnow
#

Ideally you wouldn't need to rollback it since it's mostly an implementation detail required for syncing Transform changes to physics positions, but it'll do for now

#

I also still can't tell if bevy_xpbd is truly deterministic or not 🤔
I was testing bevy_gaff with varying amounts of lag (even one full second), and it was still visually behaving perfectly deterministically when using keyboard controls for movement, but the logs say that it is desyncing every now and then. The logging seems to use a custom previous position component though, so maybe that's just not updated correctly or something

#

Also grabbing objects via mouse causes desyncs quite easily, but idk if it's caused by e.g. indeterministic input handling or spatial queries or something else

quartz heart
vestal minnow
#

But ideally it'd be more complex, maybe with pre-recorded inputs for movement, and maybe some joints and spatial queries

#

could maybe recreate the demo shown here in some way, although it's still a bit simple imo

quartz heart
#

For me the videos on the site doen't load for some reason.

vestal minnow
#

Yeah it's just a big cube that can be rolled on the ground, and there's a ton of smaller cubes that stick to the larger cube on contact

#

so it's kinda like a snowball becoming bigger, but with cubes, and the demo has deterministic rollback networking

#

But it doesn't really matter what the demo is, just something complex enough that it should be a reliable determinism test and ideally include as many features as possible

severe urchin
#

seems like LinearVelocity and AngularVelocity are "changing" (ie being mutably dereferenced) even though their values dont change, for static bodies that can't move. could that be possible?

#

hmm unless one of my systems is mutably referencing them heh

#

nope, not me afaik

#

debugging some netcode and it looks like my static walls' linvel and angvel are changing every tick, where bevy defines changing as having been mutably dereferenced

#

i wonder if it's possible to tell bevy to undo the mutably referenced marker if we know the component wasn't changed

vestal minnow
#

there were systems that were setting the velocities of static bodies to 0 (since they don't have velocity) even if they were already zero

severe urchin
cinder summit
#

Definitely a lot more complex than what you see in many networked games, where you usually try to supress motion on any axis that isn't useful for gameplay

drifting marsh
quartz heart
#

Is xpbd stateless?

vestal minnow
# quartz heart Is xpbd stateless?

Define stateless
Some things are stored for two or more frames like current and previous collisions (for collision started/ended events and in the future maybe persistent contact manifolds) but there's not much long term state. Mostly it's just components and small configuration resources

#

Also for the broad phase and spatial queries there are acceleration structures

quartz heart
#

Primarily for networking, Unity insisted that physix can’t be used for networking and only their new starless physics engine can be used for fully networked experiences.

As you need to predict and roll back constantly.

#

For example stacking cubes becomes really challenging with a starless engine, and often you end up with continua small movements which make the stack collapse after a few frames.

vestal minnow
#

Yeah I guess bevy_xpbd is somewhat stateful, which enables some performance optimization and useful APIs

#

Can't say much about how it affects networking

#

I wonder how you would implement e.g. a broad phase with a stateless approach though, just rebuild acceleration structures from scratch every frame?

quartz heart
#

(And it is a big performance bottleneck)

vestal minnow
#

The nice thing with bevy_xpbd is that you could just make a StatelessBroadPhasePlugin and replace the built-in one with that

cinder summit
#

With my current rollback code I don't think I roll any of the PreviousX components back, tho I do also avoid a bunch of them because my code acts directly on Position/Rotation, rather than using Transform/GlobalTransform. I wonder if that is why my simulation always drifts after a few seconds

#

I can't imagine the state of caching layers would matter all that much tho, if you apply updates before anything uses it it should act as if there was never any state to begin with

vestal minnow
#

And maybe Transform and PreviousGlobalTransform if you operate on transforms (which you don't)

severe urchin
#

ExternalForce and ExternalTorque too surely?

vestal minnow
#

Yea if you use them then probably those as well

drifting marsh
vestal minnow
#

Interesting 🤔

drifting marsh
#

Is CollidingEntities used internally anywhere or would it only need to be rollbacked if used?

vestal minnow
#

I don't think it's used anywhere right now at least

drifting marsh
#

Also, PreviousGlobalTransform needs to be rollbacked because of one of the systems in plugins::sync. I haven't checked which one specifically.

vestal minnow
#

Yeah it's probably transform_to_position

#

It skips entities if the values of their global transforms haven't changed, so if PreviousGlobalTransform isn't correct, Position and Rotation are recomputed

#

I think

drifting marsh
#

Out of curiosity, why is there a Position/Rotation component instead of using Transform?

cinder summit
vestal minnow
#

Also GlobalTransform has drifting issues due to the Affine4, which would require ugly workarounds like bevy_rapier's number rounding hack

#

or Affine3? idk

vestal minnow
# cinder summit What are PreviousPosition and PreviousRotation even for? 🤔

XPBD uses them in the solver in a few places:

  • Computing contact positions at the current state (Position) and before substep integration (PreviousPosition) to compute the relative tangential motion for handling static friction
  • Computing new velocities after constraints have been solved using v = (x - x_prev) / delta_time. XPBD is position-based (hence the name), so velocity updates are derived from positional updates
  • Probably other things
cinder summit
#

Hmmm, wouldn't some of those require that it's set to Position before velocity is applied and constraints are solved? 🤔

vestal minnow
#

PreviousPosition is set equal to Position right at the start of substep integration, before velocity is applied

#

unless I misunderstood the question

cinder summit
#

If PreviousPosition is set equal to Position at the start of physics, we don't need to roll it back right? 🤔

vestal minnow
#

hmm

#

valid point 🤔

drifting marsh
#

I don't seem to get desyncs turning it off. I'll leave it off and see if it causes desyncs.

#

The only reason I added it was because bevy_gaff does

vestal minnow
#

Yeah I don't think you should need to roll back PreviousPosition and PreviousRotation in theory (and probably in practice) unless the engine does something dumb somewhere

#

And yeah bevy_gaff does roll it back, but I don't think it's actually needed, and it's probably there just in case it contributes to desyncs since bevy_gaff still has some desync issues when there's latency

junior flower
#

Does the ShapeCaster component (I forget if that’s the actual name or not) cast from the position at the end of the frame, or is it from its position at the start of the frame? And/or is there a mode to have a cast run from the previous position to the current one?

Usecase is interpolated projectiles that e.g. fire off a particle system when they hit something, but at the point they hit them at, not where they ended up at the end of the physics frame.

I’m on my phone and it’s kinda tricky moving around GitHub on mobile, so please forgive me for asking something that’s probably really quick to see from the source code.

junior flower
#

This was apparently a case of rtfm. Looks like I can set the origin of the shapecast to be the offset to the original position and then direction/max toi to whatever you land it in its end position. Easy-peasy!

fallen citrus
# vestal minnow <@280866644979613697> hmm, another potential issue is that people will still pro...

I think a good middle ground will be at least to say that predicates alone can be sufficient for raycasting, provided that there's no meaningful loss in performance of doing group tests in the predicate. You can use predicates for both query filters and excluding entities, and I went ahead and wrote this as an iterator so that cast_ray can just get the first value of the iterator and ray_hits can collect from it.

pub struct RayHitIter<'w, 's, 'a, P: Fn(Entity) -> bool> {
    spatial_query: &'a SpatialQuery<'w, 's>,
    origin: V3,
    direction: V3,
    max_time_of_impact: Real,
    solid: bool,
    predicate: P
}

const OVERLAP_CHECK: Real = 0.99;
impl<'w, 's, 'a, P: Fn(Entity) -> bool> Iterator for RayHitIter<'w, 's, 'a, P> {
    type Item = RayHitData;
    fn next(&mut self) -> Option<Self::Item> {
        let mut exclude_entity = None;
        let mut cumulative_time_of_impact = 0.;
        while let Some(RayHitData{entity, time_of_impact, normal}) = self.spatial_query.cast_ray(
            self.origin + self.direction * cumulative_time_of_impact, 
            self.direction, 
            self.max_time_of_impact - cumulative_time_of_impact, 
            self.solid, 
            SpatialQueryFilter::new().without_entities(exclude_entity) 
        ) {
            if (self.predicate)(entity) {
                return Some( RayHitData { entity, normal, time_of_impact: cumulative_time_of_impact + time_of_impact})
            }
            cumulative_time_of_impact += time_of_impact * OVERLAP_CHECK;

            exclude_entity = Some(entity);
        }
        None
    }
}
#

I will test the performance and if its good I'll replace the query filter with this and submit a pull request

#

As for whether a component based approach can replace groups entirely, an option might be to do something like have a component like CollidesWith<T: Component> and groups can be generated from this under-the-hood. But my ECS + dynamic programming knowledge is very limited, this seems like the sort of thing that might require all of these components to be reflected

#

Or perhaps CollidesWith<T: Bundle> if there's a way to iterate through component IDs in the bundle

vestal minnow
#

I guess it might be possible to store the component IDs and somehow use those, but I couldn't easily find a way to do that without having to access World when adding the collision mask component

#

but my knowledge of this stuff is also quite limited so I'm not really sure what's possible

fallen citrus
#

I see, well as I learn more I'll keep it in mind

pure nebula
#

Hello, I am having an issue with xpbd_2d that my entities get their Transform.translation.z position reset back to 0.

Is there a way to solve this in the main-branch of the plugin? I tried in 0.2.0 and then the z-order remains correct. But I would prefer to use the main-branch since the physics seems to work much better there with FixedUpdate.

vestal minnow
#

Ah, I guess it got broken again :P I think I know where it's happening so I'll try to fix it

vestal minnow
pure nebula
#

I'll be away until later today/tomorrow. So I'll post an example when I get back. But I have a pretty simple setup where I'm spawning tiles and entities with xpbd colliders and rigidbodies using bevy_ecs_ldtk. I tried printing the values and first frame the z value returns as 1 but then gets set to 0 2nd frame onward. Manually trying to set the transform to something else resets the value after one frame again.

vestal minnow
pure nebula
late moat
#

is there any quick way to make visible colliders?

cinder vapor
#

e.g.

# I'm using the main git branch in this case
bevy_xpbd_2d = { git = "https://github.com/Jondolf/bevy_xpbd", branch = "main", features = [
    "debug-plugin",
] }
#

You can enable or disable it during gameplay by modifying the PhysicsDebugConfig resource:

fn toggle_physics_debug_info(mut physics_debug_config: ResMut<PhysicsDebugConfig>) {
    physics_debug_config.enabled = !physics_debug_config.enabled;
}
vestal minnow
#

Yeah collider debug rendering is only on main currently

cinder summit
#

Do we have some way to make 1-way collisions?

vestal minnow
#

you could probably copy most of the one-way platform logic from the example and just adapt it to 3D (or it might actually work as-is in both dimensions?)

cinder summit
#

In my case I'm planning to make one-way doors so it'll be a bit different from one-way platforms, but that seems usable

vestal minnow
#

Yeah that should work basically the same, just need to change the direction of the one-way behavior

severe urchin
#

i'm having trouble spawning bullets in relation to the positions of my ship. if i do my spawning before physics sets runs that frame, the bullet is always spawning effectively at the previous position, because the spawn happens and then physics runs, and then the player's ship is in their new location by the end of that frame.

if i spawn my bullets after the physics sets have run, i get the correct position of the player's ship for that frame, but then.. physics has already ran, so my bullet doesn't get integrated into the physics system until next frame - so it doesn't advance according to it's velocity etc. so it still appears one frame behind where it should be

cinder summit
#

Shouldn't the bullet also move if it spawns before physics? 🤔

severe urchin
#

when i spawn the bullet, it's origin is relative to the player. then physics runs, so the player moves, and the bullet moves too but you can see the bullet originated at the previous position of the player

cinder summit
#

I mean it doesn't really make sense to fire a bullet from the new position and also immediately move from there

#

You could make the bullet also gain the ship's velocity for the first tick, but it would still be slightly off I'd imagine

severe urchin
#

the bullet inherits the velocity of the player's ship and then some, but it still ends up originating at the old position, because i want the bullet to spawn based on the after-physics position of the ship, but if i spawn the bullet after physics, the bullet is a frame late appearing

#

at least i think that's the problem. wasn't expecting this to give me so much grief.

#

(especially noticable at higher movement speeds)

cinder summit
#

It just helps a lot if you decide on the order in which such events happen, in my case players use skills before moving (because skills can overwrite their movement), which means they would've always shot from their "previous position"

#

If you somehow had faster updates than frames/ticks you could possibly interpolate between positions and use that as the origin for the projectile

vestal minnow
#

Where exactly in the schedule are you spawning the bullets? I would imagine .before(PhysicsSet::Prepare) to work

severe urchin
#

most of my game logic sets are in fixedupate before any of the xpbd sets runs, i was spawning there too. just experimenting with spawning after physics but it didn't really solve the problem

cinder summit
#

The only way to make it feel more responsive is something like the sub-tick timing you see in games like overwatch and CS2

severe urchin
#

i want to spawn a new bullet relative to the after-physics position of my player, but also have the bullet added to the physics system and simulated that frame i think. cake and eat it situation i suppose.

#

basically i want to spawn the bullet and instead of adding Position, add PositionFn(lookup player entity, calcualte bullet pos)

vestal minnow
#

you could just do bullet_pos += (player_vel + bullet_vel) * delta_time to artificially simulate where the bullet should be when spawning it I guess

severe urchin
#

yeah that might be the way. feels a bit wrong

#

i thought about spawning before physics and then snapping the position after physics in the same frame, would that be less bad? 🤔

vestal minnow
#

that'd be fine probably

#

still feels a bit hacky, but I guess you could try it

severe urchin
#

i don't know if the player is about to slam into something, so maybe snapping post-physics is safer than predicting the origin before physics

#

hmm i can use the players Position - PreviousPosition after physics to create a delta, and add to the bullet position

vestal minnow
#

I don't think that works

#

PreviousPosition is the position before the current substep's integration step, not the position before the substep loop started

severe urchin
#

ah

#

also worried about collisions and things happening from when the bullet is spawned at the "wrong" position. could get messy

cinder summit
#

Oh right there's also another hack you can do

#

If the bullets aren't physics, you can just move them whenever

#

My projectiles do ray/shape casts then move to the new position, so I can run them after physics if I want

vestal minnow
#

but they are physics bodies

severe urchin
#

my bullets are just dynamic bodies with circle colliders

#

what's the best way to disable collisions on bullets for the very first frame, until i snap the position? just manipulate collision groups before/after?

cinder summit
#

If you disable collisions for the first frame, can't they just jump trough anything that's directly in front of you?

severe urchin
#

if i set my collisionlayers in the post-physics hack when i snap the position, and set it to not collide before, that should mitigate some weirdness

severe urchin
cinder summit
#

Wait so why would spawning it after physics not work?

vestal minnow
#

Yeah I guess changing collision layers could work in your case; maybe we should add a ColliderDisabled component or something to make it more convenient though

severe urchin
#

it would also be neat to be able to make my own bullets not collide with my own player, which i don't think the collision layers is suitable for

vestal minnow
#

could also add the collider after snapping the position, but this would make spawning them more annoying

severe urchin
#

hmm

vestal minnow
severe urchin
#

do physics entities get simulated the first frame they are added? ie, if i spawn a fresh entity at a Position, with a non-zero LinearVelocity, at the end of the frame, will that entity still be at Position?

severe urchin
vestal minnow
#

so the position will be different

severe urchin
#

ok thanks

vestal minnow
#

if spawned before physics

vestal minnow
#

the main caveat is that it needs to loop through collisions separately from the narrow phase (since it's a separate system and not a callback/hook) so it might add a bit of overhead

foggy lava
#

is it normal for camera jittering when not building in release mode?
(when a camera's copying player position)

severe urchin
#

now i'm just predicting the ship position by one timestep forward and spawning the bullet there, and it's working nicely. will ignore that and hope it doesn't become a problem later 🙂

  // predict the position of the ship after physics runs later this frame,
  // and spawn the bullet relative to the new location of the ship.
  // this is so the bullet can still be simulated this frame.
  let dt = 1.0 / FPS;
  // see the xpbd integrator for this logic.
  // abdridged. not supporting Locked Axes, normal gravity, etc.
  let next_rot = *rot + Rotation::from_radians(ang_vel.0 * dt);
  let next_linvel = lin_vel.0 + dt * ex_force.force() * inv_mass.0;
  let next_pos = pos.0 + dt * next_linvel;

  let bullet_origin = next_pos + next_rot.rotate(bp.bullet_spawn_offset);
  let bullet_linvel = next_rot.rotate(Vec2::Y * bp.bullet_speed) + next_linvel;
cinder summit
foggy lava
#

that sounds tough to fix, maybe I should just make the player its parent
and fix my hacky AnimationPlayer-finding code that breaks when I do that

shell ermine
cinder summit
#

@vestal minnow That example makes some assumptions about getting collisions when you stop touching, but that doesn't seem to actually be true and I end up being able to go back trough the one-way gate sometimes ... Is it still possible to figure out when collisions with something end when they get filtered? 🤔

cinder summit
#

Actually it's pretty obvious I guess, I can just increment a number each execution, update it if I skip the collision again, then remove things that aren't from the current iteration

foggy lava
cinder summit
#

If you want to reset the rotation wouldn't it make more sense to set Transform.rotation to default?
What exactly do you mean by "reset of the world jitters"?

foggy lava
#

the rotation respects the parent player's rotation, even if it's set to Quat::IDENTITY every frame it'll still rotate

#

the world jitter is hard to explain, some frames don't have the rotation fixed and some do, so the camera's direction has flashes of other directions?
I can take a video if you want

cinder summit
foggy lava
#

yep!

cinder summit
#

I think it might be that the system that inverts the player's rotation has system ordering issues now

foggy lava
#

it's the same system, so yes

#

I essentially traded position-based jitter for rotation-based jitter... lol

cinder summit
#

😂

#

Should be as simple as adding a

.after(PhysicsSet::Sync)
.before(bevy::transform::TransformSystem::TransformPropagate)

I think ... At least if you have physics in PostUpdate and the camera update system in PostUpdate

foggy lava
#

that's definitely better, but still has issues
I'll try it without the camera parenting nonsense, brb

#

yeah that fixed it, thanks :)

severe urchin
#
  .add_systems(
      PostUpdate,
      systems::camera_follows_player
          .before(bevy::transform::systems::propagate_transforms)
          .before(bevy::transform::systems::sync_simple_transforms),
  );

that's how mine's scheduled. the system sets the camera's translation to the plauers without copying the rotation:

   //..snip
   camera_trans.translation.x = player_x.min(max_x).max(min_x);
   camera_trans.translation.y = player_y.min(max_y).max(min_y);
#

it's nice and smooth

#

(well, 60fps like the physics..)

severe urchin
late moat
#

hi! Trying to use bevy_ecs_ldtk to create tilemap collision, but all the colliders end up at the same place? I asked on the help channel for that plugin and they don't know why the transforms are wrong. Any help would be really appreciated

vestal minnow
#

0.2 or main?

#

for bevy_xpbd

late moat
#

0.2

vestal minnow
#

yeah a lot of issues have been fixed since 0.2 so you could test if the main branch works

#

the main branch of bevy_xpbd should work with bevy_ecs_ldtk since some people are already using them together #1124043933886976171 message
(although there was another issue, but that was just fixed)

late moat
#

yep that was it. Has the crate just not been updated in a while?

vestal minnow
#

Yep, I just haven't made a new release yet. I still have a couple of things I'd really like to add for 0.3 (namely child colliders, which was planned to be one of the main additions but is still somewhat WIP) but I should've just made a release ages ago tbh

late moat
#

if I set the linear velocity of a kinematic body with an update function, will it be stopped at walls?

vestal minnow
#

at some point we'll probably add something like Godot's collide and slide and a built-in character controller

late moat
#

so for a player character, would you recommend a dynamic or kinematic body at the moment?

vestal minnow
#

With a dynamic body you need to implement less things manually (but on the flip-side, you might have a bit less control)

#

so it might be a bit easier to get started at least

#

bevy_mod_wanderlust is also an existing dynamic body character controller, but bevy_xpbd support is WIP

royal helm
#

I could put some more work in to getting it fully workin with xpbd