#Avian Physics

1 messages ยท Page 9 of 1

vestal minnow
#

I need to try it again

#

another thing on the todo list

cinder summit
vestal minnow
#

I used to be able to keep the number of issues below 10 pretty well, but now I have a bit of a backlog there as well

red gulch
#

I'm trying to modify the one_way_platform example to use sensors and events, but I think I'm missing something?

for collision in events.read() {
        let can_allow_collision = should_allow_collision(&collision.0);
        println!("can allow: {}", can_allow_collision);
        if !can_allow_collision {
            res_collisions.remove_collision_pair(collision.0.entity1, collision.0.entity2);
        }
    }

I've changed a bit of logic for determining when a collision should be allowed, but I'm printing my results and it is what I'd expect.

As I understand it, I should be removing the collision from the collisions resource if I want the entities to pass through each other, is that right? Is there another mechanism I need to use to actually make the entities stop when they collide?

vestal minnow
cinder summit
#

Removing the collision pair is how you make them pass trough eachother yea. I think I also did the one-way thing differently ... I should check if my changes actually make sense, maybe I can improve the example ๐Ÿค”

#

And yes collision events don't work

#

If you remove the collision pairs, no events for it are generated

vestal minnow
#

Yeah you need to use the Collisions resource here unfortunately

red gulch
#

This is unfortunate news lol

#

That's okay though, learning opportunity and all

cinder summit
#

This is how my one-way collision stuff works ... It works in a subtly different way from how the example worked when I copied it, but idk if this is perfect either ... It has worked fine for me at least ๐Ÿค”

vestal minnow
#

Looks cleaner and more capable than the current example based on a quick glance

cinder summit
#

I still don't quite like how it works however ... It probably needs some extra logic to check the point of the collision besides just the normal ... Otherwise a shape like this would behave weirdly:

 _____
|__ __|
  | |
  |_|
#

Assuming the allowed normal is bottom to top, then hitting the T parts and going trough seems kind of wrong ...

vestal minnow
#

Do you have many T colliders? ๐Ÿ˜‚

cinder summit
#

No but I have arcs and they could have the same issue thonk

vestal minnow
#

ah true

red gulch
#

No built-in T colliders? Imma head out ๐Ÿ˜ 

vestal minnow
#

you could make it as a compound collider with two cuboid shapes

cinder summit
#

Luckily the only place I use these one way colliders is on cuboids, where it seems to work fine, allowing me to pass trough only one of the cuboid's faces

vestal minnow
#

Yeah I'd imagine most one way colliders to be those 2D platforms or things like dungeon doors like in your case

#

I've gone through all these files in parry now to change types

#

still 436 errors

#

and waiting for the next wave of errors

red gulch
#

Yikes

#

Good work though!

cinder summit
#

I'm starting to wonder if it's called parry because it parried all the clippy warnings instead of solving them thonk

vestal minnow
#

Thanks ๐Ÿ˜‚ nothing to show for this parry fork thing yet tho

#

true

cinder summit
#

Also damn that's a lot of shape files

#

bevy primitives don't have that many files thonk

vestal minnow
cinder summit
#

๐Ÿค”

bounding/
โ”œโ”€โ”€ bounded2d.rs
โ”œโ”€โ”€ bounded3d.rs
โ””โ”€โ”€ mod.rs
primitives/
โ”œโ”€โ”€ dim2.rs
โ”œโ”€โ”€ dim3.rs
โ””โ”€โ”€ mod.rs
vestal minnow
#

hmm, I just realized that changing these to Glam is basically implementing bounding volumes for the Bevy primitives

cinder summit
#

Just use bevy_math and yeet the whole bounding volume module ๐Ÿ˜‚

vestal minnow
#

just switch traits

#

ye

#

I am using bevy_math, just not primitives yet

#

need to get it to compile first

cinder summit
#

I just need a better name than Size and then I think the bounding volume PR would be done ... Ofc it would still need intersection tests and implementations on the primitives so you can use them ๐Ÿค”

vestal minnow
#

impls are for a separate PR but yeah

vestal minnow
#

bang, no wrong assumptions

cinder summit
#

Having something called Unit be a radius of a sphere sounds kinda confusing tho tbh ๐Ÿ˜‚

#

It almost sounds like it should be a constant where every size is of unit length

vestal minnow
#

it's a dynamic unit, whatever you want it to be

#

I wish physics was like that

cinder summit
#

Worst part is that calling it HalfSize works now, but what if someone invents bounding cones and one of the axis is no longer a half size? ๐Ÿ˜‚

vestal minnow
#

That's a future problem ๐Ÿ˜…

#

imagine using bounding cones tho

#

maybe no one has just tried it and it's the most efficient bounding volume thonk

cinder summit
#

Everyone knows that the future of physics is based on bounding cones, CCD and sequential impulses

vestal minnow
#

I mean CCD and sequential impulses are very standard

cinder summit
#

CCD isn't actually that standard tho. Some engines don't even support it ... Even engines without substepping ๐Ÿ™ƒ

vestal minnow
#

I think Box2D has it on by default for everything, PhysX supports it, Rapier supports it, Bullet supports it...

#

I think Roblox supports it lol

#

don't remember

cinder summit
#

I mean obviously bigger physics engines would have it

#

If you want a realistic physics simulation with things that move fast you kinda need CCD

#

But in a game you can totally just work around it as long as you have some number of substeps

vestal minnow
#

yeah

#

we really need Direction2d::new_and_get to get both the direction and the length of the original vector

#

it's painful to do manually

#

PR time I guess...

cinder summit
vestal minnow
#

It is a Blender primitive ๐Ÿค”

peak timber
vestal minnow
#

BoundingTrollFace

peak timber
#

I really hope they optimize this to not take 6 gb per project eventually

#

like, use a global cache or something lol

vestal minnow
#

I'm pretty sure there was a Rust blog post about how they're improving that

peak timber
#

nice

#

oh hey I use nightly

#

maybe I should turn this on

#

for some reason I can't reproduce this anymore

#

time to make a PR and pray I'm not responsible for breaking XPBD dogkek

vestal minnow
#

okay but seriously, why tf would you write this

let _1 = 1.0;
#

I...

#

why...

peak timber
vestal minnow
#

it's used once, and it's not even close to where the variable is declared

peak timber
#

I don't know why anyone would do that, even if they were a beginner

#

tbh

#

I like how small my 65% keyboard is but the number of typos has also gone up 65% since I bought it

#

why is this at the bottom of the docs too

#

in addition to this

#

oh, it's references

vestal minnow
# peak timber

The numbered list thing? They're added automatically because of footnotes

#

yeah

#

dunno if there's a way to get rid of them

peak timber
#

sigh, PR templates

#

lol

#

imagine having to explain your change more than "Add thing"

vestal minnow
#

I usually squash merge with PR description like what Bevy does

#

sigh

let _0: Real = 0.0;
peak timber
#

lmaoo

#

how many are there if you search let _

vestal minnow
#

Most of them are just let _ = smth to discard the return value of a function, but there's 97

#

I've removed quite a few already too

peak timber
#

going to do a sanity check then remove it from draft

vestal minnow
#

Thanks, I'll review when I lose motivation fixing these errors

peak timber
#

lol

vestal minnow
#

I've been doing this for like 6 or more hours probably

peak timber
#

yikes

#

of course I forgot to edit this after CTRL+Ving it lol

#

ok I think there's still potentially an issue with dynamic rigidbodies

#

ill look into it

cinder summit
#

@vestal minnow Does change detection work as I'd expect on CollidingEntities?

vestal minnow
#

I'm pretty sure it's only modified on CollisionStarted and CollisionEnded

#

but those could have bugs ofc

cinder summit
#

As long as it's supposed to work it's fine I guess

#

I'm definitely not working on some really hacky code ... Surely I wouldn't do such a thing thonk

peak timber
#

lol

#

does it involve bounding monkeys

cinder summit
#

Luckily not ๐Ÿ˜‚

peak timber
#

not yet

#

holy mother of god what have I done

cinder summit
#

Something without bounding monkeys at least thonk

vestal minnow
#

lgtm

peak timber
#

lol

vestal minnow
#

from afar it looks really good tbh

peak timber
#

I like the cloud part

cinder summit
#

From afar I just don't know what I'm looking at

peak timber
#

the resolution is bad, fog doesn't work, and wtf is that red thing

cinder summit
#

And then when I look closer I'm even more confused ๐Ÿ˜‚

cinder summit
peak timber
#

yea I need a better cubemap

vestal minnow
#

I like the door that is like 10 meters off the ground

peak timber
#

lol

vestal minnow
#

what is an "orthonormal subspace basis"

cinder summit
vestal minnow
#

the doc comment is even more confusing

Applies the given closure to each element of the orthonormal basis of the subspace orthogonal to free family of vectors vs. If vs is not a free family, the result is unspecified.

cinder summit
vestal minnow
#

Glam doesn't have this ๐Ÿ˜ญ

peak timber
#

fun

cinder summit
#

At least wikipedia has info about what an orthonormal basis is, and I think it's the same thing because inner product space sounds a lot like subspace

vestal minnow
#

I'll just assume it's basically like using Glam's any_orthonormal_vector and running the closure on the return type ๐Ÿ™ƒ

#

we'll see in the tests

vestal minnow
peak timber
#

lol

vestal minnow
#

this might take a while longer

red gulch
#

I've noticed when I set my gravity resource to too high of a number, I start to have my player entitiy clipping through object's its colliding with.

The effect I am going for is the player entity falling slowly under certain conditions.

Can anyone suggest a better approach because I think changing gravity is probably a pretty naive way to implement that lol

#

I imagine there has to be some feature of the engine I'm not aware of yet.

peak timber
peak timber
#

I need to make sure this still runs in the PhysicsSet, I don't know if you can do in_set inside configure_sets

#

looks like you can

#

ok should be ready for review

junior flower
#

Oh, there's no "allowed to drop through soft collision" logic, that's probably what makes it look simpler

cinder summit
#

iirc I rewrote how things get added and removed from the list

#

And yea no dropping trough that doesn't exist in my game ... The doors need to keep you in, not be optional ๐Ÿ˜‚

junior flower
#

A separate cut-down example that really is just "one way" would probably be a decent addition to the examples

cinder summit
#

I think the old code used checks to see if you were already inside to allow you stay in. My code just says "You touched the right normal so you can pass"

junior flower
#

How does the incrementing id in the Local come into it? I can't grok what that's doing

cinder summit
#

It does have the theoretical edge case where you can pass and immediately fall trough again tho ๐Ÿค”

cinder summit
#

It's a workaround cause collision events for removed things aren't very accurate

junior flower
cinder summit
#

Yea, would be easy enough to solve, if it wasn't the desired behavior ... I think it would also need some extra checks so that things spawned under a character are also added to the passing list

#

That's actually 90% of my overlapping entity warnings ๐Ÿ˜‚

junior flower
#

It's amazing just how complicated things become when you really start using them

cinder summit
#

In my case the one way collisions are literally a door problem ๐Ÿ˜‚

junior flower
#

I remember you talking about them a while back. Is it for something like a boss room or somehting?

cinder summit
#

Similar to what you'd see in boss rooms yea. In my case I have it on almost every room with monsters. It's a one way collision so your party can enter after you, but no one can leave (well until you abuse bugs in my character controller to fly over the door)

vale thunder
#

Hello, I'm trying to create pickups for my game that rotate and go up and down when they're on the ground before being picked up (similar to minecraft), however as soon as my little cube lands on the ground, rotating gets weird (probably due to the constant collisions). My code looks like this for the rotation

