#Avian Physics

1 messages Β· Page 15 of 1

cinder summit
#

Planes normally don't behave like cubes in 3D after all

inner perch
#

OK, well I can always try to figure that out, but I expect I'll just not let it get to that point.

vestal minnow
#

cool art style though

cinder summit
inner perch
#

That reminded me of my childhood TV in the 80s

#

on PBS

cinder summit
inner perch
#

exactly

#

ok thanks guys or gals

vestal minnow
vestal minnow
last panther
vestal minnow
#

yep, it'd be super easy

cinder summit
#

I thought you only needed to go like 10k from the origin to get artifacts πŸ˜‚

vestal minnow
#

I don't remember how far away this was, it was like over half a year ago lol

abstract forge
#

Yea for 32 bit floats I would say 1000000 is abour where you start getting errors on 0.1 or more per operation

abstract geyser
#

I'm trying to get a basic physics simulation with buoyancy working for a large "age of sail" style ship. I've managed to make some decent progress, but I'm struggling a bit with CenterOfMass. I think the proper way to do things is by setting ColliderDensity, but I'm generating a collider trimesh from my Ship's mesh (bevy components crate), and I feel like I really need to be able to set the COM really low in the ship towards the keel. If I add a CenterOfMass component on my entity it seems to just be reset I'm guessing by the physics engine at runtime. If I try to manipulate ColliderDensity then the COM is too high up.

Really looking for some advice on how to handle this problem. Using bevy inspector I can manipulate the COM to a lower point on the ship and it seems to float pretty well, but I can't for the life of me figure out how I should be approaching this because it seems like COM isn't intended to be manually adjusted like this.

abstract geyser
#

I think I may be on to a good direction. Looked at the example and I can add a child entity with another collider and set a higher density on that one. It seems like that affects the parent so may work out. Will post back.

thin hare
#

when iterating over collisions.collisions_with_entity(entity) can entity show up as entity_1 or entity_2?

vestal minnow
thin hare
#

Gotcha, i worded it crazily but that's basically what i was asking haha

vestal minnow
#

Yeah no worries πŸ˜„

thin hare
#

also how's the rebrand/rework going?

vestal minnow
#

Pretty well, I'll probably start making actual PRs soon for all the stuff I've been working on. I still have a few more things related to joints that I need to work on, and I also want to compare the contact solver to other engines a bit more. Then I can focus more on updating docs and examples and doing release prep

#

I'm aiming for having things ready on the main branch in a couple of weeks when Bevy starts the release candidate phase (a new thing we'll likely try for this release) so that people can try out the new solver and stuff, and then I'll release the new crate once Bevy 0.14 is released

#

I'll probably do one more release for bevy_xpbd that doesn't have all of the new stuff, and is mostly just a 0.14 update to help people migrate. And the new crate (whatever it'll be called) will have the new stuff

thin hare
#

Awesome, really great work btw, after using rapier for a few years I was surprised how much more ergonomic working with xbpd is, it's so nice to have everything take place within the normal ECS world and not have to constantly access a context resource for everything

little berry
#

It just feels good to use.

cinder summit
#

It's mature in a different way ... xpbd has better docs and is a lot more ergonomic, afaik it's also more deterministic and it's just generally easier to use if you do anything weird (like rollback networking) ... Sure it might have lower performance and less features, tho even those could be argued to be untrue because rapier just has different performance issues and a different feature set πŸ€”

#

I for one would rather use the library that allows me to have my own collider type than the one that has all the obscure joint types I'll never use πŸ˜‚

vestal minnow
#

(next release will technically have more joint types than Rapier lol)

#

For performance, one of the next big steps would probably be (parallel) simulation islands, but that'll probably be a bit tricky with the current implementation... We probably can't just iterate through and solve all joints for a given island when there are multiple different types of joints, or at least not as easily. This might be why Rapier uses GenericJoint for everything

cinder summit
#

Having sleeping logic that's not broken and speculative CCD might help with performance too tho thonk

vestal minnow
#

speculative CCD is done, I still need to find why the sleeping doesn't work tho

#

the sleeping is sub-optimal anyways since per-body sleeping is typically not recommended

cinder summit
#

The new solver also generally ran better than xpbd right?

vestal minnow
#

Not sure about the solver but performance is typically better since the narrow phase is only run once per frame

#

I guess for simulation islands we might have to add a joint enum and do something like this unless we want a bunch of dynamic dispatch...

pub enum JointKind {
    Fixed(FixedJoint),
    Prismatic(PrismaticJoint),
    Revolute(RevoluteJoint),
    Spherical(SphericalJoint),
    Generic(GenericJoint),
}

pub struct Joint {
    pub entity1: Entity,
    pub entity2: Entity,
    pub kind: JointKind,
}

Rapier had something similar before it switched to using GenericJoint for everything

#

It just doesn't feel very ECS-ey from an implementation perspective

little berry
#

So this crate doing the enum would be a convenience up for me :^)

vestal minnow
#

It would make this system spam redundant at least

solve_xpbd_constraint::<FixedJoint, 2>,
solve_xpbd_constraint::<RevoluteJoint, 2>,
#[cfg(feature = "3d")]
solve_xpbd_constraint::<SphericalJoint, 2>,
solve_xpbd_constraint::<PrismaticJoint, 2>,
solve_xpbd_constraint::<DistanceJoint, 2>,
#

everything could just query for Joint

cinder summit
#

Just make a system with a Query<AnyOf<&FixedJoint, &PrismaticJoint, &RevoluteJoin, &SphericalJoint, &GenericJoint>> πŸ˜‚

little berry
#

I was spamming options like a caveman.

vestal minnow
#

I keep forgetting that exists

cinder summit
vestal minnow
#

doesn't help with the island / constraint graph issue tho

little berry
#

And this pattern is pretty rare.

vestal minnow
#

I believe I started following Bevy around 0.5 or something

little berry
#

Since we're on offtopic anyways, can we talk about the crazy shit happening in the rendering dev for bevy.

#

Can't believe these wizards.

vestal minnow
# vestal minnow I believe I started following Bevy around 0.5 or something

0.5 release post:

Expect to see progress in the following areas soon:

  • "Pipelined" rendering and other renderer optimizations
  • Bevy UI redesign
  • Animation: component animation and 3d skeletal animation
  • ECS: relationships/indexing, async systems, archetype invariants, "stageless" system schedules
  • 3D Lighting Features: shadows, more light types
  • More Bevy Scene features and usability improvements
    ferris_sob
little berry
#

archetype invariants

What are those?

vestal minnow
#

My understanding is that they allow you to specify constraints to what components can or cannot be used together, like an entity with X cannot have Y

little berry
#

That would be convenient.

vestal minnow
little berry
#

Due to the overhead of verifying these rules against the World's archetypes, this is likely best done only during debug mode,
Poor debug mode is struggling as it is 😦

cinder summit
vestal minnow
#

third?

colliders: &Query<(
    Ref<Position>,
    Option<&AccumulatedTranslation>,
    Ref<Rotation>,
    Option<&LinearVelocity>,
    Option<&ColliderParent>,
    Has<Sensor>,
    Has<RigidBody>,
    Option<&ContactSkin>,
    Option<&SpeculativeMargin>,
    &C,
)>,
cinder summit
#

Hey at least those are spaced appart so that there's never 3 in a row thonk

#

Another one I like is Option<(&A, &B)>, which has a subtly different meaning

vestal minnow
#

You can do that??

cinder summit
#

Yes

vestal minnow
#

wait this query is wrong, hol' up

little berry
#

Why Has and Added on the same query?

cinder summit
#

I rarely have queries where each component is individually optional tho, either it's just one, there's a whole group that needs to either exist or not, or I want at least one of them

vestal minnow
#

I'm increasingly confused... the variable for Has<C> is also named is_rb even though C is a collider thonk

cinder summit
#

Which would map to Option<&A>, Option<(&A, &B)> and AnyOf<(&A, &B)>

cinder summit
vestal minnow
#

Nah can't be me, surely not

little berry
#

The person wishing you the worst β€” past you.

#

I hate that guy.

vestal minnow
#

my god this is the ugliest system I have ever seen, I always feel like throwing up looking at this

#

and it's annoyingly not that easy to do in a much nicer way

cinder summit
#

Wait is this the collider transform propagation thing?

vestal minnow
#

no, init_transforms

cinder summit
#

Oof, and here I was hoping this wasn't actually ran in my project πŸ˜‚

little berry
#

It's the price we pay for being able to add any arbitrary physics components and have everything just work.

cinder summit
#

Actually wait ... init transforms ... Is that in PreparePlugin or SyncPlugin? thonk

vestal minnow
#

PreparePlugin

#

also I don't love the "prepare" name but idk what to call it

cinder summit
vestal minnow
#

yeah it'd be nice for some components, but some probably need manual initialization anyway

#

also if conditional requires aren't supported then it might be annoying

#

like we might only want to add force and velocity components for non-static bodies

cinder summit
#

If they are conditional they aren't really required now are they?

#

Maybe that would just signify that it's time to split RigidBody into three markers πŸ˜‚

#

Oh wait but then we need archetype invariants to prevent people from making a static kinematic dynamic body πŸ™ƒ

vestal minnow
#
#[require_if(without(Static), require(LinearVelocity, AngularVelocity))]
struct RigidBody;
vestal minnow
#

It'd just be a RigidBody which is dynamic by default but you can add Static to make it static

#

And then for kinematic bodies, I guess a separate component

#

Hmm, maybe it's just a CharacterBody which is kinematic by default but adding a RigidBody makes it a dynamic character πŸ€” idk that might just be weird

edgy nacelle
#

What are some ways to "run physics multiple times" in the same "game loop" on subsets of all entities? I'm thinking this would help me with two scenarios:

  1. Multiple floating origins: let's say there are two "rooms" containing interacting objects; each room's size is on the order of magnitude of 1 x 1 x 1, but they are 10^9 apart, so that I want to simulate each room separately, each with their own origins. I would probably do this by "running xpbd" separately for each room (since they don't interact at this time).
  2. Rollback: for a networked game, the client side might receive updates from the server about a state a few steps in the past, and it would run a few steps forward again to catch up to the current client time, all within the same "game loop".
little berry
vague pebble
vestal minnow
# edgy nacelle What are some ways to "run physics multiple times" in the same "game loop" on su...

Simulating groups of entities separately is difficult since they share the same world and bevy_xpbd simulates entities using normal Bevy systems. It might be possible to have different ECS worlds and to simulate them separately, but I haven't tried it and I imagine it'd be pretty painful.

But for those two scenarios:

  1. This would likely require first-party support for floating origins. This is something I plan on experimenting with. The engine could simulate all of the bodies together, but essentially just ignore interactions between bodies that belong to different chunks/origins.
  2. There are several people already using bevy_xpbd with networking. They are probably more knowledgeable on how it works than I am. But for running simulation steps on-demand, it's possible to make custom physics runners; you can just run the PhysicsSchedule manually and advance the Time<Physics> clock by the desired amount.
edgy nacelle
#

Thank you both for the pointers! I'll need to look into custom runners / schedules in Bevy.

#

I'm also looking into how big_space (https://docs.rs/big_space/) does floating origin, I suspect there is only one floating origin for the whole world / one chunk.

cinder summit
glacial nebula
#

Sorry for the necro-response, but multiplayer support is one of my goals with the crate. The floating origin rendering is non-destructive - the high precision coordinates can be shared between clients and the floating origin system handles crushing that down to f32 for rendering.

#

I also want to support physics, but that would probably live in a sibling crate. Not sure how feasible that will be with bevy_xpbd because I'll probably need to manage my own physics contexts as well as component syncing.

vestal minnow
#

Syncing of what components?

glacial nebula
#

Syncing the physics state with the entity positions, essentially.

#

I think the main thing I would need is the ability to have independent, non-overlapping physics contexts, and the abililty to ignore the value of Transform.

#

Because all entities will be inside a say, 2km cube, if you are only looking at the Transform.

vestal minnow
#

It should be straightforward to make a custom sync plugin for physics-position-to-transform syncing at least. There's already a fork integrating big_space with bevy_xpbd

glacial nebula
#

How does that work with Transform?

#

Does xpbd have its own internal representation of position seperate from the transform?

vestal minnow
#

Yes, Position and Rotation

#

there are several reasons for it, including custom sync setups like this

glacial nebula
#

Cool!

#

I would probably (?) split this off onto a server, to have it handle all physics calcs, so I suppose it will have it's own view of the physics world anyway.

glacial nebula
vestal minnow
vestal minnow
glacial nebula
#

The idea is that for physics in large worlds, you want to group objects (island detection), and position the origin at the center of each merged group. From the perspective of the physics simulation, each of these sets of objects would need to be simulated separately, even though they are all near their local physics origin.

#

But, tbh, if this ends up being over the network anyway, then it might be a non-issue. Each physics island could be running in a separate physics instance.

#

For local prediction, you probably only need to care about physics relative to the player, and won't need to care about multiple physics islands.

#

I'm currently working on supporting multiple reference frame hierarchies, to allow you to render multiple viewports, each with their own floating origin. So, not sure when (if ever) I will get to the physics. πŸ™‚

glacial nebula
#

Cool, thanks!

vestal minnow
#

I was trying to find a good video of it working but this is the best I found, doesn't really show the physics though
#general message

vestal minnow
glacial nebula
#

Same idea, different purpose

#

Islands don't interact, so you can use that to run each island with a local origin for physics.

vestal minnow
#

yeah, makes sense, although I'm still not sure why you'd need to simulate each island separately other than making sure that objects from different islands don't interact by filtering them in the broad phase

glacial nebula
#

Iirc that's how space engineers works.

glacial nebula
#

So it doesn't matter if you are on the other side of the galaxy, if you are only interacting with objects in your vicinity, then the physics simulation only needs to be relative to that group of objects.

vestal minnow
#

Yes, but you can still simulate all bodies simultaneously. The solver only cares about the constraints given to it (or generated based on contacts), and the broad phase can make sure objects from different islands don't interact

glacial nebula
#

I think we're saying the same thing?

#

As long as the sets do not interact, that's all you need

vestal minnow
#

Yeah we probably are, I just thought you meant running separate simulations like "simulate island 1, simulate island 2", and I'm just saying we can run everything together but make sure the sets don't intersects in terms of what constraints are generated

#

so everything except the broad phase and spatial query pipeline should be able to remain basically unchanged, unless I'm missing something

#

Either way, I'm interested in experimenting with built-in support for floating origins some time after the upcoming bevy_xpbd release, and I'd be happy to try supporting big_space, probably behind a feature flag

glacial nebula
edgy nacelle
#

Is it a good idea to run physics (& probably game logic too) on a different schedule that tries to stick to a "physics tick rate" as opposed to the render schedule? So slowdowns in rendering don't affect the physics, and rendering just takes whatever state the world is in at the start of the render frame. What are some issues with this? (e.g. I'd probably need to interpolate the positions that actually get rendered? Or issues with physics changing the world while rendering is happening?)

