#Avian Physics

1 messages ยท Page 3 of 1

royal helm
#

just been busy with other stuff

#

I'll just do it as soon as the clean up PRs I have are in, I'd like to more solidly separate concerns about the physics world and the controller's state anyways, which this should be useful for finding the stragglers

vestal minnow
#

Btw are you aware of anything that is currently missing in bevy_xpbd but would be required in bevy_mod_wanderlust? A few days ago we added contact queries (like Parry's contact) since the character controller apparently needs it, and I was wondering if there's anything else that's been missing

royal helm
#

I don't think so, the main one was just shapecasting/raycasting and then contact manifolds

#

I just have a shoddy implementation of penetration correction inside the controller which is why I need the contacts

#

the raycasting is mainly used for sampling of normals since shapecasting is a bit iffy on that

#

Tbf I think I could still make it work without raycasts or the contacts, it just makes it more robust to weird colliders

vestal minnow
#

Cool, it'll be nice to have a proper character controller to suggest to people as an option since it's a pretty common request

#

No hurry though, we probably also need 0.3 to be released first :P

severe urchin
#

how ready is the child colliders pr? i have a bunch of code i'm standing by to remove once that lands. worth me giving it a try already?

#

i have dynamic rigidbodies that i want to additionally give large sensor colliders to, denoting how far their gravity field extends

vestal minnow
#

I think that should work fine already. The main issues are with handling arbitrary nesting in a stable way (GlobalTransform causes issues...)

#

But yeah a RigidBody with direct children shouldn't have any issues

severe urchin
#

ok i'll give it a go, thanks

royal helm
#

abstracting colliders is going to be difficult

vestal minnow
#

abstracting? (in this context)

royal helm
#

for the controller I mean

#

just annoying I guess

vestal minnow
#

oh I thought you were talking about child colliders lmao

#

which is probably enough for now since we don't really have other proper collision detection crates

#

although I kinda want to experiment with it eventually, could even try implementing Bevy's primitive shapes RFC and use it for some collider shapes

#

(not sure if that'd make sense but could try)

shell ermine
#

though I think looking at it it might be better to make the xpbd and rapier features be separate crates

#

so that you can push out a release for the main crate without having to wait for both xpbd and bevy_rapier to release updates

royal helm
#

Honestly I still think an interop crate for all these physics libraries would be a good idea

#

It isn't really any individual thing, but having to re-implement several things because each library has its own slightly different way (or just type) to do the same thing isn't really great

#

I'm already essentially writing one because controllers are a bit too deeply entwined with the physics engines guts

vestal minnow
#

How would you implement an engine-agnostic collider type like you mentioned?

royal helm
#

Probably just have an intermediary type that mirrors the shapes the libraries have

#

either that or just have 1 "source" collider type from one of the physics engines

cinder summit
#

I mean all the features come from parry, the biggest issue would be that they're both different component types, since parry obviously doesn't #[derive(Component)]

carmine sluice
cinder summit
#

Very true

shell ermine
#

they both use parry primitives

royal helm
#

sure for now

cinder summit
#

We really need bevy to get something to describe colliders, otherwise we can't import physics from gltf files either ๐Ÿค”

vestal minnow
#

for now

royal helm
#

the problem comes from migrating

#

which is why I think a mirror type would just be better long term

shell ermine
vestal minnow
#

would be glam based ofc

royal helm
#

so theres a bit of a distinction here

#

we could precompute a decomposition of each basic shape I guess

shell ermine
#

just use sdfs for everything /s

royal helm
#

but that's still not great because the decomposition might be too low or high resolution

carmine sluice
carmine sluice
vestal minnow
#

and some spatial subdivision/voxelization stuff

vestal minnow
vestal minnow
royal helm
#

yes, but right now there is a distinct "this shape is what the collider will be"

#

because we have a separate Collider type

#

if you add a torus as a collider to an entity and it comes out being a pancake then it'll be a bit confusing for some

#

so mostly there does need to be some sort of "IntoCollider" thing

vestal minnow
#

yeah what I was imagining is that the new Collider would basically be an enum (or store an enum) and then each variant would contain a shape like Collider(ColliderShape::Ball(Ball)) where Ball would be a primitive shape

royal helm
#

gotcha, yeah, that was more my idea as well

vestal minnow
#

I mean that's just parry's TypedShape I guess

#

just with shape primitives from e.g. bevy_geometry

royal helm
#

I'm also a bit unsure how we can even generify calling methods like cast_ray between libraries

#

It feels like the interop crate itself would have to implement the integration rather than the other way around

#

because how do you query what you need from the ECS world?

vestal minnow
#

yeah I'm not sure if stuff like that can be generalized nicely

#

the APIs + implementations can be so different

#

I guess again there could just be an official collision detection + spatial query plugin that everything uses

#

would still be physics-agnostic maybe

#

or idk

#

I wonder if I could plug in Rapier inside bevy_xpbd just for the solver ๐Ÿค”

#

very unnecessary ofc but just to test modularity and such

vestal minnow
royal helm
#

it still won't help with what I need to query in any given system

#

since you can't query for a trait resource

#

id have to know beforehand that I am using rapier or xpbd

#

which kind of defeats the point

vestal minnow
#

yeah true

royal helm
#

1 sec

#

I might have an idea on how to fix it but it seems cursed as fuck

vestal minnow
#

sounds great ferris_spooky

shell ermine
#

I didn't consider that oxidized_navigation only used the collider shapes and voxelized them so it was pretty simple to make generic

#

while a character controller needs way more integration

royal helm
#

I mean hmm, this could work it'd just require a lot I think

#

I was thinking of having the RapierSystemParam just be a decomposed SystemParam in a way

#

where rapier sets the specific component ids and then constructing the final SystemParam out of that

#

but it seems a bit too dynamic

#

or maybe "deferred" system param initialization would be a better term?

#

I guess that is just what SystemParam::State is in the first place

#

eh, maybe this won't work

#

since SystemParam isn't object safe

#

yeah I don't really know what to do here, the only other option I can think of is having a "type override"

#

where for interop you have a file you use backend::*;

#

but that seems finnicky as all hell

vestal minnow
#

yeah idk if it's possible to generalize functionality like cast_ray in a meaningful and robust way

royal helm
#

I mean it should work the same given the same inputs to any physics engine

#

it's just the type/api level that is finnicky

vestal minnow
#

yeah API level is mostly what I meant

#

but there's also query filters, weirder properties like "solid" and "stop at penetration"...

#

which aren't necessarily shared across engines

#

(although in our case most of them are because parry)

royal helm
#

query filters I don't think should be hard to generify

#

they are effectively just |entity: Entity| -> bool {} closures

#

with possibly added state

#

so you could generify that with just a

pub trait Filter {
    fn test(&self, entity: Entity) -> bool;
}
vestal minnow
#

could maybe include ECS access in some implementations

#
  • filtering by collision layers can be separate
royal helm
#

I think the best bet for cast_ray is just setting a convention and a trait

#

as a physics library export a common type like SpatialQuery that is a SystemParam and implements SpatialQueryMethods

vestal minnow
#

yeah that could work I guess

#

I just feel like you will pretty much always need some manual integration for each engine since the APIs can have different requirements and the data can be formatted differently (local or world-space normals?)

#

so I'm unsure how useful an interop crate that covers things other than basic data types would be

royal helm
#

well the point is that the libraries themselves would deal with that to conform to the common apis

#

otherwise the alternative is every user that wants to switch physics engines has to do that themselves

#

which essentially means you are vendor locked to one

#

(unless you want to undergo a massive amount of work yourself to migrate your project)

#

I mean other engines already do this, dealing with stuff like local vs world space normals is just part of integration

vestal minnow
#

yeah you're right, I forgot how interop crates are meant to work lmao

#

I need sleep

royal helm
#

but yes at the very least common data types would be incredibly useful on their own

#

because they are the things being stored in components

#

glam for math types, Collider enum that is shared across bevy libraries would make interop/switching significantly easier

vestal minnow
#

for something like Rapier, wouldn't a separate Collider add significant overhead? since it would internally need to convert it for parry

royal helm
#

for heightfields/trimeshes it would double the memory overhead

#

or well for all colliders yes, but most are negligible

#

performance overhead not as much

#

but could always do some stuff to mitigate that on our end as well

#

but yeah interop generally will increase memory cost

cinder summit
#

@vestal minnow I'm considering implementing SDF collisions, but I have no clue how I would go about wiring that up to bevy_xpbd, seems like it wouldn't be as simple as making a new collider type in parry that's for sure ๐Ÿค”

vestal minnow
#

it would probably require a separate collider component if it's not possible to make a custom collider type for parry

#

but if you had that SdfCollider working, you could then make a custom narrow phase (only for the SDFs, the normal narrow phase would remain) that computes the collisions, and then you'd insert the contacts into Collisions

#

the solver currently doesn't use Collider directly anywhere so it would work normally

#

same with the broad phase, if the entities have ColliderAabbs and other required components, it should work even without Collider

#

So basically, just find a way to somehow compute SDF contacts, and then add them to Collisions, and everything else should probably work

#

*with a reasonably sized grain of salt

cinder summit
#

Hmmm, that seems fairly doable ... And it would require custom SpatialQuery stuff I guess ๐Ÿค”

vestal minnow
#

yeah, custom spatial query stuff

#

that might be a bit more painful

cinder summit
#

Also an interesting idea: a floating character controller could skip shapecasts and just use the SDFs

#

Might even be able to make something really fancy and apply a cone/cylinder beelow the player to the geometry so you always get correct distances, than some hacky best guess ... Maybe two or more different shapes if you want to have inverse kinematics that looks right? ๐Ÿค”

royal helm
#

I mean that isn't really any different from shapecasting

#

in that scenario

cinder summit
#

The thing with shapecasting is that we don't update spatial query stuff every substep

#

Which means you can't get a truly accurate float, and there's a bunch of weirdness with the shapecasts from parry that always ends up causes unexpected behavior if you throw it an edge case

vestal minnow
#

(especially without the incremental updates lmao)

cinder summit
#

It's still faster without the incremental updates tho ๐Ÿ™ƒ

#

If only they just worked

#

But it would just generally not be worth it. Especially when just shapecasting once per tick nets me a nice 60% server load :')

#

Before I fixed the incremental update my game wouldn't even run with these numbers tho

cinder summit
#

Ever since I updated bevy_xpbd so I could implement the one-way gates I've been able to walk trough my terrain ... Is this an intended feature from some improved contact stability stuff? thonk

#

If I have a plane/box and a 5m radius trimesh which is half above and half below the surface I can just walk straight trough it, and then sometimes get stuck on some non-existant geometry inside ... Very odd

cinder summit
#

@vestal minnow Is there anything I should keep in mind to make sure my collision logic can provide stable contacts? These sdf collision seem to all really just be point cloud-sdf collisions, except you can give the points radii and snap them to the surface cheaply (even repeat that procedure to get more stable contact points I guess?)

vestal minnow
# cinder summit <@545959292281552928> Is there anything I should keep in mind to make sure my co...

The most important thing is that the contact points and normals are valid, but if possible, it's also good to add collisions that are nearly penetrating but not quite, since the non-penetrating state can turn into a penetrating state mid-solve because of other constraints moving bodies around. If there's a way to get actual contact manifolds instead of a single contact, then that's a plus as well

#

I'm not familiar with the actual sdf contact logic though so idk what's possible

late moat
#

hi, I'm struggling to make a grounded check for my platformer character. Do shapecasts not inherently check that the entity is not itself?

vestal minnow
#

(it's actually .without_entities, oops)

late moat
#

I'm not able to get it to detect the ground. This is my code for making and testing the shapecast:

fn spawn_player(mut commands : Commands, assets : Res<AssetServer>){
    commands.spawn((
        SpriteBundle{
            texture : assets.load("sprites/circle.png"),
            transform : Transform::from_translation(Vec3::new(64.,128.,5.)),
            ..Default::default()
        },
        LockedAxes::new().lock_rotation(),
        RigidBody::Dynamic,
        Collider::ball(8.),
        Restitution{coefficient : 0.0 , combine_rule : CoefficientCombine::Min},
        Player{ max_speed: 64., accel :  6., decel : 10., jump_force : 100., grounded : false, ground_max_distance : 0.1},
        ShapeCaster::new(Collider::ball(8.), Vec2::ZERO, 0, Vec2::NEG_Y)
    ));
}

fn player_ground_check(mut player_query : Query<(&mut Player, Entity, &ShapeHits)>){
    if let Ok((mut player, ent, hits)) = player_query.get_single_mut(){
        player.grounded = false;
        for hit in hits.iter(){
            if hit.entity == ent { continue;}
            let dist : f32 = hit.point2.length();
            println!("dist {}", dist);
            if dist <= player.ground_max_distance{
                player.grounded = true;
            }
        }
    }
}
#

I get weird results. The distance only gets printed very sporadically, and also when I rub up against this one specific part of the level, which is on the player's left instead of below it

vestal minnow
#

I think the default has max_hits of 1, so if it's detecting the player, it's not continuing to check for the ground

kindred charm
#

I think you need .with_ignore_origin_penetration(true)

vestal minnow
#

And the shape caster seems to be the same size as the collider, so sometimes the very edge might hit the environment due to numerical precision

kindred charm
#
ShapeCaster::new(
                Collider::cuboid(self.size.x - 0.5, self.size.y - 0.5),
                Vector::NEG_Y * 0.05,
                0.,
                Vector::NEG_Y,
            )
            .with_ignore_origin_penetration(true) // Don't count player's collider
            .with_max_time_of_impact(0.2)
            .with_max_hits(1),

Here is what i'm using in my spawn player command

#

Should be easy to adjust for a ball collider

severe urchin
#

@vestal minnow would you expect this test to pass? it doesn't for me. not sure if i've overlooked anything.

#[test]
fn body_with_velocity_moves_on_first_frame() {
    let mut app = create_app();

    app.insert_resource(Gravity::ZERO);

    app.add_systems(Startup, |mut commands: Commands| {
        // move right at 1 unit per second
        commands.spawn((
            SpatialBundle::default(),
            RigidBody::Dynamic,
            LinearVelocity(Vector::X),
            Position(Vector::ZERO),
        ));
    });

    // one tick only.
    tick_60_fps(&mut app);

    let mut app_query = app.world.query::<(&Position, &RigidBody)>();

    let (pos, _body) = app_query.single(&app.world);

    assert!(pos.x > 0.0);
}
#

(it passes if i call tick_60_fps twice)

kindred charm
#

And initializing your ShapeCaster would go like this ShapeCaster::new(Collider::ball(8.), Vec2::NEG_Y * ground_max_distance, 0, Vector::NEG_Y)

late moat
#

well either that or I can control the distance using max_time_of_impact

#

and just cast from 0,0

vestal minnow
severe urchin
#

i think it still runs them all on the first tick, i'll add a print statement to Update to check

late moat
kindred charm
#

ignore origin penetration should be true

severe urchin
vestal minnow
#

hmm

late moat
#

but if the cast starts below the player, if the player is on the ground, surely it needs to hit immediately?

severe urchin
# vestal minnow hmm

my wild guess is that you do some sort of setup using commands and don't call apply_deferred before those components are needed to get into a query that does the simulation ๐Ÿคทโ€โ™‚๏ธ

late moat
#

setting to true doesn't fix it

kindred charm
#

Oh now I see. Your ShapeCaster is still intersecting your player collider though right?

vestal minnow
late moat
#

it seems to be. The distance is always the same when I print it

severe urchin
#

i found 1 instance of apply_deferred before setup

severe urchin
#

in prepare i think

#

(adding apply_deferred after clamp_restitution in prepare didn't help though)

late moat
#

even if I place the shapecast inside the player, with a radius of 4, and ignore_origin set to true, it still doesn't work

ShapeCaster::new(Collider::ball(4.), Vec2::ZERO, 0., Vec2::NEG_Y).with_ignore_origin_penetration(true).with_max_hits(1)
kindred charm
#

I have to go in a few minutes will look at it later if your issue is still not resolve but I still don't really get the distance check

#

You just want to check if your shape hits are not empty

#

Way simpler

#

Unless you want some more advanced logic

late moat
#

but shapecasts go forever don't they? Until they hit?

#

so I need to check that the cast isn't colliding with some ground that's ages away

kindred charm
#

You can just set the max_time_of_impact in your shapecaster initialization

late moat
#

is that not hard to get exact? Like why time and not max_distance?

vestal minnow
#

it's basically a fancy term for distance

kindred charm
#

Yeah

late moat
#

so casts travel a set distance per second?

vestal minnow
#

yep

late moat
#

so I have that ignore_origin thing set to true and it still hits immediately

vestal minnow
#

or time of impact = how long until first hit when moving at 1 unit/s

cinder summit
# vestal minnow The most important thing is that the contact points and normals are valid, but i...

So the way it all seems to work is by just sampling points against an SDF. If you want to calculate collisions between two sdfs you just pick points in space and snap them to the surface of the first sdf, then test them against the second sdf. There's probably a fair amount of optimization available with how you pick points. Getting near-contacts should be very easy tho, when checking a point against an sdf you just get positive numbers for non-penetrations, and negative numbers for penetration, could probably just set a threshold for what non-penetrations to pass on to xpbd ... Main challenge really becomes picking the points (and ofc optimizing when colliding with large compoud sdfs, which are very common)

vestal minnow
#

btw for the threshold you could use NarrowPhaseConfig property prediction_distance since it's what other contacts use

#

I noticed it was private so I made it public now

cinder summit
late moat
vestal minnow
cinder summit
#

Hmmm, getting stable grounded results? My approach for this has been working quite well. Let me check all the hacks I added to it to make it work

#

Filtering the caster's entity definitely helps, and you'll also want a shapecaster that's slightly smaller than the player and have it start a bit above the ground. Then you want to discard every hit that says the toi is 0.0

severe urchin
#

i think i know why, will format it and push something to demonstrate

late moat
# vestal minnow hard to say, but I think parry (the collision detection lib) handles the `ignore...

this worked, but I have a slight problem with that the filter has to include the entity it's being spawned inside, so I end up with this horrible mess of code. Is there any simpler way to do this?

fn spawn_player(mut commands : Commands, assets : Res<AssetServer>){
    let pe : Entity = commands.spawn((
        SpriteBundle{
            texture : assets.load("sprites/circle.png"),
            transform : Transform::from_translation(Vec3::new(64.,128.,5.)),
            ..Default::default()
        },
        LockedAxes::new().lock_rotation(),
        RigidBody::Dynamic,
        Collider::ball(8.),
        Restitution{coefficient : 0.0 , combine_rule : CoefficientCombine::Min},
        Player{ max_speed: 64., accel :  6., decel : 10., jump_force : 100., grounded : false, ground_max_distance : 8.0}
    )).id();

    let filter : SpatialQueryFilter = SpatialQueryFilter::new().without_entities([pe]);

    commands.entity(pe).insert(ShapeCaster::new(Collider::ball(4.), Vec2::ZERO, 0., Vec2::NEG_Y).with_query_filter(filter).with_max_hits(1).with_max_time_of_impact(8.0));
    
}
severe urchin
cinder summit
#

@vestal minnow I see this // Todo: Reuse manifolds from previous frame to improve performance comment in the narrow phase code, do you have any plans on how to reuse the manifolds? Trying to make this collision code have as few (ideally none) allocs, but this one seems a bit harder ... I guess I just have it take a &mut Vec as input and assume that'll eventually be a reused one?

vestal minnow
# cinder summit <@545959292281552928> I see this `// Todo: Reuse manifolds from previous frame t...

Parry's contact_manifolds takes a &mut Vec<ContactManifold> that will automatically be reused by exploiting spatial and temporal coherence if possible. The main issues with this when I last tried it were (1) it needs to use Parry's ContactManifold, so we'd need to do type conversions, and (2) it also seemed to cause collision instability

But if we did implement it, I'd probably add a contact_manifolds_persistent that takes a &mut Vec<ContactManifold> as well

#

or just make contact_manifolds take the vec instead of adding a separate function

cinder summit
#

I guess I'll implement it like that then ... I'm actually making some decent progress on this sdf collision stuff somehow ... It's just gonna need to have some restrictions you might not have with regular collision logic ... Tho I guess no one is gonna miss arbitrary sdf on arbitrary sdf collisions, just like how you don't trimesh-trimesh

vestal minnow
#

For people who have had issues with collision events being missed or CollidingEntities not being updated correctly, it should be fixed on main now that I finally finished up #112

vestal minnow
cinder summit
# vestal minnow I also added methods for adding new contacts to `Collisions` in case that's usef...

Hmmm, might be useful, wiring up my collisions to bevy_xpbd was actually the next step for my sdf collisions ... I should be able to have correct collisions for point or line based shapes like spheres, capsules and rounded cones (now that's a primitive you don't see often). Ofc no real contact stability work yet, but I can't really test that propperly if I don't see how the changes impact things

cinder summit
#

@vestal minnow The way the narrow_phase plugin is set up is a bit odd. I'd expect I'd need to disable it, and implement my own, but it also handles things like collision events and for some reason it's also responsible for checking sleeping entities and entities on non-overlapping collision layers. So I guess it's easier to just leave it enabled, and add my own system to add to Collisions?

vestal minnow
# cinder summit <@545959292281552928> The way the narrow_phase plugin is set up is a bit odd. I'...

Hmm, yeah it handles things that it probably shouldn't, I'll refactor it in a moment. The collision "validity" checks are unnecessary since they should be done during the broad phase, and wake_up_on_collision_ended should be in the SleepingPlugin.

I'm not sure where collision events and CollidingEntities stuff should be though; a new plugin like ContactReportingPlugin? Might make sense since not all projects require contact reporting

cinder summit
#

A ContactReportingPlugin makes sense yea

#

And yea I'd expect those validity checks to be done in the broad phase, especially since it already skips static-static, and sleeping-sleeping or sleeping-static is a similar optimization

slim ledge
#

Hey is there a Plugin or code sample equivalent of Rapier's DebugRenderer?

cinder summit
#

There's the debug-plugin feature

vestal minnow
#

and can be configured globally with PhysicsDebugConfig or at an entity-level with the DebugRender component

slim ledge
#

I somehow missed it. Thanks, it works

vestal minnow
#

But you can also add new collisions during PostProcessCollisions and it should work probably maybe potentially

cinder summit
#

Hmmm, the structure of manifolds is more complex then I thought ... I imagined it would just be a list of points with local positions and normals for each. But it's a list of [normals and lists of normals and points]

#

Is the top layer the contacts made based on geometry, and the manifolds extra points sampled around it?

vestal minnow
#

Currently, I don't think the manifold itself is used for anything though, so you could maybe put all contacts in one manifold even if they had different normals. For semantic reasons and robustness I don't recommend it tho

cinder summit
#

The main issue with it afaict is the Vec<Vec<>> it ends up creating

#

It's interesting the structure shows something about how the manifolds work tho

vestal minnow
cinder summit
#

Hmmm ... I guess it depends on how many manifolds you normally get for each point

#

If it's usually something like 4 it might be worth it, but if it's all over the place it would just be wasting some more memory

vestal minnow
#

Yeah, might need to benchmark with different situations

vestal minnow
#

@cinder summit wake_up_on_collision_ended is now in the SleepingPlugin, and I also have branches for the two other refactors. They ended up being slightly trickier than I expected, but might be working now. I'll properly test and finish them up tomorrow

late moat
#

hi! Just trying to check for collisions with the player and these exit sensors that I have in each level, but the collisions are never detected and I'm not sure why. Here's my code

fn check_exit_collision(mut collision_event_reader : EventReader<CollisionStarted>, mut level_selection : ResMut<LevelSelection>, exit_query : Query<(Entity, &ExitBlock), Without<Player>>, player_query : Query<Entity, With<Player>>){
    if let Ok(player_ent) = player_query.get_single(){
        //println!("collisions detected: {}" , collision_event_reader.iter().len());
        for (exit_ent, exit_block) in exit_query.iter(){
            for contact in collision_event_reader.iter(){
                if (contact.0 == player_ent && contact.1 == exit_ent) || (contact.0 == exit_ent && contact.1 == player_ent){
                    println!("okay! Switching level to level {}!", exit_block.level_to_spawn);
                    *level_selection = LevelSelection::Index(exit_block.level_to_spawn as usize);
                } 
            }
        }
    }
}
vestal minnow
#

@cinder summit I managed to do the refactor finally, so NarrowPhasePlugin is only responsible for managing Collisions, and there's a ContactReportingPlugin that only sends collision events and updates CollidingEntities.

Some kinda confusing and arbitrary collision state handling with things like during_current_frame is still needed though... Collisions has to store collisions from the previous frame for the events (and in the future maybe persistent contact manifolds) and you also don't want to discard contacts between sleeping bodies

#

But overall, the structure is more modular and less coupled now

#

I think I'll also move the broad phase, narrow phase, contact reporting and contact queries under one collision module now. It's a bit weird to have the contact data structs and contact queries under narrow_phase, and having a shared module for collision things is also nice for high-level collision docs

cinder summit
#

Hmmm, guess it's finally time to test these collisions then ๐Ÿค”

cinder summit
#

Hmmm, wait that refactor of moving the checks to the broad phase is also an optimization isn't it? ๐Ÿค”

vestal minnow
#

Most of the checks were already there, but yeah it might be a slight optimization

#

The checks were mostly just unnecessarily copied in the narrow phase

cinder summit
#

Guess I'll have to check the performance numbers again before I test the SDF collisions ... Probably also need a consistent test case ๐Ÿค”

drifting marsh
vestal minnow
cinder summit
#

Did not see this breaking change coming, good thing pattern matching saves the day ๐Ÿ‘€

-    collisions.retain(|(entity1, entity2), contacts| {
+    collisions.retain(|Contacts { entity1, entity2, manifolds, .. }| {
@@ -54,7 +54,7 @@ pub(crate) fn one_way(
-        if contacts.manifolds.iter().all(|manifold| {
+        if manifolds.iter().all(|manifold| {
vestal minnow
#

yeah I thought it's unnecessary to duplicate the entities for args since they're accessible from the contacts

#

Oh that's your one-way wall thingy, I was confused and thought the one_way_platform_2d example was broken lmao

cinder summit
#

Yea I have basically a copy pasted and simplified version of it

#

With the ability to specify the direction rather than it always being up

#

Had to simplify it cause the other code caused desync

vestal minnow
cinder summit
#

Haha, did someone else make the same workaround? ๐Ÿ˜‚

vestal minnow
#

Didn't this have other issues? ๐Ÿค”

#
  • hacky
cinder summit
#

Yea, the 255 shouldn't actually ever happen, you shouldn't get a qbvh with 255 levels of depth

#

This workaround just makes invalid behavior go from crashing to going on as if nothing is wrong

#

Eventually the performance of incremental update degrades so much it stops being usable in a game

vestal minnow
#

Another potentially slightly breaking change incoming :)

#

I grouped collision detection stuff under a new collision module that makes docs nicer and the structure more logical. Just affects imports tho, and the same stuff is still in the prelude, so it's not really breaking
https://github.com/Jondolf/bevy_xpbd/pull/184

#

I'm unsure if I should also move collider components there... currently all components are just in components which is nice for seeing all components at once, but it'd also make sense to have colliders in collision

cinder summit
#

Grouping by components doesn't usually make a lot of sense

vestal minnow
#

Yeah I agree in general, but where would e.g. RigidBody go? Or Mass?

#

I guess I could have a dynamics module or smth though

cinder summit
#

These aabbs are pretty close to the worst case possible, no wonder it runs so poorly ๐Ÿ˜‚

#

Now I wonder what would happen if I just put both narrow phases in my app thonk

vestal minnow
#

Should just work assuming you don't duplicate the collision state handling logic

#

I doubt it'd have a significant perf impact since they use different collider types

#

although it'd query a bit more ig

cinder summit
#

Put both collider types on an entity and get aabb race conditions thonk

vestal minnow
#

I think it would still work probably

#

just duplicate contacts if the colliders overlap perfectly

peak marsh
#

Is ShapeHits even available for 2D? I tried to query it but I'm not getting any hits.

#

Nvm I'm dumb, have to spawn ShapeCaster first.

peak marsh
late moat
#

can do!

#

this code spawns the player:

let pe : Entity = commands.spawn((
            SpriteBundle{
                texture : assets.load("sprites/circle.png"),
                transform : Transform::from_translation(spawn_trans.translation),
                ..Default::default()
            },
            CameraTarget(true),
            LockedAxes::new().lock_rotation(),
            Friction::new(0.0),
            RigidBody::Dynamic,
            GravityScale(2.0),
            CollisionLayers::new([WorldLayers::PLAYER], [WorldLayers::WORLD]),
            Collider::cuboid(15., 15.),
            Restitution{coefficient : 0.0 , combine_rule : CoefficientCombine::Min},
            Player{ max_speed: 64., accel :  6., decel : 10., jump_force : 130., grounded : false, ground_max_distance : 8.0}
        )).id();

        commands.entity(pe).insert(ShapeCaster::new(Collider::cuboid(14.,14.), Vec2::ZERO, 0., Vec2::NEG_Y).with_max_hits(1).with_max_time_of_impact(4.0).with_query_filter(SpatialQueryFilter::new().without_entities([pe])));

as you can see I have to spawn the player on its own without a shapecaster so that I can make a filter to exclude the player entity, then I add the shapecaster afterwards

#

and this code checks the hits, in my case it checks if the player is grounded:

fn player_ground_check(mut player_query : Query<(&mut Player, &ShapeHits)>){
    if let Ok((mut player , hits)) = player_query.get_single_mut(){
        player.grounded = !hits.is_empty();
        
    }
}
peak marsh
peak marsh
late moat
#

no worries, glad I could help!

brisk bay
#

Question - I'm using bevy-xpbd to make a physics based game where you control a rope with two mice (each mouse controlling one end of the rope). It's working fantastically so far - way more stable than rapier was - except that maybe 20% of the time I get what seems to be a physics death spiral when starting the game.

When I don't get the death spiral, the rope jerks around rather energetically for the first fraction of a second, which makes me think I'm initializing it in an un-physical configuration. Are there any useful tricks to initializing a system of jointed bodies in a smoother way?

#

It actually seems to freeze every time when I'm recording a screen capture, which is interesting, otherwise I'd show you what it looks like in a normal startup

junior flower
#

I can't help, but just wanna say that that looks like a tremendous amount of fun

severe urchin
#

is it multiplayer, or do you have 2 mice plugged in?

#

the only time i've noticed huge energy spikes when spawning is when i've accidentally spawned something on top of something else it collides with, in which case it gets moved off at a high speed

#

i've not dealt with joints much though

vestal minnow
# brisk bay Question - I'm using bevy-xpbd to make a physics based game where you control a ...

Yeah this looks super fun!

You should just make sure the distances between the rope segments are correct at the start, and if you are specifying the attachment points/anchors, make sure they're the correct way around :P Also check if things are overlapping at the start, that could make things rather explosive

Other than that, I don't really have any specific tricks to make the initial state stable. One thing you could try is to start with a high compliance (low stiffness) and decrease it to the desired value over time, so that the joints wouldn't freak out and overshoot as much at the start. This feels a bit hacky though, so ideally it would be stable from the get go

vestal minnow
#

Hmm, I'm trying to implement debug rendering for ray casts + shape casts, but I'm a bit torn on if I want the methods in SpatialQuery to also have debug rendering...
Gizmos require mutable access, so I would need to make all of the methods take a &mut self, which means you wouldn't be able to have multiple systems with SpatialQuery run in parallel. You also wouldn't be able to conveniently use your own gizmos in systems with SpatialQuery.

#

I think a decent compromise would be to only have debug rendering for RayCaster and ShapeCaster, and to add drawing utils to PhysicsDebugRenderer (or Gizmos) so that people could easily render the results of SpatialQuery methods, but only if they want to

#

Also, I wonder how I should render shape casts ๐Ÿค”
A ray, but with the shape + hit rendered at hit points? Or just a ray and hits, like how I'll probably render ray casts?

vestal minnow
carmine sluice
#

And the default colors seem fine

cinder vapor
#

Yay

brisk bay
#

Aww thanks y'all ๐Ÿ™‚

brisk bay
brisk bay
vestal minnow
#

the PhysicsDebugPlugin also renders joint things on the main branch with the debug-plugin feature enabled

vestal minnow
brisk bay
#

Okay, I've figured out my issue, thanks for the assistance! Turns out the extra energy when spawning and the death spiral application freeze were more or less separate physics issues.

The extra energy came from a misalignment of joint anchors at each end of the rope, where I calculated link positions with a full gap at the start, but set up the link's anchor assuming a half-gap at the start. Now they're both half-gaps. Pausing and stepping the simulation made this very visible, I'm sure the debug view updates would've shown this as well but I didn't update.

The death spiral application freeze seems to just come from doing physics work and application setup work at the same time. A 0.1 second delay between app startup and starting physics solved this issue.

#

In Unity I'm used to using some kind of anchor auto-configuration to make it impossible to misalign joints during initialization like this; is there some way to do that in bevy_xpbd? At least for a 2d revolute joint, I would think the anchor points not coinciding would very often be unintentional. Like, set the anchor point on one body in its local space, and automatically set the anchor point on the other body to the corresponding location.

vestal minnow
#

The auto config would probably be enabled by default like in Unity, but can be disabled

vestal minnow
cinder summit
#

@vestal minnow I remember there was some talk in the rendering-dev channel about aabbs for bevy, did they have any plans for what to use or to make one?

#

Since I'll be needing to use a non-parry bvh for shape/raycasting, I'm wondering if it makes more sense to just make a generics approach in bevy_xpbd, that can then be used for any future collision detection impl ... I guess we'd also need a bvh to speed up the broad phase too ... Ideally one that can actually update ๐Ÿ˜‚

vestal minnow
#

I'm on mobile rn though so I can't look for the discussion

#

But if we do end up making a new collision detection lib for bevy_xpbd, we would eventually need a BVH for spatial queries and probably the broad phase, so it would definitely be useful to make one

vestal minnow
#

No crates were mentioned tho (other than Parry's Qbvh)

#

And bvh, which was the other nalgebra-based one I think

#

I think bvh initially used glam and switched to nalgebra actually ๐Ÿค”

shell ermine
#

it used to use nalgebra, then switched to glam, then switched back to nalgebra

cinder summit
#

That sounds great ๐Ÿ˜‚

#

I think @thorn solstice mentioned that crate isn't as optimal as it could be. I might be able to implement something, but I don't really have any clue what type of bvh we should be aiming for, I guess using aabbs is the obvious choice here at least ๐Ÿค”

thorn solstice
#

I haven't tried implementing it yet. But I've played with the one in An Introduction to BVHs and it produces something that's faster to traverse than the bvh crate by around 40% across a wide range of standard test scenes. I used:

fireplace_room (143165 tris)
sponza (3746636 tris)
bistro (3872303 tris)
hairball (2880000 tris)
san-miguel (9932385 tris)
cornell_box (3968 tris)
cinder summit
#

Hmmm, guess I'll look at that approach then ... I wanted to see what parry's qbvh uses, but as usual the docs don't ell me anything ๐Ÿ™ƒ

cinder summit
#

Also I've fixed my aabbs but I realized bevy_xpbd still uses that angular velocity padding hack ... With things like rolling spheres it causes a lot of unnecessary aabb overlaps ... Not entirely sure what the right solution here would be, but if there's any ideas for solutions I could try to implement something for my sdf collisions at least ... Wouldn't be too hard to add extra info to limit how big certain aabbs get for most of the simple shapes at least ๐Ÿค”

vestal minnow
#

Might be a bit more expensive, but it's only run once per frame and not once per substep, and it would definitely be faster than having unnecessary overlaps

vestal minnow
#

But it should be pretty simple to replicate for your case as well; shape.compute_swept_aabb(...) is just this:

/// Computes the swept Aabb of this shape, i.e., the space it would occupy by moving from
/// the given start position to the given end position.
fn compute_swept_aabb(&self, start_pos: &Isometry<Real>, end_pos: &Isometry<Real>) -> Aabb {
    let aabb1 = self.compute_aabb(start_pos);
    let aabb2 = self.compute_aabb(end_pos);
    aabb1.merged(&aabb2)
}

and merged is this:

fn merged(&self, other: &Aabb) -> Aabb {
    Aabb {
        mins: self.mins.inf(&other.mins),
        maxs: self.maxs.sup(&other.maxs),
    }
}

(inf is component-wise min, sup is component-wise max)

#

So if you have a way to compute the AABB of an SDF with a given position and rotation, it should work

vestal minnow
#

Hmm, the perf of move_marbles actually seems to be worse with these AABBs thonk

#

Eh, it's the same, ig I just had a random lag spike

peak marsh
#

I want to round my Transforms to prevent jitters (low-res pixely game), where should I schedule the system in so that they're done after the physics stuff?

vestal minnow
#

I think it should work though

#

(on the main branch)

peak marsh
#

Thanks! It looks like it's working to me, although I think I still need to tweak the camera movement.

#

Low-res games are a lot more finicky than I thought thonk

cinder summit
vestal minnow
#

I also feel like the correct thing for quickly spinning objects would be CCD once we have that

cinder summit
#

Wouldn't CCD still need AABB checks? Or does it work separately?

vestal minnow
#

Hmm, probably does

cinder summit
#
let ltf = rot * Vec3::new(-half_bounds.x, half_bounds.y, half_bounds.z);
let rtf = rot * Vec3::new(half_bounds.x, half_bounds.y, half_bounds.z);
let lbf = rot * Vec3::new(-half_bounds.x, -half_bounds.y, half_bounds.z);
let rbf = rot * Vec3::new(half_bounds.x, -half_bounds.y, half_bounds.z);

(
    ltf.min(rtf).min(lbf).min(rbf).min(-ltf).min(-rtf).min(-lbf).min(-rbf),
    ltf.max(rtf).max(lbf).max(rbf).max(-ltf).max(-rtf).max(-lbf).max(-rbf),
)

I guess I need to optimize this aabb check tho, I think I can calculate the bounds of a box with a single rotation instead of 4 ๐Ÿค”

cinder summit
#

There we go, I also implemented the swept aabbs ... Seems to perform a fair bit better, and it's nice that my aabbs no longer become multiple meters because the spheres are spinning in place infinitely because there's no friction or angular damping ๐Ÿ˜‚

vestal minnow
#

I think you need to use bitmasks directly, like CollisionLayers::from_bits which is const

#

IIRC I tried making other methods const, but it was blocked by a Rust feature that hasn't stabilized yet

#

Make the bits?

#

yeah we could add const usage to the docs or examples probably, bitmasks are just generally more confusing imo so I prefer the non-const API

#

Ya that pattern should work

enum Layers{
    Player = 1 << 0,
    Enemy = 1 << 1,
    Ground = 1 << 2,
    // ...
}
#

We can definitely add it in the docs, not sure if we want 2 collision layer examples tho since there's already one with the non-const approach

#

I guess that example could show both ways

#

Hmm, good point, that might be a bit more annoying with the PhysicsLayer enum approach

peak marsh
#

I'm trying to get my kinematic body to not get stuck inside colliders but I'm kind of confused. I stole the kinematic collision code from this example here: https://github.com/Jondolf/bevy_xpbd/blob/a5987536790dc2a1057dd991c360fb7a21ca606a/crates/bevy_xpbd_3d/examples/basic_kinematic_character.rs#L130-L157
I used CollisionLayers so that the character doesn't collide with props sitting on top of the ground. It works, and the character can pass through it, but if you jump in the middle of it you get "stuck".

GitHub

2D and 3D physics engine based on Extended Position Based Dynamics for Bevy. - Jondolf/bevy_xpbd

#

It's really weird, because even if exclude the props from the bodies queries in the kinematic function, the player still gets stuck inside it, which is weird since the prop is Static and the player is Kinematic

vestal minnow
#

Could remove that and see what happens

peak marsh
#

No dice, it's still stuck. I can even walk on top of it, even though I can pass through it. I might make a minimal reproduction later.

peak marsh
#

Ok I'm feeling really stupid (again). Just to clarify are kinematic bodies supposed to collide with static ones?

vestal minnow
#

No

peak marsh
#

Ok, I think I'm progressively narrowing down the problem. It seems that adding ShapeCaster to my kinematic body causes it to collide with static bodies. It explains why I can pass through static bodies horizontally while still being able to land on top of it, it's because my ShapeCaster was pointing down. Is this intended behavior?

vestal minnow
#

No, the shape caster doesn't have anything to do with actual collisions. Are you sure you don't have movement logic that affects the vertical velocity when the shape caster detects hits?

peak marsh
#

Hmm, I think you're right...

#

I'm guessing that the caster isn't affected by physics layers?

vestal minnow
#

Not unless you add a spatial query filter

peak marsh
#

Thanks for the guidance, I at least figured out the issue! Are there any plans to make the caster easier to use? For example, I needed to filter the entity it belongs to so that it behaves nicely. Though tbh, a general character controller would probably be the best solution.

vestal minnow
#

Yeah a very common issue for people has been that they don't want the shape caster entity itself to be counted, so I'll probably make that a setting that's enabled by default. Eventually I'd like to have a built-in character controller as well, but bevy_mod_wanderlust is also going to support bevy_xpbd at some point (there's a WIP PR) so we'll have a 3rd party controller soon-ish at least

peak marsh
#

That looks like a really sweet plugin, I'll definitely keep an eye on that!

cinder summit
#

I think in the end you still get memed because you can't const impl BitOr on stable iirc

vestal minnow
#

Yep, I'll add this before 0.3 release

#

I usually do a docs improvement spree before every release

cinder summit
#

@vestal minnow Any idea if there's normally any tactics used to filter things (with CollisionLayers) early on the BVH level?

vestal minnow
#

For reference, you can check the spatial query methods in pipeline.rs, Rapier also has a similar file

#

Idk if other BVHs handle it differently tho, I've only used Parry's Qbvh

#

But yeah I don't think the BVH itself handles any filtering, but the methods used for BVH traversal can

cinder summit
#

Hmmm ... Would it just filter against nodes it finds, or does the bvh actually hold some data about what is below it

vestal minnow
#

Idk how the visitors work, but I think the callbacks you can give them just return true or false, and that determines if you continue the search

#

And for e.g. collision layers there's just an if that skips the leaf if it has incompatible layers

#

But this is done on the user-side so you can do any filtering

cinder summit
#

I'm considering if it makes sense to add something that propagates some filter information up the tree, so you can skip nodes that don't match your collision layer filter (or whatever other data, hopefully also a mask tho). I can't find a lot of info about how people use BVHs, mostly just about how they're made or very simple applications of them

#

Actually most BVH information also seems to just store triangles in them ... I guess that's what you'd do for raycasting or a trimesh narrow phase?

cinder summit
#

Also looks like there seems to be some interesting tradeoffs between the BVH2 approach and the SIMD-powered BVH4 approach. Supposedly the less wide your tree the less overhead you get with optimizing it, and the traversal isn't a huge part of the frame's cost. But if you have static data the BVH4 approach can still be a decent amount faster ... Might be an interesting optimization to experiment with at some point, there's a GDC talk about titanfall's SIMD BVH4 and it mentioned they split large static geometry into a separate tree ... It might also have some caching implications tho

vestal minnow
#

wait for relations to drop and make an ECS-based BVH with the querying capabilities of the ECS ๐Ÿ™ƒ

cinder summit
#

Don't think using the ECS directly would be optimal, but it sure would be pretty fancy

#

I'm a bit stuck on how the order of operations would work for bevy_xpbd tho ...
Right now I'm thinking:

  1. Add/update all colliders with swept aabbs
  2. Run broad phase, narrow phase, integration, etc
  3. Update the aabbs to the normal aabbs at the new position/rotation
  4. Optimize the tree
vestal minnow
vestal minnow
#

I tend to just look at how Rapier does these things, but I'm not sure if that's good or not :P

cinder summit
#

Honestly having 2 different BVHs just sounds kinda inefficient, it does allow you to have to trees that are maximally optimized for their specific purposes, but now you also have to optimize both of them and have pretty much all data twice

#

I think the only thing spatial queries have that the broad phase doesn't need is colliders without rigid bodies, tho those are generally pretty rare

#

I also think we can exclude sensors from the BVH, since they can only detect collisions and not be detected. The broadphase could also just search things if it's a dynamic/kinetic rigid body or a sensor and is not sleeping ... Makes me wonder if we should slap some extra component on static bodies so we don't have to iterate over them

cinder summit
royal helm
vestal minnow
#

However, I don't think they're actually using that broad phase anymore, but instead use their hierarchical SAP thing that doesn't use a BVH

#

Their hierarchical SAP is just a combination of sweep and prune and multi-layered spatial subdivision that has several grids with different sizes

vestal minnow
peak marsh
#

Is there a way to define the origin of a collider?

cinder summit
#

I think most parry colliders are at local 0,0,0. But there are some exceptions, like capsule_endpoints ... I think you might also be able to give them a relative offset if it's something like a compound collider ... And I guess soon we'll have child colliders which could also be used (probably the least efficient option tho)

peak marsh
#

compound collider
Oh it looks like that might work, I'll try it out

peak marsh
#

How do you change the collider's mass? The docs says:

You should generally not create or modify this directly. Instead, you can generate this automatically using a given collider shape and density with the associated from_shape_and_density method.

But the from_shape_and_density method doesn't exist...

vestal minnow
#

You could do just ColliderDensity(2.0) with that

#

And you can also set mass properties for a body independently of the collider mass props with the individual components like Mass and Inertia; note that the collider mass props will be added on top, so you'd use a collider density of 0 if you don't want that

peak marsh
#

Thanks, I'll give that at try.

However, my plan is to add a ColliderDensity component tomorrow
Nice, you're doing god's work :D

vestal minnow
#

Would anyone be free to do a quick test for the child-colliders branch btw? I think I'll merge that and the collider scale PR early tomorrow, but it'd be nice to have someone test it in an actual project to see if there are any immediately apparent issues that I haven't noticed in my own testing

#

I'm aware that at the moment they can be a bit more jittery and unstable than normal colliders in some cases, but otherwise I think everything should be working

vestal minnow
#

Actually I think I might just merge them both in a few minutes and make follow-up issues for the remaining known problems. I've been testing quite a bit already and haven't really seen issues apart from the occasional instability with offset child colliders. I think I might know what's causing it as well, but the PR is already very large and delayed so I'll fix the issues in follow-up PRs

cinder summit
#

I see we need open source games that use xpbd so you can implement new features in them and see if it works

vestal minnow
#

Your game ๐Ÿ‘€

cinder summit
#

My game doesn't have any usecases for child colliders tho ๐Ÿ™ƒ

vestal minnow
#

I might technically have access to the repo still, haven't checked though lmao

cinder summit
#

Yea I think you do

#

I cleaned up some of the repo access for others, but I'd probably run into weird physics issues eventually so I kept yours ๐Ÿ˜‚

#

Which I guess means you now also have access to SDF physics, maybe even a BVH soon ๐Ÿค”

vestal minnow
cinder summit
#

I only scale 1 mesh in my game, and it doesn't have physics thonk

vestal minnow
cinder summit
#

You can look at the SDF physics ... I'll opensource it eventually anyway

#

I also need to opensource the game, but considering I've pushed that back like 4 times now I think it's not gonna happen this year ๐Ÿ˜‚

vestal minnow
#

They're just standard Bevy events and the Collision event does have a basic code example in the docs so I kinda assumed it'd be relatively clear, but I agree it should definitely be documented better

#

CollisionStarted vs. CollisionEvent::Started

#

I don't have anything specific in mind

vestal minnow
# vestal minnow `CollisionStarted` vs. `CollisionEvent::Started`

I'm not sure which one is better, separate event types or one enum, but originally I just kinda though it'd be useful to have them separate so that you need to iterate less if you need just one event type. I can see how the enum pattern could be nice as well though

#

For filtering events, you could just check if entity1 and entity2 match some query with query filters

cinder summit
#

I literally never use the collision events ... They feel kind of cursed to use, but I think it's the only way to get start/end without tracking it yourself

cinder summit
vestal minnow
#

Well at least perf isn't bad, but collisions breaking is a bit odd

cinder summit
#

Might be that ColliderParent in the broad phase

vestal minnow
#

Oh the one in update_aabb? I could make that optional

#

lemme do that real quick

cinder summit
#

Actually it might happen later, cause I bypass update_aabb

vestal minnow
#

you could also implement the child collider stuff for your sdfs but it's also a bit... cursed

#

in what way are collisions broken? just not detected?

cinder summit
#

Haven't checked the specifics but they just phase trough everything, which suggests that either the broad phase doesn't find them, or their collisions don't get handled

vestal minnow
#

oh the solver also requires ColliderParent I think, I'll make it optional too

vestal minnow
#

I made it optional in both the broad phase and solver

#

It'll just default to using the entity itself if ColliderParent is None

#

Wait I think you also need ColliderTransform in the solver ๐Ÿคฆ

#

I probably need to make that optional as well

cinder summit
#

Yea can confirm, things still phase trough everything, but they do at least get to the narrow phase

vestal minnow
#

I'll be back in a minute...

cinder summit
#

Seems to work now

vestal minnow
#

Yessss

#

Thanks for testing that nothing broke horrendously

#

well... after fixing the stuff

cinder summit
#

I was thinking I was struggling with building things like SDF collisions and a BVH, but it sounds like these child collisions are much worse ๐Ÿ˜‚

vestal minnow
#

I think I'll hit merge on the 2 PRs and finally be free of child colliders for now, although they are sometimes a bit bouncy still which I need to fix

#

One thing I realized today is that for the broad phase I can't just expand their AABBs based on the rigid body velocity, because if the body is rotating and the collider is offset relative to it, the collider will of course rotate around the body and have speed from that. So I actually need to consider the linear velocity at an offset position

#

fixing this fixed some of the instability

#

but because it resembles uniform circular motion, the direction of the movement changes so I can't just use the offset velocity directly either

#

this I'll fix later

cinder summit
#

Are you saying making an AABB requires a sweep using all of thse?

  • Position
  • Rotation
  • AngularVelocity
  • LinearVelocity
  • Parent Rotation
  • Parent LinearVelocity
  • Parent Angularvelocity
vestal minnow
#

Yes except not AngularVelocity (it's the same as the parent's) and LinearVelocity would be computed (the offset velocity)

#

For computing the offset velocity I just need the position delta between the collider and parent and then I need the parent's linear and angular velocity

#

for 3D it's currently just offset_lin_vel = lin_vel + ang_vel.cross(offset), but ideally it'd consider the circular nature of the motion when the parent is rotating

vestal minnow
# cinder summit I was thinking I was struggling with building things like SDF collisions and a B...

I wouldn't say it's much worse, but there's a lot more work than you'd expect and a billion special cases, like you need to handle adding and despawning colliders while correctly updating their ColliderParents and the mass properties of bodies considering all the offsets and scaling in potentially infinitely nested hierarchies... oh and also you can't use GlobalTransform for numerical reasons, so you need to do custom transform propagation...

#

and then you need to support separate material properties, collision layers, events etc. for the different entities

#

and also ideally not break modularity and make everything super coupled

#

oh and also you can't access the data of colliders once they're removed of course, and we don't have hooks for that, so to handle mass property updates and other things correctly you need to manage another resource

#

I kinda want to see how Rapier handles child colliders, it's probably not as complex I'd imagine

cinder summit
#

I wonder if all this Iterator support I'm building would be useful for xpbd in any way ๐Ÿค”
You can construct a Bvh from an Iterator, and the traversal can be done with an Iterator:

fn test(query: Query<(Entity, &CollisionLayers, &ColliderAabb, &Position)>) {
    let iter = query.iter();
    let bvh = Bvh3d::new(iter.map(|(e, l, aabb, pos)| ((e, l), (Vec3::from(aabb.0.mins)-**pos, Vec3::from(aabb.0.maxs)-**pos), **pos)));
    for (entity, layers) in bvh.cast_ray(Vec3::ZERO, -Vec3::Y, 10.) {
        println!("{:?}: {:?}", entity, layers);
    }
}
#

The traversal is mostly like this to avoid allocs, tho I still need to alloc a small VecDeque, shouldn't be too hard to reuse that tho

royal helm
#

@vestal minnow do child colliders act as if they were a compound collider for you?

#

I'm a bit confused on the offset velocity

cinder summit
#

They can have different material properties and collision layers so I'm pretty sure they don't act like compound colliders

royal helm
#

Ya I just mean do they act in terms on collision as the same rigidbody

#

one can be bouncy and the other not but both should move the same velocity

cinder summit
#

Yea I think they do function as one rigid body, otherwise they would just be two independant colliders with maybe some constraint between them

#

The offset velocity is specifically to create the AABBs for the child colliders I think

#

If those AABBs are wrong, they could miss some collisions

#

If that's somehow velocity or rotation related I'd imagine that would appear as unstable behavior

vestal minnow
#

The velocity of a body is the velocity at the body's Position, so if the collider is offset relative to that and the body is rotating, the collider at the offset will have a different velocity

#

Before child colliders, you can't really have had offset colliders properly, so this hasn't been an issue

royal helm
vestal minnow
#

There's just one rigid body and one actual LinearVelocity component, but for expanding the AABB of the child collider the offset needs to be taken into account

#

Same thing if there's just one collider but it's offset

#

Because the uniform circular motion around the rigid body origin will make the collider have extra velocity independent of the origin's velocity

#

But again, this velocity is only used in the AABB expansion to avoid missed collisions

royal helm
#

so in this restitution example the one with 0 will still get some angular velocity right?

#

because the bouncy part is up in the air

royal helm
#

gotcha okay

peak marsh
#

Nice!!!

mellow orbit
#

I am trying to convert my code from rapier3d, and everything seems great until I add joints. Can't seem to keep them from yeeting everything into the void at infinite velocity ๐Ÿ™‚

trim ether
#

Hi!
I have just started learning xpbd and I'm not so sure that I'm doing the collision checks the right way.
Is there a better way to identify the two colliding objects?

trim ether
#

I see, so there is no concrete way of doing this.

vestal minnow
#
  • Use methods in Collisions (new resource on main branch/upcoming 0.3) like collisions.get(entity1, entity2) (retrieves data for collision between two known entities) or collisions.collisions_with_entity(entity)
#
  • What .โงฒ. suggested
trim ether
vestal minnow
#

Yep

trim ether
#

Thanks!

mellow orbit
#

Hey, quick question: I find the disconnect between parry shapes and bevy shapes to be ... I dunno the right word... annoying? Confusing? A little ugly? Something between all those. So, is there any downside to using convex_decomposition_from_bevy_mesh() everywhere?

vestal minnow
# mellow orbit Hey, quick question: I find the disconnect between parry shapes and bevy shapes ...

There's several downsides to that:

  • Creating colliders using convex decomposition is slow; the algorithm it uses, VHACD, can take several seconds or even minutes for complex meshes.
  • Convex decomposition creates compound shapes that are made from several convex hulls. These are approximations of the shape and are less accurate than primitive shapes like Collider::ball. A ball based on trimeshes or convex hulls would have vertices, so it wouldn't roll perfectly straight.
  • Computing collisions is much faster and simpler for primitive shapes like balls and cubes than for trimeshes and convex hulls. For a ball, it's mostly just a simple distance check.
#

My plan is at some point to maybe:

  1. Implement the primitive shapes RFC for Bevy to have a unified set of shapes that can be used for e.g. rendering, gizmos and collision detection
  2. Try to create an alternative for Parry using those shapes (although some custom shapes will still be needed for e.g. convex hulls)
    This would make things more unified and hopefully less annoying.
cinder summit
#

Or we could add sdfs to bevy and then use my sdf collisions thonk

vestal minnow
#

Mhmm

cinder summit
#

Hmmm ... bevy_sdf and bevy_raymarching ... That sure would be nice

vestal minnow
#

can you make arbitrary lines/curves with sdfs?

cinder summit
cinder summit
#

I don't think shape implements any trait nor are they one type, so you can't really do much with the

mellow orbit
#

The other problem I'm having -- again, probably being silly because I'm new to this -- is that I can't position the collider relative to the shape. In rapier3d, the collider is or can be a child, so that can have a separate transform.

cinder summit
#

There's child colliders on main I think

mellow orbit
#

The use-case being: I have a ground-plane, and I drew a box below that as the collider. (At least in rapier3d, that worked better than trying to make a thin collider.)

cinder summit
#

You can also do some other stuff, like with capsules you can use capsule_endpoints to have an offset collider, and compound colliders might work too

mellow orbit
#

But I guess the other way is: how do I use the half-space collider? Like, if I just want it to be "can't go -y", is that... (0.0,-0.0,0.0)?

#

Yeah, nothing should be below the ground

#

So theoretically that's fine, right?

#

but the reason I used a box in rapier3d was there were weird problems where stuff got stuck

cinder summit
mellow orbit
#

wait is there a different way to just have ground?

#

I may have missed something very very obvious LOL

cinder summit
#

I think a box is the most standard way

#

The way I set up my plane-looking boxes is by having the mesh be offset relative to the collider

mellow orbit
#

So going back to that... do I need to wait for child-colliders to land to do that?

#

I can also just use a very simple heightfield ๐Ÿ™‚

cinder summit
#

If you make the mesh the child you can do it on 0.2. But you can also just use bevy_xpbd main

vestal minnow
#

For them to be suitable for e.g. colliders, they would need to be simple and lightweight mathematical representations and not contain rendering-specific configuration.

mellow orbit
#

Thanks, that makes sense.

vestal minnow
mellow orbit
vestal minnow
#

But yeah "swing" by default is the local X axis and "twist" is the Y axis

vestal minnow
mellow orbit
#

What happens with the third axis now? It is it unlimited, or fixed?

vestal minnow
mellow orbit
#

thanks.

#

oooh, incidentally, from the next line in the paper: "All limits can be made soft by using ๐›ผ > 0."

#

lol except not that character -- it is ๐›ผ

vestal minnow
#

yep, compliance (alpha) is just the inverse of stiffness, i.e. 0 is infinitely stiff (a hard constraint)

mellow orbit
#

I'm still having some conceptional problems, I guess. Does that constraint apply to the limits applied to the otherwise allowed degrees of freedom for a joint or to the non-allowed degrees of freedom?

#

Like, for a PrismaticJoint, does it mean "how much the thing can be pushed off track" or does it mean "how much the thing can be pushed past the ends of the line"?

vestal minnow
#

I'm not sure if I fully understood the question, but for a prismatic joint, the limit does "if the distance between the bodies is greater than the maximum distance, move the bodies towards each other until the distance is within the allowed extents (and the constraint is satisfied). Otherwise, do nothing."

#

Limits are "inequality constraints", i.e. they only apply when some criteria is met (like the distance is over max or below min)

#

A prismatic joint only allows 1 DOF that has configurable limits (the "free" axis). You can think of the other DOFs having a limit of [0, 0]; the distance or offset must always be the same value, i.e. relative movement isn't allowed. This would be an "equality constraint".

#

A joint with 6 DOF and no limits would do nothing

mellow orbit
#

Let me try to illustrate my question with another example. Imagine a box with a hinged lid. The lid is a "revolute" joint, allowing rotational freedom on one axis. (Let's say X.) The limits in the Z and Y directions are effectively hard constraints (you can't twist the lid that way), as are the degrees of translation -- it doesn't slide. When you close the lid, collision with the box itself effectively enforces a limit. When you open the lid, with most hinges, it can't go all the way back and around. But that limit is usually kind of "springy". It's a soft limit.

vestal minnow
mellow orbit
#

Thanks! Would it be helpful to file an issue?

vestal minnow
mellow orbit
#

Cool. Gotta go now, but will later

fallen citrus
#

Found some strange behavior that happens when rigidbody type is changed after an object is initialized: I spawn two cubes at the same height, one is static and the other is dynamic. Beneath them are two platforms, the top is static and the bottom is kinematic. When I change the static cube to be dynamic, it does not collide with the static platform but does collide with the kinematic platform. If it is initialized as kinematic then later changed to dynamic it works as expected and collides with the static platform.

obsidian blade
#

hello, what would be the way to add all the physics components like RigidBody to an already existing entity, without ruining it's position?
to be more specific the bevy_ecs_ldtk crate gives me spawned tiles that are already positioned correctly, but if I add the components, the position is reset

vestal minnow
obsidian blade
#

0.2

#

should I be using the main branch?

vestal minnow
#

It has a lot of new features and fixes, so it can be useful. 0.3 should be released by the end of the week though

#

I think this issue was mentioned before and fixed, I'll see if I can find it

obsidian blade
#

oh okay, yeah, then I might aswell start using that already if the update is so soon. got it!

fallen citrus
obsidian blade
#

the main branch fixes all

#

all hail the main branch

vestal minnow
obsidian blade
#

thanks!

vestal minnow
#

I guess I semi-accidentally fixed it since quite a lot in the code related to that stuff has changed

fallen citrus
#

By the way I tried testing the predicate-based raycasting, my implementation was 15%-200% slower though I believe this is due to unnecessarily cloning the spatial query filter every time it hits an entity that does not pass the filter. I have also experimented with an API to get around this: instead of adding the InteractsWith component with commands.insert(), it can be added with a custom command which can fetch the ComponentId when the command is applied. If you don't want to do it with a command you can also get ComponentId from the ComponentIdFor<T> system parameter

#

And it would be no more or less convenient to use an "InteractionId" that is analogous to component ID except would be friendlier for projects with too many components than would be reasonable for a bitflag type

#

The main problem I had was that I got lost with figuring out how change detection ticks work, in order to update the CollisionFlags groups you have to check every entities components every time they change. This involves a &World param so you can't mutate CollisionFlags, you must insert with commands, and I couldn't figure out how to only do this on entities whose components are added/removed.

#

But I don't think any of this is a no-go in principle, it just needs a better programmer than me to figure out (such as a future version of me, who I'm sure is a much better programmer)

vestal minnow
trim ether
#

Hmm I'm guessing this isn't intended... Is there a special parameter for reflecting on the surface normal?
The walls are RigidBody::Static

fallen citrus
lavish laurel
#

Been hitting the attempt to add with overflow panic (https://github.com/dimforge/parry/issues/146), thought I was doing something wrong but I guess not? Are there any temporary workarounds for it or should I just ignore it for the time being

vestal minnow
vestal minnow
lavish laurel
vestal minnow
#

Ah, yeah I'm not aware of it being an issue on the main branch anymore

#

so you can ignore it until 0.3 or try the main branch

lavish laurel
cinder summit
broken lake
#

I've just switched to xpbd from just using normal transforms.
Couple questions.

How do I make it so I'm not on ice.
I put velocity to 0 at the start of the movement function and make velocity = to move speed but that seems to cause a minor jitter.
I tried velocity += movespeed,

I'm also not sure how to change my rotate enemies towards targets function.
How do I use rotation in xpbd?

vestal minnow
# broken lake I've just switched to xpbd from just using normal transforms. Couple questions. ...

How do I make it so I'm not on ice.
You could set Friction higher (edit: if it's top-down, LinearDamping might be what you want, see messages below)

I put velocity to 0 at the start of the movement function and make velocity = to move speed but that seems to cause a minor jitter.
I tried velocity += movespeed,
I'm not sure what could be causing jitter in this case. Have you tried just setting a constant velocity in some direction and seeing if that also jitters?

I'm also not sure how to change my rotate enemies towards targets function.
How do I use rotation in xpbd?
On the main branch, you can use normal Transforms for most things, so transform.look_at() could work. Otherwise, you would use the Rotation component (or AngularVelocity if you want it to be more gradual).

#

No, if it's top-down then you could use LinearDamping or just have a system that does e.g. lin_vel.0 *= 0.99
(note: LinearDamping(0.99) isn't equivalent to the above, the damping method is different)

thorny wharf
#

Would physics work right if I make terrain that is a mesh (not a height field) and is split into chunks? It won't be a complete mesh, meaning the shape will have holes on the sides. But during normal gameplay, nothing should interact with it from the backface side of the mesh.

vestal minnow
#

I don't see why it wouldn't work

thorny wharf
#

Awesome

mellow orbit
royal helm
#

For what it's worth, heightfields in parry are just trimeshes

#

It's just a difference in how you construct it

obsidian blade
#

hello, is there a big performance difference between having a RigidBody::Static + Sensor or using SpatialQueryPipeline::aabb_intersections_with_aabb every frame?

vestal minnow
#

But I haven't actually compared the performance, so it's hard to say for sure

obsidian blade
#

got it, thanks!

broken lake
#

Should I be replacing Transform to Position?

#

setting position doesn't seem to be working

vestal minnow
#

In 0.2?

broken lake
#

ye

#

I've been trying to add xpbd to my project

vestal minnow
#

ya using Transform wasn't supported in 0.2 yet but it does work on the main branch and 0.3 which will come in a couple of days

#

in 0.1 and 0.2 you need to use Position and Rotation

broken lake
#
    player_query: Query<&Position, With<Player>>,
    mut objects_query: Query<
        (&PlayerAttach, &mut Position),
        (Without<Player>, Without<WeaponSlot>),
    >,
) {
    if let Ok(player_transform) = player_query.get_single() {
        for (attach, mut transform) in objects_query.iter_mut() {
            println!("before {:?}", transform);
            transform.0 = player_transform.0 + attach.offset;
            println!("after {:?}", transform.0);
        }
    }
}
       TankTreads,
       tank_treads_sprite,
       Collider::cuboid(64., 48.),
       PlayerAttach::default(),
       Position::default(),
   ));
   commands.spawn((
       TankBody,
       sprite_bundle,
       Collider::cuboid(64., 64.),
       Position::default(),
       PlayerAttach::default(),
   ));
   commands.spawn((weapon_slot, Position::default(), Collider::cuboid(32., 32.)));
   commands.spawn((
       PlayerBundle::default(),
       Collider::cuboid(64., 64.),
       Position::default(),
       Transform::from_xyz(0., 0., 0.),
       LinearDamping(5.),
   ));```


This doesnt actually update the position of the attached entities.
#

And I'm trying to figure out why

vestal minnow
#

They don't seem to have RigidBody

#

so they're not physics objects

broken lake
#

If I add a rigid body they just fly around the screen because they bump into eachother

#

Should I add them to sperate layers?

vestal minnow
#

It looks like they're spawning at the same spot, so they will be heavily intersecting which causes a massive burst of velocity. You probably want to move them so that they're not overlapping at the start, or if you don't want them to collide against each other at all, you could use CollisionLayers

broken lake
#

I'm pretty sure I've done it wrong but basically I want the tanktreads body and weapon to be sperate sprites

#

So I can swap them out rotate them and have seperate collisions

#

But they are the same entity

#

Well in this they are seperate entities but they are the same character

vestal minnow
#

On the main branch, you could make a parent tank entity and have the tank parts as children of that entity. In 0.2 though, you can't have colliders on children, so there would need to be just a single collider on the tank

broken lake
#

So should I just use Transform for all the other sprites

#

The player entity is basically just a position I use to make sure they all stick to the same xy

#

I have a player attach component so they just get their transform = to player position

vestal minnow
#

You could do something like this

commands.spawn((
    PlayerBundle::default(),
    SpatialBundle::default(),
    RigidBody::Dynamic,
    Collider::cuboid(64.0, 64.0),
    LinearDamping(5.0),
))
.with_children(|child_builder| {
    // On main, these could also have colliders, but not in 0.2
    child_builder.spawn((TankTreads, tank_treads_sprite));
    child_builder.spawn((TankBody, sprite_bundle));
    child_builder.spawn((weapon_slot));
});
#

Children are positioned relative to the parent with transforms, but you can't have colliders on them in 0.2, only on main/0.3

broken lake
#

Cool I'll try with the child approach

#

I cant remember why I didn't go with it in the end lol

#

Still need to fix the enemies spawning and rotations

#

Also I notice a little jitter in the movement but I don't quite understand how thats happening

#

But thats a seperate issue

vestal minnow
#

The default physics timestep is a fixed 60 Hz in case that matters for the jitter

#

nvm I see the jitter too and my screen is 60 Hz

broken lake
#

Yeah I just realised my map size was too big.

#

I'm using a tiling crate

#

and 128x128 is too big causing a bit of a jitter

#

Thanks for all the help btw I prefer this crate to rapier after a referral from @sleek thicket

broken lake
#

Whats the best way to choose a location for the spawn?
I used to rely on the transform

let min_spawn_distance = 100.0;
            let spawning_distance = 300.0;

            let distance_x = rng.gen_range(-spawning_distance..spawning_distance);
            let distance_y = rng.gen_range(-spawning_distance..spawning_distance);

            let adjusted_distance_x = adjust_spawn_distance(min_spawn_distance, distance_x);

            let adjusted_distance_y = adjust_spawn_distance(min_spawn_distance, distance_y);

            let spawn_location = Transform::from_translation(Vec3::new(
                player_transform.0.x + adjusted_distance_x,
                player_transform.0.y + adjusted_distance_y,
                100.0,
            ));

            let sprite_bundle = SpriteBundle {
                sprite: Sprite {
                    custom_size: Some(Vec2::new(32.0, 32.0)),
                    ..default()
                },
                transform: spawn_location,
                texture,
                ..default()
            };

            commands.spawn(EnemyBundle::basic(
                50.0,
                50.0,
                16.0,
                AttackSpeed(Timer::from_seconds(0.2, TimerMode::Repeating)),
                10.0,
                sprite_bundle,
            ));
pub fn basic(
        health: f32,
        max_health: f32,
        speed: f32,
        attack_speed: AttackSpeed,
        attack_damage: f32,
        sprite_bundle: SpriteBundle,
    ) -> Self {
        EnemyBundle {
            enemy: Enemy,
            stats_bundle: StatsBundle {
                health: Health {
                    current: health,
                    max: max_health,
                },
                move_speed: MoveSpeed(speed),
                attack_speed,
                damage: Damage(attack_damage),
            },
            sprite_bundle,
            reward: Reward::Experience(ExperienceEvent(10.0)),
            enemy_type: EnemyType::Basic,
            damageable: Damageable,
            range: Range(48.0, false),
            collider: Collider::ball(16.0),
            rigid_body: RigidBody::Dynamic,
            targetable: Targetable,
        }
    }

But I have to change the position now.

vestal minnow
#

Transform can still be used for the initial position even in 0.2, but if you use Position then it'd be just Position(Vec2::new(...))

#

oh or did you mean specifically how to position them in a non-overlapping way?

broken lake
#

Same

#

They all spawn at 00

vestal minnow
#

Hmm ok, you can try Position(Vec2::new(...)) then

broken lake
#

Will that conflict with the rigid body I init in the new

#

When I spawn new enemies

#

They always spawn 0,0

#

Even though I spawn them with a transform

#

Which is why I assume I need to use position

#

but if I add position doesn't it conflict with the defaul rigid body because that also adds a new position

#

ye

#

Ah cool

#

Ye that worked

#

ty

broken lake
#

And sorry last question about rotation trying to figure out an ez way to do this

#
fn move_enemy_to_target(
    mut enemies: Query<
        (
            &mut LinearVelocity,
            &mut Position,
            &mut Rotation,
            &MoveSpeed,
            &Range,
            &MovingTarget,
        ),
        With<Enemy>,
    >,
) {
    for (mut velocity, mut transform, mut rotation, speed, range, target) in enemies.iter_mut() {
        if range.1 {
            continue;
        }

        let player = target.1;
        let difference = player - transform.0;
        let movement = difference.normalize_or_zero() * speed.0;

        velocity.0 += movement;
        let angle = difference.y.atan2(difference.x).to_radians();
        rotation = Rotation::from_radians(angle);
    }
}

#

Easier to see

vestal minnow
#

*rotation = ... probably

#

you need to dereference it to mutate

broken lake
#

Yeah

#

Forgot that

#

Nah they aren't rotating

#

Looks funny though

#

I've adding damping though so they aren't insanely fast anymore

#

Tried using transform to rotate them but thats not working either

#

How it would have been before adding physics

#

Also whats the best way to add a max velocity because I'd like it to instantly stop when done moving but if I put damping to = movespeed it makes everything move at the same speed

#

And I realise if I add velocity = 0 then velocity = movespeed to reset it

#

Then anytime I hit something with velocity from something else it will set to 0 again

mellow orbit
vestal minnow
#

Yeah I think that should be possible

#

I think there was an easy way to implement that but I'll check

#

Basically it would still solve contacts when they're overlapping, but it would skip adding velocity caused by the contact if the body was just added

#

Not really

mellow orbit
#

Right now, in a situation which might end up going either way, the object is not merely spawned on the wrong side of the wall but hurled at the speed of light into the abyss

vestal minnow
#

It wouldn't change the direction in which the bodies move, it would just make the correction more controlled

mellow orbit
#

(maybe also log a debug-level message when this happens?)

#

god help us all

#

When it goes ballistic, you know "huh, everything vanished", which is not a great debugging experience.

vestal minnow
#

I don't think it's good to use explosive behavior as a way of indicating that you could position your bodies better

#

Idk in what situation you want bodies to go at the speed of sound at spawn rather than getting gently pushed into a non-penetrating state

mellow orbit
#

I feel like the better alternate options might be: 1. leave it stuck, or 2. crash

#

right, hence crashing

vestal minnow
#

crashing feels a bit harsh imo

mellow orbit
#

My rationale: in many cases "went to infinite speed" is a effectively a crash, in that probably whatever you were trying to do is now completely impossible and your world is in an unexpected state. It's just a crash you might not notice right away.

#

But I agree it seems harsh as a default behavior, and a debug message probably is fine.

#

agreed on that.

vestal minnow
mellow orbit
vestal minnow
#

Yeah I think I'll just keep the current behavior for now but add a log when a dynamic body is spawned overlapping a collider

#

Later on we could also add the option to do the non-explosive correction

mellow orbit
#

On a different note, on some discussion I noticed above: what is the deal with Position, going forward with 0.3 and beyond?

vestal minnow
#

I'll add stuff about this in the docs of Position/Rotation tomorrow

#

Oh I just noticed that we hit issue/PR number 200 on GitHub ๐Ÿ‘€

#

Oh wow, when 0.2 was released, we were at just 72... it's been a while since the last release I suppose :P

mellow orbit
vestal minnow
#

I don't think so

mellow orbit
#

Thank you again for your help (and responsiveness and etc!)

vestal minnow
# vestal minnow I don't think so

If you were using f64, you could have slightly more precision with Position/Rotation, but in normal systems I'd imagine it's negligible

mellow orbit
#

Now, I'm going to go play Cities Skylines II until bevy 0.12 and xpbd 0.3 are released ๐Ÿ™‚

vestal minnow
#

I went ahead and implemented the warning already https://github.com/Jondolf/bevy_xpbd/pull/202
It just logs "{:?} and {:?} are overlapping at spawn, which can result in explosive behavior." (where {:?} are replaced by the entities)

#

and now I'll go to sleep

cinder summit
#

I feel like this should be behind a #[cfg(debug_assetions)], so the check gets optimized out on release builds

#

Weird that I've not seen things behave explosive when the reprediction forces the client back inside an SDF collider that the server doesn't have ๐Ÿค”

vestal minnow
#

(including me pretty often)

#

I guess these warnings could be behind a feature though, whether that's debug-plugin or something else, but ideally something that is enabled by default

cinder summit
#

Yea I guess that's a good point ... I made my release mode unusable for developing ๐Ÿ˜‚

[profile.release]
lto = "thin"
codegen-units = 1
strip = true
panic = "abort"

I instead have other crates set to opt-level=3 and my own to opt-level=1 with debug_assertions enabled ... Kinda wish we had a better check than "debug_assertions" tho, since that auto disabled with opt-level > 0

cinder summit
#

That feature is relatively recent so only on main atm

vestal minnow
vestal minnow
gentle steppe
#

Nice

vestal minnow
#

I think every intended feature and bug fix is finally done for 0.3 ๐Ÿ‘€
now all I have left is docs improvements and 0.12 migration

gentle steppe
#

do you have a changelog?

#

I'm already using the main branch, but I'm just curious what happened between 0.2 and 0.3

vestal minnow
#

that post might take a while to write...

gentle steppe
#

That's awesome

#

I don't mean to disparage rapier because I'm sure it's quite good but all the stuff I tried with it surprised me or I just couldn't get it to work. And I haven't had that issue with xpbd.

vestal minnow
#

Thanks, I try to make things as logical and ergonomic as I can

vestal minnow
# vestal minnow I will have a GitHub release and also a blog post on my website [like the one fo...

Also this aged well ๐Ÿ™ˆ

As I mentioned in the previous post, I will unfortunately have to take a long break from active development due to school. I am not abandoning the project, but I will not be able to add many new features or improvements until around the end of March next year when I should be free to work actively again.
says this, ends up making a release that's bigger than the previous one

gentle steppe
#

hah

#

Your studies are important

#

But I'm also glad xpbd is improving

vestal minnow
#

yep, I do pretty well in school as well and the matriculation exams I had went fine, so I'm not too worried

#

I just originally wanted to put out a disclaimer that I might not have time so that I don't have pressure to work on bevy_xpbd when I should be studying

gentle steppe
#

Yeah, that's smart

severe urchin
#

jondolf are you studying computer science, or something related? if so, hopefully you can get credit for bevy_xpbd in some way. in the UK if you were doing a comp sci degree you could probably make it your final year dissertation project.

vestal minnow
#

I'm not in uni yet so no ๐Ÿ˜… just the last year of high school

#

In a year I will be though

#

High school is just studying a bit of everything, not a specific degree

#

(although you can choose what courses you take to some extent)

#

Our school only has one or two courses with programming, and one of them was very introductory python programming related to math

severe urchin
#

ah right, ha. good stuff. well maybe bevy_xpbd 1.0 just in time for the final-year uni project ๐Ÿ˜›

vestal minnow
#

official bevy_physics as final year project :P

severe urchin
#

my school didn't have any programming courses either fwiw.. although i was writing nonsense in visual basic 6, not physics engines

severe urchin
broken lake
#

Do you need rigid bodies to handle collision or are colliders able to do that seperately

vestal minnow
#

In 0.2 I think colliders need to have rigid bodies to detect collisions, but on main colliders work on their own. But for collision response, you still need rigid bodies currently. A collider without RigidBody acts like a sensor

broken lake
#

So if I want a projectile to detect its hit something

#

Can I just use a sensor to detect that its hit another collider?
And if so do I need to add them to the same collision layer or is there a default collision layer?

vestal minnow
#

A collider without CollisionLayers interacts with all layers by default. You could make the projectile a sensor, but it needs to be a rigid body to be affected by velocity

broken lake
#

Because of the rotation issue I had saved it in a seperate branch and I'm gunna wait for 0.3 ๐Ÿ™‚
Im assuming that 0.3 isn't ready yet?

vestal minnow
#

No, but all I have left is docs improvements and some release prep
#1124043933886976171 message

#

should be released right after Bevy 0.12 releases

#

whenever that is

broken lake
#

ty

radiant sundial
#

in current bevy-xpbd master, are there small spheres ~0.05 in diameter automatically placed in the middle of each RigidBody?

#

where do these come from, and why are they there?

vestal minnow
#

probably a bit unnecessary though

radiant sundial
vestal minnow
#

Ideally it should work but there are probably numerical precision issues at those smaller scales

#

I'll add something like Rapier's physics scale at some point, it should help

radiant sundial
#

precision issues? why? I thought floating point mantissa has the same precision regardless of its exponent

#

to clarify: I thought that precision issues happen when you operate on floats of wildly different scales, but there are no issues if all numbers have the same scale (no matter large or small)

#

i'm wrong apparently, since small things start to jitter, but wanna understand why

gentle steppe
#

float precision is the best near 1

vestal minnow
#

I'm not that familiar with floating point error details, but that cuboid would have a mass of 0,000008 if the density is 1, and the solver has to deal with other small numbers like the substep delta time, so it could be that some numbers are very close to zero (or very large if the small number is the divisor) which could cause precision issues

vestal minnow
#

could test with f64 to verify that it's a precision issue tho

radiant sundial
# vestal minnow could test with f64 to verify that it's a precision issue tho

unfortunately, debug render doesn't work with f64:

bevy_xpbd_3d = { git = "https://github.com/Jondolf/bevy_xpbd", branch = "main", features = ["debug-plugin", "f64", "3d", "collider-from-mesh"], default-features = false }
   --> C:\Users\user\.cargo\git\checkouts\bevy_xpbd-87d8ac3552aaa63b\da2ab00\crates\bevy_xpbd_3d\../../src\plugins\debug\renderer.rs:418:25
    |
418 |                 .sphere(point.adjust_precision(), default(), 0.025, point_color);
    |                  ------ ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec3`, found `DVec3`
    |                  |
    |                  arguments to this method are incorrect
vestal minnow
#

ah, I'll fix that real quick

#

it's annoying that CI doesn't catch that

radiant sundial
#

in 2 places, line 418, as well as line 470

vestal minnow
#

should be fixed now

vestal minnow
#

Hmm, that's a bit strange... would you mind making an issue? I can investigate further when I have time

radiant sundial
#

(that's just a cube on a halfspace, friction=0.3, restitution=0.7, everything else default)

#

yeah I'll make an issue

vestal minnow
#

I'm currently revamping and updating quite a lot of high-level docs, the table of contents is looking kinda fire

#

Makes me realize how big the engine is :P

#

Previously it was just an unstructured list of common tasks that was missing a lot of things (+ there was also a list of features)

#

now it's at least structured

vestal minnow
#

You can just do lin_vel.0 += vector

#

But yeah some examples probably should multiply by delta time, I'll test tho

peak marsh
#

It looks like that RenderLayers no longer has any effect on colliders, on the latest commit. Previously the scale would be affected, but it doesn't seem to work anymore thonk

vestal minnow
#

Uhh... it was previously affected?

#

How would RenderLayers affect anything physics related?

peak marsh
#

Hmm, previously the colliders would be affected by the scale of the camera's RenderTarget. So when you're rendering to an off-screen image and scale the image up, both the sprites and the colliders would be scaled accordingly. But it doesn't seem to be working anymore.

vestal minnow
#

bevy_xpbd doesn't even use bevy_render other than for creating colliders from Meshes

#

I guess bevy_gizmos uses bevy_render but I only use the gizmos directly

peak marsh
#

Actually, I think the debug-plugin is just fooling me. It's not being rendered in the layer I want, so things are completely misaligned.

vestal minnow
#

I think you can change render_layers in GizmoConfig

#

but I haven't used render layers so idk

peak marsh
#

Thanks, that did the trick! Also thanks for the caster update!

#

Also, about debug-plugin, is there a reason why it's behind a build flag?

vestal minnow
#

It enables bevy_gizmos which in turn enables some other deps, and people might want to use bevy_xpbd in a headless context

#

However I could make it a default feature and allow people to enable PhysicsDebugPlugin by adding it manually instead of automatically adding it when the feature is enabled like we currently do

peak marsh
#

allow people to enable it by adding PhysicsDebugPlugin
Yeah, that would definitely be nice!

vestal minnow
#

It would also make docs nicer since I currently can't link to the plugin when the feature is disabled... yeah I think I'll make it a default feature

#

just in time for 0.3 :P

#

it wouldn't even add dependencies other than bevy_gizmos because some other default features already enable bevy_render

vestal minnow
#

I guess the main con with this approach is that you can't easily toggle the debug rendering through the command line because you now need to add the plugin manually, but I'd say it's about the same effort as commenting/uncommenting the plugin

#
  • previously you would have needed to comment out any debug configuration if you disabled the feature, but now you can have the feature on without the plugin
peak marsh
#

Nice! I guess people who want the cli workflow can just add their own cfg in their code.

vestal minnow
#

yep

peak marsh
#

Err, okay I think kinematic stuff is broken in the latest commit. Spent like 2 hours debugging my project. But turns out that cargo run --example basic_kinematic_character is broken too...

#

The character just falls through the floor

vestal minnow
#

oh whoops, it's not broken, I just changed it to use Transform for positions and accidentally moved the ground up instead of the player ๐Ÿ˜… so it's just spawning the player below the ground

peak marsh
#

That means my code is actually broken ๐Ÿ˜ญ

vestal minnow
#

oof

vestal minnow
outer wren
#

Hi, I've been trying to update CollisionLayers on an entity after its been spawned. Currently my function runs on the update stage, I've tried a CollisonLayers mut query and inserting a new component, they both seem to change the groups and mask values but the entity still collides with the same things as before the function is run. Is this approach fundamentally wrong? I'm on the main branch. Thanks

vestal minnow
#

previously it wasn't updating the collision layers for the broad phase correctly

outer wren
#

Great, thank you

vestal minnow
#

I updated the examples to multiply by delta time where appropriate, among other fixes and improvements like refactoring the character controller examples to be slightly more complete with a CharacterControllerBundle
https://github.com/Jondolf/bevy_xpbd/pull/210

#

also I did this

#

for the character controllers? yeah I could add a MaxVelocity thing

#

eh, it's not strictly a character controller thing and might be unnecessary for the example so I might just leave it as is

vestal minnow
#

ah yeah just clamping the input direction length to 1.0 but you can still have e.g. 0.6 if you're using a joystick or something

#

Bevy just doesn't have a nice input thing built-in that would support both keyboard and controller as far as I know

#

so currently it's just using keyboard input

#

yeah I'll probably add the clamping but in this case it just does nothing since the length is always 0 or >= 1 with keyboard input

#

alternatively I could add leafwing to the examples but idk if that's overkill

#

yes but that's the same as .normalize()/.normalize_or_zero() which it already does

#

or I guess not all of the examples do that actually

#

but the character controllers do

#

adding gamepad support is more than a few lines I'm pretty sure

#

or it might be just a few lines looking at the cheatbook ๐Ÿค”

vestal minnow
#

I think I got it working with both keyboard and gamepad input, but I haven't actually tested with a gamepad yet (does a PS5 controller work? I know some games don't support it on PC)
I added a MovementInputEvent and split the movement system into three systems, one for keyboard input, another for gamepad input, and a third one for actually handling movement based on the movement events (Move or Jump)

#

It does add about 90 lines of code, but I think it's good practise to have the input handling be separate anyways and it's nice to have a semi-complete character controller example since we don't have an official one

#

wait I'm bad at math, 60 lines of code

#

I think a total of 230 LoC is still pretty good considering it has a functional (yet basic) character controller with keyboard and gamepad support and all of the setup stuff + some comments

#

tomorrow I'll test if gamepad input actually works

#

thanks

vestal minnow
#

to not dampen y

#

could just increase gravity I guess

#

ah yeah keyboard input had it that way around because it needs to be negative for the movement to make sense, but I should do the negation in movement and not the input system

#

maybe LinearDamping and AngularDamping should be vectors so that it allows you to dampen different axes separately

#

idk, I'd have to check but I think Rapier has scalars at least

#

gravity compensation?

#

there's GravityScale

#

it'd be weird to special case gravity for damping imo

#

gravity is mostly just sugar for ExternalForce

gentle steppe
#

modeling gravity as a force. shaking my head. did einstein teach us nothing?
||this is sarcasm btw||

vestal minnow
#

the input directions should be fixed now

#

or at least be the same across keyboard and gamepad

#

yep, just need to properly migrate to Bevy 0.12 and wait for it to release

#

and prepare release notes

#

wanderlust seems to have a friction coefficient that is the ground's friction coefficient when grounded and otherwise an air damping coefficient of 0.25

#

and then computes and applies forces

#

I should probably separate friction and air damping as well for the character controllers

#

and add a separate Grounded component to make the logic clearer

#

yep, just need to add autostepping, proper move_and_slide, jump decay, agnostic up vector, coyotee time jumping...

#

and slope handling

#

but it'd be nice to have a properly ECS-integrated character controller, I feel like Rapier's KCC is very weird and needs a ton of special casing

#

I feel like it could be implemented with just components and a bundle, and then maybe have a world query (or SystemParam) to allow move_and_collide type logic

gentle steppe
#

And it would be nice if it allowed you to use input action mapping like what leafwing provides

vestal minnow
#

yep

junior flower
#

I've not looked in a huge amount of detail but that devlog looks fantastic

bold cedar
#

FYI, if using bevy_xpbd_2d and it appears like your starting translations are being ignored (everything is moving to the origin), switch from PhysicsPlugins::default() to PhysicsPlugins::new(FixedUpdate) head desks

bold cedar
#

FixedUpdate works for me for now, just porting some of my toy exercises from rapier and spent some time head scratching over that bit of oddness

true dragon
#

I'm migrating from Rapier to XPBD (2D).

#

I'm using the rapier contact events to figure out the magnitude of the force of a collision.

#

I cannot seem to find an equivalent in XPBD?

#

Is there a way to get not only collisions, but also the magnitude of the impact of said collisions?

merry tide
#

I am seeing some issues with my tiny game when converting to WASM. I am not saying it is XPBD. I am thinking it is not.

#

You have perhapsly seen me yapping in the WASM-channel. Any chance of getting someone to look at it, paid or otherwise? Happy to pay if I get this issue fixed. But it is out of pocket and I am an old alcoholic. So $100.

#

Happy to pay people to tell me I am wrong, as usual. As long as I get a running Ponkatris.

#

And I don't want Godot. I want Bevy/XPBD. I came for the best physics engine. And by God. This is the hill.

#

OMG, I haven't updated this library in years. There is a 0.3?

astral smelt
#

Regarding cocporn's message above:

Is it expected for a Collision event to be generated more than once per frame for a collision? We are seeing up to 4 of these in a ball-cuboid collision (and this seems to show up more reliably at lower framerates). From the docs, it sort of sounds like this could be expected behavior. (one collision, multiple contact pairs if the overlap is just right?)

Should we be using CollisionStarted?

(as an aside, if so, Collision feels like a very unoptimal name for that event)

vestal minnow
astral smelt
#

Yeah, 0.2.

vestal minnow
#

Also I agree Collision isn't great; on main there's a much more capable Collisions resource that you should be able to use instead, so I might even remove the Collision event

#

Or I guess it's not equivalent since events are consumed

#

And if you were using the resource, you could potentially miss collisions if you don't run your system every frame (since they wouldn't be in the resource anymore)

#

Idk, I'll probably leave the event be for now and reconsider its name/existence later

merry tide
#

Thank you both for chiming in!

#

I will update it tomorrow.

vestal minnow
merry tide
#

Great! Huge fan.

#

To me it seems like the most stable physics engine I could get my hands on.

vestal minnow
merry tide
#

That's what she said.

#

Holy f, I need to sleep.

#

Thanks again

#

Huge fan.

vestal minnow
#

You just can't compute the forces directly in the narrow phase collision detection, so you first need to run the solver to get them

merry tide
#

I trust you to do this great.

#

Great.. ly? Greatly.

true dragon
vestal minnow
#

(the API has changed from 0.2 tho)

true dragon
#

(but I suppose now I'm working on intuition rather than experience)

vestal minnow
#

Collisions are only handled if there's penetration in XPBD, you can't resolve overlap if it doesn't exist

true dragon
#

I see. My thinking probably stems from interpreting "penetration" as in the real world. I.e. something actually enters/breaches something else.

#

Which would be an unwanted case in a physics simulation.

#

Thanks for clearing it up!

#

Another thing if I can bug you with it:

I see no way to work with impulse forces in XPBD. Is this the case? I'm wanting add an external force to something regardless of its mass.

vestal minnow
#

looks like 0.2 didn't have impulses either, but they do exist on the main branch

#

you can also just change velocity

vestal minnow
#

force = mass * acceleration (unit is Newtons)
impulse = force * delta_time = mass * velocity (unit is Newton-seconds)

true dragon
#

I see!

vestal minnow
#

to make it not dependent on mass, just add to velocity directly without a mass term

mellow orbit
#

translating from rapier, "impulse" is just ExternalForce where with_persistence is false, right? Or is it something else?

vestal minnow
# mellow orbit translating from rapier, "impulse" is just ExternalForce where `with_persistence...

On main there's also ExternalImpulse and ExternalAngularImpulse. The magnitude of the velocity change during a frame is different for forces and impulses. Impulses aren't multiplied by delta time while forces are.

https://github.com/Jondolf/bevy_xpbd/blob/f2f11668e18c78132d879249a70bd1a2297de218/src/components/forces.rs#L373

The other difference between our forces and impulses are that forces have with_persistence = true by default (because they're "continuous") while impulses have with_persistence = false (because they're "instantaneous" / applied in a single burst)

vestal minnow
#

I just checked what the auto-generated release notes for 0.3 would look like, so here's 0.3 at a glance :P

#

it's quite long but still missing a lot of detail since a lot of the PRs are pretty impactful fixes or improvements

#

now I technically have everything ready, just have to wait for Bevy 0.12

#

(well, the blog post is definitely not ready, but that can come afterwards too)

#

0.1 to 0.2: 4,432 additions and 606 deletions
0.2 to 0.3: 11,725 additions and 2,321 deletions

0.3 to 0.4: 33,000 additions and 9,200 deletions??
0.4 to 1.0: โˆž additions and โˆž deletions

vestal minnow
#

Yep :p should probably aim for two releases per Bevy release

#

And yeah water could be a good example for sensors and forces, I just don't know what to call the example... water indicates fluid simulation which it is not

#

Yeah maybe something like that

#

Or maybe some gravity switching thing where some areas have inverted gravity

peak marsh
#

Just checked out the new kinematic character example, but why is there a CharacterController filter here thonk :
https://github.com/Jondolf/bevy_xpbd/blob/f2f11668e18c78132d879249a70bd1a2297de218/crates/bevy_xpbd_3d/examples/basic_kinematic_character.rs#L311-L314C4

I tested it on my own project, but collisions becomes really buggy after adding that.

GitHub

2D and 3D physics engine based on Extended Position Based Dynamics for Bevy. - Jondolf/bevy_xpbd

vestal minnow
#

Oops, yeah that doesn't do what I intended

#

I meant to have it handle collisions between character controllers and everything else, but that code requires both bodies to be character controllers

#

I'll fix it later today

peak marsh
#

Alright, cool!

#

Also, it looks like that the movement code now all happens in Update using deltas. Since the input and movement code is now separated, can't the movement code just stay in PhysicsSchedule?

vestal minnow
# peak marsh Also, it looks like that the movement code now all happens in `Update` using del...

Yeah, I think I'll do this since it's generally recommended to handle actual rigid body movement in a fixed update schedule of some kind (PhysicsSchedule in this case). Although it should be basically equivalent here since it's multiplying by the delta time.

The main two reasons I didn't do this are (1) PhysicsSchedule looks more like an internal thing, and (2) in the PhysicsSchedule you should currently use DeltaTime instead of the normal Time resource, which can be confusing

#

I wonder if I could replace DeltaTime and SubDeltaTime with custom clocks using the new time API though... I haven't looked into it much yet so idk

vestal minnow
#

this way people could just use Time and it'd "just work"

#

also maybe we should change the default fixed timestep to 64 Hz to match Bevy's defaults

vestal minnow
#

Ooh it works ๐Ÿ‘€

#

I can remove PhysicsTimestep completely and replace it with Time<Physics> where Physics is a custom clock that is an enum storing the same configuration as PhysicsTimestep

#

Before:

.insert_resource(PhysicsTimestep::Fixed(1.0 / 60.0))

After:

.insert_resource(Time::new_with(Physics::Fixed(1.0 / 60.0)))

And you can just use Time instead of DeltaTime or SubDeltaTime everywhere

#

Since it's updated based on the schedule

#

This way I can also make physics systems more schedule-agnostic since the time resource is unified

peak marsh
#

Nice! ๐Ÿ‘

full verge
#

Is there some resource or something similar to 'physics_pipeline_active' from rapier3d? Basically I need a way to query if the physics pipeline is active

vestal minnow
full verge
#

Thanks ferris

cinder summit
#

@vestal minnow How can I escape the Collider dep for mass properties?

vestal minnow
#

Do you mean how you can compute mass props for your bodies without Collider?

cinder summit
#

Yea, and without systems that calculate it using a Collider later

vestal minnow
#

Isn't update_mass_properties the only system that does that

#

or are there others

#

If you take out the colliders, it's just this

fn update_mass_properties(mut bodies: Query<(Entity, &RigidBody, MassPropertiesQuery)>) {
    for (entity, rb, mut mass_properties) in &mut bodies {
        let is_mass_valid =
            mass_properties.mass.is_finite() && mass_properties.mass.0 >= Scalar::EPSILON;
        #[cfg(feature = "2d")]
        let is_inertia_valid =
            mass_properties.inertia.is_finite() && mass_properties.inertia.0 >= Scalar::EPSILON;
        #[cfg(feature = "3d")]
        let is_inertia_valid =
            mass_properties.inertia.is_finite() && *mass_properties.inertia != Inertia::ZERO;

        if mass_properties.mass.is_changed() && is_mass_valid {
            mass_properties.inverse_mass.0 = 1.0 / mass_properties.mass.0;
        }
        if mass_properties.inertia.is_changed() && is_inertia_valid {
            mass_properties.inverse_inertia.0 = mass_properties.inertia.inverse().0;
        }

        // Warn about dynamic bodies with no mass or inertia
        if rb.is_dynamic() && !(is_mass_valid && is_inertia_valid) {
            warn!(
                "Dynamic rigid body {:?} has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle`.",
                entity
            );
        }
    }
}

(warning stuff optional)

#

Idk how mass properties are computed for SDFs though, probably some rough approximation

cinder summit
#

I think the easiest option would be if I could say "this collider is X kg, and the center of mass is here" (I can't know that for certain if it's not a simple SDF tho, but the user could always override it) ... Not sure if that's enough for what physics needs tho

#

The volume is easy to know for some SDFs, but when you do fancy operations with them, the whole SDF turns into a mysterious black box, tho I guess those also can't really be dynamic colliders, unless I sample the SDF at which point I can approximate the center of mass and density ๐Ÿค”

#

There's also fun SDFs that have infinite volume ๐Ÿ˜‚

vestal minnow
vestal minnow
#

(although we don't handle it like mass == 0 -> static)

cinder summit
#

Interia should be proportional to mass right? I wonder if a constructor that takes these two fields would work ... Tho maybe that would need a breaking change later with that weird angular interia parry seems to have logic for ๐Ÿค”

vestal minnow
#

yeah angular inertia is proportional to mass

#
  • of course how the mass is distributed relative to each rotational axis
#

a lot of shapes have known formulas, but idk how it'd work with SDF operations and whatnot

cinder summit
#

Most primitives should be easy, but yea figuring it out when any sort of operation is involved would be hard ... Especially any operations that result in bound SDFs, because those are just impossible to reason about, but I'll probably drop all operations that guarantee bound SDFs anyway ๐Ÿค”

#

Dynamic objects probably won't be non-primitive shapes anyway

vestal minnow
#

approximate the shapes as their AABBs ๐Ÿ™ƒ

cinder summit
#

I actually considered doing that ๐Ÿ˜‚

#

No clue how to make a Matrix3 out of it tho ๐Ÿค”

cinder summit
vestal minnow
#

nvm that's done internally I think so I'm pretty sure you don't need that

#

"just" the "angular inertia tensor of the rigid body from its principal inertia values and axes"

#

which is exactly what you linked now that I look more closely ๐Ÿ˜‚

vestal minnow
#

Just has a weird issue where objects get a random jitter roughly once a second when moving, almost like the simulation stops for one frame

#

Also it could be considered weird to have Time<Physics> contain configuration about the timestep, like implementing Time<Virtual> and Time<Fixed> in one type

#

there's a separate PhysicsTimescale resource already with a simple code example in docs, but that'd be a nice actual example as well yeah

#

you seem to be suggesting new examples every day haha, I like it though

#

I'll add it to my list

cinder summit
#

I mean it would be very easy to make that even without an xpbd example, you just set the timescale on virtual lower and done

#

Tho I guess if you want it to feel decent you want to up the frequency of updates too, otherwise it becomes a jittery mess ๐Ÿค”

vestal minnow
#

One is that substeps need to have the separate timer or somehow compute it

#

so some kind of Time<Substeps> would be needed

cinder summit
vestal minnow
#

also FixedOnce needs to be enablable(?) somehow

cinder summit
#

Is xpbd runs in FixedUpdate there would only be FixedOnce and Variable, and the way to set FixedOnce in a server is to just overwrite Time<Virtual>'s delta somehow

#

Because whatever the delta was on the server, ti's actually just the fixed timestep

vestal minnow
#

also also, it's nice to be able to advance physics independently of Time<Virtual>/Time<Fixed> when running physics manually for example

cinder summit
#

Yea the manual updates are useful ... Either way I think the physics schedule/time should probably stay at least until FixedUpdate becomes easy to use

#

After that it might be worth seeing what the general opinion is on how it should work if a bevy_physics existed ๐Ÿค”

vestal minnow
#

Yeah that's kinda the mindset I have for developing bevy_xpbd in general

#

"What should bevy_physics look like"

#

(not that we're close to it yet, but in terms of the future)

cinder summit
#

Kinda hard to envision what bevy_physics would look like when there's a bunch of rough edges around that would make a bevy_physics unpractical to implement