fn move_and_rotate(mut query: Query<(&mut Transform, &Pickup)>) {
    for (mut transform, _) in query.iter_mut() {
        transform.rotation.y += 0.5;
    }
}```
The cube has a dynamic rigidbody and a 1x1x1 collider
#

any tips?

wraith oriole
#

instead of mutating the transform you could try giving it an angular velocity instead

vale thunder
#

For getting it to bob up and down, would it be recommended to use linearvelocity in a similar fashion then?

wraith oriole
#

yeah using velocity is the way you're supposed to move things, you can modify the transform as well but velocity is meant to be the primary way of doing it

#

you could also do it so the rigid body/collider itself doesn't move at all and have the mesh be a child entity and just animate that, then you don't need to worry about someone missing a collectible because the collider is much larger than the visuals

vale thunder
#

Makes sense! Got it thanks again :D

junior flower
#

Assuming it makes sense, personally I'd separate the bobbing animation/rotation from the physics entirely and instead make them a child object of the rigidbody. Figured it'd be worth throwing it out there in case it was something you'd not yet considered (Edit: I should read more carefully, that's what Scottlecrab suggested last)

vale thunder
#

appreciate it anyways :)

merry tide
#

Sorry, I deleted my previous message. But if I run it like this:

        .add_plugins(PhysicsPlugins::new(FixedUpdate))
        .insert_resource(Time::new_with(Physics::fixed_hz(144.0)))

...would you not expect time.delta_seconds() in a system run on the physics schedule to be more or less constant? Because now I am getting this:

2024-01-02T19:52:11.015934Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0180284
2024-01-02T19:52:11.032644Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0155575
2024-01-02T19:52:11.032870Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0155575
2024-01-02T19:52:11.033225Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0155575
2024-01-02T19:52:11.049415Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0167611
2024-01-02T19:52:11.049745Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0167611
2024-01-02T19:52:11.065430Z  INFO ponkatris_arcade::level_objects::player: Delta: 0.0166252

What is the best way of going about making this as stable as possible?

vestal minnow
#

okay I can reproduce ๐Ÿค”

merry tide
vestal minnow
#

I kinda found the issue, but have no clue why it's not doing what I'd expect thonk

#

The generic Time clock is set to use the physics clock for the PhysicsSchedule like this

*world.resource_mut::<Time>() = world.resource::<Time<Physics>>().as_generic();

But it doesn't seem to actually do it properly?

#

@merry tide If you replace Time with Time<Physics> in your system, does it work?

merry tide
vestal minnow
#

alright, I'll need to try and find why it's not working correctly with Time

merry tide
#

Great, thanks!

vestal minnow
#

Ohhhh I think I found why

#

If you run before PhysicsStepSet::Substeps, it probably returns a consistent delta time, but systems running after it don't. This is because the clock is set back to Time<Virtual> (basically real time) after the substepping loop

#

I just need to make it return to Time<Physics> instead, and it works

#

I'll push a fix tomorrow

merry tide
#

Cool, thanks a lot!

vestal minnow
#

Thanks for reporting the issue!

peak timber
#

have you had a chance to review my PR

vestal minnow
#

still fixing errors ๐Ÿ˜‚

peak timber
#

you have a much longer attention span than I do

#

I would have given up by now lol

vestal minnow
#

I'm decent at doing mechanical brainless activity for long periods of time

peak timber
#

I did rewrite two entire libraries from Python to both TS and Dart, so I guess it just depends on how much I want the thing lol

vestal minnow
#

I guess I really want glam collision detection

peak timber
#

is it faster?

vestal minnow
#

one of the blockers for official physics :P

#

we don't want nalgebra in the dependency tree

#

because duplicate math libs would be annoying and confusing

#

and we can also use Bevy's geometric primitives for the collider shapes

#

and APIs are just nicer

#

speed-wise, idk

#

Glam has some automatic SIMD stuff, not sure if Nalgebra has it... but it does have other SIMD stuff

#

ughhh third wave of errors

#

it was like 30 for a sec

#

getting smaller though

#

although I just commented out simd bvh stuff...

peak timber
#

you've gotta pray to the compiler at night

merry tide
#

BTW, by adding FixedUpdate and that 144Hz-thing, it looks like gravity is very noticeably slower. That shouldn't be the case, right? Is it related to the time-stuff?

torn hedge
#

hi, sorry it's me again.

both cubes are just Dynamic Rigidbodies, and are spawned in like this:

commands
  .spawn((
      Name::new("Cube"),
      PbrBundle {
          mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
          material: materials.add(Color::rgb_u8(124, 144, 255).into()),
          transform: Transform::from_xyz(0.0, 5.0, 0.0),
          ..default()
      },
      RigidBody::Dynamic,
      AsyncCollider(ComputedCollider::ConvexHull),
      GravityScale(2.0),
  ));

the player is again just the dynamic character controller from the examples, with the difference that it's in first person.

im on the git main branch of XPBD, so up2date

any ideas what is happening here? :)

peak timber
torn hedge
#

yeah technically i'm aware of that, dunno why i went with the AsyncCollider.
but it shouldn't really make difference, no?

peak timber
#

doubt it

torn hedge
#

funnily enough i could not reproduce it when the collider is just Collider::cuboid...

vestal minnow
#

primitive shapes are typically more efficient and stable

#

should still work with a convex hull too though

torn hedge
#

with the convex hull i can quite reliabily reproduce the issue shown above :/

vestal minnow
#

but I've mainly seen it for very big faces

#

so I doubt it'd be the issue here...

torn hedge
abstract forge
winter cape
#

I've had similar issues with convex hull colliders when the two objects are moving and collide, just randomly explosive. Not sure what causes it so I also switched to primitive colliders

vestal minnow
#

adding the SleepingDisabled component should fix it for now

#

It's basically trying to mark the bodies as sleeping, but for some reason it instantly wakes them up and causes a small jitter... but in other cases, sleeping works fine

peak timber
#

@vestal minnow physics working as intended (aside from severe input lag) at extremely low FPS now - thanks

floral acorn
#

I'm afraid this is gonna be another one of those horribly obvious questions, but I'm having a little trouble changing a Collider's orientation with respect to its mesh. Given:

    commands.spawn((
        Collider::cuboid(20., 20.),
        MaterialMesh2dBundle {
            mesh: meshes.add(shape::RegularPolygon::new(20., 4).into()).into(),
            material: materials.add(ColorMaterial::from(Color::WHITE)),
            transform: Transform::from_xyz(0., 100., 0.)
                .with_rotation(Quat::from_rotation_z(PI / 4.)),
            ..default()
        },
        Player,
        RigidBody::Dynamic,
    ));

I'm getting:

#

I seem to be missing the magic for having the collider's edges match the mesh's edges here.

#

ah. I think I see... as a child, with separate transform? let's try that here...

#

yep, that was it! Thanks for rubber duckying

final dove
#

are there plans to add interpolation for fixed timesteps in the future? Was working on my own solution and realized it was going to take a bit more grease than I thought

vale thunder
floral acorn
#

Is it possible to turn AngularVelocity off altogether for a mesh? I know I can set it to 0 during an Update system, but that does allow a slight rotation to happen in between updates.

winter cape
floral acorn
#

thanks! ๐Ÿ‘€

floral acorn
#

(for those in the 2d context, it's something like:

    commands
        .spawn((
            LockedAxes::ROTATION_LOCKED,
            MaterialMesh2dBundle {
...
red gulch
#

Is there a way to spawn an entity inside another as a form of drop without causing explosive behaviors? I've tried keeping the original entity in a hash set the spawned entity maintains for collisions to ignore (much like the one-way platform example) but it doesn't seem to do anything.

#

loose pseudocode ```
struct Foo(HashSet<Entity>)
struct Bar

spawn Foo
spawn Bar(HashSet containing Foo.entity) at Foo.transform

// collision handler for Foo and Bar

if Bar.hashset contains Foo.entity {
if !penetrating
Bar.hashset.remove(Bar.entity)

remove collision

} else {
fire event!
}```

#

the idea is to spawn Bar inside Foo and have their collision ignored until they separate, then once they collide again, we can fire our event

fallen citrus
#

by mutually exclusive collision flags I mean that neither belongs to any group that the other interacts with

#

If you don't make a duplicate collider and their flags are mutually exclusive then I think there would be no way to detect when they are no longer overlapping. But now that I think of it, having this whole thing be a built-in feature would be very useful. I also run into this scenario right now but have a dumb solution of gradually scaling up the orphaned collider from a scale of 0.01

red gulch
red gulch
#

Any reason why a CollisionEnded event would fire when the left side of my entity exits the collision, but not when the right side exits the collision?

#

Bear in mind I have in no way even looked at how the normals of either entity are interacting

merry tide
#

@vestal minnow Did you make any progress on the timing with FixedUpdate? I feel bad badgering people during the weekend, so let me add to this query: Happy weekend!

vestal minnow
merry tide
#

It feels like what I want to do should be relative simple to do. I just want a bouncing ball somewhat deterministic.

#

I also had a playtester telling me that the physics were affected by which screen he was playing it on.

vestal minnow
#

Yeah I meant to fix the time inconsistency but got invested in a big collision detection thing, my bad; I'll make a PR to hopefully fix it now

vestal minnow
merry tide
vestal minnow
#

As for gravity being faster, make sure your Time<Fixed> Hz and Time<Physics> Hz match

#

If Time<Fixed> is 144 Hz and you have e.g. Time::new_with(Physics::fixed_once_hz(60.0)), that means that you will advance the simulation by 1 / 60 seconds every 1 / 144 seconds, so the simulation will essentially be running at double speed

merry tide
#

Let me try to repro it, I think I saw it in stranger circustances.

#

Perhaps I am mistunderstanding, but, would you expect these to perform similarly visually?

.add_plugins(PhysicsPlugins::default())

...and...

.add_plugins(PhysicsPlugins::new(FixedUpdate))
.insert_resource(Time::new_with(Physics::fixed_once_hz(144.0)))

?

vestal minnow
#

Have you configured the timestep used by FixedUpdate?

#

It's 64 Hz by default iirc

#

Time<Physics> is separate

merry tide
#

Making it 64hz does indeed make it run similarly (eyeballing it). Thanks!

vestal minnow
#

yeah they should be the same; either both 64 Hz or both 144 Hz (or whatever value you want)

merry tide
#

Perhaps that last code is enough to also fix the timing reporting into the system also?

vestal minnow
#

or, explicitly specify Time<Physics> instead of Time in the system

merry tide
#

Ah, OK. But should I, being a noob, just be running this from github as the dependency you think?

vestal minnow
#

If you want the fix now, then yeah you could

merry tide
#

Well, I feel I know you guys better than I know my parents now.

#

I will just do that, great!

vestal minnow
#

(or I didn't merge yet but will soon)

#

just waiting for tests

#

oh they're done lol

#

I'll merge now

merry tide
#

Great. And should I be using this: features = ["enhanced-determinism"]?

#

I read the docs, BTW. Haphazardly. ๐Ÿ™‚

#

The build system in Rust is actually pretty insane.

vestal minnow
merry tide
#

That's cool.

#

This is the reported delta time now:

2024-01-05T16:40:48.159156Z  INFO ponkatris_arcade::level_objects::player: Time: 0.015625
2024-01-05T16:40:48.175372Z  INFO ponkatris_arcade::level_objects::player: Time: 0.015625
2024-01-05T16:40:48.192755Z  INFO ponkatris_arcade::level_objects::player: Time: 0.015625
[...]

Seems to just be stable, great!

#

Thanks so much!

vestal minnow
#

No problem! This was a good bug to fix

#

or the bug wasn't good, but fixing it was ๐Ÿ˜…

merry tide
#

Great! ๐Ÿ˜„

graceful glacier
#

Hello ๐Ÿ‘‹
In the process of moving from Rapier3D to XPBD I found an issue probably related to applying external forces to the car.
In my code I now use RayCaster and it's way cleaner ๐ŸŽ‰ However, as you can see in this vidรฉo, it seems that the external forces (that I set to non-persistent) are not applied correctly when the car is rotated. I multiply the car rotation to the force point but it didn't fixed the problem. Would you mind taking a look at the changes and help me fix the issue?

graceful glacier
cinder summit
#

How would distance constraints behave when I put them on two physics based character controllers? Would it make the controllers pull on eachother, or just prevent any further movement than the specified distance?

royal helm
vestal minnow
#

Yep

royal helm
#

or at least try to not

#

Might lose or gain some mysteriously because integration is hard

vestal minnow
#

There was also a bug where distance constraints forced the distance to always be equal to the rest distance regardless of the min/max distance limits, but that should be fixed on main (i.e. you can make it only have a max distance, not doing anything at a smaller distance)

merry tide
#

I am seeing some strange stuff when changing the rotation of the level object, and I think I am doing it incorrectly. Can I share a video? I am not using the controller at all, it seems to be sticking to the wall.

#

I am changing the rotation through a Query<(&mut Rotation, &ObjectRotation)>.

#

And just setting it using ```rust
*rotation = Rotation::from_degrees(
object_rotation.original_rotation
+ (object_rotation.degrees_per_second * current_game_time.as_secs_f32()),
);