cinder summit
edgy nacelle
wanton nebula
#

Hi, first of all thanks for this crate! I just started using it recently and it's very well documented! πŸ™Œ I have a question regarding turning off collision detection between 2 entities. E.g. in a skeleton's bones I'd like to ignore collision between adjoinig bones. The CollisionLayers don't seem to be a good fit for this as I'd need to use a unique bit for each bone. Am I missing something obvious? If not, I'd be happy to try to contribute a solution for this

little berry
wanton nebula
#

Hi again, I found a little bug in prepare/init_transforms so I opened a PR to fix it (https://github.com/Jondolf/bevy_xpbd/pull/360), then I added a test and found some more. Any reviews are much appreciated! Also, I'll be using this crate for my project extensively and if you're looking for some help with maintenance of this crate I'd be down for it.

junior flower
# wanton nebula Hi, first of all thanks for this crate! I just started using it recently and it'...

I'm sure it's not anywhere near as succinct as what you're looking for, but you can get access to the whole list of collisions from the Collisions resource and use the retain associated function to remove collisions. There's an example here that uses it: https://github.com/Jondolf/bevy_xpbd/blob/434be4595ea6b4efa0c16ff22f906ba527c1386d/crates/bevy_xpbd_2d/examples/one_way_platform_2d.rs
You'll be able to at least use that for now to tide you over

#

The example is using it to allow dropping through platforms, but you'd be able to do it with something like this:

#[derive(Resource, Deref)]
pub struct PairsToIgnore(HashSet<(Entity, Entity)>); // store lowest index of the pair in .0

fn ignore_collisions(mut collisions: ResMut<Collisions>, pairs_to_ignore: Res<PairsToIgnore>) {
    collisions.retain(|collision| {
        let (a, b) = if collision.entity1.index() < collision.entity2.index() {
            (collision.entity1, collision.entity2)
        } else {
            (collision.entity2, collision.entity1)
        };

        !pairs_to_ignore.contains(&(a, b))
    });
}
wanton nebula
echo pendant
#

so i'm possibly using the library in an unintended way, but essentially i have

  • character that is a dynamic rigid body with mass
  • camera that is a dynamic rigid body with a VERY tiny mass
  • DistanceJoint between the two with a max length

i want the character to pull the camera along, and have it lag slightly behind

the issue i'm having is that when the character stops, the camera pulls the character back

is there a way to have a one-way force? so the character only applies force to the camera, and not vice-versa?
or would i have to implement a one-way joint perhaps?

#
            Mass(PLAYER_MASS / 100000.0),

this is the mass i'm trying for the camera, to limit how much force it can apply to the character, but it doesn't seem to work too well, camera still moves the character a visible amount

#

PLAYER_MASS = 1.0

#

ooh reducing the linear damping on the camera may have helped

vestal minnow
# echo pendant so i'm possibly using the library in an unintended way, but essentially i have -...

There is a Dominance component that could be used for this. The caveat is that if you for example gave the character a higher dominance than the default, it wouldn't affect just the jointed camera, but also all other interactions like collisions. You could probably give the camera a negative dominance and keep the character as default though

echo pendant
#

ooh! i'll look into that, thanks!

#

absolutely perfect, does exactly what i want

πŸ˜… lots of docs to read through, i'm sure i would have found it eventually, but you saved me a lot of time!

vestal minnow
#

Nice! Yeah there's a lot of docs haha, I'm planning on reworking them a bit to make them easier to browse

vestal minnow
#

Hmm, I'm not sure if I should make the crappy per-body sleeping "work" again, or leave it broken/disabled for this release and do it properly when we implement simulation islands later πŸ€”

#

I technically have it working again, but the per-body approach is just buggy and can cause weird jumpiness/jitter when bodies wake up. This was already kinda happening with the old solver, but it seems even worse now because of scheduling and narrow phase changes

little berry
#

I'd rather instability be avoided at the cost of performance, but I'm sure there are others who would prefer otherwise.

vestal minnow
#

Yeah, I think that's better especially since this is a major solver rework, wouldn't be a good first impression if there are random mini explosions and other weirdness whenever bodies wake up

#

although it's mostly for piles of objects

#

I'll see if I can at least fix the instability issues even if it's buggy in other ways, but otherwise I'll probably leave sleeping out for now (sry @cinder summit)

cinder summit
#

I'd imagine fixing per-body sleeping would be a nightmare in general, especially since any bit of Changed<T> can break it, because that's how it's broken now

vestal minnow
#

I changed the way component changes trigger wake-ups so that it ignores changes that happened during physics

#

uses somewhat cursed change tick tracking

cinder summit
#

If we want good sleeping later it'll probably need to make sure to only catch non-physics changes in and check that the new values are non-zero πŸ€”

vestal minnow
#

ah yea I should check for non-zero too, good call

#

my current issue is that sleeping bodies very randomly start sinking into the ground (without velocity??) but I think I might know why

vestal minnow
#

For now, I might actually do a scuffed version of sleeping where bodies can only sleep if they're not in contact with dynamic objects. This way, random dynamic objects lying on the ground can still sleep, but piles of dynamic objects won't

#

Yeah, this seems like a decent compromise until we have simulation islands. Should give a performance boost for larger worlds with dynamic objects that are just lying on the ground for example, without causing any instability issues

ashen nest
#

Hey I was using this and for some reason the children of the object don't get attached to it and just stay put any idea why this is happening?

vestal minnow
#

Do they have both Transform and GlobalTransform? Bevy requires both for transform propagation

ashen nest
zinc talon
vestal minnow
#

Dang, we sure have a lot of plugins lol

vestal minnow
#

Reworking and flattening the module structure further. Before and after:

#

In the first one:

  • components just contains a bunch of components with no clear separation of concerns, and some components are still stored elsewhere so it's not even comprehensive at all
  • resources has the same issue; no separation of concerns, and it's pretty random which resources are there vs. elsewhere
  • Why is constraints a top-level module? It's mainly a solver implementation detail
  • plugins is weird, because it has sub-folders with sub-plugins, and really it's just a folder for basically all functionality in the engine
    New structure:
  • yeet plugins, components, and resources, flatten structure
  • Organize everything by logical concerns
  • Add dynamics module for encapsulating rigid body dynamics (solver, sleeping, rigid body components, etc.), which also gives a nice place for more high-level docs
#

(I still need to update the module docs to have a more consistent and clear summary in the first paragraph though)

carmine sluice
cinder summit
vestal minnow
cinder summit
vestal minnow
#

Not sure where else hierarchy stuff would be handled

#

doesn't really make sense in bevy_math (except maybe the Transform itself)

#

Wait bevy_hierarchy is its own crate πŸ€”

#

And it also has a "group by type of thing" structure

#

I feel like we could probably merge bevy_transform and bevy_hierarchy, and maybe make Transform just a general transformation type in bevy_math

vestal minnow
#

Honestly, I feel like we should get rid of f64 support once we have proper floating origins for large worlds, since supporting both f32 and f64 through feature flags makes a lot of code more annoying or confusing, frequently trips up contributors, and also means that we need to copy any Bevy types we might want to use to work with f64...

#

And then it's also just generally more efficient to use f32 and only use f64 in places where the extra precision is really needed

cinder summit
vestal minnow
#

yes, with physics ideally working even for multiple floating origins (i.e. multiplayer support)

vestal minnow
#

I'm still working on the big rework and rebrand (see #346, although it's somewhat outdated by now) so I haven't had as much time to do "general maintenance" lately, like properly responding to issues and fixing them. A part of this is also that some things are just blocked on me finishing the rework, and I don't want me or others to spend too much time working on things that will soon be replaced or fixed by the new solver anyway.

#

After the release, I plan on doing a quick organizational pass: improve the issue labels (maybe Bevy-style labels), write up some kind of contribution guide, go through all the issues and respond to them / fix trivial issues, and also open a bunch of my own issues for missing features, performance work, and so on. I think we need to keep a better track of work, make it easier for people to contribute (including learning resources for physics simulation), and in general have a bit more structure.

royal helm
#

Does xpbd integrate ExternalForce with kinematic bodies?

#

I get that kinematic is "excluding forces" but yeah, just wonderin since I'm going to re-add that functionality with a controller

vestal minnow
royal helm
#

Gotcha ty! LovelyRat

vestal minnow
#

Np!

wanton nebula
# vestal minnow As for maintenance, did you have something specific in mind? I would of course a...

Nice, thanks for the thorough review and no rush! I'd be happy to help with anything like fixing issues, testing, refactors and features (within my capabilities - I'm still learning more about the internals) and it also helps me to learn more about the project. I probably won't have a consistent time availability to dedicate to it tbh and I don't mind waiting till you're finished with the rework before doing any more stuff

ruby verge
#

hi, i'm trying to shapecast a circle in 2d just to get colliders within a certain range of the player each frame and i'm not sure what i should set the SpatialQuery properties to. direction and max_time_of_impact don't really make sense for this application.

#

or is there a better alternative aside from manually checking distances to transforms?

vestal minnow
#

This doesn't return the distances though

ruby verge
#

thanks, i should have read the docs a bit more carefully

vestal minnow
#

But if you just need the entities intersecting the circle, it should be enough

sleek thicket
#

you probably should get distance to closest point and not transform, otherwise large objects would get weird

ruby verge
#

that would be useful to have in the future, but calculating manually for only those entities that are in range shouldn't be that costly anyway

sleek thicket
#

that's if you need exact distance and not just everything within range

vestal minnow
#

for distances to closest points, you could just do point projection for the entities that are in range

sleek thicket
#

i was just doing extra raycasts since i needed that for obstructions anyway

wanton nebula
vestal minnow
#

Yeah, that should work. A more efficient version would do this filtering in the broad phase already so that it wouldn't unnecessarily compute the contacts in the narrow phase for the pairs you want to ignore

#

This will be a built-in feature for joints later, but right now there isn't a very clean or performant way to do it, especially because each joint type is its own component type

#

Or I could just add an IgnoreCollisionsWith component for now I guess... that'd be very easy and pretty efficient

wanton nebula
junior flower
# wanton nebula finally got to try this - the order of the entities is not guaranteed, but somet...

Yep that’ll work πŸ™‚

There’s a comment in what I originally wrote about storing them in entity index order to avoid the second hash/lookup but it’s probably negligible since Entity is a small type.

Tangentially related: You’ll find that because the order is not guaranteed you’ll want to be doing something similar in collision events, too. The way I see folks handling that is doing this: for ((a, b)) in [(entity1, entity2), (entity2, entity1)] { … }

wanton nebula
vestal minnow
#

Yeah I've been considering ordering the entities in collision pairs by the entity ID, not sure how useful it'd be though

#

Currently it's ordered by the X-extents afaik because of the broad phase implementation

wanton nebula
vapid monolith
#

@vestal minnow is it possible to get the aabb of a collider (2d)?

vestal minnow
# vapid monolith <@545959292281552928> is it possible to get the aabb of a collider (2d)?

You can either use the collider's aabb method to compute it (takes the position and rotation) or query for the ColliderAabb component directly.

Note that the ColliderAabb is the AABB in global space, and it's expanded based on the body's velocity for collision purposes, so it often doesn't match the actual extents of the collider, except for stationary objects

vapid monolith
#

ah alr thx

vestal minnow
#

np!

wanton nebula
#

Hey, I'm having some trouble with a SphericalJoint and with_swing_limits . When combined with non-zero gravity, the swing limits don't seem to be respected and they get broken by gravity. I am using with_compliance(0.). I tried digging into what's going on, but no luck so far

frail robin
#

I'm trying to place objects in the game close to each other, but it seems like the collision is being detected without actual contact.
Is this a rounding error?
Both objects are kinematic bodies.

sleek thicket
#

probably the safety margin prediction_distance

sleek thicket
sleek thicket
#

it worked?

vestal minnow
cinder summit
#

Hah, I was just about to ask if that would get fixed in the next release πŸ˜‚

frail robin
cinder summit
#

People have run into that so many times it's kinda crazy it didn't have a fix yet

frail robin
#

Is this a bug? I thought it's a default config.

sleek thicket
#

it's a buggy fix to another bug iirc

cinder summit
#

It's somewhere between a bug and a design flaw I guess ... Prediction distance really shouldn't be a concern of end users beyond some stability/ccd type of stuff πŸ€”

vestal minnow
#

and yes it has been an issue for way too long lmao

frail robin
#

Now my future kitchen can be placed perfectly:

vestal minnow
#

nice, I hope your future house will have more than just a kitchen

vestal minnow
#

can be set per-entity with SpeculativeMargin

#

same as Rapier's "soft CCD", I just dislike that name a lot and haven't seen it anywhere else

sleek thicket
#

it doesn't feel that speculative though

vestal minnow
#

Bepu and Box2D call it speculative collision, Unity also calls it speculative CCD afaik

vestal minnow
sleek thicket
#

something behind the scenes? the result was a consistent margin for me

vestal minnow
#

The contact is speculative, the margin (i.e. max distance for speculative contacts) is derived from the velocity and clamped by the maximum bound

#

It just speculates a rough estimate of where the contact could be based on the closest points, it's not an actually accurate prediction

#

which is fine typically, but can cause ghost collisions in edge cases

sleek thicket
#

oh, that's very different from what it currently does

vestal minnow
#

yes

#

currently it's just for stability