Which I think is probably wrong.
graceful glacier
#

Hey bevy-physicians ๐Ÿ‘‹
I would like to know if you have any idea why my car is juddering/jiggling. It seems maybe related to XPBD and more specifically the order in which I update the camera's target.
The strange thing is that my car is acting correctly on my laptop which runs the game at 60 fps (video #3), that's the only main difference as it doesn't work great at 140 fps.
The video #1 and #2 shows two cameras targeting the car, the first one is also following it.
I am using the bevy_dolly crate for the camera.
Do you have any clue on when I should trigger the camera's update? I already tried:

  • Running both dolly camera update system and the camera position itself after PhysicSet::Sync
  • Using Position and Rotation instead of Transform when moving the camera
  • Using bevy_framepace to limit the fps to 60.
  • Configuring the time step to be fixed at 60hz (all above videos are using this setting already).
graceful glacier
# graceful glacier Hey bevy-physicians ๐Ÿ‘‹ I would like to know if you have any idea why my car is j...

Aaaaaand... while writing this long message I understood that my laptop was running at 60 fps with a physics timestep of 60hz but my desktop was running at 140 fps also with a 60hz physics timestep.
I therefore fixed this bug by setting a physics timestep to a fixed 144hz. You can try this game by cloning my repo (press i to hide the debug tools).

.insert_resource(Time::new_with(Physics::fixed_hz(144.0)))
merry tide
# merry tide And just setting it using ```rust *rotation = Rotation::from_degrees( ...

It behaves the same if I write it like this:

      for (mut transform, object_rotation) in object_rotation_query.iter_mut() {
            // convert the degrees per second to a rotation in radians
            let rotation = object_rotation.original_rotation + (object_rotation.degrees_per_second * current_game_time.as_secs_f32());
            let rotation_in_radians = rotation.to_radians();
            transform.rotation = Quat::from_rotation_z(rotation_in_radians);
        }
merry tide
#

Is it because of the system ordering?

                update_current_game_time
                    .after(PhysicsStepSet::SpatialQuery)
                    .run_if(in_state(GameState::Running)),
                object_rotation
                    .after(PhysicsStepSet::SpatialQuery)
                    .after(update_current_game_time)
                    .run_if(in_state(GameState::Running)),
cinder summit
vestal minnow
#

i.e. don't use apply_positional_constraint or whatever it's called in the constraint and handle it manually

lofty lynx
#

Something is off with my raycasts, and I can't figure out if I'm doing something wrong, but my rays are always at the origin, this is confirmed both by the behaviour, and also by the debug rendering plugin. I know I've likely got something off with the systems, as I'm doing networking and I'm not currently running xpbd in my network schedules, but that shouldn't affect this. I've checked that global transforms are being propagated correctly, so it's likely not related to that either, do you know what might be up? I can send you the repo in case it's not obvious what's happening

#

They're attached to moving bullets and have the raycast origin as (0, 0) for the record

vestal minnow
#

I think the RayCasters/ShapeCasters need to be on an entity with a RigidBody or Collider at the moment

lofty lynx
#

Ahh, yeah I am missing that

vestal minnow
#

I meant to fix this, but got a bit sidetracked; a workaround for now is to just add RigidBody::Static or RigidBody::Kinematic, shouldn't affect behavior in this case

lofty lynx
#

That works! Thanks! It is a bit unexpected yeah, I was specifically using a raycaster for these bullets because I didn't want to have to deal with the ccd that would be required if they were normal colliders ๐Ÿ˜‹

atomic wigeon
#

Hm, does anyone have any idea why adding a RigidBody to some tile entities would cause them to:

  1. No longer render (they have a Sprite component)
  2. Plummet performance (140fps -> 35fps)

There are about ~280 entities with rigid bodies. For reference, I get ~140fps in the many_shapes example and ~30fps in move_marbles. The rigid bodies are static, and are applied to the walls. I have the PhysicsPluginDebug enabled, but don't see the gizmo debug outline on the walls.

I've verified that the tiles aren't moving and that the collider size is non-zero - it's a (32,32) cuboid.

I've attached 3 screen recordings for context.

  1. No rigid bodies, just colliders. This runs smoothly and renders the wall tiles as expected at ~140fps.
  2. Rigid body with colliders. This doesn't render the wall tile sprites and is unperformant, rendering at ~30fps.
  3. Rigid body without colliders. This doesn't render the wall tile sprites but is performant, rendering at ~140fps.

I'm a bit stumped so would appreciate any insight.

#
let collider = Collider::cuboid(tile_size.x, tile_size.y);
let rigid_body = RigidBody::Static;

The relevant components ^

cinder summit
#

Maybe something with the sync plugin? On rigid bodies it tries to take the position/rotation and update the Transform wit them

#

If they somehow end up at 0, 0, and it also happens to at least one dynamic entity, the collisions there would probably explain the performance issue ๐Ÿค”

noble pier
#

Just porting my code from using rapier to xpbd and very happy with xpbd so far.

However, I have a issue with a buoyancy simulation where I have a raft that is a rigid dynamic body with one collider attached as a joint in each of the four corners, acting as pontoons.

The raft spawns a bit over a ocean surface. It initially falls down nicely, but as soon as one of the corner pontoons comes in contact with the water surface and an external buoyancy force is applied to make the pontoon float, the raft starts spinning around much more than expected. (Note that the ocean is not directly handled by physics engine. By "contact" I mean that the water height is compared to the translation.y of the pontoons. Forces / damping are then applied manually.)

It calms down after a while and does not exhibit this spinning behavior anymore. At a first glance, it seems like the very first time a force is applied to the pontoons, the problem arises, even when testing with very small magnitudes.

Any idea what might be causing this problem?

I noticed that the documentation for ExternalForce set_force mentions that "... the torque caused by any force will not be reset.". Not sure if what is described there could be causing the initial exaggerated spinning(?)

For more details, the two relevant files would be as follows
https://github.com/claudijo/pirate-sea-jam/blob/origin/ocean_shader/src/plugins/buoy.rs

https://github.com/claudijo/pirate-sea-jam/blob/origin/ocean_shader/src/plugins/raft.rs

Cheers!

noble pier
noble pier
vale thunder
#

A little offtopic but does xpbd provide a way to render collision boxes or are you guys just using bevy gizmos for that

vestal minnow
#

Add PhysicsDebugPlugin

vale thunder
#

oooh

#

sick ty

vestal minnow
#

it uses gizmos under the hood as well

vale thunder
#

i feel like i googled so much without finding this ๐Ÿ˜”

#

thank you though i appreciate it this will be useful

vestal minnow
#

haha no worries

peak timber
#

yo my PR got merged

#

dope

#

I'll be waiting for the flood of issues to be opened about how it doesn't work and how I broke everything kekw

noble pier
noble pier
# noble pier <@545959292281552928> Let me first congratulate you on a very nice lib. Hope my...

Sorry for spamming the thread, but I've made a small code modification to exaggerate the issue and a short clip that shows the what's going on....

The minor code change is just to make sure a minimum none-zero force in the positive Y-direction is applied for each frame, which will slow down the falling of the raft.

As seen in the clip, the very first time any of the corner pontoons hit the water, the raft goes a bit haywire, but subsequent "bounces" in the water plays out as expected and are much less explosive.

wraith oriole
#

have you tried changing the float system to run in FixedUpdate and also change the force so it isn't persistent, doubt it'll change much but there could be something funky going on just because of that

#

you could also change the center of mass so it's below the raft, which'll make it harder to tip over

noble pier
peak timber
#

when they finally settle on top of each other, it's like a massive explosion goes off and they all launch apart

#

probably related

noble pier
# peak timber probably related

Yeah, maybe. I guess there are many things that can cause colliders to explode. Not so easy to know if it is related. I have a hard time figuring out what is going on here.

Seems like if the raft is falling without any angular velocity it will go haywire when an upward buoyancy force is applied at water level, start spinning and consequently gain some angular velocity, and after that when hitting the water, it will go into the water much more gently.

Also, it only seems to be a problem when having multiple colliders (pontoons) attached as fixed joints to single parent.

But it beats me what the root cause could be.

vestal minnow
#

@noble pier Sorry for not responding, I've been kinda sidetracked working on collision detection stuff and Bevy's new primitives.
I'll try if I can figure out the issue

noble pier
pulsar flower
#

im making a 2d game editor/playground and i spawn rigid bodies with different colliders, how can I edit existing colliders? I dont understand the data types that the colliders are built from.
im thinking adding a component to each entity with a struct that contains the fields that are used to make a new shape like cuboid(x,y), and then when I want to edit the collider shape, I will despawn it and spawn an updated collider (I need to define a different struct for each kind of shape).
is there an easier way?

vestal minnow
#

alternatively, set the collider component like

*collider = new_collider;
fair fractal
#

what are these yellow circles being drawn on my rigidbodies with the debug renderer?

#

can't figure out how to turn them off

vestal minnow
vestal minnow
#

I think you can also disable it by disabling the axes

fair fractal
#

I'd rather stick witha stable build. I can just turn the axes off though I guess, don't really need them either

vestal minnow
vestal minnow
fair fractal
#

okie thanks ๐Ÿ‘

#

yup that seemed to work

pulsar flower
vestal minnow
#

And then that has methods to get the specific type of shape, but it's a bit painful since it's an Arc<dyn Shape> IIRC

merry tide
merry tide
#

It seems like it is just broken that something next to something that is rotating is acting like that.

fair fractal
merry tide
fair fractal
#

Dynamic? Kinematic? Static?

merry tide
#

No, it is an actual Static body. This is probably fixing my issue!

fair fractal
#

Yeah I'd try changing it to Kinematic

#

but even then I could see the issue continuing

#

you might have to manually set the rotational velocity too

merry tide
#

Let me try it, but that makes a lot of sense.

#

I am in a broken branch, but I will test this as soon as I can. And I am sorry about being snooty.

fair fractal
#

haha didn't sound snooty to me

merry tide
#

I was a little snooty. ๐Ÿ™‚ I've been up all night. This was never a dealbreaker to me, but it makes sense when you say it like that.

noble pier
# vestal minnow <@626852373519794176> Sorry for not responding, I've been kinda sidetracked work...

@vestal minnow, Hope your work with collision detection stuff is progressing well.

Sorry to bother you again, but I made some small progress getting a grip of my issue with initial explosive behavior when my joints are affected by external force for the first time.

I noticed that commenting the following lines in the function apply_angular_correction() from the file angular_constraint.rs will remove the symptoms.

*body1.rotation += Self::get_delta_rot(rot1, inv_inertia1, p);
https://github.com/Jondolf/bevy_xpbd/blob/main/src/constraints/angular_constraint.rs#L69

*body2.rotation -= Self::get_delta_rot(rot2, inv_inertia2, p);
https://github.com/Jondolf/bevy_xpbd/blob/main/src/constraints/angular_constraint.rs#L72

This makes the joined entities rotate freely in relation to each other, and prevent the initial tension that eventually snaps (in lack of better words) that is generated when the joints initially hits the water and are affected by an external force (buoyancy).

This is obviously not the correct fix, but does it tell you anything or give you an idea of what is going on?

(It seems like it would be less weird if the raft bounced dramatically each time the buoyancy force was applied, not just the first time the raft falls down without any angular velocity)

vestal minnow
#

Could you try normalizing the rotation after those lines?

noble pier
# vestal minnow Could you try normalizing the rotation after those lines?

Thanks. Looked kind of promising, but unfortunately didn't help.

My guess is that there is an issue when applying an external force to one or more colliders/dynamic rigid bodies that are joined to a common collider/rigid body. When the force makes the angular velocity go from 0 to a none-zero value the explosive behavior occurs.

noble pier
merry tide
fair fractal
merry tide
fair fractal
#

Fair

#

I guess the "proper" way to do it would be too use a dynamic body and a motor joint to keep it in place and rotate it

#

Or i guess you could just not use joints, give it a higher dominance than the Pachinko ball and a gravity scale of 0 and then apply a rotational velocity to it

vestal minnow
#

I'm pretty sure the rigid body type shouldn't really matter here

merry tide
#

It feels like it should just work. I think it does in Box2D. But it is not a pressing issue.

vestal minnow
merry tide
#

Yes, but is the problem that I am applying the force incorrectly?

#

Really, it isn't a pressing issue, but it would be fun if it worked.

fair fractal
# merry tide It feels like it should just work. I think it does in Box2D. But it is not a pre...

Yeah I think a lot of other engines usually infer velocity from Delta rotation/position for kinematic bodies but it seems like bevy xpbd doesn't. The problem is the collision solver needs this velocity information to correctly resolve the collision I believe. Thats what it looks like to me at least in the video you're posting. Just a funky artifact from an improper collision resolution

vestal minnow
#

If you're setting the rotation manually, that could potentially cause collision issues unless you run the system in a very specific part of the schedule, so it's generally better to use AngularVelocity. But the speed here is slow enough that I doubt it's the issue

fair fractal
vestal minnow
#

Setting the velocity will move it at that speed

#

But the engine won't touch the velocity (so e.g. collisions, joints and so on won't do anything)

fair fractal
#

Ooh nice. I did not know that ๐Ÿ‘€ that seems super useful

vestal minnow
#

So it's still user-controlled

merry tide
#

Is it simple to rewrite the code I already shared to make it apply angular velocity instead? If I want to rotate it at a specified degrees per second?

vestal minnow
#

where ang_vel is the AngularVelocity component

#

it's in radians per second but you can just convert your degrees to that

merry tide
#

Yeah, that doesn't really work for me either as I need to be able to deduce the current rotation from the game time, etc. But I am not going to worry about it right now.

#

I tried making it so that I set the rotation and the angular velocity, tho. Perhaps that is the correct thing to do?

#

It does something, I probably just did it all wrong. ๐Ÿ˜„

#
pub fn object_rotation(
    mut object_rotation_query: Query<(&mut Transform, &mut AngularVelocity, &ObjectRotation)>,
    current_game_time: Res<CurrentGameTime>,
) {
    // Check that we have a current game time
    if let Some(current_game_time) = current_game_time.0 {
        for (mut transform, mut angular_velocity, object_rotation) in object_rotation_query.iter_mut() {
            // convert the degrees per second to a rotation in radians
            let rotation = object_rotation.original_rotation - (object_rotation.degrees_per_second * current_game_time.as_secs_f32());
            let rotation_in_radians = rotation.to_radians();
            transform.rotation = Quat::from_rotation_z(rotation_in_radians);
            angular_velocity.0 = rotation_in_radians;
        }
    }
}

Am I just being a dumbass?

vestal minnow
#

Setting the angular velocity probably isn't that helpful if you set the rotation anyway

merry tide
#

Yeah, I am going to be a Gen Z'er and say that this "yeets" the ball into outer space. ๐Ÿ™‚

vestal minnow
#

or to be precise, that'd be the change in rotation after some delta time

merry tide
#
pub fn object_rotation(
    mut object_rotation_query: Query<(&mut Transform, &mut AngularVelocity, &ObjectRotation)>,
    current_game_time: Res<CurrentGameTime>,
    time: Res<Time>,
) {
    // Check that we have a current game time
    if let Some(current_game_time) = current_game_time.0 {
        for (mut transform, mut angular_velocity, object_rotation) in object_rotation_query.iter_mut() {
            // convert the degrees per second to a rotation in radians
            let rotation = object_rotation.original_rotation - (object_rotation.degrees_per_second * current_game_time.as_secs_f32());
            let rotation_in_radians = rotation.to_radians();
            transform.rotation = Quat::from_rotation_z(rotation_in_radians);
            angular_velocity.0 = rotation_in_radians * time.delta_seconds();
        }
    }
}

This actually works a little. It seems to almost do it. But the walls get jittery, and it still snuggles up to the wall every once in a while. Not using the absolute transform.rotation makes it not work the way I want, because I need the current rotation to be a function of time to make the level somewhat deterministic.

#

Would it be strange to deduce the angular velocity based off the delta in frames that follow each other, perhaps as an option?

vestal minnow
#

I think that might be similar to Rapier's RigidBody::KinematicPositionBased but I don't remember exactly how it works

merry tide
#

Yeah, cool. So it isn't an insane idea, I guess. Thanks for the help, I will do this next episode. ๐Ÿ™‚

#

Do you think implementing something like that would be a thing for an absolute noob like me? Is it something you would want in the codebase?

vestal minnow
#

I'm not sure if I want it in the codebase at the moment, but maybe? I just haven't seen it in engines other than Rapier before

#

It might also be more of a character controller thing than a physics feature

#

I don't really want the split into RigidBody::KinematicVelocityBased and RigidBody::KinematicPositionBased since I find it to be a bit weird, but a separate component could maybe be alright

merry tide
#

Sure, cool. ๐Ÿ™‚

vestal minnow
#

The way this would probably be implemented though is to just set the velocity in IntegratorPlugin based on the difference in Position and PreviousPosition, divided by the delta time

merry tide
#

That would make sense. Perhaps you could just add it is another system in the pipeline that makes some other values available.

balmy glacier
#

what's the units for collider density? kg/m^3?

vestal minnow
#

or I guess it technically doesn't have a specified unit, but if you treat distance units as meters and mass as kilograms then yeah

#

Parry doesn't give them explicit units iirc

balmy glacier
#

cool. if you don't have established units then it makes sense to set the default to 1.0

fair fractal
#

Would you recommend working at a scale where 1 unit = 1 meter for the physics engine? It's what I'm doing rn but it feels a bit weird to be setting the camera projection scale to 0.01 ๐Ÿ˜…

#

or would it be better to just scale up my forces and gravity and keep 1 pixel in bevy as 1 pixel on the screen

vestal minnow
#

Yeah it's generally recommended to keep values reasonable like 1 unit = 1 meter, since having bodies be e.g. thousands of units in size could potentially cause stability issues

#

but I haven't really noticed it myself so I'm not sure if it's a common issue in practise

#

Ideally we'd probably have a physics scale like Rapier so that you could use pixels but they get internally converted for the physics engine

fair fractal
#

honestly the physics scale in rapier confused me when I used it

#

it seems like sometimes units get converted and sometimes they did not

vestal minnow
#

yeah it's confusing, especially the way it's documented

#

seb told me it doesn't do anything from the user's view point, only internally

#

I'll try to find the message

fair fractal
#

lol no worries

#

is seb a developer at dimforge or something

vestal minnow
#

Sรฉbastien Crozet, dev (owner?) at Dimforge, main author of Rapier, Parry, Nalgebra and their predecessors NPhysics, NCollide, etc.

#

Here's the physics scale convo #math-and-physics message

fair fractal
#

sweet thanks

atomic wigeon
#

Do CollidingEntities online retain collisions for a few frames? I'm looking for a way to find all active collisions when a player is standing on top of a Sensor / Collider, rather than the discrete moment when the collision starts / ends.

Ideally I don't have to write something to track this state myself, though I can if needed. Assuming a solution exists in the crate that I'm missing.

cinder summit
#

Not 100% sure how it behaves if a collision started that physics update and ended before the last substep tho

junior flower
#

https://github.com/Jondolf/bevy_xpbd/blob/main/src/plugins/setup/mod.rs#L144-L145
Unless I'm misunderstanding, it looks as though ReportContacts (which is when report_contacts runs and updates CollidingEntities) happens after all sub-steps, so it seems as though it could be skipping over collisions in the situaion NiseVoid describes entirely?

https://github.com/Jondolf/bevy_xpbd/blob/main/src/plugins/collision/contact_reporting.rs#L152-L188
CollidingEntities appears to hold the entities for the entire time they're in contact instead of only being present for a single frame

#

It may be doing something inside the substeps to make sure that a momentary collision is included, though. I've not read it close enough but Jondolf can probably answer to that for sure

atomic wigeon
#

That's helpful context, thanks both ๐Ÿ™ I'm seeing a handful of updates where the collision is persisted, then I get a CollisionEnded event and CollidingEntities is empty. Probably some bespoke issue with my setup ๐Ÿ˜… I was wondering if colliders sleeping may be involved, but after adding SleepingDisabled I'm seeing the same behavior.

Going to test a bit more.

junior flower
#

CollisionEnded is triggered on the same conditions as the other entity being removed from CollidingEntities, so that condition sounds expected

#

(it's the code in the bottom half of the second link I posted)

atomic wigeon
#

Looking at the sensor example in the xpbd 2d crate, it looks like the collision start / end events happen at the "point of collision". CollisionEnd fires while the pill is overlapping the pressure plate. Let me know if I'm misunderstanding.

Based on the code you linked, if CollisionEnd fires, then it was also removed from CollidingEntities. This would track with what I'm seeing in my game, but isn't the behavior I'd expect.

#

See recording ^

junior flower
#

That sure looks incorrect!

#

I think I remember seeing someone talking about when a collider is perfectly overlapped it stops detecting it

#

perfectly overlapped + not moving*

atomic wigeon
#

Ah, that could be it. If so, I'll need to write a work-around...

junior flower
#

Trying to see if I can see where that info went. I'm pretty sure I saw someone talking about it.
I assume you're using the released version and not the main branch from github? (Asking this because it'll help me figure out where I need to look for it)

atomic wigeon
#

The recording of the sensor example I sent is using the main branch of bevy_xpbd, just a local clone of the repo.

My game where I'm seeing the same thing is on bevy_xpbd_2d = "0.3.2". Looks like 0.3.3 is the most recent, I can test it there rq too

#

Looking at your link ๐Ÿ‘€

junior flower
#

But if you're using the main branch.............

atomic wigeon
#

Looks good, actually ๐Ÿ‘ I had a stale clone, just pulled. The example is good now ๐Ÿ™‚

#

Going to check if this was included in the 0.3.3 release or if I should point my game towards the main branch

#

Thanks for your help โ™ฅ๏ธ

junior flower
#

Glad to be of service!

vestal minnow
#

Idk what's a good way to pull specific changes from the commit history without including any breaking changes so I made the release pretty small since I did it semi-manually

atomic wigeon
#

one thing on the main branch I'm noticing is that I need a rigidbody and a sensor for collisions to be picked up. on 0.3.2 i believe just a sensor was sufficient. do rigidbody's have a purpose if you don't need physics?

noble pier
#

Curious if there are any showcase projects that successfully combine bevy xpbd 3d together with rollback networking, eg bevy ggrs? What's happening in that space?