#

with XPBD, it was especially important for stability to have a bit of wiggle room for the distance at which collisions are accepted

#

it's not quite as important with the new solver, but still helps; it's more-so to avoid tunneling now though

cinder summit
frail robin
vestal minnow
#

huh, it doesn't detect collisions?

cinder summit
#

If it's just position that changes a sensor would also work for the version that is being placed I think

cinder summit
vestal minnow
#

ah yea that gets skipped ofc

vestal minnow
frail robin
frail robin
#

Will try sensor for placing. Will need to rework the logic a bit to handle them differently.

vestal minnow
#

Could also use just a collider initially, and only add the rigid body when placing

frail robin
#

Thanks!

cinder summit
vestal minnow
#

yes, but it might still skip static-static contacts atm

#

so if you want those to be detected, it can't have a RigidBody::Static

cinder summit
#

Yea, it would need to be Sensor without RigidBody

vestal minnow
#

and at that point slapping a Sensor on top doesn't add much

cinder summit
#

I still find Collider without either reporting collision events weird tbh πŸ˜‚

vestal minnow
#

Or that it's weird that a collider without a rigid body or a sensor component still sends collision events

cinder summit
#

Luckily it doesn't matter for most usecases, and I don't think many people have had serious performance issues because of it, so collision layers are an okay workaround for now I guess

vestal minnow
cinder summit
#

It makes more sense if you consider Collider equal to CollisionShape in Godot ... Either way probably not the most important issue to fix right now, but if there's ever a time to reorganize the components in a breaking way it might be good to look into some alternative designs ... Which I guess would be when required components and/or construct lands πŸ€”

vestal minnow
#

yeah, I'm definitely not entirely happy with the current design in terms of the relationships between colliders, sensors, static bodies, and collision events, so I'd be happy to make changes if there's a better / more logical approach

cinder summit
#

Maybe observers can also make the collision events situation less painful

vestal minnow
#

and I'm definitely open to any breaking changes for the foreseeable future :P as long as they don't cause entirely unnecessary churn

cinder summit
#

"entirely unnecessary churn" ... You mean like when you introduce a Direction3d type then rename it to Dir3? thonk

vestal minnow
#

well back then people preferred the longer name before the type was actually used :P

#

I kinda treat bevy_xpbd as a way of freely experimenting with things to hopefully find what would be best for bevy_physics

#

so I'm open to experimental stuff and breaking changes, it's better to try as many things as possible and explore designs in 3rd party than 1st party

vestal minnow
#

Maybe we could even do something where collision events are only sent for entities that have an event listener to avoid sending unnecessary events and cloning a bunch of data

#

Another nice bonus here is the event bubbling, rigid bodies could listen to collision events of their child colliders too, which avoids having to query for the ColliderParent etc.

#

For querying for all collisions, you could still use the Collisions resource

wanton nebula
# wanton nebula Hey, I'm having some trouble with a `SphericalJoint` and `with_swing_limits` ....

@vestal minnow sry, any idea what’s happening here? The joint is connecting a static and dynamic body. When I add gravity motion of the dynamic body breaks out of the angle limits of the joint. From what I see the motion applied from gravity is added to AccumulatedTranslation which is taken into consideration in the constraints solver, so I’m still confused about what’s happening

vestal minnow
# wanton nebula <@545959292281552928> sry, any idea what’s happening here? The joint is connecti...

Do you have a minimal repro? This seems to be working fine

// Kinematic rotating "anchor" object
let anchor = commands
    .spawn((
        PbrBundle {
            mesh: meshes.add(Cuboid::default()),
            material: materials.add(Color::CYAN),
            ..default()
        },
        RigidBody::Kinematic,
        AngularVelocity(Vector::Z * 1.5),
    ))
    .id();

// Dynamic object rotating around anchor
let object = commands
    .spawn((
        PbrBundle {
            mesh: meshes.add(Cuboid::default()),
            material: materials.add(Color::CYAN),
            transform: Transform::from_xyz(0.0, -2.0, 0.0),
            ..default()
        },
        RigidBody::Dynamic,
        Collider::cuboid(1.0, 1.0, 1.0),
    ))
    .id();

// Connect anchor and dynamic object
commands.spawn(
    SphericalJoint::new(anchor, object)
        .with_local_anchor_2(Vector::Y * 2.0)
        .with_swing_limits(-1.0, 1.0),
);
#

(using a rotating kinematic body so that you can actually see the limit working)

wanton nebula
tribal hazel
#

hi i might be misunderstanding but i'm trying to use raycasts from the character and the rays are hitting the player collider despite the parent entity being ignored like ```rust
.with_query_filter(SpatialQueryFilter::from_excluded_entities([
parent.parent_entity()
]))

#

sorry won't be able to respond to answers immediately i'm going to bed

vestal minnow
#

same haha

#

I would probably double-check that the entity you're excluding is the entity with that collider, but it's a bit hard to say what the issue could be

tribal hazel
#

here's the spawning code

commands
        .spawn((
            Player,
            SpatialBundle {
                transform: Transform::from_translation(Vec3::new(0.0, 5.0, 0.0)),
                ..default()
            },
            input_manager(),
            RigidBody::Dynamic,
            collider,
            ShapeCaster::new(cast, Vec3::ZERO, Quat::IDENTITY, Direction3d::NEG_Y)
                .with_max_time_of_impact(0.2),
            LockedAxes::ROTATION_LOCKED,
            Controller::default(),
            Friction::ZERO.with_combine_rule(CoefficientCombine::Min),
            Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
            GravityScale(0.0),
        ))
        .with_children(|parent| {
            parent
                .with_children(|parent| {
                    parent.spawn((
                        Front,
                        RayCaster::new(Vec3::Z, Direction3d::NEG_Y).with_max_time_of_impact(2.0),
                    ));
                    parent.spawn((
                        Belly,
                        RayCaster::new(Vec3::new(0.0, 1.5, 0.4), Direction3d::Z)
                            .with_query_filter(SpatialQueryFilter::from_excluded_entities([
                                parent.parent_entity()
                            ]))
                            .with_max_time_of_impact(1.0),
                    ));
                    parent.spawn((
                        Foot,
                        RayCaster::new(Vec3::new(0.0, 0.4, 0.4), Direction3d::Z)
                            .with_query_filter(SpatialQueryFilter::from_excluded_entities([
                                parent.parent_entity()
                            ]))
                            .with_max_time_of_impact(1.0),
                    ));
                });
        })
        .with_children(camera::spawn);
vestal minnow
vestal minnow
vestal minnow
#

(and yea now I'm actually going to bed lol, goobmight)

tribal hazel
#

yup that did the trick

#

sorry πŸ˜…

vestal minnow
#

np, glad that you got it working :)

vestal minnow
wanton nebula
# vestal minnow (using a rotating kinematic body so that you can actually see the limit working)

Hey, I did some more experiments and here's a minimal example where it seems to break (unless I'm doing something wrong): https://github.com/exoexo-dev/bevy_xpbd/blob/joint-and-gravity-example/crates/bevy_xpbd_3d/examples/joint_and_gravity_3d.rs. You can run it with e.g. cargo run --example joint_and_gravity_3d --no-default-features --features "3d f64 parry-f64 debug-plugin use-debug-plugin" (it's based on this PR https://github.com/Jondolf/bevy_xpbd/pull/364 as I'm using it to ignore collisions between the anchor and the object, but even with e.g. CollisionLayers it's the same). I've set the gravity on a toggle by G key - it's off on startup

GitHub

Objective
Allow to set ignored collisions per entity.
Solution
Added an IgnoredCollisions component which is checked in the broad phase to filter out ignored collisions before any detection checks....

abstract tendon
#

so i have a fps controller with kinematic body.
when i move, everything is fine
when i turn my head, everything is fine
but when i both move and turn my head, there is a jitter. and yes i use

app.add_systems(
    PostUpdate,
    camera_follow_player
        .after(PhysicsSet::Sync)
        .before(TransformSystem::TransformPropagate),
);
``` for camera follow.

i always moved my player with directly changing its linear velocity
```rs
  linear_velocity.x = wishdir.x * 5.0;
  linear_velocity.z = wishdir.z * 5.0;

but when i removed this code and added position update the jitter is gone

  player_transform.translation.x += wishdir.x * 0.03;
  player_transform.translation.z += wishdir.z * 0.03;

i guess changing linear velocity directly is wrong. should i add acceleration to linear velocity?

cinder summit
#

Setting linear velocity should be fine if instant acceleration/deceleration is acceptable ... Shouldn't introduce any jitter at least ... How is wishdir calculated, and where does this system run?

zinc talon
#

What's the standard way to just "turn off" physics? I was thinking I could slap a run condition on the integrate set, which would probably get the job done but be heavy-handed

#

On second thought, that doesn't seem to work πŸ€”

wanton nebula
vestal minnow
#

just based on a quick look, setting the minimum and maximum swing angle to be equal seems a bit odd, since it means that there is no allowed swing at all

#

if you wanted equal swing in both directions, the minimum bound should be negative (I should probably make this clearer in docs)

#

but that should still constrain the angle to the specified value, so if it's not working then there probably is some issue

wanton nebula
vestal minnow
#

yeah, makes sense

tribal hazel
#

What would you recommend for simulating wall collision for a kinematic body like a player?

vestal minnow
# tribal hazel What would you recommend for simulating wall collision for a kinematic body like...
#

I'll most likely add some kind of built-in collide_and_slide functionality in the future

#

originally I was thinking that character controllers should be third party, but it'd probably be valuable to have a built-in solution too (even if it was in its own crate)

#
  • I just want to try making a proper character controller lol
tribal hazel
abstract tendon
#

everything you need are in this folder

#

they are pretty short and readable enough i believe

cinder summit
#

What immediately stands out to me is:
These two systems handle input, but PreUpdate is also where inputs get generated, so they won't run consistently unless you add an .after(InputSystem)

.add_systems(PreUpdate, movement_input_changer)
.add_systems(PreUpdate, player_look)
``` and there's this `.after` referring to a system in another schedule:
```rust
player_move
   .after(player_look)
abstract tendon
#

so i added .after(InputSystem) to those two input systems and removed .after(player_look) on player_look but its still jittery

cinder summit
#

Could also be that it's just jitter from the 60Hz physics schedule not running smoothly, but then it would probably only happen sometimes (unless your FPS isn't stable or it's some weird number that's only slightly off from 60 like 75)

abstract tendon
#

well, my fps jumps around 300 to 200

cinder summit
#

Wait now that I think about it ... It might just be that the camera updates at a different rate than the physics ... Even if it's a smooth 60 physics steps per second, if the camera moves 300 times per second and only jumps in position 60 times that's not gonna look smooth ... Could use variable delta for that, or just add a big of smoothing to the position the camera tracks

#

Oh and setting the player's velocity should also come before physics rather than after it, tho that one frame delay isn't related to the jitter

abstract tendon
#

yeah it actually make sense. so uh, how am i gonna smooth that? an example would be nice

#

after limiting game fps to 60, its just smooth af. now i need to smooth that camera for higher fps

cinder summit
#

The way I do it in my game is saving the target position of the camera, and lerping from the target position to the new position, using that as the new target position and the point the camera follows

#

Tho in my game I only do this for height atm πŸ€”

abstract tendon
#

so for 60fps camera movement, i should save camera position at every 16.6 miliseconds and lerp it to new position, right?

cinder summit
#

If you want to interpolate it perfectly yea. You can also go for more general smoothing which can come in various forms

abstract tendon
#

well im open to any idea

cinder summit
#

I think a fairly minimal camera smoothing approach would be something like this:

let new_pos = positions.get(player);
let (target_pos, speed) = camera_props.get(camera);
let Ok((dir, length)) = Diration3d::new_and_length(new_pos - target_pos) else { **speed = 0.; continue;};
**speed = (length * time.delta_seconds()).max(**speed);
if speed > length {
   *target_pos = *new_pos;
   **speed = 0.;
} else {
   *target_pos += dir * speed;
}