vestal minnow
# noble pier Curious if there are any showcase projects that successfully combine bevy xpbd 3...

bevy_gaff is a WIP demo that uses bevy_xpbd, bevy_ggrs and bevy_matchbox for p2p networked physics using rollback. It only syncs inputs and relies purely on determinism, which can currently cause desync issues since we don't seem to have perfect determinism yet (in bevy_xpbd or bevy_rapier)

There are also other larger projects that have networking working with bevy_xpbd (syncing more than just inputs), but I don't think they're open source

balmy glacier
#

I have a bunch of bricks that I'm trying to connect with fixed joints. I've checked the colliders and they're correct. if I set them to dynamic bodies and don't add the fixed joints, they tumble like I'd expect and I don't get any warnings. when I add the joints, they explode on the first frame and give me a ton of intersection-on-spawn warnings. the second image is of the joints, with anchor color in red and separation color in blue. I'm adding the joints with just FixedJoint::new(entity_a, entity_b). should I be setting the joint anchors differently?

sleek thicket
fair fractal
#

I'm confused about the PhysicsSet System Set. I assume that if I want to run a system after the physics engine does its thing I can specify my_sys.after(PhysicsSet) but it's unclear what schedule I should be putting it in?

#

would it just be the PhysicsSchedule?

#

like I want it to run after PhysicsSet::Sync

#

after a bit more digging in the source it looks like maybe I should put it in PostUpdate?

cinder summit
fair fractal
#

oo

#

i just used default

#

didn't realize you could add it to different schedules

#

is that how you would get it to update at a fixed interval?

cinder summit
#

You can also configure the physics time to give you a fixed interval, but using FixedUpdate can be a lot simpler if you also have other things running at a fixed rate

fair fractal
#

Why am I getting contacts even when objects are not actually touching? In this video the contact points are rendered in blue. As you can see they are appearing long before the collisions between the colliders (which are rendererd in orange)

#

it's problematic because when I check for collisions in Res<Collisions> the contacts are showing up there too, when objects aren't actually colliding

#

there are contact manifolds in the collisions too, not just empty collisions

finite blaze
#

I wonder how far down one needs to go for float determinism!
For example this blogpost says that calls to external libraries (like sound libs, etc) can change the float precision, so one needs to change it back
https://gafferongames.com/post/floating_point_determinism/

finite blaze
#

On several reads of blogposts from that linked one, take it with a grain of salt. It comes from a person with a vested interest on complicating game networking, removing net neutrality and bidding for sections of low latency connections..

noble pier
finite blaze
#

Well, compensating means extrapolating or predicting client side (quite typical). Thing is if you have determinism you don't need to send state, you can send only inputs of the system which reduces networking for example. It's all tradeoffs

noble pier
#

But how often do you think that you need to send "keyframes" / state in worst case scenarios?

finite blaze
#

It depends on the type of game. RTS with thousands of units? Prohibitive

#

(E.g age of empires, total annihilation)

noble pier
#

Right.

finite blaze
#

(I just read all blogposts from the linked page I posted, he describes several strategies and their tradeoffs, quite a good read)

noble pier
#

Will add it to my read list. Thanks. Just looking into implementing multiplayer into my hobby game project.

vestal minnow
# finite blaze I wonder how far down one needs to go for float determinism! For example this bl...

With Rust, I'm pretty sure fp determinism should be possible by just using libm math for operations that are platform-specific (e.g. especially transcendental functions like sin, cos, atan...).

Glam has a libm feature for this, and bevy_xpbd uses it through the enhanced-determinism feature. This does make things a bit slower though since it doesn't use intrinsics and instead uses the same implementations for each platform

finite blaze
#

I wonder what performance penalty there is if any

vestal minnow
#

But I think there's currently at least one sin that doesn't use libm in 2D so it's probably not working perfectly in bevy_xpbd atm

#

that one is easy to fix though of course, just libm::sin

finite blaze
#

I struggle a bit coming up with things that would need deterministic physics apart from debugging. The best I can think of is being able to do p2p and delegate object calculations to clients in a round robin manner, as an anticheat

sleek thicket
cinder summit
vestal minnow
#

Things like Linerider too, you don't want the track to just not work on some platforms

cinder summit
merry tide
#

This is before anything I was yapping about regarding to rotation. I just cannot make this work:

#

It should have a ball be able to bounce straight up, but it doesn't. And changing the angles on the walls flips which way the ball is going. But. If you do this:

#

If I do this, it bounces perfectly up.

#

So I don't even know, it seems to work with 45 degrees but not with another set of degrees.

vestal minnow
merry tide
#

They are both two colliders, I never merge colliders here.

#

I can show you how this crumbles so early, the same level with having something that is not 45 degrees seems to be solved in a way that always makes the ball bounce off to a random side.

#

You would expect this to behave the same without touching the controls.

#

But it doesn't.

#

These are static wall-objects, BTW.

#

It seems like it solves the correct bounce up by accident. It just feels a little arbitrary.

#

And if you all know a game like TrackMania, you should be on board with the idea of having something deterministic and timeable.

vestal minnow
# merry tide So I don't even know, it seems to work with 45 degrees but not with another set ...

This was discussed some time ago already, but the issue here is basically that the ball first bounces from one wall and then the other instead of accumulating the forces into a single impulse where the X coordinates would cancel out.

I think the reason it works with 45 degrees is that the initial bounce goes perfectly sideways, so the second bounce will go perfectly upwards (assuming there is enough restitution). With other angles, it's probably more likely to initially bounce in a slightly different direction, which also affects the second bounce

(here's a lil picture showing the situation)

merry tide
#

That makes sense. ๐Ÿ™‚ And that is what you see in the world.

#

But if it is 35 degrees it makes no sense, and it is not what you see in the world.

#

And that is arbitrary.

vestal minnow
#

But yes, determinism is an issue here too

merry tide
#

I think I was wanting 1, but that was just because it seemed like what I could want intuitively.

#

Full disclosure, as much as I am getting to work here, most of the things I am a total noob at.

#

But my guess would be that "it's 2023" (when I started) and a ball bouncing on walls wouldn't be that much of an issue.

vestal minnow
#

Have you tried with the enhanced-determinism feature by the way?

merry tide
#

Yes, it is turned on.

#

This is my Cargo.toml-file for that part.

#

It just irks me to no end. We have the coolest physics engines, but we really cannot do Breakout.

vestal minnow
#

I might try some things with your project if that's fine, I believe I should still have access

merry tide
#

Hold on. If you're going to do that, and I welcome you. I am on that different branch now.

vestal minnow
#

alright, thanks

merry tide
#

I have sort of merged them into a single thing, but you need to start it as the editor if you're going to test it.

#

It's all in the README.

#

Again, it is no real biggie. But I just want my balls to bounce. ๐Ÿ™‚

#

I can also just make a WASM-version of it that shows it and push it to the site.

#

You will find a lot of nasty code in there. But I am trying to make it better. Day by day. ๐Ÿ™‚

#

I have messed around a lot with the physics settings also, so if they're not particularly correct now, sorry about that.

vestal minnow
#

@merry tide Do you have an example of non-deterministic behavior? For me it's always bouncing the same way on restart (but not directly upwards like you said)

merry tide
vestal minnow
#

Ah, makes sense

merry tide
#

Yeah, I was unclear in how I worded myself.

vestal minnow
#

So the "not bouncing directly upwards" thing is the only issue here?

merry tide
#

Well, I think that isn't the only issue I am looking at. I think what you are talking about with the 1) solver is what I am looking for.

#

Because it fails like this in so many ways.

#

But that would be me rehashing the stuff we've been talking about before.

vestal minnow
#

I'll see if I can implement the Jacobi solver as an option in a reasonable way

#

It would require some refactors to how constraints are handled though

merry tide
#

Keep in mind this isn't a huge issue. It is "just me" and my needs. And I think a lot of people don't really need this. But I just find it odd that you cannot really do a predictable breakout-clone. But now I am just saying the same things again. So look at this a couple of times before deciding to realizing it.

cinder summit
merry tide
#

But, that being said, I am pretty sure I cannot realize what I am trying to do if it works the way it currently does. And that seems also a little strange.

merry tide
cinder summit
#

Physics behave in a certain way in reality, and users will expect it to be the same in a game, unless the physics are very clearly weird

merry tide
#

You cannot predict the behavior from the physics setup. But you can predict it if you're seen it before in the exact same configuration, which makes it deterministic.

#

Yes. For me they are clearly weird, but again, I think I am strangely representing somewhat of an edge case, I think.

vestal minnow
#

Tbf real life physics isn't necessarily perfectly deterministic either, so perhaps being indeterministic is more realistic thonk

cinder summit
merry tide
#

Yeah, but can I redescribe the breakout-case? Where that doesn't really work? Which makes tesselation not really work either.

vestal minnow
vestal minnow
cinder summit
#

A better sarcastic comment would've been "If unity can get away with not being deterministic, maybe that's the more normal approach" ๐Ÿ˜‚

vestal minnow
#

and Unreal I believe

merry tide
#

I think we can agree that for my game there is a lot of CPU power for solving this specific thing. And I would just like to have that as an option.

#

Unity doesn't have this issue as far as I can tell.

vestal minnow
#

Yeah it uses Box2D for 2D which uses sequential impulses

merry tide
#

OKok.

vestal minnow
#

Which doesn't have the issue of positional corrections mid-solve

merry tide
#

Yeah, exactly, that makes sense. That describes it perfectly.

cinder summit
vestal minnow
#

yeah

cinder summit
#

I have no clue what "sequential impulses" actually are tho ๐Ÿ˜‚

vestal minnow
#

it's weird saying "sequential impulses for xpbd" lol

merry tide
#

I have this mental model where it is the difference between accumulating the impulses and averaging them before applying them, versus applying them in sequence.

vestal minnow
cinder summit
vestal minnow
#

okay that was a horrible analogy lol

cinder summit
#

eXtended Sequential Impulse Based Dynamics, XSIBD. No more NVIDIA patent trolling thonk

merry tide
#

This is before I made it run with fixed physics.

sleek thicket
#

what's the new one?

merry tide
#

I haven't really made a version of this yet. I can make it quickly, I think. But honestly, I am shooting a lot from the hip here. Because it didn't run deterministically before (even running differently on different Hz on different monitors), I have been messing around a lot with different settings. But I think there is a version that is running on the fixed schedule now, but I haven't pushed it there yet.

cinder summit
merry tide
#

I think we already had a round about this where the timestep was shared and made consistent. But I don't think I updated that URL in particular.

vestal minnow
#

gains a lil energy

sleek thicket
#

a lil.

vestal minnow
#

Restitution and dynamic friction are tricky here, since the way it's currently calculated depends on the current velocity, and if we accumulate the impulses caused by restitution, it'll just apply a huge impulse

sleek thicket
#

either way it was kind of an edge case, the bigger problem is ghost collisions that probably can't even be resolved, and the hopefully resolved problem with A+W/W+D level

vestal minnow
fair fractal
#

what does prediction distance do anyway? is it some sort of narrow phase optomization?

vestal minnow
# fair fractal what does prediction distance do anyway? is it some sort of narrow phase optomiz...

Currently, the solver applies positional corrections one by one instead of accumulating them and applying them all at once at the end. This means that the bodies can move relative to each other mid-solve, sometimes going into newly penetrating states.

If the collider sizes were exact, this could lead to missed collisions since collision detection is run before the solver (and therefore can't detect the mid-solve penetrations). To account for this, we use the prediction distance to accept collisions that are not necessarily penetrating yet, but close. If they end up penetrating during the solver, the collision is handled, otherwise it's skipped

fair fractal
#

ah ok I see

vestal minnow
#

The issue here is that collision events and similar APIs currently also count the non-penetrating collisions, which is weird and unexpected from the user's point of view

#

In your case your game's scale isn't the default scale, so the prediction distance is way too big

#

You can probably make it like a tenth of what it is by default

#

or even less

#

but yeah collision events firing for non-penetrating collisions is a bug that I'd like to fix at some point when I have time

fair fractal
#

I'm just curious, is there plans to get rid of prediction distance by accumulating positional corrections and applying them at the same time? or is it better that it works the way it does now?

vestal minnow
#

With XPBD, the current approach (Gauss-Seidel solver) has better convergence than accumulating (Jacobi solver), so things are more stable with less iterations required

#

but Jacobi has some benefits too

#

like potentially nicer parallelism and constraint order independence

fair fractal
#

ah okay

#

didn't realize there were such pre existing algorithms to collision solving

vestal minnow
#

If we used impulse-based dynamics, which is much more common than XPBD, I don't think this would be an issue to begin with since the solver operates on velocities instead of positions

#

but everything has tradeoffs

fair fractal
#

right right. I don't know much about how xpbd works but from the limited knowledge I have it seems kind of like it's a similar difference between euler integration vs vertlet integration for motion, just taken to a whole new level

vestal minnow
#

Kinda yeah

#

(if we're going to integrators though, Euler splits into three core types: explicit, semi-implicit/symplectic, and implicit. Explicit has issues with systems just gaining energy, and implicit is too expensive, so almost all engines, including bevy_xpbd, use semi-implicit)

glacial geyser
#

I'm seeing a pretty significant performance hit (~90fps difference) when I chunk a large terrain made up of polyline colliders. Is there a way to optimize this further? I'm chunking so re-computing the polylines on the fly isn't too costly.

cinder summit
glacial geyser
#

It's less performant with more chunks -- so it goes from 2 polylines to probably around 50.

cinder summit
#

If they're not static rigid bodies they could collide with eachother ... And maybe collisions at the edges could makes sense ... Other than that it sounds kind of weird tho ๐Ÿค”

glacial geyser
#

Each chunk is a child of one static rigidbody

#

Well it's two levels deep: Map -> MapChunk -> PolylineCollider

#

Oh very interesting -- I just made each PolylineCollider it's own static rigidbody instead and we're back at 120fps.

#

So it looks like the slowdown comes from the hierarchy.

cinder summit
#

Hmmm ... Maybe it doesn't consider them child colliders properly, or maybe the check in the broadphase doesn't account for this edge case ๐Ÿค”

stiff ledge
#

I'm just trying out different parts of the bevy ecosystem, and I'm seeing a lot of instability with a simple chain pendulum of capsules connected by spherical joints. They aren't clipping at all on spawn, and there is space between the colliders, so I'm not sure what is giving the system so much trouble. Attached is a video of the one time it didn't immediately explode on load, and it is still acting quite odd.

vestal minnow
#

How are your joint anchors set up?

stiff ledge
#

Let me copy out the relevant parts to recreate this; it's a bunch of kitbashed tutorials together just trying stuff out so most of the code is irrelevant.

#

creating the chain: ```rust
fn spawn_capsule(
commands: &mut Commands,
transform: Transform,
radius: f32,
depth: f32,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
) -> Entity {
commands
.spawn(PbrBundle {
mesh: meshes.add(
shape::Capsule {
radius,
depth,
..default()
}
.into(),
),
material: materials.add(Color::rgb_u8(124, 144, 255).into()),
..default()
})
.insert(TransformBundle::from_transform(transform))
.insert(RigidBody::Dynamic)
.insert(Collider::capsule(depth, radius))
.insert(Restitution::new(0.2))
.id()
}

fn spawn_capsule_chain(
commands: &mut Commands,
transform: Transform,
links: i32,
radius: f32,
depth: f32,
gap: f32,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
) -> Entity {
let length = radius * 2.0 + depth + gap;
let first = spawn_capsule(commands, transform, radius, depth, meshes, materials);
let mut last = first;
for i in 1..links {
let offset = transform.translation + Vec3::new(0.0, -length * i as f32, 0.0);
let new = spawn_capsule(
commands,
transform.with_translation(offset),
radius,
depth,
meshes,
materials,
);
let anchor = Vec3::new(0., length / 2., 0.);
let joint = SphericalJoint::new(last, new)
.with_local_anchor_1(-anchor)
.with_local_anchor_2(anchor);
commands.spawn(joint);
last = new;
}
first
}```

#

setting up the swing point / chain: ```rust
let swing_point_height = 5.;
let swing_point_loc = Transform::from_xyz(0.0, swing_point_height, 0.0);
let swing_arm_length = 2.0;

let swing_point = commands
    .spawn(RigidBody::Kinematic)
    .insert(Collider::ball(0.2))
    .insert(Swing)
    .insert(TransformBundle::from(swing_point_loc))
    .id();

let depth = 0.7;
let radius = 0.15;
let gap = 0.2;
let chain_height = radius * 2. + depth + gap;
let chain = spawn_capsule_chain(
    &mut commands,
    Transform::from_xyz(
        0.0,
        swing_point_height - swing_arm_length - chain_height / 2.0,
        0.0,
    ),
    2,
    radius,
    depth,
    gap,
    &mut meshes,
    &mut materials,
);
let joint = SphericalJoint::new(swing_point, chain)
    .with_local_anchor_1(Vec3::new(0., -swing_arm_length, 0.))
    .with_local_anchor_2(Vec3::new(0., chain_height / 2., 0.));
commands.spawn(joint);```
#

swing system: rust fn swing(time: Res<Time>, mut query: Query<&mut Transform, With<Swing>>) { for mut sw in query.iter_mut() { *sw = sw.with_rotation(Quat::from_rotation_x( f32::sin(time.elapsed_seconds() * 2.) * 1.3, )); } }

#

It's not the exact same setup as the video (that was lost to me just experimenting with other stuff), but it has the same issues.

vestal minnow
#

Thanks, I'll try to see what the issue is tomorrow if that's fine, it's quite late for me here

stiff ledge
#

There's no rush, I'm just messing around at the moment seeing what's available.

fair fractal
glacial geyser
#

Thanks! I haven't got to map generation yet, that's just an uploaded image. But I do plan on doing some sort of noise-based generation. The main issue I'm trying to solve right now is performant destructible terrain. I want the contour to be perfectly aligned to the outside of the pixels, which means I can't use a lot of the existing contour algorithms since they all use the center of pixels.

errant chasm
#

can someone help me figure out how to rotate the player towards the direction they're moving in ? ๐Ÿ˜…

#

im using the code example in kinematic_character_3d

cinder summit
#

@vestal minnow It's kind of hard to keep up with all the changes I need to make to keep my sdf collisions working (gizmos are broken, I never fixed child colliders, I'm missing a few fixes from the narrow phase, etc) ... Could we create something like a collider trait, and a plugin that adds all systems to make that trait work? Maybe also some example of a custom collider type, something simple like the OnlySpheresCollider ๐Ÿ˜‚

fiery mortar
#

Using Bevy XPBD 2D:
I am struggling to find out how to make 2 bodies have a limited angle of rotation around their revolute joint axis,
angle_limit with angle_limit_lagrange set to non nil doesn't seem to have an effect

cinder summit
fiery mortar
#

Yes I was also wondering that

#

Is it in rad? deg? circle ratio?

cinder summit
#

Radians sounds the most likely at least

fiery mortar
#

I tried with them and it didn't seem like I had a result

fiery mortar
#

I am quite confused, does it have yet to be implemented?

fiery mortar
#

I didn't get translation lock to work neither ๐Ÿ˜ญ

vestal minnow
# cinder summit <@545959292281552928> It's kind of hard to keep up with all the changes I need t...

I think something like that might be doable... We could add a collider trait and make the systems and plugins generic, and add some higher level plugin for collision detection

It could be something like a CollisionPlugin that takes a generic collider and adds the sub-plugins like BroadPhasePlugin, NarrowPhasePlugin and ContactReportingPlugin for that collider type. It would also make things clearer for users, since e.g. "broad phase" and "narrow phase" might be unfamiliar for many

#

Custom colliders are a rather niche use case, but I think it's still a cool thing to support, and it'd also be useful for the potential "dimension unification" if we added e.g. separate Collider2d/Collider3d components

#

(also can we nest plugin groups?)

errant chasm
cinder summit
vestal minnow
#

We're silently just building bevy_peck in Bevy... shapes and bounding volumes added already, and who knows, maybe support maps soon

#

all that would be left for basic collisions is GJK and EPA, and some mass property stuff lol

cinder summit
#

Having mass properties for primitives would be nice ... Then I don't have to hack around not having them for my SDFs ๐Ÿ‘€

#

Maybe from_primitive should be a part of the collider trait ๐Ÿ˜‚

vestal minnow
#

Then it'd force you to implement all the primitives for your collider type

#

Or just panic with unimplemented! lol

cinder summit
#

Can't wait for the

match primitive {
    Primitive::Sphere(v) => Sphere(v),
    _ => todo!()
}
vestal minnow
#

I think I will still work on bevy_peck too... Barry is very nice to get a more "native" alternative quickly, but a separate and more custom-built solution could be very valuable as well

cinder summit
#

Main benefit to working on barry first is you can fix some of the low hanging fruit while also seeing how things currently work under the hood

#

At that point having it as a fallback for all the missing stuff of bevy_peck wouldn't have as many flaws anymore

vestal minnow
#

Yep

cinder summit
#

Anyway if you want I could try to implement this collision trait, I'd just need to know what kind of interface it would need ... I think some stuff in bevy_xpbd's collision module isn't even used anymore either after some changes to the narrow phase ๐Ÿค”

vestal minnow
#

Making the colliders generic in bevy_xpbd could also ease the transition thonk
If people had issues with e.g. bevy_peck, they could swap the colliders out with the old ones

cinder summit
#

It could even help with the transition from parry to barry thonk

vestal minnow
#

Especially if we added a feature to make parry/barry optional (you'd probably like that)

cinder summit
#

And then hide both of them behind a feature flag so you can save 10s compile time for the ultimate sphere game

vestal minnow
#

I think just this might be almost enough for collisions specifically

pub trait AnyCollider: Component {
    type Position;
    type Rotation;

    fn mass_properties(&self, density: f32) -> ColliderMassProperties;

    fn contact_manifolds(
        other: Self,
        position1: Self::Position,
        rotation1: Self::Rotation,
        position2: Self::Position,
        rotation2: Self::Rotation,
    ) -> Vec<ContactManifold>;
}
#

WIP tho, haven't checked everything yet

cinder summit
#

You also need a method to get the aabbs

vestal minnow
#

yeah that too ofc

cinder summit
#

But yea, mass, contacts and aabbs are about all I have right now, so I'd imagine that alone should be enough

#

There used to be a check for collisions and then getting the manifolds but that seems to have changed already

vestal minnow
#

What check?

cinder summit
#

I think the code went something like "Did they collide? Oh great, what are the manifolds"

#

Even if it was necessary for a specific implementation it could still just pass Vec::new() as result tho ๐Ÿ˜‚

vestal minnow
#

I don't think I remember a separate check like that tbh

cinder summit
#

It was quite a while back at least ... I was looking at main earlier because it didn't work correctly with my sdf collisions and the narrow phase looks a lot different now ... Collision pair reuse also wasn't commented anymore iirc

#

Still no solution for the Vec of Vec nightmare that is ContactManifolds and ContactData tho ferris_sob

vestal minnow
vestal minnow
#

by making a flattened iterator

cinder summit
#

I like how I just create it like this too

ContactManifold {
    normal1: m.normal1,
    normal2: m.normal2,
    contacts: vec![ContactData {
        point1: m.point1,
        point2: m.point2,
        normal1: m.normal1,
        normal2: m.normal2,
        penetration: m.penetration,
    }],
}
#

I still don't get how things don't explode with my sdf collisions ๐Ÿ˜‚

vestal minnow
#

Ya the APIs could be improved

#

relatively low-level stuff tho

cinder summit
#

Well at least my floating code causes explosions ... I really should convert that to be some kind of constraint, that way I can apply a smaller force 6 times instead of messing with something that has so much force it can throw the player 1000 meters into the air ๐Ÿ˜‚

vestal minnow
#

I think generic colliders for spatial queries might require changes to Parry

#

Time for Barry :)

cinder summit
#

I think we could make a separate trait for that too

#

That way we can create a bevy_xpbd_plocbvh crate ๐Ÿ˜‚

#

Maybe it doesn't even really need a trait ... Having different APIs for different spatial query pipelines might be reasonable ๐Ÿค”

vestal minnow
#

Raycasting we can do, but shapecasting and some other queries take composite shapes that we can't nicely abstract away with traits

#

with Parry at least

cinder summit
#

There are no shapecasts, only spherecasts ๐Ÿ˜‚

#

I guess in parry it doesn't make as much of a performance difference to use a sphere vs another shape

vestal minnow
#

Okay I think I have the basics for generic colliders through a CollisionPlugin working now...

#

Next I need to do stuff like child colliders and make the OnlySpheresCollider example

#

I might have a PR ready tomorrow maybe

cinder summit
#

Damn that's some high level collision trait speedrunning right there ๐Ÿ‘€

vestal minnow
#

There's other things I should probably be doing but this is more fun lol

#

Gizmos might not be very doable via traits... could probably use primitives tho

#

Like have some .to_primitive() method that returns and enum, and pattern match that

#

although we don't have primitives for all shapes... could still add them to the enum separately

cinder summit
#

Yea I think that would be fine

#

Atm I don't have gizmos either

#

I used to have AABBs working at least but they broke for some reason ferris_sob

vestal minnow
#

@cinder summit Do your colliders support scaling?

#

I'll probably add scale and set_scale methods to the trait to support scaling via Transform, but I'm not sure if it should be on the same trait or on a separate trait like ScalableCollider

vestal minnow
#

I made a draft PR for the generic collider stuff already in case you want to try it; it's WIP though, and I'll probably end up splitting the CollisionPlugin and generic colliders into separate PRs
https://github.com/Jondolf/bevy_xpbd/pull/302

#

You'd just need to implement AnyCollider for your collider and replace CollisionPlugin<Collider> and PreparePlugin<Collider> with your collider's versions

#

though I think ideally the PreparePlugin wouldn't handle colliders and it'd be done by something else

cinder summit
fiery mortar
#

I have some questions regarding Bevy's physics:

  • How do you effectively limit the angle of rotation with a revolute joint, I tried setting angle_limit but no effect

  • How do you lock the translation of an entity run-time, I tried changing the LockedAxes component but no effect

Am I getting something wrong ๐Ÿ˜ญ

cinder summit
#

I think LockedAxes should work, are you working with dynamic rigid bodies and just looking at physics interactions? (rather than direct mutations to transform/position/rotation)

fiery mortar
#

Yes I am

#

I am working with dynamic rigid bodies specifically

#

I never touch the translation / rotation directly

#

I know it can cause unexpected behavoiur

hard helm
#

With polyhedra, it's just applying the transform to each vertex and the inverse transpose to each face normal.

cinder summit
#

If you do a non-uniform scale, the distances won't be correct anymore. The distance could measure geometry that is no longer the closest

#

In many cases you could make a new non-uniformly scaled SDF, but an ellipsoid for example is 30x more code than a sphere

hard helm
#

You can probably transform the other direction, e.g. converting a ray into the SDF's local space. That's what I do in some cases.

#

That way a sphere remains a sphere.

#

There would be no way around it for two (relatively) sheared SDFs, though.

cinder summit
#

Yea, it would be doable for raycasts, but not any type of collision

vestal minnow
fiery mortar
tepid yarrow
#

Currently in the middle of migrating from rapier2d to xbpd2d and I've come across this issue that my KinematicBody does not move smoothly. Is this a common issue? I cannot find why this happens for me

tepid yarrow
#

nevermind, I just implemented my camera follow system incorrectly ๐Ÿ˜„

worthy plank
#

Can you say more? I'm playing with a few approaches to follow cam and definitely have one or two that stutter so obviously won't work but nothing I love yet

vestal minnow
worthy plank
#

Ah, much better

fiery mortar
fair fractal
#

Is there some VHACD settings that will always create the closest possible convex decomposition? With the config I'm using I keep getting results like this. (white is the original shape, orange is the decomposed hulls). I tried doubling the resolution and it doesn't seemed to have helped at all

#

I really just want an exact convex decomposition. maybe implementing my own algorithm might be better? it seems like VHACD is slow for calculating exact decompositions

vestal minnow
#

I don't think it can give exact decompositions in all cases though

#

I think the ACD even stands for "Approximate Convex Decomposition"

fair fractal
#

Yeah it definitely seems like it's designed specifically for approximating high detail concave polygons into approximations of convex polygons. What I want is the opposite lol, just decompose relatively low detail concave polygons into exact convex hulls. It's being used as terrain collision data for levels

vestal minnow
#

I think you might want polygon triangulation; you could then make a convex hull for each triangle

#

some approaches include earcutting and Delauney triangulation, there are some crates for those

#

I think Parry might also have them implemented to some extent

fair fractal
#

collider::trimesh?

#

it looks like I have to calculate the tris myself for that ๐Ÿ˜ฆ

#

probably still easier than convex decomposition lol

vestal minnow
#

yeah, with polygon triangulation

fair fractal
#

polygon triangulation?

#

I don't see that anywhere

fair fractal
#

ohh

vestal minnow
fair fractal
#

well, I'm not sure if this is a you, or a parry2d question, but if I decide to go that route, would the physics engine have any issues with long thin triangles for collision detection or collision resolution? It looks like there are a few different algorithms where some more complex ones avoid such thin long tris

vestal minnow
#

I'm not sure, but I think long thin triangles should be fine assuming they're not unreasonably long

#

like thousands / tens of thousands of units long

#

probably

#

you could maybe also make a compound collider that consists of many convex hulls instead of having a single trimesh

#

I think that might be what the result of convex decomposition is

#

it decomposes the polygon with VHACD, adds the parts to a vec, and makes a compound shape from that

fair fractal
#

Sweet, thanks for all the info man! I'll probably use ear clipping and a compound shape like that

topaz yacht
#

Quick question regarding collisions, does Kinematic not interact with Static bodies? That's what I'm observing, and the docs seem to point to it, but the wording confused me a bit. Also it's not what I expected, hence my doubts. If so, are you meant to handle Kinematic - Static collisions on your own?
Edit: the actual question I guess is, are collisions reported but the kinematic body retains its velocities, you need to change them yourself?

cinder summit
#

I think the collisions get detected, but kinematic bodies don't get affected by outside forces, so they can move trough static bodies. If you want it to have normal physics behavior you'd need dynamic rigid bodies

fiery mortar
#

Hello

vale thunder
#

yo

fiery mortar
#

So Translation Locked also works when it's constrained by a joint?

wheat narwhal
#

Does anyone know if there is a way to do a one-off raycast? I get a Ray returned from Camera.raycast_to_world, and I'm wondering if I need an entity with a RayCaster, and to set its origin/direction to the same as the ray, or if I can just do a one-off raycast via bevy_xpbd : O

vestal minnow
vestal minnow
fiery mortar
#

Great :)

vestal minnow
#

working for me at least

fair fractal
#

If I wanted to get the point on a collider which is closest to the specified target point, I would want to use collider.shape.project_point, right?

fair fractal
#

sweet now I gotta figure out how to work with nalgebra ๐Ÿ˜จ ๐Ÿคฃ

vestal minnow
#

I should really add a method to Collider

fair fractal
#

I guess probably project_point_local will be easier then I can at least use bevy transforms

vestal minnow
fair fractal
#

dang that was fast

#

wait is that repo for both 2d and 3d crates?

#

I thought they each had their own repo for some raisin

vestal minnow
#

2D and 3D are under the same repo and source code, they just use different feature flags

#

same as Rapier

#

most code can be shared between dimensions

#

the dimension-specific code is just behind clauses like #[cfg(feature = "2d")]

fair fractal
#

makes sense

fair fractal
#

is the CenterOfMass component automatically calculated/added to rigid bodies?

vestal minnow
#

yes

fair fractal
#

probably only for dynamic ones though, right?

vestal minnow
#

Currently for all types of rigid bodies, but I might change it so that kinematic and static bodies don't have mass props since they don't really need them

fair fractal
#

well currently it works to my benefit ๐Ÿ˜› I need to know center of mass for large static bodies because for calculating dynamic gravity attraction

vestal minnow
#

If I removed mass props from static and kinematic bodies, you could probably still get them with collider.mass_properties()

#

it just wouldn't take child colliders into account

#

(since it's for a single collider)

#

Hmm, in theory I could maybe add some system param that queries the hierarchy and gets the "true" mass props for an entity

fair fractal
#

I actually don't need mass properties, since I'm just using a simplified dynamic gravity attractor component which allows you to just manually set the gravity pull and falloff and other such properties. It's not realistic but I imagine it will make it easier for level editing

#

still need the center of mass though to know where the attraction should pull toward

fair fractal
#

well I just realized I don't even need the center of mass either actually ๐Ÿคฆ

#

since it's more like super mario galaxy physics I'm not actually attracting toward the center of mass, I'm attracting toward the nearest point on the collider

sleek thicket
#

could also iterate through all attractors in range but i have a hunch that in this case it'll be a bug attractor too

#

and sending ray down to get surface normal is probably too rigid for SMG physics

#

i had the ray down gravity system in unity but it didn't feel ideal. either way @ me if you come up with something interesting, i still want to add it in bevy eventually

fair fractal
#

none of it involves raycasting at all, but that might be because my case is simpler than most people's probably, since it's in 2d rather than 3d

sleek thicket
#

ah. yeah, i'm doing it in 3d

#

what i wanted is closer to psychonauts milkman conspiracy level than SMG anyway

#

i think in 2d SDF could work better

#

@cinder summit

fair fractal
#

basically I iterate over every "gravitational body" and do a spatial query against all the "dynamic gravity entities". the gravitational bodies have 3 simple properties, the max_gravity, falloff, and falloff extension, so I can calculate an aabb around the gravitational body's center of mass pretty easily with just that

#

I thought about sdfs, but then I decided against it because I didn't want to implement that functionality into my level editor ๐Ÿ˜†

sleek thicket
#

why?

fair fractal
#

probably a dumb reason but I'm super tired of working on my level editor

sleek thicket
#

it seems like the perfect use case for it though

fair fractal
#

I just got it to a usable state a couple weeks ago and I'm not looking forward to working on it again

#

sdfs? not for mine. the basis of my level editor works on polygonal geometry

#

so it doesn't seem like sdfs would fit in very well

sleek thicket
#

...why not?

fair fractal
#

doing geometric calculations on 2d sdfs is way different then doing them on 2d polygon meshes

#

integration with the physics engine I imagine would be a nightmare (for spatial querying)

sleek thicket
#

nise is working on that from what i understand

fair fractal
#

interesting, might have to check that out

sleek thicket
#

#showcase message

fair fractal
#

but the core of the gravity vector calculation works pretty simply and I think it could be translated to 3d fairly easily too. Basically you just get the closest point (to the player, or whatever other physics object) on the collider of the gravitational body (i call this the attraction_target). then you just find the difference between the player and the attraction_target and that vector points in the direction that you want gravity to be. and the magnitude of that difference vector is basically the distance from the gravity body, which you can calculate the strength of the gravity from pretty easily. I'm just using linear falloff for simplicity, so it's basically (difference.distance / max_distance) * max_gravity

sleek thicket
#

you're not doing anything to allow one-sided gravity?

fair fractal
#

no, not right now. probably will need it in the future though

sleek thicket
#

that's the main reason i went with ray in the first place

#

i figured i can just use dash to slam into another gravity surface

fair fractal
#

hadn't considered that before ๐Ÿค” I'm not sure how one sided gravity might become an issue though. Hopefully I can cross that bridge when I get to it ๐Ÿ˜…

sleek thicket
#

e.g. you're making a hole in the planet, you need to make sure that you don't get attracted to the planet from below/inside, or to the walls

fair fractal
#

ah I see. so like you'd probably want to keep the same gravity all the way throughout the hole?

#

until you come out the other end

sleek thicket
#

if you use center of planet then it's not an issue, but then there's an issue with anything that isn't just a basic shape

fair fractal
#

off the top of my head, I'd probably implement a trigger collider that the main gravitational body references. When you touch the trigger the current player gravity does not change until it stops touching the trigger. probably would have some implementation issues though

sleek thicket
#

yeah, it screams bugs later on

#

what i did is just separate collider meshes into layers that make sense

#

there are bugs either way though

fair fractal
#

Collider meshes into layers? not sure I get what you mean

#

separate collision layers?

sleek thicket
#

e.g. when you're on convex slope that changes gravity, if you stop then you start jittering because switching to new gravity changes ray enough to fall on previous face

#

can also be on the edge

#

you jitter between falling and on slope

#

it's fixed fairly easily by storing previous value though

fair fractal
#

ahh I see what you mean

#

you know what's really stupid is I've never even played super mario galaxy

sleek thicket
#

me neither

fair fractal
#

lol

sleek thicket
#

there was just 1 video that took apart its' gravity

#

i think this one?
https://youtu.be/QLH_0T_xv3I

Let's find out how Super Mario Galaxy's gravity and physics engine broke all the rules, and changed the Mario series forever.

๐Ÿฆ https://twitter.com/JasperRLZ
๐Ÿ’ฐ https://patreon.com/JasperRLZ
๐Ÿคผ https://discord.gg/bkJmKKv
๐ŸŒŽ https://noclip.website

๐Ÿ“ฐ Thomas Grip - Planning: The Core Reason why Gameplay Feels Good ( https://frictionalgames.com/2017-...

โ–ถ Play video
fair fractal
#

haha yeah I just searched for that and found it when you said that

sleek thicket
#

tbh it looks like they used a bunch of different methods

#

so i guess thinking about it as fields could work too

#

but tbh it looks like SDF to me ๐Ÿ˜‚

fair fractal
#

yeah I wouldn't be surprised if they did

sleek thicket
#

oh yeah there we go...

#

this one is the case where just using ray makes sense though, just make inside mesh as gravity-changing...
i really need to play this thing...

fair fractal
#

lol same

#

so whan you say sdfs you really mean a vector field right?

#

cuz I don't really understand how you could infer direction from an sdf unless you sampled multiple points

#

oh okay they explain how it works at 12 min

fair fractal
#

right

#

but distance doesn't give you a direction

sleek thicket
#

considering the shapes they used in SMG, i think this is it...

cinder summit
#

You can also sample a few points to estimate a gradient, that's slower and less precise tho

torn hedge
#

is it generally recommended to put the PhysicsPlugin in to FixedUpdate (PhysicsPlugins::new(FixedUpdate)) and all of my systems too?
for example my character movement that is physics based?

currently i just added the physics plugin in with its default, which is PostUpdate. and all my systems run in Update.

cinder summit
torn hedge
cinder summit
#

Yea, before PhysicsSet::Prepare or after PhysicsSet::Sync, depending on if you want it to run before or after physics

torn hedge
#

me adding to the linear velocity so that the character moves makes probably sense to run before physics?

cinder summit
#

Yea, most things that actually affect physics would go before physics

torn hedge
#

great, thank you!

cinder summit
vestal minnow
#

I might just do that now actually

#

although I'm not sure if it should also show the penetration depth by changing e.g. the normal arrow length

cinder summit
#

A penetration depth of 0 isn't too uncommon tho ๐Ÿค”

vestal minnow
#

yeah, could have a minimum length or something

cinder summit
#

Also I'm trying to debug some issues where I get stuck in colliders, but now I'm just realizing I don't even know what expected manifolds on the inside of solid colliders would be ๐Ÿ˜‚

#

This sure doesn't look correct at least ๐Ÿค”

vestal minnow
#

my arrow gizmo code is disgusting

let back = Vector::NEG_Z;
let up = dir.try_normalize().unwrap_or(Vector::Y);
let right = up
    .cross(back)
    .try_normalize()
    .unwrap_or_else(|| up.any_orthonormal_vector());
let up = back.cross(right);
let q = Quaternion::from_mat3(&Matrix3::from_cols(right, up, back));

self.draw_collider(
    &Collider::cone(head_length, head_width * 0.5),
    &Position(b - dir * head_length * 0.5),
    &Rotation(q),
    color,
);

renders a cone collider for the tip ๐Ÿ˜‚ also doesn't use Quat::from_rotation_arc

#

it's also just wrong in some cases

#

luckily 0.13 has arrow gizmos

#

and support for multiple gizmo configs... I can finally do physics gizmo configuration nicely

cinder summit
vestal minnow
#

Maybe? Not sure what the expected result is for this kind of edge case

#

would make sense tho

cinder summit
#

I don't think this by itself is the main problem tho, this only goes wrong after you're already halfway into the wall ๐Ÿ˜‚

vestal minnow
#

since they're just opposites

#

in global space

#

like is the normal pointing towards the wall or the player

#

it depends on the order of the entities in the contact (which currently depends on the position along the X axis because sweep and prune)

#

also ignore the box jittering

cinder summit
#

Like in my example ... Where they do this

vestal minnow
#

huh

#

alr

cinder summit
#

Well even if it worked correctly they wouldn't overlap, like this

cinder summit
vestal minnow
#

sleeping issue

#

the box has insomnia

vestal minnow
cinder summit
#

Nice, it works ... And now I can see that my guess on what was going wrong was correct

vestal minnow
cinder summit
#

I use a local repo because something after 0.3.2 broke my sdf collisions ๐Ÿ˜‚

vestal minnow
#

I need to finish that generic collider thing

#

my main issues are that I don't really want to add collider generics to the PreparePlugin or SyncPlugin, so I might want some ColliderBackendPlugin or similar that handles that stuff

#

and adding a high-level CollisionPlugin also isn't ideal because then disabling e.g. the BroadPhasePlugin would be more annoying

#

it'd require nested plugin groups which aren't a thing

#

I'd basically like to have this

PhysicsPlugins (plugin group)
    CollisionPlugins (plugin group)
        BroadPhasePlugin (plugin)
        NarrowPhasePlugin (plugin)
        ContactReportingPlugin (plugin)
    ...other physics plugins

but keep the ability to disable individual collision plugins without needing to disable the entire CollisionPlugin and add the desired sub-plugins manually

#

but also support disabling all collision plugins at once by just removing CollisionPlugins/CollisionPlugin

#

For now I'll probably just ignore the idea of a high-level collision plugin and have a generic BroadPhasePlugin, NarrowPhasePlugin and ColliderBackendPlugin

#

That should be good enough for the generic collider use case until there's a nicer way of managing plugin hierarchies or dependencies

cinder summit
vestal minnow
#

yes, updating the AABBs is the only thing IIRC

#

I could probably move that to the ColliderBackendPlugin

#

I'm working on it rn

#

*or in a few minutes

#

I like the ColliderBackendPlugin idea in that the PreparePlugin and SyncPlugin will no longer need to be aware of colliders

#

so "rigid body logic" and "collider logic" will be more separate and work independently

vestal minnow
#

@cinder summit The collider backend plugin file is 790 lines lol, I can see why that could be a pain to maintain as 3rd party

#

not even counting the narrow phase stuff you probably needed to copy

#

this yeets like half of the prepare plugin file which is nice

#

and a large chunk of the sync plugin

#

I'll make the sphere collision backend example thingy and then make a new PR

#

We could add support for Rapier's colliders ๐Ÿ’€

#

although it'd be basically the same as our current colliders

atomic wigeon
#

Has anyone else been flooded with buffer-related log output when they enable PhysicsDebugPlugin::default()? Seeing tons of:

 INFO Created buffer Valid((13, 599, Metal)) with BufferDescriptor { label: Some("LineGizmo Color Buffer"), size: 143280, usage: BufferUsages(VERTEX), mapped_at_creation: true }    

INFO Created buffer Valid((14, 599, Metal)) with BufferDescriptor { label: Some("LineGizmo Position Buffer"), size: 23880, usage: BufferUsages(VERTEX), mapped_at_creation: true }   

Likely a misconfiguration on my end since it's only happening in one of my projects, but if anyone's encountered this I wouldn't mind a lead ๐Ÿ˜›

cinder summit
#

Hmmm, it might be one of those things that gets filtered in my app ... What crate is the message from?

vestal minnow
#

@cinder summit I seem to have all of the generic collider stuff working reliably now (haven't tested child colliders yet tho)

Adding a custom backend is very straightforward, just add a couple of plugins:

.add_plugins((
    DefaultPlugins,
    PhysicsPlugins::default(),
    ColliderBackendPlugin::<CircleCollider>::default(),
    NarrowPhasePlugin::<CircleCollider>::default(),
))

I believe you can have any number of different collider types at the same time without significant overhead, so you don't even have to disable the existing Collider-based plugins

#

I'll finish up the example and then finally make a PR

cinder summit
vestal minnow
#

I probably will lol

#

the orbit thing isn't an ideal example, but I'm not sure how else I should make circles collide more than once...

#

can't really have a ground plane unless I implement collisions against that too

#

I could make the ground a massive sphere ๐Ÿค”

cinder summit
#

Make a custom gravity system

#

Like planet gravity

vestal minnow
#

that's what my current example is

#

this but with collisions
#off-topic message

#

the center is an attractor

#

I could make the attractor follow the mouse ๐Ÿค” that could be cool

#

could also hit the particles with it

pastel timber
#

Hey, I don't know much about bevy reflection but am getting this error when adding colliders / rigid bodies within an asset loader. Is this something that can be fixed either in my code or the library?

scene contains the unregistered type `bevy_xpbd_3d::components::collider::Collider`. consider reflecting it with `#[derive(Reflect)]` and registering the type using `app.register_type::<T>()`
vestal minnow
#

hmm... after this generic collider thing, maybe we could technically split it into separate Collider and CompoundCollider components without significant overhead

#

then at least Collider could be reflected

#

but might not be as nice API-wise I guess, not sure

pastel timber
#

you can create compound colliders through parenting right? I didnt realize there was an additional compound collider type

vestal minnow
#

Yes parenting works, but compound colliders are also a thing. I believe it's required for colliders created using convex decomposition since they consist of several convex hulls

#

creating a separate entity for each convex hull would probably be unnecessarily expensive and a pain to deal with

cinder summit
vestal minnow
#

yeah that could work

#

which is fine, could add some particles that are clusters though

#

this feels like a separate orbit example and not custom_collider though

cinder summit
#

It would be interesting if you could switch between regular and custom colliders

#

Ideally see if it has any FPS impact too (it should probably be a lot faster than parry)

hard helm
#

This is a problem I also have with my physics solver (which does use Bevy ECS), preventing the solver from running each island in parallel.

#

It can't be worked around by using Query::get_unchecked, because I need multiple parallel queries. Maybe an exclusive system using UnsafeWorldCells would work.

vestal minnow
#

The red things are child colliders of the center thing

#

And use transform scale to make sure that works

#

There's just another determinism issue where the initial touch is explosive on some runs but not on others ๐Ÿฅฒ

cinder summit
#

That's a pretty cool example ๐Ÿ‘€

vestal minnow
#

Thanks, I just thought more about what I can make with just circles, and came up with that

#

kinda looks like covid though thonk maybe I should change the red to something else