You just move the camera at some speed to make sure it reaches the target_pos in clearly defined maximum amount of time (1s in this case because length * time.delta_seconds(), could just multiple that by say 4 to get 0.25s), make sure to take the maximum speed between the current speed and last speed, and if it would ever overshoot the target reset the speed and set target to the new pos (this means we've reached the target) .. You then move the camera based on that target_pos instead of the player's position

#

There's a few minor edgecases where it might be suboptimal tho. Specifically if you move fast, then move slower it will hit the target pos, stop for 1 frame, then go to the new speed ... It might make sense to slowly lower the speed if it's close enough to the player

#

The downside is of course that any camera smoothing can lag behind the player ... The upside is that often you already don't follow the player but some point in front of them (in many 2D games) or next to them (with a 3D third person camera), and such an approach could be shared with the smoothing for physics-related jitter

abstract tendon
#

welp, anything for smooth player controller

cinder summit
#

Legend has it a lot of games known for their good controls have had their controls worked on for months with dedicated playtests just for that ... Something about wanting movement to be fun even if it's just in a test level with just a few cubes

abstract tendon
#

It doesnt need to be "fun". Im fine as long as there is no jitter

vestal minnow
#

The axis properties are public but there aren't any helper methods currently. The upcoming release will support local frames (anchor + reference orientation) for this though

wanton nebula
royal helm
#

does xpbd cache anything related to compound colliders?

#

like is it a bad idea to update the relative position of 1 of the colliders frequently?

cinder summit
#

If they're real compound colliders it might cause some issues because things that teleport aren't usually stable, but afaik there's no real caching πŸ€”

vestal minnow
#

In either case I don't think there's really caching though

#

except maybe mass properties, since moving the colliders around affects the center of mass of the body, assuming the colliders have non-zero density

red shale
#

@vestal minnow Would bevy_xpbd be able to solve displacement of struts, given some weight and elastic modulus? Something like world of goo, or bridge constructor?

vestal minnow
#

the stiffness of joints can also be configured

#

I'm not sure how those types of games handle it though, might have some more custom solution

red shale
#

I wrote a solver following some papers but it only works for a fully constrained systems. A β€œdangly” strut will just not converge. I guess worst case scenario is I can use my solver for all constrained struts and xpbd for dangly one just for an effect

vestal minnow
#

Okay more contact updates for the xpbd rework:

  • Both contact computation and contact constraint generation are handled by the narrow phase. This way, we only need to iterate over everything once, and don't have to duplicate queries or other computations. Constraint generation can also be multithreaded.
  • The narrow phase logic has been extracted into a NarrowPhase system parameter. Users could in theory manage it manually.
  • Speculative contacts use an unbounded speculative margin by default, similarly to Box2D V3 and Bepu. This means that there should be no tunneling for any objects by default, other than maybe for extremely quickly spinning objects or bodies overlapping due to contact softness. And for those cases, swept CCD can be used. Speculative contacts are very cheap as well, so this doesn't really hurt performance.
#

So basically
tunneling: yeet*
performance and code quality: πŸ“ˆ

#

This is using 6 substeps, but I now have 4 as the default since it's enough for the vast majority of cases with TGS soft

#

Which means default performance πŸ“ˆ further

#

(the old default was 12, which is kinda excessive)

#

(and it was still less stable for a lot of cases)

royal helm
#

I don't seem to get collision contacts for a child collider of a kinematic rigid body

#

is this intentional?

vestal minnow
royal helm
#

for what it's worth I am setting the position of the secondary one after SubstepSet::ApplyTranslation

#

but yeah it doesnt

#

the box is dynamic and that moving collider is a child to a kinematic rigid body

#

the parent one fell through the ground somehow lol

vestal minnow
#

Yeah that's strange, child colliders work for at least static and dynamic bodies (that environment is technically child colliders) so I don't see why it would work for kinematic too

#

*wouldn't

#

The child collider should have a ColliderTransform component, does that get updated when you move it around?

royal helm
#

nope

abstract forge
#

@vestal minnow I had a question about trying to do collide and slide inside of the physics substep right now we are trying to calculate the final position and the final velocity but are running into a bit of a issue with a invalid query for position and spatial query (as seen here)

pub(crate) fn kinematic_controller_collisions(
    collisions: Res<Collisions>,
    collider_parents: Query<&ColliderParent, Without<Sensor>>,
    spatial_query: SpatialQuery,
    mut character_controllers: Query<
        (&RigidBody, &Collider, &mut Position, &Rotation, &mut LinearVelocity),
        With<Player>,
    >,
) {

and was wondering if there was another way to do this as spatial_query and Position seem to be incompatible to use in this way in the ecs.

error

error[B0001]: Query<(&bevy_xpbd_3d::components::RigidBody, &bevy_xpbd_3d::plugins::collision::collider::parry::Collider, &mut bevy_xpbd_3d::components::Position, &bevy_xpbd_3d::components::rotation::Rotation, &mut bevy_xpbd_3d::components::LinearVelocity), bevy_ecs::query::filter::With<test_game::player::Player>> in system test_game::player::player_physics::kinematic_controller_collisions accesses component(s) bevy_xpbd_3d::components::Position in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`.
vestal minnow
#

I might deprecate the system param in favour of just the resource at some point, not sure yet

vestal minnow
#

thanks :)

vestal minnow
# royal helm nope

This narrows it down at least, if it's not updating the collider transform properly

#

I gotta go to bed in a bit but I can take a better look tomorrow

vestal minnow
vestal minnow
#

cylinder is a child collider of the capsule kinematic rigid body

#

I'm guessing it's related to the scheduling then

vestal minnow
#

it also works after SubstepSet::ApplyTranslation (and is more stable)

abstract forge
#

@vestal minnow hey I am still working on that collide and slide algo from yesterday but I was wondering what would be the best way to get delta time during the physics substep.

vestal minnow
#

Just Res<Time<Substeps>> and then .delta_seconds() should work

vestal minnow
#

in the SubstepSchedule the default Time resource also uses the substep time, similarly to how Time in FixedUpdate is actually Time<Fixed>

abstract forge
abstract forge
#

have you played with making a collide and slide algo for the engine?

vestal minnow
#

Not yet, but I want to

#

the repo has a few character controller examples but they're not quite collide and slide

abstract forge
#

Im trying to play with making one do you think it is something that should be done in the physics substep or just in the normal update loop?

vestal minnow
#

I'd say in the substepping loop, but the spatial query pipeline is currently updated just once per frame so ray casts and shape casts wouldn't have the latest state at each substep

#

So maybe something where the movement and collisions use substeps, but environment checks via spatial queries would only be done once per frame

#

I haven't looked too deeply at how collide and slide works yet

#

or hmm, you probably don't need substeps since you know how much the character can move before hitting something (I think)

#

since you cast beforehand

abstract forge
vestal minnow
#

yeah afaik Rapier also just casts the shape and moves the character by the amount it is allowed to move, either freely if there are no obstacles, or to the time of impact

#

and then has some logic for applying collision impulses

abstract forge
#

the only thing I would be worried about is the case where the collide and slide ends and then the engine pushes the player into a wall between frames and then collide and slide would get confused but ig that could be mitigated by just setting the pos and manageing the vel vec ourselfs.

vestal minnow
#

Why would the engine push the player into a wall? If it's a kinematic body

abstract forge
#

Me setting the lin vel and then the engine moveing it into a wall during the substep but that might be a missunderstand on my part

vestal minnow
#

Yeah if you set lin vel then the engine will move it

#

but with collide and slide I imagine you can just set the position directly

abstract forge
#

Yea thats kinda what I was saying.

vestal minnow
#

oh sry I read that message badly lol

#

yep you're right then

zinc talon
#

I've been abusing bevy_eventlistener pretty heavily in a project, and I suddenly had this crazy urge to use it for sensor collision detection

#

I'm not sure whether it can be done as a third-party solution though, would a PR be accepted? It would obv be feature gated

thin hare
#

are there any plans for [bevy_xpbd new name here] to be upstreamed in the future? that would be so boss

zinc talon
# thin hare are there any plans for [bevy_xpbd new name here] to be upstreamed in the future...

It's been discussed. Bevy would like a first-party physics solution, but it's blocked on a number of things, and <officialAnswer>bevy_xpbd's next iteration may become a suitable solution, but isn't necessarily the solution we'll go with.</officialAnswer>
I personally think it's a shoe-in, it's more ECS-ey than any other solution and it's based on an incredibly capable solver and is generally well-written and could be maintained fairly easily if Jondolf decides to get hit by a bus or just stop maintaining it. I wouldn't be surprised if it got upstreamed. And I might be a bit surprised if something else got upstreamed.

thin hare
#

That's what I'm saying, no shade to the maintainers of bevy_rapier, but xpbd feels far more ergonomic

vestal minnow
# zinc talon I've been abusing bevy_eventlistener pretty heavily in a project, and I suddenly...

There's an issue for bevy_eventlistener entity event support. I think it'd be pretty hype to support it and it'd make a lot of patterns much nicer. Afaik the plan for Bevy is to upstream bevy_eventlistener as a part of upstreaming bevy_mod_picking (see https://discord.com/channels/691052431525675048/1236111180624297984), and that's very likely to happen during the next release cycle, so I'd probably wait for that

vestal minnow
# thin hare are there any plans for [bevy_xpbd new name here] to be upstreamed in the future...

And yeah JoshValjosh's answer is pretty accurate. My personal goal is of course to get it upstreamed down the road, but there's still a few blockers and things we need to work on.

  • Some pretty fundamental physics engine things like simulation islands are missing (I plan on implementing this after the upcoming release though)
  • There's a ton of optimization we can do, the current performance just isn't good enough
  • There are still relatively major features that haven't been implemented, like joint motors (and a character controller if we want it first-party)
  • Ideally we don't want Nalgebra in our dependency tree since duplicate math libraries are confusing and add complexity; this is much trickier for Rapier, but we also depend on Parry currently
  • bevy_xpbd still uses XPBD, which has some legal ambiguities, although we did get an "I believe it should be okay" from one of the inventors. The next version replaces XPBD for contacts with another solver, but joints still use XPBD for now (might get replaced later on as well)
  • Bevy probably doesn't want an f64 feature flag, but we need some solution for large worlds. I plan on experimenting with built-in floating origin support for this.
  • I'm not sure if Bevy would like the way both Rapier and bevy_xpbd handle the 2D/3D split with a somewhat questionable crate structure. I think alternatives are worth trying out.
    bevy_rapier is currently more advanced in terms of performance and its feature set, but I feel like it just won't be able to get to the same level of nativeness and check all the marks, especially without compromising other consumers of Rapier itself. I think we have a better shot at that, but we'll just have to wait and see :P Rapier is also working on improving their docs and ergonomics
sleek thicket
#

shapes/volumes and casts were added without upstreaming, right? maybe it'll be possible to build on top of that in smaller chunks

vestal minnow
#

Bevy's casts don't return normals yet and are just for the bounding volumes currently, but that's my plan yea

sleek thicket
#

yeah, everything has a feature creep just in case it's needed, but the core that's commonly used by everyone isn't really that big

vestal minnow
#

for collisions we do need a ton of things, especially if we want to keep trimesh colliders and convex polyhedra (and convex decomp) which are pretty important for 3D

#

we don't need everything Parry has, but most of it we do unless we want to remove existing functionality in bevy_xpbd and drop support for some shapes

cinder summit
vestal minnow
#

Yeah for bounding volumes it wouldn't be very useful, but we probably want proper ray casting and shape casting for the primitives eventually

#

Can't wait to implement collider support for extruded shapes πŸ₯²

#

I feel like it shouldn't be too bad tbh

cinder summit
#

The implementation for SDF collisions is trivial at least, I just check for the 2d plane and the height separately πŸ€”

vestal minnow
#

Some should be pretty trivial to do at least with support mapping, like extruded capsules and ellipses, but a "proper" solution would probably do polygonal feature mapping for a lot of the shapes (identify the intersecting features and compute the contact(s) for them)

#

for extruded rectangles and circles you could of course reuse cuboid and cylinder stuff

zinc talon
# vestal minnow There's an [issue](<https://github.com/Jondolf/bevy_xpbd/issues/361>) for bevy_e...

Makes sense! I did want to pick your brain on something... eventlistener wants to send two events per collision, but right now xpbd only sends one for a pair. After trying a few things, my favorite solution was to just create a new event type, say EntityCollisionStarted, and impl EntityEvent for that. That way we can send CollisionStarted in the same way without breaking existing usages. Does that sound reasonable?

vestal minnow
#

I don't really like that we're currently sending events for every collision, since it leads to copying a ton of data unnecessarily

zinc talon
#

What's the solution for that? Requesting specific collision notifications or something?

vestal minnow
#

If we keep the per-pair collision events, we could add a component like ActiveCollisionEvents for enabling them for an entity (iirc Rapier has something like that), and for entity events we could potentially send events only for entities that have a listener in the hierarchy

thin hare
#

the main thing I'm seeing is that with certain values I haven't pinned down yet, the player and all of the joints have their transforms all set to infinity

vestal minnow
thin hare
#

That seems like a solid guess, here is the loop where I'm spawning the chain segments and anchors:

    for i in 0..chain_iterations {
        let previous_entity = next_entity;
        let translation = segment_translation(i);
        next_entity = commands
            .spawn((
                PbrBundle {
                    mesh: meshes.add(Capsule3d {
                        radius: 0.125,
                        half_length: 0.125,
                    }),
                    material: materials.add(Color::BLUE),
                    transform: Transform::from_translation(translation),
                    ..default()
                },
                RigidBody::Dynamic,
                Collider::capsule(0.5, 0.25),
                chain_layers,
                Name::from("Link"),
            ))
            .id();

        commands.spawn(
            DistanceJoint::new(previous_entity, next_entity)
                .with_limits(0.01, 0.05)
                .with_local_anchor_1(Vec3::Y)
                .with_local_anchor_2(Vec3::NEG_Y),
        );
    }
vestal minnow
#

It's a bit annoying to tune but basically you want to make sure that position1 + rotation1 * local_anchor1 == position2 + rotation2 * local_anchor2 in the initial state

thin hare
#

ahh, so the issue is likely with my initial rotations?

vestal minnow
#

If the bodies aren't rotated then it doesn't matter, you just need to ensure that the global positions of the anchors match

#

I'll clone that repo real quick and test things

thin hare
#

thanks, I'm trying to tweak it now as well, setup() is essentially the only relevant system at the moment

vestal minnow
#

Btw @thin hare you switched from Rapier, right? Rapier uses half-extents for cuboid colliders and things like capsule height, but xpbd uses full extents to match Bevy's shape constructors

#

so that could be related

thin hare
#

yeah, I'm still going through and making sure to correct some of those mismatches

vestal minnow
#

also setting the joint compliance higher like .with_compliance(0.01) makes it less stiff so it doesn't immediately explode and you can see what's going on

#

the chain parts also use capsule colliders almost the size of the player (just thinner), not sure if that's expected, and the anchors are Y and NEG_Y even though the chain goes sideways

thin hare
#

I was just being lazy on that front and assuming the colliders would rotate, and yeah I increased the segment size was because I was using the debug renderer at first and it seemed to panic if the colliders were too small

vestal minnow
#

hm, interesting that it panics, I'll have to look into that at some point

thin hare
#

it didn't look like it was an issue with bevy_xpbd itself, i believe the issue was in dims

#

i can check now actually

#
thread 'Compute Task Pool (0)' panicked at /home/spooky/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_math-0.13.2/src/primitives/dim3.rs:40:9:
assertion failed: value.is_normalized()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_xpbd_3d::plugins::debug::debug_render_axes`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
vestal minnow
#

ah yea I think that should be fixed once Bevy 0.14 is released, it's related to unnormalized values causing crashes for sphere gizmos iirc

thin hare
#

for the joint anchors are they relative to the colliders size, or just universal vectors

#

like if i have a cube with a width of 4, does Vec3::X translate to (2.0,0,0) or (1.0,0,0)

vestal minnow
#

they're just offsets for the attachment point in the local space of the given body

#

relative to the center of the body

thin hare
#

Cool, thanks!

abstract forge
abstract forge
#

@vestal minnow I’m not really sure what is causing the raycast result to end up so far away from where the cast originates as the max length should be capped as the max velocity.

vestal minnow
#

How are you getting the point?

abstract forge
#
let mut snap_to_surface = dir * (hit.time_of_impact - 0.001);
gizmos.arrow(origin + snap_to_surface + hit.point2, origin + snap_to_surface + hit.point2 + floor_normal, Color::YELLOW);
vestal minnow
#

That looks fine to me... I'm on mobile rn so it's a bit hard to read the code properly, but I'll check in a bit when I get back to my computer

#

One thing to note is that the points and normals are in local space, but if the shapes aren't rotated then it shouldn't matter

abstract forge
#

yea the cast are hard coded to Quat::default()

vestal minnow
#

of course it won't be exactly correct but at least the point shouldn't be far away like that

abstract forge
#

I mean it makes it right in the center of the player but it is still wrong

vestal minnow
#

is the time of impact large there then? could log the values to check

#

I don't see how the point would otherwise be so far away

#

It'd just mean that the velocity is large too for whatever reason

abstract forge
#

Time of inpact is 0

vestal minnow
#

okay... is the origin wrong?

abstract forge
#

well in that video without hit 2 the the begining of the ray is the origin

abstract forge
vestal minnow
#

I'll try to repro this

abstract forge
vestal minnow
#

Thanks! I'll try that

thin hare
#

Anyone able to point me in the right direction for making this chain less elastic? I need it to impede movement if the player goes to far but:

  1. Stiffer, less stretching of the chain
  2. Get rid of the snap back behavior
    I know a single distance joint will do that pretty reliably, but I want to be able to have the chain links have collision for wrapping around objects,

Joint code below

        commands.spawn(
            DistanceJoint::new(previous_entity, next_entity)
                .with_limits(0.01, 0.1)
                .with_local_anchor_1(Vec3::Y * 0.5)
                .with_local_anchor_2(Vec3::NEG_Y * 0.5)
                .with_compliance(0.001)
                .with_linear_velocity_damping(50.0)
                .with_angular_velocity_damping(10.0)
                .with_rest_length(0.05),
        );

thin hare
#

Also should this be a spherical joint? the docs mention those being good for chains so I'm trying to tweak that now

vestal minnow
vestal minnow
thin hare
#

Hmm, making the chain lighter makes things more elastic, going to try making the player heavier now

#

Heavier player is a little better but the chain is still very elastic

#

Lowering the compliance past 0.001 makes everything fly off with infinite values

brave crown
#

I've been working with ldtk, and previously hand-rolled my movement/collision. I was able to mashup the kinematic_character_2d example to get decent results, but I notice I can jump and stick to the walls 🀣

Effectively, the player character is the same as in the example (minus the max slope angle, which I omitted). Each tile from the LDtk level that's tagged a certain way got a rect collider and static rigid body attached.

Hoping there's some concept I can use to avoid this. Sticking to the walls is cute, but not desirable πŸ₯Ή

#

Not sure what the options might be. Maybe there's some sort of repulsion force I can put on the tiles to avoid penetration? Idk.

#

Now that I am here explaining the problem, I wonder if part of this is because the character is being Grounded when the shape caster hits the top side of any of the lower tiles making up the wall. πŸ€” Negative. Grounded is not present when sticking to the wall.

brave crown
#

Okay, unsurprisingly when I put the max slope angle back in, everything works as expected. Seems like I was incorrectly resetting the Y velocity in the collision system. I just set the max angle to something small and this works-ish. There's still a little stick, but not enough to be a concern.

#

Now I have one more issue to smoke out re: the Z values not working like they did for moving this between tileset layers. No clue how that broke. Possibly something with the Position/Transform syncing? Not sure.

glacial geyser
#

I'd like to use bevy_xpbd for pixel-perfect collision on a very large bitmap. Wondering if it makes the most sense to just impl AnyCollider instead of trying to compute a precise polyline/trimesh? It's for a worms-like game, so being able to quickly modify the bitmap every frame without needing to re-compute collider shapes would be ideal.

#

I suppose with AnyCollider you can only compute collisions with Self, so I would need my own top-level Collider wrapper if I wanted to have the bitmap and parry shape colliders interact?

noble junco
# vestal minnow Can't wait to implement collider support for [extruded](<https://github.com/bevy...

There is https://github.com/bevyengine/bevy/pull/13346 which adds Aabb support for them. That still needs reviews though πŸ˜…

GitHub

Objective

Implement Bounded3d for some Extrusion<T>

Solution

Implemented Bounded3d for all 2D bevy_math primitives with the exception of Plane2d. As far as I can see, Plane2d is pretty muc...

vestal minnow
vestal minnow
solid plank
#

Hi all, I have just started learning bevy and have been messing around with bevy_xpbd. Huge thanks to @vestal minnow for the awesome crate!

That said, I have a super beginner question.
I am attempting to make a game with ball collisions roughly similar to the game of pool/snooker, but I can't quite seem to get the physics right.

I have a minimal example where I have 1 ball which hits another ball with some backspin.
When the ball collides with the other ball I would like it to grip the plane it's on and spin back.

I am not sure if my physics setup is incorrect, or if this isn't really possible to achieve using sphere and cuboid colliders (since obviously in real life the balls aren't perfectly spherical).

If someone could point me in the right direction that would be greatly appreciated.

I have attached a GIF and the code I am using.

solid plank
zinc talon
#

Darn I was just about to suggest more bounciness

thin hare
#

Has anyone tried messing around with SoftBody physics in xpbd?

fiery mortar
#

Hi, any plans to support bigspace?

vestal minnow
#

There's already a fork with basic support, but afaik it doesn't work if you have multiple origins (like for multiplayer)

glacial nebula
vestal minnow
#

(also side note for y'all: I'm on a vacation in Rome until Sunday so I can't code and might not respond like normal)

hollow barn
#

I needed to upgrade to bevy track and alongside had to hack xpbd to work with bevy track. Biggest problem rn is deps - need a not yet merged branch of nalgebra and need parry to update to it. Otherwise needed fixes mostly to colors. Should I send a PR to the branch that you used for bevy track?

#

so it compiles locally with patch.crates-io, but also needs that for any consumers ofc.

#

also can't upgrade to latest parry, works with v13 tops

#

or like, one can, but I don't know enough physics for that

vapid monolith
#

how do i prevent explosive behavior? i already have restitution at 0, so that shouldnt be the issue

cinder summit
#

Depends on whats causing the explosive behavior

vapid monolith
#

maybe restricting max lin vel could work

#

but that doesnt seem like really optimal

cinder summit
#

You stop explosions from overlapping by not overlapping them ... I've heard mentions that explosions should be less bad with the new solver (which we hopefully get soon) tho

vague pebble
#

Question what can make a collider sometimes not work? I am pretty sure I am not movin it via transform

#

Man this is some bologni

#

This guy be like not working but then when I videotape him he starts workibng

cinder summit
vague pebble
#

He doesnt collider

#

like i move him via velocity he colliders

#

but via forces he bugs out idk

#

OHHHH

#

i figured it out it has something to do with adding forces

cinder summit
#

If it's related to forces it could have something to do with the physics running on a different clock than Update?

vague pebble
#

You are probable right I guess the force system runs after update perhaps

#

Need to check xpbd systems

cinder summit
#

By default xpbd runs a 60Hz loop in PostUpdate. This means that if your FPS is lower than 60, it runs multiple physics updates per frame sometimes, if it's higher than 60 it doesn't run any physics updates some frames, and if it's roughly the same it can go either way, or remain perfectly stable for a while

vague pebble
#

oh i see

#

I should probably utilize fixed step in this case then no, specially since i am using a pid controller for my hitboxes and boio there are a lot of them

cinder summit
#

FixedUpdate (or well all schedules in FixedMain I guess) is generally the way to go. I'd really like to see the remaining footguns removed and for it to become the standard approach. It hasn't been moving along super fast tho since it's mostly just networking people pushing for fixed step stuff

vapid monolith
#

Also why does that even happen? Cant i just disable that specific mechanism or scale it down?

#

If its not restitution what else might be responsible for this?

cinder summit
#

It's the penetration constraint that's doing them ... It just yeets things away from eachother to stop them from overlapping ... There might be various bugs in other systems involved that cause it

#

Jondolf fixed a whole bunch of issues on the new solver iirc, some of those could definitely cause overlaps in the right circumstances πŸ€”

vague pebble
#

It even detects the collision but just doesnt handle it

vapid monolith
#

should be a fairly easy fix i feel like

cinder summit
vestal minnow
# vapid monolith Also why does that even happen? Cant i just disable that specific mechanism or s...

In general, physics engines have to resolve overlap to have functioning contacts. Otherwise bodies could just sink into each other. The thing that is different is the approach used for solving the overlap.

XPBD solves contacts at the position level by moving overlapping bodies apart, and then updates the velocity based on the magnitude of the positional correction. Then it applies a velocity correction to account for restitution.

An impulse-based solver (like the upcoming one) applies an impulse to prevent further overlap, and also (typically) boosts that impulse based on the current penetration depth to solve the overlap.

The new solver should have less explosiveness and solve the overlap more smoothly. I might also expose more configuration options, like a maximum bound for the magnitude of the correction impulse.

vague pebble
#

Oh i solved it by increasing the collider size

#

godverdammt

vapid monolith
vestal minnow
#

It might be possible yes, but you'd need to plug into a pretty specific part of the solver to make it work properly

#

(brb in 5 to 10 minutes)

fringe mango
#

is there any way to filter collision events by the components that the two entities have? currently, the way im handling this is by doing queries of the components that i want and checking if the entities within the collision are part of that query, but because theres no order for the entities in a collision, i also have to check both ways. this seems a little hacky and i was wondering if there was a more idiomatic way of doing this

vapid monolith
vestal minnow
cinder summit
cinder summit
vestal minnow
fringe mango
#

and colliding entities made it so that every single frame two entities were colliding, the code was executed

fringe mango
# fringe mango is there any way to filter collision events by the components that the two entit...

as an example, heres what a version of my code looks like right now:

pub fn normal_damage(
    mut collision_reader: EventReader<CollisionStarted>,
    damage: Query<&Damage>,
    mut health: Query<&mut Health>,
) {
    for CollisionStarted(entity1, entity2) in collision_reader.read() {
        for (entity1, entity2) in [(entity1, entity2), (entity2, entity1)] {
            if let (Ok(damage), Ok(health)) = (damage.get(*entity1), health.get(*entity2)) {
                health.value -= damage.value;
            }
        }
    }
}

and here's something along the lines of what i want to do:

pub fn normal_damage(
    mut collision_reader: EventReader<CollisionStarted<Damage, Health>>,
    damage: Query<&Damage>,
    mut health: Query<&mut Health>,
) {
    for CollisionStarted(damage_entity, health_entity) in collision_reader.read() {
        let damage = damage.get(damage_entity).unwrap();
        let health = health.get(health_entity).unwrap();

        health.value -= damage.value;
    }
}
vague pebble
fringe mango
# vague pebble You can query for a marker component unique to that entity

lol funny enough thats actually exactly what i had before trying to change it around a little bit, heres the part of the code:

#[derive(Event)]
pub struct HitHurtCollision {
    hitbox: Entity,
    hurtbox: Entity,
}

pub fn get_hit_hurt_collisions(
    mut collision_reader: EventReader<CollisionStarted>,
    mut hit_hurt_collision_writer: EventWriter<HitHurtCollision>,
    hitboxes: Query<&Hitbox>,
    hurtboxes: Query<&Hurtbox>,
) {
    for CollisionStarted(entity1, entity2) in collision_reader.read() {
        // #1124043933886976171 message
        for (hitbox, hurtbox) in [(*entity1, *entity2), (*entity2, *entity1)] {
            if hitboxes.contains(hitbox) && hurtboxes.contains(hurtbox) {
                hit_hurt_collision_writer.send(HitHurtCollision { hitbox, hurtbox });
            }
        }
    }
}

pub fn normal_damage(
    mut hit_hurt_collision_reader: EventReader<HitHurtCollision>,
    hitboxes: Query<&Damage, With<Hitbox>>,
    mut hurtboxes: Query<&mut Health, With<Hurtbox>>,
) {
    for HitHurtCollision { hitbox, hurtbox } in hit_hurt_collision_reader.read() {
        if let (Ok(damage), Ok(health)) = (hitboxes.get(*hitbox), hitboxes.get(*hurtbox)) {
            health.value -= damage.value
        }
    }
}
#

i just thought it wouldnt be super convenient to have to attach the hitbox and hurtbox components all the time

vague pebble
#

Another way is to create a resource

#

Easier to acess multiple time in my opinion

#

Something like a hashmap with a name pointing to your entity

#

#[derive(Resource)]
pub struct HitboxAcessor(pub HashMap<String, Entity>);

fringe mango
#

hmm yeah maybe

#

honestly i think i prefer doing it this current way tho

vestal minnow
# fringe mango as an example, heres what a version of my code looks like right now: ```rs pub f...

I'm not aware of a much nicer pattern right now, no. I'm not really sure how we could nicely (and efficiently) add query filters for collisions like the API you proposed, although I would be interested if someone figures out a nice solution.

Something that we might add in the future though is entity events for collisions with something like bevy_eventlistener, which would allow you to listen for collisions for specific entities by just attaching event listeners for them

vague pebble
#

It even makes sense if the damage could work both ways

vestal minnow
vapid monolith
#

yep ive done so already :)

#

I just wasnt sure where to exactly modify it

fringe mango
#

so maybe it would actually make more sense to always have the Hitbox and Hurtbox components

fringe mango
vestal minnow
fringe mango
#

i think another thing that bothers me a little is that the collisions don't really have an order, so you always have to do some type of workaround such as for (entity1, entity2) in [(entity1, entity2), (entity2, entity1)]

vapid monolith
#

so it doesnt affect the other constraints

vestal minnow
#

But I probably still wouldn't recommend relying on a specific order

#

in case it's changed later on

vestal minnow
vestal minnow
#

I'm happy to answer things in the evenings but I literally don't have access to a computer so I'm a bit limited in what I can do currently :P

fringe mango
#

im having an issue where a collision seems to send two CollisionStarted events, is this intentional?

vapid monolith
fringe mango
vapid monolith
#

ugh ok

fringe mango
#

heres the code im using to test this btw

pub fn test_collisions(
    mut collision_reader: EventReader<CollisionStarted>
) {
    for _ in collision_reader.read() {
        println!("thing happened");
    }
}

running in update, and only two entities have collider components

vague pebble
#

For example if you are utilizing a trimesh collider that can occur. Because of the proximity of two vertices

vestal minnow
#

And are the entities in the same order in both events

#

Physics also runs at a fixed 60 Hz by default so it can sometimes run multiple times per frame, which in Update could look like it's firing twice (assuming the entities do actually stop and start colliding in between the physics frames)

vague pebble
#

Oh yeah that is something i meant to ask how can I make my schedule run at the same fixed rate as the physical engine?

#

BEcause fixeupdate in bevy is 64 hz

#

Should i just set it to 60?

vestal minnow
#

You can either add your systems to the actual PhysicsSchedule or configure physics to run in FixedUpdate and just use that

#

it's also possible to configure the physics time step

#

I'll pull up docs real quick

vague pebble
#

Oh man I would personally love you if you did so

vestal minnow
#

Running in PhysicsSchedule might be fiddly since you need to order your systems relative to actual physics systems or system sets to avoid conflicting queries or system ordering issues, so I'd probably run physics in FixedUpdate. That'll most likely also become the default at some point, at least once some of the remaining caveats are fixed

vague pebble
#

So just set it to 60 hz and chabam?

vestal minnow
#

You can keep it at 64 Hz too, physics doesn't have to be 60 Hz

#

One weirder thing that you might need is to configure Time::new_with(Physics::fixed_once_hz(64.0)) when running physics in FixedUpdate since you might get issues with two separate fixed timesteps (FixedUpdate and the engine's own default fixed timestep)

#

I'll most likely try to make it Just Workβ„’ in FixedUpdate for next release though

#

since needing to use the fixed_once_hz thing is kinda footgunny/weird

vague pebble
#

it is weird

#

My colliders go shabalabingbomm when the rates differ, but with higher fpss they dont. Hard to understand what is happening

fringe mango
# vestal minnow Do you also get `CollisionEnded` events in between or is it just two `CollisionS...

i believe it's just two CollisionStarted for the same two entities, and the entities are in different orders. printed lines are:

started: 3v1, 4v1
started: 4v1, 3v1
ended: 3v1, 4v1
ended: 4v1, 3v1
started: 3v1, 5v1
started: 5v1, 3v1
ended: 3v1, 5v1
ended: 5v1, 3v1

code to test:

pub fn test_collisions(
    mut collision_reader: EventReader<CollisionStarted>,
    mut collision_reader2: EventReader<CollisionEnded>
) {
    for CollisionStarted(entity1, entity2) in collision_reader.read() {
        println!("started: {:?}, {:?}", entity1, entity2);
    }

    for CollisionEnded(entity1, entity2) in collision_reader2.read() {
        println!("ended: {:?}, {:?}", entity1, entity2);
    }
}
vestal minnow
# fringe mango i believe it's just two `CollisionStarted` for the same two entities, and the en...

With the implementation in 0.4, I believe the entity order is based on the relative positions of the X extents of the bodies, and that can change when the bodies move relative to each other. The different order is treated as a different collision pair even though really it is still the same two entities.

This might(?) be fixed in the upcoming release since the entity order is always the same with my current implementation (lower ID always first).

fringe mango
#

is there any way for me to temporarily handle this in my code?

#

it does somewhat consistently fire two collision events, but occasionally it also fires only one :(

tropic forum
#

How do i get velocity before collision?

ps. Found the bug. I was using same entity and was confused why vectors the same after collision

vapid monolith
#

@vestal minnow if you have time, could you tell me if its possible to make something like a broad phase check if we are colliding with anything before spawning? i wanna have randomized spawning but idrk how i would do that without actually spawning the entity first

cinder summit
fringe mango
# vestal minnow With the implementation in 0.4, I believe the entity order is based on the relat...

decided to investigate this bug a little bit more, and in this test project i made, i noticed that the collision is only triggered twice when the projectile is moving towards the left. i also noticed that when shooting exactly left, the second collision event occurs when the two colliders touch internally, but the further up/down i shot the projectile, the closer the event was triggered when the two colliders were touching externally.

not really sure if this is helpful info but hope its of aid somehow πŸ‘

thin hare
#

Anyone have any ideas for what I can do to make this chain stop going wild? (it is a chain of colliders connected by distance joints)

cinder summit
thin hare
#

If the player moves back towards the anchor the chain flies around unpredictably, and on occasion this will cause the app to crash

cinder summit
#

Do the colliders in the chain have any mass? What are the properties of your distance joints?

thin hare
# cinder summit Do the colliders in the chain have any mass? What are the properties of your dis...
// Chain Segment
            let new_primary = commands
                .spawn((
                    PbrBundle {
                        mesh: meshes.add(Capsule3d {
                            radius: 0.125,
                            half_length: 0.25,
                        }),
                        material: materials.add(Color::BLUE),
                        transform: Transform::from_translation(spawn_translation)
                            .with_rotation(Quat::from_axis_angle(Vec3::Z, 90.0_f32.to_radians())),
                        ..default()
                    },
                    ChainPrimary,
                    RigidBody::Dynamic,
                    Collider::capsule(0.5, 0.125),
                    Friction::new(1.0),
                    CollisionLayers::new(
                        ColLayer::PlayerWidget,
                        [ColLayer::Terrain, ColLayer::Object],
                    ),
                    Segment,
                    Name::from("Link"),
                ))
                .id();

// Joint
            let new_final_joint_entity = commands
                .spawn((
                    DistanceJoint::new(new_primary, target_entity)
                        .with_limits(0.0, 0.6)
                        .with_local_anchor_1(Vec3::Y * 0.5)
                        .with_local_anchor_2(Vec3::NEG_Y * 0.5)
                        .with_linear_velocity_damping(1.0)
                        .with_compliance(0.0),
                    FinalJoint,
                ))
                .id();

visual sparrow
#

@vestal minnow this might have come up before, but with the rebrand coming up, how should I go about naming crates based on XPBD? Should I name them xpbd_foo and then rebrand them as well or already go for something like avian_foo?

#

Also: do you have a Kofi or something set up? I couldn’t find anything and would like to chime in something small as a thank you for your work πŸ™‚

thin hare
#

Second this, I would love to contribute to a kofi/patreon/github sponsor

tropic forum
#

Hello. I want to react to collisions before collided entity started moving;
I move fast, collide into enemy, get collision event - my velocity expected to be big vector, but target is full speed too after collision.

I want to capture moment when i have big velocity vector, but target velocity close to zero. How i can do that?

vapid monolith
#

i wish parry had support for regular polygons :x

#

it would be way better serialization wise instead of having to serialize all the points

#

wonder if its possible to do this yourself :v

cinder summit
#

You could contruct the colliders based on bevy_math's primitives, then serialize those, there's a impl IntoCollider<Collider> for RegularPolygon

vapid monolith
#

would have to impl a custom parry shape i guess

vapid monolith
#

misunderstood lol

#

yea thats an option, did that before but you end up having to sync those then

#

which is more annoying that wasting that bit of space lol

cinder summit
#

Yea, just load it from a different component if that exists, and only fall back to storing the points if you have no clue what shape it is

vapid monolith
#

actually might not be as hard to do as i thought

#

they already kinda have support for this

#

i remember xpbd makes a custom shape for ellipses too or smth

#

could also get away with converting the collider into a convex polygon on the fly

vestal minnow
#

oki I'm back from my vacation trip now, easing back into dev mode

vestal minnow
#

I should probably ping all the 3rd party xpbd crate authors when I do the actual rebrand πŸ€” and post a follow-up about the current state in the original rebrand issue

vestal minnow
vestal minnow
# vapid monolith i remember xpbd makes a custom shape for ellipses too or smth

Yup, ellipses have a custom shape since Parry doesn't have built-in support for them. A custom regular polygon collider should be pretty straightforward to implement too. It should be very similar to a convex polygon collider, but the fact that it's a regular polygon might allow some small optimizations and simplifications

#

I'll try to implement it now actually

carmine sluice
lavish orbit
#

yo, would it be possible to use a joint as a way to keep the camera close to the player?

#

for third person

vapid monolith
#

@vestal minnow do you know how i could make a collider for stellations? i feel like it would be necessary to create a compound shape by splitting off the triangles from the center polygon.. should i make a polyline or a trimesh from the vertices and then decompose?

#

(also im only really interested in doing that in 2d)

vestal minnow
vapid monolith
#

that was fast

#

:o

vestal minnow
vapid monolith
#

but ur saying that making a trimesh would be more optimal right?

vestal minnow
#

No not necessarily, I'd probably make a compound collider from triangles and/or other polygons (not the same thing as an actual trimesh)

vestal minnow
#

hmm I wonder if we should add built-in stellations for Bevy's regular polygon primitive

vapid monolith
#

if u do that you would prob need to do that for 3d polyhedra too

#

which is a pain iirc

vestal minnow
#

yeah we don't have a RegularPolyhedron either, might be worth adding

#

or ConvexRegularPolyhedron, i.e. just the platonic solids

vapid monolith
#

hmm yea

#

there would also be the question of formalization for stellated regular polygons; do you include depth or do you use a constant factor for that

#

actually i might be totally off, seems like they arent actually defined by two circles but their number of vertices and the step size (according to wikipedia)

vestal minnow
#

for 2D, it could be roughly like this

pub struct Star {
    pub circumcircle: Circle,
    pub vertices: usize,
    pub density: usize, // >= 2
}

where vertices and density are p and q of the SchlΓ€fli symbol respectively and share no factors (enforced on construction probably)

vapid monolith
#

hmm yea

#

always thought you could define them with two circles and the number of vertices which would get rid of the overlap issue

#

but apparently not

#

i guess as a simplification it would best to just represent them as regular polygons during collision and then render them correctly for now

vestal minnow
#

FYI y'all, I made a bevy-0.14 branch targeting =0.14.0-rc.2 (and actual 0.14 once it's released)

#

pretty sure it's blocked on Parry getting updated to support Nalgebra with Glam 0.27 though

#

so it has a local crate path for now

#

oh and it's just the 0.14 update, doesn't have the rebrand/rework stuff yet

#

I'm now finally trying to replace the god-awful ColliderStorageMap thing with component lifecycle hooks, I've been waiting for this :P

cinder summit
vestal minnow
#

RCs require that I think

#

didn't work without it

cinder summit
#

You can specify 0.14.0-rc or 0.14.0-rc.2 and it should work. It's important to include the .0 tho, since the rcs are for 0.14.0, not 0.14

vestal minnow
#

okay that works yea

hollow barn
#

so you could have a branch available with a disclaimer

#

seems like it should work soon

#

how's moving from parry looking?

#

is it still in plans?

vestal minnow
hollow barn
#

it did for me, I didn't have to fork parry.

#

lemme check when I get back to pc

#

you should have same version of nalgerba in your deps

#

but then have patches override

#

if you depend on different nalgebra directly then it'll only override yours iirc

vestal minnow
#

well I have this

[dependencies]
parry2d = { version = "0.15", optional = true }
parry2d-f64 = { version = "0.15", optional = true }
nalgebra = { version = "0.32", features = ["convert-glam025"], optional = true }

[patch.crates-io]
nalgebra = { git = "https://github.com/waywardmonkeys/nalgebra.git", branch = "support-glam-027", features = [
    "convert-glam027",
], optional = true }

and it's not working. I also tried using the same git override for Nalgebra in the dependencies

jade solstice
#

I think patch only works at the binary level, not within libraries

vestal minnow
# hollow barn is it still in plans?

Yeah I plan to work on it more and see where it ends up. I'll probably approach it more from the perspective of upstreaming geometric queries like ray casts, point queries, and so on to Bevy itself since that's wanted for Bevy anyway, and then the remaining stuff that is more controversial for upstreaming can maybe live in its own crate

#

It has been on the backburner for a while due to the xpbd rework, but I want to get back to working on it after 0.14 releases

vapid monolith
#

doesnt bevy still use an old version of glam anyways?

cinder summit
vestal minnow
#

it uses 0.27 which that branch adds support for

cinder summit
#

The features should be in the [dependencies] block and not in the patch one tho I'm pretty sure πŸ€”

vestal minnow
vestal minnow
cinder summit
#

That's not quite how the patch.crates-io thing works tho ... It just modifies how crates are fetched instead of using crates.io

#

The version needs to match what you're pulling in in dependencies too

jade solstice
cinder summit
jade solstice
#

it's better to say it only works in the top level Cargo.toml

cinder summit
#

Yea, it would be an absolute trainwreck if every level could do this πŸ˜‚

vestal minnow
#

Okay the patch works, but only if I make my own version of it targetting Nalgebra 0.32.5. The existing PR targets 0.32.3, because that's what Nalgebra's main branch uses, but they've already released 0.32.5 on a separate branch, and Parry uses that

hollow barn
#

the joy of dependencies

hollow barn
#

is there rfc for it already?

vestal minnow
#

Not really, and it's probably something better handled by a working group and implemented incrementally

hollow barn
#

yeah

vestal minnow
#

Like maybe a "geometric query" working group that implements all the standard queries, like contact queries, intersection tests, distance queries, closest point queries, point projection, ray casts, and shape casts

hollow barn
#

is it really controversial tho? bevy already has rudimentary ray/shape casts

vestal minnow
#

It's not controversial in the sense that I think there's reasonable consensus that we want these, but some of the details might be more controversial, like how we handle code duplication between 2D and 3D for GJK, Circle/Sphere, Rectangle/Cuboid, Triangle2d/Triangle3d, Segment2d/Segment3d, and so on

#

A lot of these queries can also be somewhat related and we basically need e.g. GJK and support mapping for some queries and shapes

#

So some kind of cohesive vision would be useful

#

And a working group could help with reviews and getting the implementation details right

#

Then for collision purposes we would also need support for things like convex polyhedra, a specialized triangle mesh representation, SAT helpers, a convex hull computation algorithm, convex decomposition, maybe voxelization...

#

And for the spatial query pipeline we need a good BVH

#

But these may be more controversial for upstreaming, at least until Bevy gets first-party physics (assuming it some day will)

hollow barn
#

how expensive is it to switch rigid body types between dynamic and kinematic?

vestal minnow
#

Changing the rigid body type shouldn't have any extra cost afaik

vestal minnow
vestal minnow
#

Looks like we can use observers to implement entity events for collisions pretty nicely, no bevy_eventlistener needed πŸ‘€

commands.spawn((
    RigidBody::Dynamic,
    Collider::cuboid(1.0, 1.0, 1.0),
    Observer::new(
        |trigger: Trigger<CollisionStarted>, mut query: Query<&mut LinearVelocity>| {
            let entity = trigger.entity();
            if let Ok(mut lin_vel) = query.get_mut(entity) {
                // Do something idk
                lin_vel.y = 100.0;
                println!("Entity {:?} started colliding.", entity);
            }
        },
    ),
    // ...
));
#

Doesn't have event bubbling of course but I don't necessarily want that for collision events anyway

junior flower
#

That’s pretty exciting
Not sure I like that naming collision with β€œtrigger colliders” in Unity

#

Though in this case I guess it works out lol

vestal minnow
#

ah wait this doesn't quite work like I thought yet since it's a general observer and doesn't target just itself

#

you'd need to add .with_entity(entity) too I think

vestal minnow
# vestal minnow Looks like we can use observers to implement entity events for collisions pretty...

yeah this would need to be written like this...

let entity = commands
    .spawn((
        PbrBundle {
            mesh: cube_mesh.clone(),
            material: materials.add(Color::srgb(0.2, 0.7, 0.9)),
            transform: Transform::from_xyz(0.0, 20.0, 0.0)
                .with_scale(Vec3::splat(cube_size as f32)),
            ..default()
        },
        RigidBody::Dynamic,
        Collider::cuboid(1.0, 1.0, 1.0),
    ))
    .id();

commands.spawn(
    Observer::new(
        |trigger: Trigger<CollisionStarted>, mut query: Query<&mut LinearVelocity>| {
            let entity = trigger.entity();
            if let Ok(mut lin_vel) = query.get_mut(entity) {
                // Do something idk
                lin_vel.y = 2.0;
                println!("Entity {:?} started colliding.", entity);
            }
        },
    )
    .with_entity(entity),
);

not sure if I like that observer components default to global observers

vestal minnow
#

of course observers added via app.observe() or world.observe() would be global by default though

#

we could probably add an intermediate abstraction for this, but having the component be global by default feels footgunny to me

junior flower
#

Not sure if this answers your question(?) but what I’ve worked on in Unity/Unreal (consumer titles) generally uses a mix of systems. Event-based stuff like β€œwhen the player reaches this point” is OnTriggerEnter in almost all cases, but things that need more detailed responses generally ends up being sweeps + some kind of priority sorting.

junior flower
#

I’ll see if I can find anything detailing similar systems. None of the stuff I’ve worked on has any public info.

I’m general, though, it’s β€œshape cast, register the collision with some manager + metadata, manager processes them in the proper order” where β€œproper order” is e.g. β€œthere’s a shield between the origin and this collision, so ignore it”

#

(I’d be willing to bet, though, that the majority of games don’t need to worry about it too much, fwiw)

#

You got any concrete examples? I’ll have a think. Even in ECS sometimes you’ve just gotta bite the bullet and process things serially

#

In between the two of those I guess: what you’ve got now and something you think will probably cause problems once you add it

#

A concrete example of a problem that we had and how we fixed it:

Shields would originally destroy projectiles (via OnTriggerEnter), which broke down for very fast projectiles that could overlap the player and the shield on the same frame

We changed it so that the shield was β€œjust another defence collider” and had the projectiles shapecast to be able to get ordered collisions

#

Ah, perfectly in line with the example I gave hehe

#

You can probably do the same with xpbd’s collision events as-is. I think it includes the toi? If it does you’d gather the relevant events, sort by toi, and then process them in order from there

vestal minnow
#

there's the penetration depth but collisions have no toi in that sense

junior flower
#

Jondolf can probably chime in here but I just looked and the events are only entity pairs. Maybe you can get the penetration amounts from collisions resource?

#

Ty πŸ™‚

#

Penetration depth doesn’t quite equal toi, but for simple shapes it’s probably close enough

#

For a sufficiently complex system you’re probably going to need a way to order the collisions in time (or as close as you can get to it; there’s always odd outliers like things falling down onto horizontally moving projectiles) and some way to register processors for those collisions so that they can be executed in order for each collision. I can’t off the top of my head think of how to do that in an β€œECS-y” way tbh. Maybe you can do something with one-shot systems or manually running schedules?

#

A coworker recommended I tell you to look at the Smash Brothers videos. He wasn’t specific but said they’ve got a lot of good information including stuff on collisions

#

Sec, googling the channel now. Sakurai puts out videos where he talks in great detail about how he thinks about games

sleek thicket
#
junior flower
#

Yes I think it’s that one. Sorry, on a train atm and don’t have very fast internet

#

Will do

#

Yes that’s the channel. One of the directors I primarily work with looooves to link those videos to people lol

#

The vast majority of stuff I work on is so heavily tied down with NDAs that we just can’t publish anything unfortunately 😦

#

Depends on the NDA. Sometimes they have β€œknow-how” clauses too which would cover inner working even without code

#

There’s so much cool tech that goes into modern games and I’m sure the vast majority of programmers want to share with anyone who’ll listen

#

The collision filtering/β€œdrop through” thing I made a PR for bevy_xpbd a while back was borne of me not being satisfied with the solution we used in one of our recent games and wanting to do it β€œright” haha

I need to send in a PR to rename that example, actually: it’s a two-way platform, but the file is named one-way oof

#

I guess so. I think that it’s a platform saves it. Would probably be good to separate it out into two so that anyone who just wants a one-way e.g. door doesn’t have to filter out the drop-through toggling code as well

#

I’d probably use a collider in the target area and make sure that all players are present to do something like that

#

You mean soft platforms?

#

Or one-way pathways?

#

I’m trying to think of what you mean but I don’t think I’ve actually played that many top-down games 0.o

#

Oh right right sorry

#

Right it’s 9pm and my train is finally arriving at my home station so time for me to collapse soon. Have yourselves good days/evenings/nights

#

I’ll have a look and poke some more coworkers to see if they’ve got any links etc I can share with you

granite pasture
#

hey everyone. regarding the collision started/ended eventreaders, i'm confused about the behaviour of when my player entity enters a sensor collider from the left side like in the video example. am i implementing it incorrectly?

glacial geyser
#

I'm wondering if it's possible for SpatialQuery::project_point to not project on to sub-colliders of a compound collider? In this video, the circle is the projected point where solid=false. It turns red when is_inside, otherwise it's green. My desired behavior is for the circle to always be on the edge between gray and black here.

cinder summit
#

@vestal minnow What exactly is the plan for 0.14 releases? Will we get one release with lots of changes, or a 0.13 -> 0.14 release with few changes, and then the whole rework? πŸ€”

vestal minnow
#

In terms of the rework, I just made an avian branch based on the bevy-0.14 branch. I'll make branches (and PRs) for the new stuff targeting that branch, and then at the end I'll merge all of that to main

#

Already made a rework-structure branch that has most of the new module structure and some other stuff

#

After that's merged to avian I'll try to somehow work the new solver, CCD, and so on into logical mergeable chunks

#

unless I just... make one mega PR lol

vestal minnow
# glacial geyser I'm wondering if it's possible for `SpatialQuery::project_point` to not project ...

I don't think that's really possible, at least with SpatialQuery. Parry represents the compound collider as just a Vec with all the sub-shapes (and some acceleration structures), To project onto a specific one, you'd have to manually get that shape and do the projection onto it yourself.

What you could do (if possible) is something where you have a completely separate collider for the shape you want to project onto, maybe as a child collider

#

Hmm, or in this specific case you could maybe also do point projection onto just the AABBs of the colliders, assuming that the collider is axis-aligned. But IIRC we don't have a SpatialQuery method for that yet

hollow barn
#

avian is new name for the lib?

vestal minnow
#

That's the current top candidate and very likely final name, yes

#

The logo/banner looks like this (might still get minor tweaks)

#

fancy lines depicting water ripples courtesy of @cinder summit :P

glacial geyser
edgy nacelle
vestal minnow
#

Kinda true but also not πŸ˜› Fluid dynamics is not something I have concrete plans for, but I did already implement a very basic but somewhat functional integration with Salva one weekend
#off-topic message

vestal minnow
#

Thought it'd be good to have a coherent overview there as well, not just in bits and pieces on this Discord :P

thin hare
#

After generating a collider with an AsyncCollider is there a way to get the size of it? like if i generate a collider for a cuboid of an arbitrary size am I able to fetch the extents of that computed collider?

vestal minnow
thin hare
#

Perfect!

vestal minnow
#

the position you give doesn't matter if you're interested in just the size

thin hare
#

No I think this is exactly what I needed

#

another follow up question, If I generate a collider for a simple shape, like a cuboid, i'm assuming there is no performance implication? Like it would functionally be the same as manually adding a Collider::cuboid

vestal minnow
#

Like, if you gave an entity a mesh with a Cuboid shape and then used AsyncCollider to generate a collider for it?

thin hare
#

Yeah

vestal minnow
#

That isn't quite the same thing functionally, because the mesh created from the Cuboid doesn't technically know it is a cuboid, it just becomes a triangle mesh (Mesh) formed by vertices and indices. And similarly when a collider is generated from this Mesh, it doesn't actually know that it resembles a primitive shape based on the input, so it becomes a triangle mesh collider

#

(or it uses convex decomposition depending on your configuration)

#

A triangle mesh collider is less efficient than primitive shapes like cuboids, and it also has no real volume because the triangles are effectively infinitely thin, which is more prone to stability issues

thin hare
#

So for a simple cube would a convex hull be more performant?

vestal minnow
#

Collider::cuboid would be best, but yes a convex hull is also better

vague pebble
#

Question let say I want to make a collider that follow along an animation, should I make it a child of the bone or is better to point out his global transform and move it kinematically?

#

I dont know how inherited transforms are handled in the physics system

vestal minnow
#

I'm not too familiar with bone setups and how this is typically handled, but child colliders do currently move with their parents, like how transforms normally work in Bevy

#

Rigid bodies as children of other entities are more cursed and I generally don't recommend using them

#

But yes for colliders, transform propagation should work properly

vague pebble
#

What I did was create multiple dynamic bodies, and move their velocities according to the global transforms. But it feels a little heavy.

#

I was between that and kinematicbodies.

#

Dont know which one to chose

vestal minnow
#

with kinematic bodies you'd at least need to handle collisions manually, and the built-in joints wouldn't really work

#

depends on what you need

vague pebble
#

my goodness

#

I was right them boss?

#

Here was I thinking it was overenginnering

visual sparrow
hollow barn
#

@vestal minnow til that bevy is a real word

#

and is bird related

#

and I pronounced it right heh

vestal minnow
#

yeah haha

hollow barn
#

tho I do want to pronounce it beview

vestal minnow
hollow barn
#

i never read that lol

tepid epoch
#

How can I do a manual intersection test between two colliders? Check if AnyCollider::contact_manifolds is empty?

vestal minnow
tepid epoch
#

Thanks πŸ™Œ

vestal minnow
#

np!

vestal minnow
carmine sluice
#

Are you okay if I promote this?

#

Also you should add this to Github Sponsors πŸ™‚

#

err, add this to Bevy People

#

Words are hard

vestal minnow
#

I'm not exactly sure what to do for the tiers and goals though, I guess I could also add the bronze, silver, and gold tiers for companies, maybe with the "I'll add your company's logo to the README of bevy_xpbd" or something

vestal minnow
carmine sluice
#

IME that's not why folks donate

vestal minnow
#

yup

#

I also don't really have any tangible goals like "I can work on this full time!" since I'll be in university for several years anyway :P

#

One thing I do need to figure out though is whether other Finnish people can legally sponsor me thonk or if I need a money collecting permit or something

#

Not sure if allowing Finnish people to donate is considered as "appealing to the Finnish public" even if I'm not specifically targeting them in particular

#

I've seen a couple of profiles do this "Do NOT donate to me if you are from Finland!!" thing but it feels weird

carmine sluice
#
vestal minnow
cinder summit
visual sparrow
#

If I cancel at some point, know that it is because I'm also a student haha

vestal minnow
#

Wow, thank you so much! The first money I've made from doing this in my eight-ish years of hobbyist dev haha ❀️

visual sparrow
#

I really appreciate your work. After years of using rapier (and nphysics, back in the day), your physics stuff was such a breath of fresh air. My day-to-day experience with Bevy wouldn’t be what it is today without your work, and I thank you for that ❀️

visual sparrow
cinder summit
#

Well that's simple ... Only colliders can collide with colliders thonk

#

If it has no collider it can't collide 🧠

#

But the more serious answer is that Sensor (or neither sensor nor rigid body) can't collide with anything (but can be found in spatial queries iirc) but do report collisions, while all rigid bodies can collide with eachother, except static-static doesn't do anything and kinematic doesn't have collision responses

#

I think anyway πŸ€”

vestal minnow
#

the fastest merge in the west

cinder summit
vestal minnow
#

the template and all the other ones use that so I followed suit πŸ˜‚

visual sparrow
# cinder summit But the more serious answer is that Sensor (or neither sensor nor rigid body) ca...

Thanks, that helped a bit! Could you expand on when I have to add a Sensor? I'm asking because in my code, I have some hitboxes and hurtboxes with Collider but without any RigidBody and they seem to report collisions the same way no matter if they have a Sensor.
Is it correct if I assume that a Sensor modifies the behavior of whatever it is attached to to "report collisions as you normally would, but do not try to solve the resulting penetration"?
Side note @vestal minnow, is it intentional that a Collider with no RigidBody and no Sensor is not drawn by the debug gizmos, but a Collider with Sensor is?

cinder summit
fickle ivy
hollow barn
#

I'd be careful

#

@vestal minnow eg EFF having their donation bank accounts available on website was classified as money collection

#

i'd at very least remove any mention of you being in Finland from github

#

@vestal minnow if you open an entity outside Finland (eg Estonia) you could do that freely tho

#

but ircs opinion was that being resident of Finland and having github sponsor is illegal

#

me and them are all not lawyers ofc lol

last panther
#

Hey @vestal minnow, what did you use for the speculative collision?
Or do you know any resources on implementing it?

vestal minnow
#

I don't know if it would be enough if I just added that warning like "Do not donate to me if you are Finnish"

#

With that, I would consider myself to be "clearly limiting my appeal outside of Finland", but of course ultimately I cannot prevent people from donating

#

As for removing mentions that I'm Finnish, that just seems kinda shady and like I'm just hiding something

#

Unless I guess you count the mention that I'm Finnish as "appealing to the Finnish public"

hollow barn
#

you never know with Vero

#

fwiw tons of people do that, but also might be that they are just lucky

vestal minnow
#

For now I just added that warning, my interpretation is that it should be enough. The Finnish wording translates more closely to:

You must have a money collection permit if the collection is directed towards Finland. The money collection is directed towards Finland if donations are intended to be received from the residents of Finland.
and I am explicitly stating that I don't want to receive donations from Finnish people. But yeah, all of this is hella ambiguous, so I'll probably look into it more still

#

I really wish we had a lawyer funded by the Bevy Foundation ferris_sob

visual sparrow
#

Wish I had a "perkele" emoji to react with. This is so silly πŸ™ƒ

hollow barn
#

there is little overlap between us law and finnish law

#

if you are in union you could ask union lawyer

#

this is employment related in some way

vestal minnow
# last panther Hey <@545959292281552928>, what did you use for the speculative collision? Or do...

My main reference is Box2D V3 (Box2c), and to a lesser extent Bepu and Rapier.

  • The speculative margin is the maximum distance at which a collision pair generates speculative contacts. This is unbounded for every rigid body by default, which eliminates almost all tunneling.

  • Each AABB is expanded in the movement direction based on the body's velocity, clamped by the speculative margin if it is bounded. (Box2D might have a way to avoid this expansion, but I haven't looked into it yet)

  • The effective speculative margin is the actual margin used for contact computation, and it is clamped based on the velocities.

// Compute the effective speculative margin, clamping it based on velocities and the maximum bound.
let effective_speculative_margin = {
    let speculative_margin1 =
        speculative_margin1.unwrap_or(*self.default_speculative_margin);
    let speculative_margin2 =
        speculative_margin2.unwrap_or(*self.default_speculative_margin);
    let inv_delta_secs = delta_secs.recip();

    // Clamp velocities to the maximum speculative margins.
    if speculative_margin1 < Scalar::MAX {
        lin_vel1 = lin_vel1.clamp_length_max(speculative_margin1 * inv_delta_secs);
    }
    if speculative_margin2 < Scalar::MAX {
        lin_vel2 = lin_vel2.clamp_length_max(speculative_margin2 * inv_delta_secs);
    }

    // TODO: Check if AABBs intersect?

    // Compute the effective margin based on how much the bodies
    // are expected to move relative to each other.
    delta_secs * (lin_vel1 - lin_vel2).length()
};
  • Use that as the prediction distance (max distance) for the contact computation.
let contacts = self.compute_contacts(
    &collider1,
    &collider2,
    effective_speculative_margin,
    // Only match contacts if warm starting is enabled.
    warm_start,
)?;
#
  • Now, when you're actually solving the contact (normal part, no friction), use the softness parameters only if the contact is penetrating. Otherwise it is speculative, and we bias the impulse to cancel out the velocity that would cause penetration.
#
pub fn solve_impulse(
    &mut self,
    separation: Scalar,
    relative_velocity: Vector,
    normal: Vector,
    use_bias: bool,
    max_overlap_solve_velocity: Scalar,
    delta_secs: Scalar,
) -> Scalar {
    // Compute the relative velocity along the normal.
    let normal_speed = relative_velocity.dot(normal);

    // Compute the incremental normal impulse.
    let mut impulse = if separation > 0.0 {
        // Speculative contact: Push back the part of the velocity that would cause penetration.
        -self.effective_mass * (normal_speed + separation / delta_secs)
    } else if use_bias {
        // Contact using bias: Incorporate softness parameters.
        //
        // 1. Velocity bias: Allows the constraint to solve overlap by boosting
        //    the constraint response a bit, taking into account the current overlap.
        //    This is known as Baumgarte stabilization.
        //
        // 2. Mass coefficient: Scales the effective mass "seen" by the constraint.
        //
        // 3. Impulse coefficient: Scales the accumulated impulse that is subtracted
        //    from the total impulse to prevent the total impulse from becoming too large.
        //
        // See the `softness_parameters` module for more details and references.

        let bias = (self.softness.bias * separation).max(-max_overlap_solve_velocity);
        let scaled_mass = self.softness.mass_scale * self.effective_mass;
        let scaled_impulse = self.softness.impulse_scale * self.impulse;

        -scaled_mass * (normal_speed + bias) - scaled_impulse
    } else {
        // This is useful for a "relaxation" phase which helps get rid of overshoot.
        -self.effective_mass * normal_speed
    };

    // Clamp the accumulated impulse.
    let new_impulse = (self.impulse + impulse).max(0.0);
    impulse = new_impulse - self.impulse;
    self.impulse = new_impulse;

    // Return the clamped incremental normal impulse.
    impulse
}
#
  • Restitution is currently applied after constraint solving in a separate phase. The important thing here is that you store the relative speed along the normal from before contact solving (like when generating the constraints), and also check that the maximum applied impulse is non-zero to account for speculative contacts. See Box2c's restitution implementation.
#

I hope I didn't miss anything important πŸ˜… I did have to remove a couple of comments and small unrelated details

#

Oh and self.effective_mass here is what Box2c calls normalMass, it's the inverse of K, which mathematically is derived from the Jacobian using K = J * M^-1 * J^T where M is a mass matrix and ^T denotes a transpose. You don't need to worry about that implementation-wise though, Box2c has the formula for K

last panther
#

Oh wow this is way more than I was expecting, thanks

vestal minnow
#

No problem πŸ˜…

tropic forum
#

@vestal minnow hello. im trying to get collision event right after it happend but before collided entity started moving.
What i mean (dont pay attention to logic, just telling whats going on):
body(A) moves towards body(B)
body(A) crashes into body(B). Body(B) flies away
I apply damage calculated from impact power and if body(A) velocity ~ 100 and body(B) velocity == 0 then body(B) gets huge damage while body(A) gets minimal damage from impact;

But:
when i react to Collision event, body(B) already have velocity close to -100 but i expect it to be 0;

How i can workaround this problem?

vestal minnow
vestal minnow
#

np πŸ™‚

tropic forum
#

@vestal minnow i managed to get valid velocity of both items, but now i get 3-4 invocations. I think im doing something wrong:
system registration in 1st screen
system in 2nd screen
logs after collision in 3rd screen

p.s. sorry for useless information on screen. But i wanted to show Res<Collisions> and is_first_occurence

vestal minnow
# tropic forum <@545959292281552928> i managed to get valid velocity of both items, but now i g...

Hmm so this might be because the collision detection is run at every substep in xpbd 0.4, and the collision might be getting solved over multiple substeps, so it's active for several runs of that system. This will be different in the next release though, which could potentially fix the issue...

I'm not sure what would be the best workaround, but you could maybe check if contacts.total_normal_impulse is zero to determine if it's the first substep

#

(I think you could also use this impulse to determine the impact strength in the Collision event like normal, instead of trying to determine it from velocities, unless you want to compute the impact in a custom way)

tropic forum
#

@vestal minnow thanks for suggestions. But for some reason normal impulse is always 0.0 for me

vestal minnow
#

hmm okay

tropic forum
#

how i can try new release now? Should i change something in my code or just use master branch from github

vestal minnow
#

It's not released quite yet, but should come in tandem with the Bevy 0.14 release

vestal minnow
# tropic forum <@545959292281552928> thanks for suggestions. But for some reason normal impulse...

Okay other options for scuffed workarounds that could maybe work

  • An IsFirstSubstep(bool) resource that you set to true in the PhysicsSchedule before the substepping loop with .before(PhysicsStepSet::Substeps) and then set to false at the end of your crash_into_smth system

  • Go back to what you were doing before I suggested PostProcessCollisions, but make a PreviousVelocity component that you update for every rigid body before physics runs, and then use that instead of LinearVelocity

#

I really wish the new solver stuff was released already though, I think all of this would be so much easier ferris_sob

tropic forum
#

holy sh... this looks like a solution. I'll go try to implement it. I'll let you know how it ended

quartz heart
#

Trying out the avian branch with the current release candiate, but getting a strange not a bundle compile error:

`(MaterialMeshBundle<bevy::prelude::StandardMaterial>, RigidBody, Collider)` is not a `Bundle`

I really want to try the new solver, also tried the current release branch (of bevy) but that panicks at start.

I guess I just need to wait...

vestal minnow
#

That branch doesn't have the new solver just yet, I'm in the process of making PRs to add it in chunks though

#

I have this massive local branch with over 50 commits over several months that I'm trying to break up into PRs πŸ˜…

quartz heart
#

That sounds like a pain...

#

btw. really great logo and new name 😊

tropic forum
quartz heart
vestal minnow
# quartz heart How stable is the new solver? Is it close to what rapier currently does?

I haven't had time to do comprehensive comparisons with Rapier yet, but yeah, it's pretty close. Box2D V3 has been my main reference though, so it's probably the closest equivalent stability-wise.

You can see the TGS Soft solver and how it compares to other solvers in Erin's Solver2D video. I have the pyramid and some other samples replicated as well, there's an old video of that here and others sprinkled elsewhere on the Discord probably :P

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

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

β–Ά Play video
#

Some big differences from the old XPBD contact solver are:

  • There's significantly less drift, and bodies settle down better. Previously things like the pyramid would just drift and collapse.
  • Less substeps are needed for stability, which gives you better performance as well.
  • Overlap is solved more smoothly and softly, which reduces explosive behavior.
  • Contacts can overall be softer; this is a trade-off, but it's pretty important for stability. The softness can also be tuned, unlike before.
  • Speculative collisions mean that there should be essentially no tunneling by default, outside of overlap caused by contact softness. This should be pretty huge.
  • Narrow phase collision detection is only performed once per frame instead of once per substep, which gives a major performance boost. With XPBD, I think this would've caused stability issues (iirc I tried). Typically it would also increase tunneling, but with speculative collision it's not an issue.
#

And then the narrow phase rework also fixed several long-standing collision (event) bugs, and an impulse-based solver is in some other ways nicer to work with too, like you just have the contact impulses instead of having to compute them separately (users could also modify them technically)

#

Oh and triangle mesh colliders should be less buggy, both because of Parry updates and because I'm adding (optional) contact skins / collision margins like Rapier, which let you add artificial thickness to colliders, which can help with perf and stability in some cases

#

One thing that Rapier has and I don't is a block solver for 2D contacts, meaning that it can solve two contact points simultaneously, which helps give it some really stable box stacking; this is pretty niche though (Box2D even deliberately removed its block solver for SIMD optimizations) and 2D-only for now, because solving just two contacts at once in 3D can cause some other stability issues

quartz heart
#

And all of these also apply to 3d?

vestal minnow
#

yes

quartz heart
#

I can’t wait to give it a try bevy

vestal minnow
#

hehe I can't wait to get it released :P

#

I still have some annoying issues with a couple of new joint things I've been wanting to add, but if I can't get them working then I might just leave them for the next release to not delay things

#

hmm tomorrow I think I'll actually focus on getting everything else PR'd and merged first and leave the joint stuff last since it's overall less important and more WIP

quartz heart
#

That would be great, really want to try it, it will be targeting the 14 rc correct?

vestal minnow
#

Ah the avian branch didn't compile for you right? So it's currently actually targeting the Bevy repo's release-0.14.0 branch, because rc.2 had a serialization bug which was making my CI fail. It should be fixed in rc.3 which to my understanding should be getting released very very soon

#

once that's out it will target the rc again

#

iirc Francois mentioned that rc.3 is blocked on at least this, which now has two approvals already

edgy light
#

and ideally someone backporting the observer PR to the 0.14 branch

quartz heart
quartz heart
#

Ok have it working targeting:

bevy = { git = "https://github.com/bevyengine/bevy", branch = "release-0.14.0" }

(which is the same branch the avian branch is targeting)

vestal minnow
#

Got asked about how much the new solver will help with the tendency of overlapped spawning being explosive (and deep overlap just causing issues overall), so I thought I'd share a comparison here as well

Old solver:

#

It's also a lot more configurable than before

visual sparrow
true hearth
#

How supported is it to have my own system inside the SubstepSchedule that modify ExternalForce?

vestal minnow
#

You need the system to run before SubstepSet::Integrate

#

Note that the system sets and ordering will change a bit in the next release though

true hearth
#

I see, thanks. But would something similar still be possible in the future?

quartz heart
# vestal minnow New solver:

Very curious to test how the new solver handles colliders changing scale over time.

Currently it leads to explosions, hopefully the new solver will handle it more graceful.

For best stability would the size change need to happen in fixed update ?

vestal minnow
#

in the next release

vestal minnow
#

But yes it should be more graceful

#

I'll actually test that in a bit

vestal minnow
#

just changing scale in Update here

#

(newly spawned boxes always have the same initial size in this demo)

quartz heart
#

It’s looking very promising!

vestal minnow
#

I had an annoying bug while porting my old code that caused offset centers of masses to make bodies glide in the air and behave more like airplanes πŸ˜‚ managed to fix it though

#

I'll update some examples and docs, and do a couple more API tweaks, and then make that PR for the new solver

#

should hopefully be ready later today, and if not, then tomorrow

vestal minnow
#

hmm, not sure what to do for the KCC examples since they used a (bad) position-based collision solve which is a lot more annoying to do now

#

ofc a collide-and-slide type thing would probably be better, but idk if I should revamp the examples that heavily

edgy nacelle
#

What's a KCC?

vestal minnow
#

kinematic character controller