#Avian Physics

1 messages Β· Page 6 of 1

vestal minnow
#

I do feel like it shouldn't be necessary to do the normalization here in the substepping loop though, but idk, I can see later if there's some other issue that makes it necessary

#

It does feel weird that those methods add/subtract the rotation instead of multiplying though, since generally you add angles using multiplication

#

But the XPBD paper does it, so...

mellow orbit
#

I just started at the bottom -- I don't have quite enough overall sense of how everything fits together to know where in the substepping loop is right.

vestal minnow
#

Yeah this is a good starting point if it makes the problem go away

#

Just in the future it might be nice if we can find a way to avoid it since normalization is a relatively expensive operation (but that's micro-optimization, it's not slow in the grand scheme of things)

mellow orbit
royal helm
#

@vestal minnow it's integrating the quaternions I believe

#

From angular velocity maybe?

vestal minnow
#

I'm not sure what you mean

#

this is when solving constraints

#

and also it's already normalizing the quaternions during integration too

#

so they should be normalized at every substep already, but for some reason it looks like it also needs to be done in the solver, which I find a bit strange

mellow orbit
#

Is it because a single collider might be affected by multiple constraints, and those are applied as each is computed rather than atomically at the end?

vestal minnow
#

yeah probably

#

Also I have 6DOF joints / generic joints mostly working already. Some of the angular limits are just unstable and weird still, but I'll try to fix it

#

The above is basically a prismatic joint that allows rotation along one axis, and it's just created like this

let mut joint = GenericJoint::new(entity1, entity2);

joint.set_anchor_2(Vector::NEG_X * 2.0);
joint.limit_translation_x(0.25, 2.5);
joint.free_rotation_y();
joint.free_rotation_z();

commands.spawn(joint);
#

(API WIP)

#

(the automatically rotating body is unrelated in the video, it's not using joint motors or anything)

mellow orbit
#

nice!

#

it's a cylinder joint!

vestal minnow
#

Yeah that's probably the actual name haha

#

we can add a bunch more joint types really easily with this 6DOF joint, although they might be ever so slightly slower than custom-making each of them

mellow orbit
#

combine this with a distance limit (so it can rattle back and forth) and an angle limit, and you have the box hinge I was describing on github

#

Unrelated (or, not very related) -- what's the difference between compute_generalized_inverse_mass in position_constraints.rs and the same in angular_constraints.rs?

vestal minnow
#

the position one has to consider both mass and inertia, while the angular one only cares about inertia

#

For example

#

If you attach a distance joint or spring to the corner of a box, it should also rotate the box, so it needs to also consider the angular inertia

#

But if you have a prismatic joint constrain the relative rotation, mass is unimportant for the angular correction

mellow orbit
#

yes. kind of mesmerizing to watch though

#

is the anchor just set some distance from the fast-spinning block, or is that another limit of some sort?

vestal minnow
#

the anchor is offset

#

but it also has translational limits along the x axis

#

which is why it slides around

mellow orbit
#

I'm trying to think what kind of thing that might correspond to usefully πŸ™‚

vestal minnow
#

it's just a prismatic joint, except the rotational DOFs are free

#

(or one of them was slightly limited as well actually)

mellow orbit
#

I think that might be a "slot joint"?

vestal minnow
#

no idea πŸ˜‚

mellow orbit
#

searching for that just gives me casinos

cinder summit
#

It does sound like some slang for casino πŸ˜‚

vestal minnow
#

these angular limits are a pain though, I'm just switching around axes to try to fix things

cinder summit
#

This joint stuff looks pretty wild ... I should figure out a way to use such fancy physics features in my game without things behaving weirdly due to the latency or desync πŸ€”

vestal minnow
#

this is the most info the XPBD paper has about limits for multiple axes at the same time

#

and I can't tell if having two swing axes works properly

cinder summit
#

And I gotta say, jondolf is pretty on-point with what he said ... Something about focusing on joints if I pick up primitives ... I made a primitives PR and there's a lot of joints going on here πŸ‘€

cinder summit
vestal minnow
#

not really

#

this is basically the only XPBD paper on rigid body dynamics

#

others are mostly soft body / cloth / something else

#

well, there's this but it's not very helpful

vestal minnow
#

ECS XPBD SDF BVH paper, that's a nice and clear name

cinder summit
#

And just write down "Use my Rust library for all your XPBD SDF needs, it has a license that allows you to use it despite the 17 patents" πŸ˜‚

fallen citrus
#

I'm a bit confused about joints, where exactly is the local rotation between two bodies stored on something like a fixed joint? It stores local anchors, but that would just describe their relative translation.

vestal minnow
#

You can't specify the rotation atm, but I'll probably add support for proper local frames (local anchor + rotation) as part of these joint improvements I'm making

finite blaze
fallen citrus
#

So right now its basically assuming Quat::IDENTITY for local rotation?

vestal minnow
#

the XPBD paper only mentioned the attachment points explicitly so I didn't even think about rotations originally

vestal minnow
#

if you have a prismatic joint, it'll always align their axes exactly instead of allowing some initial rotation

#

right now though I want to have basically everything PhysX's joints have (and more?)

mellow orbit
vestal minnow
#

I'd consider that to be pretty much fully featured in terms of joints

#

yeah I know that exists

mellow orbit
#

Furthermore we use our own library:

Discregrid to generate cubic signed distance fields for the collision detection
fallen citrus
mellow orbit
#

it says πŸ™‚

vestal minnow
#

OH yeah it has that, I forgot

#

for fancy cloth things probably

#

and soft bodies maybe

sleek thicket
#

it's a bit off-topic but i'm curious if/how -z being forward affects development

vestal minnow
#

I always feel like it's backwards for cameras and movement

sleek thicket
#

same

vestal minnow
#

need to subtract z

linear_velocity.x += direction.x * movement_acceleration.0 * delta_time;
linear_velocity.z -= direction.y * movement_acceleration.0 * delta_time;
sleek thicket
#

i feel like the best solution would just be adding option of choosing it as a feature

vestal minnow
#

idk that'll be annoying for 3rd party plugins probably

sleek thicket
#

yeah, that's why i thought about asking the first place i thought it'd break πŸ˜‚

#

the argument for -Z doesn't sound reasonable outside of 2d either

mellow orbit
#

-z : I thought it was weird for about 60 seconds and then got used to it

vestal minnow
#

yeah it's not too bad imo, but can be a bit weird sometimes

#

and sounds unintuitive to have [x, y, -z]

fallen citrus
# sleek thicket https://github.com/bevyengine/bevy/issues/5670

I find this very confusing with bones, since blender uses Y+ for the span of the bone, so if you want to point a bone at something it needs to point the up direction at it, not forward. But it does intuitively work for anything on an upright biped's spine, since "forward" makes more sense as the direction you're facing rather than the direction the bone is pointing

sleek thicket
#

the issue is about mismatch between bevy and gltf, but i wonder if there's another one that brings up the gameplay headache since right is essentially -X and that just fucks my brain sideways

fallen citrus
#

Oh yeah I got around that one with asset preprocessing

vestal minnow
#

looks very nice based on a quick look, just needs more shapes and helpers

sleek thicket
mellow orbit
#

page 11

vestal minnow
#

I'll also try to look at engines like Bullet for inspiration if I can't fix things

#

nvm is Bullet not MIT?

#

guess not

#

it's impulse based so I can't really copy things either way though

#

so just looking for inspiration is probably fine

mellow orbit
#

zlib license β€” osi approved and non-copyleft.

vestal minnow
#

meaning it's copyrighted?

mellow orbit
#

It is copyrighted (that's how all of these licenses work), but it doesn't have a GPL-like "share alike" clause

#

Generally licenses which have that feature are called "copyleft" as a little parody of copyright.

#

Examples are GPL, Mozilla Public License, and Creative Commons Share Alike

#

The other class of open licenses are "permissive"

#

BSD, MIT, zlib

vestal minnow
#

Alright, thanks :) you clearly know a lot more about licensing and legal things that I do

#

you can be my lawyer in case NVIDIA hits πŸ˜…

#

(I'm kidding)

cinder summit
vestal minnow
#

exactly

cinder summit
#

I do know zlib has some particular issues that can make it annoying in some cases, but overall it's fairly permissive

vestal minnow
#

I don't know if I'd even want to go to America ever anyway

#

they'll have to come to me instead and enjoy the wintery delight that is ice and gray slush everywhere

#

(probably not until January though)

#

also darkness

royal helm
#

canada?

#

or some european slushy country

vestal minnow
#

Finland, close enough

royal helm
#

haha

#

finada

cinder summit
vestal minnow
#

Canland

#

this stuff

#

not my picture

#

"loska", which is slush or sleet in English

#

some months are nice and snowy but the transition period to spring is slushy and icy usually

sleek thicket
#

i just call it mud

mellow orbit
#

If you come to Boston in January or February you will feel right at home

peak timber
#

I'm trying to use xpbd instead of rapier for my voxel game, trimeshes, but I get crippling performance issues with even just a few chunks loaded...

#

Whereas if I uncomment out this code and add colliders to all of my chunks, it freezes the game & has 100% CPU usage

#

even with a super low cubic render distance (2), it's still unplayably slow

cinder summit
#

Are they static bodies? Any debug rendering enabled?

#

I know xpbd's debug renderer and having many mesh colliders are two things that don't get along at least

peak timber
#

Just added RigidBody::Static and got the same result

#

I am using the f64 feature for physics

#

and a custom gravity of -9.81 * 2.5

cinder summit
#

Hmmm that's strange ... Loading some trimeshes if they are static shouldn't do much in terms of load unless you loaded them with convex decomp

peak timber
#

should have mentioned, I'm using the big_space library - which may be causing the issues

cinder summit
#

I had a few thousand trimeshes from my voxel terrain, and as long as nothing was touching they didn't cause any real issues (other than maybe making the broadphase slightly slower)

peak timber
#

I still need to implement the SyncPlugin manually to prevent physics related issues since the coordinates would be wrong

#

but I don't know why that would cause a performance issue even incorrect

cinder summit
#

Might be worth running a profiler to see what system is creating the load πŸ€”

peak timber
#

well, every chunk technically has the same position of 0,0 since I'm using a grid with the same size as the chunk
so I guess if I don't manually update the positions for the physics engine, everything would be considered colliding?

#

that could be the issue, the player is "colliding" with every chunk

#

I'll go fix that..

cinder summit
#

Yea that does sound like it could cause trouble ... Tho tbf I've done that on a few dozen chunks and it still didn't freeze

warm gulch
#

@vestal minnow : I just upgrade bevy to 0.12 and fixed all issues related to that (basically none) and I just wanted to give you a shoutout: I really like bevy_xpbd. I think what you have done here is great and you are one of the reasons I love open source and enthusiasts just wanting to provide good stuff. My clothes are getting warm, unfortunately I can't post any progress because OBS stopped working after upgrading to Ubuntu 23.10 (for some unknown reason). Anyways, I also realized you have added bunches of examples and stuff, I am just so impressed by what you have done with this thing. GREAT WORK! You should pat yourself on the back.

junior flower
#

^ I second this

finite blaze
#

Third this!

sleek thicket
#

i'm pretty sure everyone agrees though

merry tide
#

Absolutely.

#

Great. I would love something like that, and I also appreciate all the other conversations. In Unity I used a plugin to allow me to render polylines with curves and mapped textures onto them, probably tessellating it under the hood. I never noticed the issue where it intersects with multiple objects in a single step and that turning into an issue. But for me, having few shapes and caring for consistency more than anything else that would be an awesome option, even if it has tradeoffs in terms of performance and options, really.

#

I am pretty sure the same basic issues are there, but someone conveniently have been tuning it for me behind the scenes in Unity.

#

I wrote something similar for Godot that takes a path, tessellates it and allows you to break the outline into segments that are individually textured depending on the angle. That was reasonably simple, but I could not ever get the physics to be "OK".

#

I think that would be a nice thing to have in Bevy as a general 2D game level design tool. Would that be interesting to anyone else? I am currently happy with my sub-Geometry Wars graphics, but I fully intend to move forward.

#

So, going in blind into Unity, I made this version of Ponkatris in 7 hours:

#

Buying some assets and being able to make curves everywhere.

#

I have another noob question, tho. I am trying to make a new kind of crystal in the game, one you don't bounce off but can pass right through, shouldn't this do that Restitution::new(0.0).with_combine_rule(CoefficientCombine::Min)? Because it seems to not do that, the restitution for the player is set to Restitution::new(0.8).with_combine_rule(CoefficientCombine::Average). I also tried CoefficientCombine::Multiply multiplying by zero, but it still bounces off the crystals.

#

But 0/min should be zero and no bounce?

#

Even if I set the restitution of the player to 0 and the crystal to 0, they seem to bounce off each other. Is that expected? I guess maybe it is.

#

Yeah, I guess it is. I will look at turning it into a sensor instead.

#

Yeah, of course, it makes sense the way it is.

#

Are we making the same game?

#

Cool, coolcoolcool. πŸ™‚

#

Let me know if you would want to pool some resources. I just streamed how far I got recently, it is supposed to be a daily thing. Feel free to check it out if you want. I am still aiming for a Dec 1 release.

#

I'll send you a message, DM. Feel free to ignore it. πŸ™‚

lime hatch
#

hmm.. systems added to PostProcessCollisions don't seem to run for me. Is there some gotcha?

vestal minnow
lime hatch
vestal minnow
lime hatch
#

Another thing, I'm going to write a system that removes any collisions if either of the components have a match in a struct IgnoreCollisionsWith(Vec<Entity>) component

I know layers exists, and this is less efficient, but sometimes it's not possible to solve things with layers.

Would you want it added to bevy_xpbd?

vestal minnow
#

I think that could be something that could be done better with contact hooks once we have those... if it's a common use case though, then we could add it for now at least

#

in general, collision layers and custom filtering systems should also be enough

#

(although custom systems are less optimal)

#

Probably this
#1124043933886976171 message and #1124043933886976171 message

#

a weird bug, I'll try to fix it when I can

lime hatch
#

It's just the system will be exactly the same in every game I create where layers aren't enough.

The case is basically a player holding a weapon, it should not collide with the player itself, but it should collide with other players

vestal minnow
#

yeah I think we can add that

#

makes sense

lime hatch
#

we just make sure to add a performance warning and link to layers?

vestal minnow
#

Is it bad for performance though? Just make it optional, and in the broad phase, ignore if ignored1.contains(entity2) || ignored2.contains(entity1)

#

also isn't a HashSet better than a Vec maybe?

#

or I guess for a small number of entries (like in this case typically) iteration could be faster

lime hatch
vestal minnow
#

haven't seen one

lime hatch
#

to avoid heap allocations and cache misses for small amounts of entities

#

hmmm... it seems if an entity is despawned, it will be stuck in CollidingEntities

lime hatch
mellow orbit
#

maybe inactive because it's abandoned. maybe it's just simple enough that it's done

lime hatch
#

true

vestal minnow
#

side note, got bevy_silk working with bevy_xpbd and found some things we need to add to make it nicer, namely SolverLayers/SolverGroups and some Collider helpers like project_point

vestal minnow
#

it might be enough to add else branches in contact_reporting::report_contacts to remove entities from the list if the other doesn't exist anymore

vestal minnow
stable narwhal
#

is there an easy way to apply torque off-center? I'm trying to make a joint that applies torque to itself

vestal minnow
#

Torque isn't a thing that depends on the offset, it causes the same angular acceleration regardless

#

Forces that are applied off-center do cause torque though

stable narwhal
#

I think torque applied off-center will cause a center-torque and a center-force component, but I'm not sure how to calculate that

#

I get that the engine tracks torque in the center of mass, but that's not very useful for joints

#

hmmm, I guess I can create a fake body in the place where I want to apply the torque, and fixed-joint it to the body I actually want to rotate

#

ugly, though

#

works!

glossy bloom
#

I'm getting some extreme weirdness with child colliders while migrating my project from rapier. Some of it seems to be reproducible by simply rotating a child collider. Is this a bug?

#

minimal repro: ``` // floor
commands
.spawn(PbrBundle {
mesh: meshes.add(shape::Box::new(4., 0.3, 4.).into()),
material: materials.add(Color::WHITE.into()),
..default()
})
.insert(RigidBody::Static)
.with_children(|b| {
b.spawn(SpatialBundle {
transform: Transform::from_rotation(Quat::from_rotation_x(FRAC_PI_2)),
..default()
})
.insert(Collider::cuboid(4., 4., 0.3));
});

// cube
commands
    .spawn(PbrBundle {
        mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
        material: materials.add(Color::RED.into()),
        transform: Transform::from_xyz(0.0, 3.5, 0.0),
        ..default()
    })
    .insert(RigidBody::Dynamic)
    .insert(Collider::cuboid(1., 1., 1.));
#

^the cube goes straight through the floor

#

Or am I missing something?

fallen citrus
vestal minnow
#

they do

glossy bloom
#

yes

vestal minnow
#

the contact is also detected, but the response strength is really weak for some reason so the contact data seems weird

#

Ooh I found it

#

The child collider rotation isn't taken into account for contact normals, it's only considering the body's own rotation

#

@glossy bloom Thanks for reporting this and giving a great repro! It could maybe explain some other child collider issues as well; I'll open an issue and make a PR tomorrow hopefully

#

it's weird though that they worked as well as they did in my own testing even though the normals were wrong...

glossy bloom
vestal minnow
#

Or it's actually such a simple and quick fix that I'll do it rn

glossy bloom
#

sure, thanks, I'll test it once it's up. My project has a bunch of colliders pretty deeply nested, so if there's a bug it's bound to come up lol

finite blaze
#

I was thinking on adding a flight dynamic module, where a plane is cut into manageable parts (fuselage, left wing, right wing, rudder, stabilizer). The lift and drag for the components is taken from lift and drag coefficient tables with attack angle, mass, etc.
I suppose the best approach would be to also create child objects held via joints, so each part (left wing, etc) would get their resulting force separately, applied in their center of lift, and then let xpbd do the sum against the global cg

#

(Or trying to add πŸ˜…)

#

Basically implementing a Bourg model from physics for game developers

mellow orbit
#

I just realized that a cylinder shape from parry gets changed to a convex hull when scaled non-uniformly (like to make my robot body). This is fine -- (there's even a special "scale" method where you can give nsubdivs β€” which I want to increase.

finite blaze
#

I suppose a plugin with constraints could be better? But no idea how to tackle forces at the constraint level

mellow orbit
#

Except, if I create the collider as a scaled cylinder, now when I scale the body to be oblong, it'll get extra squished.

#

This is a fancy way of hoping for that shared primitive shape thing to happen

vestal minnow
vestal minnow
mellow orbit
vestal minnow
#

I can think of at least two ways to get around that:

  1. Scale via Transform, and then also scale the cylinder collider shape with the desired subdivision count, but make the scale something very small like 1.0000001 so that it doesn't really do anything
  2. Make the mesh a scaled child entity, and have the collider on the root entity have default Transform scale but a scaled collider shape
#

but yeah, kinda hacky

vestal minnow
vestal minnow
#

I don't think it had code available though

mellow orbit
#

nice!

finite blaze
#

That sounds cool! I would be glad to read that

vestal minnow
#

||by NVIDIA||

finite blaze
#

I'm not looking into simulating fluids though πŸ˜…, with applying forces from a graph I would be happy

#

And I find that difficult enough.. Plus finding or coming up with correct values is already its own thing

vestal minnow
#

apparently I have a screenshot of it lying around, it's pretty much nothing though

#

this is from some slides I found some time ago

finite blaze
#

That's basically it from forces, but applied at the centre of lift, normally 1/3 in the front of the profile

#

Problem is coming up with densities/mass of each discrete part of the plane

mellow orbit
finite blaze
#

The models already factor control surfaces and flaps

#

Paper planes sounds easier* because the density of the material and geometry is well known πŸ˜„

vestal minnow
mellow orbit
#

@vestal minnow Is this right: xpbd substeps affect precision (to the point where things get silly at 1 or 2), but should generally give the same basic result?

vestal minnow
#

Substeps affect convergence, i.e. how well the constraints are able to reach a state where they are satisfied. For example, if you had cloth, choosing a substep count of 1 would make it very stretchy because the solver has too few iterations per frame

#

They also help prevent tunneling / missing collisions because the discrete rigid body movement is broken into smaller steps

mellow orbit
#

right, when I made it "1" my robot often slowly sank into the ground (even though that's a half-space collider)

#

How does one get to the optimal number of iterations? How did you choose 12?

vestal minnow
#

arbitrarily

mellow orbit
#

heh

vestal minnow
#

good enough performance to have a decent amount of bodies, but they're also not squishy when stacked

mellow orbit
#

Would it be crazy to have it so you give a time budget (and perhaps a min/max) and have xpbd scale based on that?

#

obviously not great for determinism. πŸ™‚

vestal minnow
#

The substep count kinda is the time budget

mellow orbit
#

Yeah, that's what got me thinking of it. Why not express that in actual (game engine) time?

vestal minnow
#

One πŸ§ͺ idea is to have a variable substep count for each body by computing the current constraint errors and using that to determine if that body should be simulated for more substeps

mellow orbit
#

FWIW on my system with my robot spinning in circles, I get one core at 12% load with substep 1, 16% with substep 2, 45% with substep 100, and 75% with substep 200.

vestal minnow
mellow orbit
#

yes exactly.

vestal minnow
#

might also be possible to make a custom system for that even in your own application

#

check if Time::<Real>::delta() > max_delta, and if so, tweak substep count

#

or something like that

mellow orbit
#

yeah

#

and the joint is

        .with_rest_length(JOINT_SPACING)
        // .with_limits(0.0, JOINT_SPACING)
        .with_local_anchor_1(Vec3::new(0.0, -ARM_LENGTH / 2., 0.0))
        .with_local_anchor_2(Vec3::new(0.0, HAND_RADIUS, 0.0))
        .with_compliance(0.05);
vestal minnow
#

could make the frame rate a bit more smooth, but it'd probably cause "unexpected" behavior as well

cinder summit
#

The smaller substeps become the more floating point error contributes to the output too right? πŸ€”

vestal minnow
#

Yes

cinder summit
#

6 has definitelly been working well in my game at least, but it's also a very simple physics simulation where most things can't even rotate πŸ˜‚

vestal minnow
#

because more substeps = delta time closer to 0

mellow orbit
#

also on the above, const JOINT_SPACING: f32 = 1. / 96.; -- there's not supposed to be a meaningful gap at all

cinder summit
#

I remember jondolf saying the reasonable range is 3-50

#

Variable substeps could definitely be interesting tho ... No need to build CCD if you can just substep enough to avoid tunneling thonk

vestal minnow
#

*a highly arbitrary estimate that depends a lot on the use case

cinder summit
#

As long as people don't do the biggest mistake in gamedev: Making full physics objects out of bullets

#

Anything that's tiny and travelling at over the speed of sound is gonna be tunneling πŸ˜‚

vestal minnow
#

Idk how you would have a variable substep count for the integrator, but for the solver it could maybe (strong maybe) compute the constraint error and continue substepping until it's below some threshold (or some max substep number is reached)

vestal minnow
#

...because if not, JPBD incoming πŸ‘€

cinder summit
#

I mean ... That's also what I thought when I couldn't find any sources for using SDF collisions for games πŸ˜‚

#

In a way SDF collisions are simpler than the other stuff too, they're just a weird in that collision detection all happens one-sidedly

vestal minnow
#

I'll add the idea to my list of πŸ§ͺ experiments

mellow orbit
vestal minnow
#

you could still do it in parallel

cinder summit
#

Optimization is definitely a common topic of research

vestal minnow
#

just skip solving a constraint if the error is small enough

cinder summit
#

Every single paper about SDF collisions is just about optimizing it for X usecase for example. And all BVH stuff is the same

mellow orbit
#

and maybe other possible explosions πŸ™‚

vestal minnow
#

I would expect it to add jitter

#

or, depends

#

not necessarily

cinder summit
#

Is there any research on determinism with physics btw?

#

Always seems like one of those things most physics engines just don't care about all that much

vestal minnow
#

Box2D ignores determinism I'm pretty sure

cinder summit
#

Which is probably why a lot of MMOs straight up don't have physics, like at all

vestal minnow
#

I haven't seen research, but idk if it's that complicated algorithmically unless you make things massively parallel

cinder summit
#

Well that's the whole thing, you want variable amounts of parallelism and determinism for anything networked. Two things that tend to not get along too well

vestal minnow
#

but even then in XPBD you could do graph-colored Gauss-Seidel or parallel Jacobi and it should be deterministic I think

#

or maybe not to the bit-level

#

Jacobi probably won't be

cinder summit
#

Tho sadly I don't have a fancy enough usecase with my single threaded server instances ferris_sob

#

Depending on the usecase bit-level determinism might be necessary, or it just needs to drift very slowly

mellow orbit
cinder summit
#

Peer to peer networking often just sends inputs, so there you need bit-level determinism cause any drift results in desync. But if you have server-authority then you can't work like that since the server can and will tell the client that everything it thinks it did just didn't happen

vestal minnow
#

graph-coloring is just finding parallelizable groups of constraints, but each of those groups is run serially so I think it'd be deterministic maybe

mellow orbit
#

oh yeah -- thanks. i remember you saying that before.

#

this also might solve the normalization issue πŸ™‚

#

jacobi approach I mean

vestal minnow
#

in Jacobi, the corrections are combined into one correction vector, so the constraint order doesn't matter

#

but for numerical reasons it might not be fully deterministic

cinder summit
#

For numerical reasons ... And quaternion reasons probably

vestal minnow
#

because the corrections could be applied in a different order which could have slight impact numerically

#

yeah

cinder summit
#

At least with translations it would only add up floating errors

#

But shuffling the order of quaternions just straight up gives you a different rotation πŸ™ƒ

vestal minnow
#

fun

cinder summit
#

It might be possible to apply rotational corrections in a different way, but that would probably be even more computationally expensive, and rotations are bad enough as is

#

But yea maximizing each of single-threaded performance, paralellism and determinism without sacrificing all of them is the real challenge probably

#

Blindly following papers or guides can get you a physics simulation, it just won't be as generally usable as necessary for bevy

vestal minnow
#

Also for fun, I tried changing components like Position and Rotation to Position2d/Position3d and Rotation2d/Rotation3d to start experimenting with the dimension unification thing... the number of errors right off the bat isn't exactly encouraging lol

cinder summit
#

I wonder how it would compare to removing parry from your Cargo.toml thonk

vestal minnow
#

probably a lot less with removing parry

#

colliders aren't everywhere necessarily

#

mainly spatial queries, narrow phase, some stuff in prepare and sync... so most of the engine lol

cinder summit
#

One of these days I'll try making a parry feature ... Parry is somehow the biggest part of my server's compiletime, gotta fix that ... Tho it doesn't really make sense to do until I at least opensourced my SDF stuff

vestal minnow
#

idk how you make it a feature nicely, should it also disable the broad phase and contact reporting stuff?

#

since they wouldn't do anything by default

cinder summit
#

I think I'd have to experiment a bit, but ideally I'd set things up so it would become even easier to provide your own collision detection

#

There's also Nyatalily with some 2D CCD collision detection stuff, would be cool if we start seeing more than just parry and my sdf stuff

vestal minnow
#

yeah that'd be cool

#

also maybe some way to get e.g. child colliders working without Collider

#

probably requires traits tho

cinder summit
#

Yea I'm thinking something like structing it like ColliderPlugin<T>, but generics can be really messy sometimes

#

Sometimes traits just don't want to cooperate πŸ˜‚

#

"Oh you wanted the wrong type of type alias? Nah that's not happening"

#

Figuring out how to reuse code with spatial queries might be harder however πŸ€”

#

My spatial queries don't even have the same API as the ones in xpbd πŸ˜‚

vestal minnow
#

I'd like to change the API to some extent anyways

cinder summit
#

My API only exposes iterators, doesn't have RayCaster/ShapeCaster, etc ... It also has an incorrect use of + 'a πŸ₯²

    pub fn ray_hits<'a>(
        &'a mut self,
        origin: Vec3,
        direction: Vec3,
        max_time_of_impact: f32,
        _solid: bool, // TODO
        filter: &'a SpatialQueryFilter,
    ) -> impl Iterator<Item = RayHitData> + 'a {
#

The iterators only make sense because my BVH returns iterators tho

#

If xpbd uses my BVH it would be easier to standardize but I don't think the performance is good enough, and just like parry the BVH can't get updated yet (just for different reasons)

vestal minnow
#

God, creating these types is already so arduous and non-DRY, like there's stuff like this

#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
#[reflect(Component)]
pub struct ColliderMassProperties2d {
    /// Mass given by collider.
    pub(crate) mass: Mass,
    /// Inverse mass given by collider.
    pub(crate) inverse_mass: InverseMass,
    /// Inertia given by collider.
    pub(crate) inertia: Inertia2d,
    /// Inverse inertia given by collider.
    pub(crate) inverse_inertia: InverseInertia2d,
    /// Local center of mass given by collider.
    pub(crate) center_of_mass: CenterOfMass2d,
}

#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
#[reflect(Component)]
pub struct ColliderMassProperties3d {
    /// Mass given by collider.
    pub(crate) mass: Mass,
    /// Inverse mass given by collider.
    pub(crate) inverse_mass: InverseMass,
    /// Inertia given by collider.
    pub(crate) inertia: Inertia3d,
    /// Inverse inertia given by collider.
    pub(crate) inverse_inertia: InverseInertia3d,
    /// Local center of mass given by collider.
    pub(crate) center_of_mass: CenterOfMass3d,
}
  • separate impls for them
#

but it's not one type, it's like 50 😭

#

and then somehow make systems work for them

#

and constraints

#

if this was a PR, it'd be like +15,000 -6,000

#

or a lot more probably

sleek thicket
#

not as wet as world query DI

cinder summit
#

And slightly different comments ... Like they say "in 2D space" vs "in 3D space"

#

In comparison, my BVH code has very little duplication for 2d vs 3d, but mostly because I don't mind the generics there because it's already a huge web of generics πŸ˜‚

#

The type aliasses are still great tho ... pub type Bvh2d<T> = Bvh<Dim2, T>;

vestal minnow
#

an extreme example maybe, but sheesh

cinder summit
#

Ah yea gotta love the big enum functions with types

vestal minnow
#

Also would I have duplicate docs for Collider2d and Collider3d? I guess so

cinder summit
#

Should they even really be the same in 2d vs 3d tho?

vestal minnow
#

could break it up and link to docs that aren't specific to dimension tho

cinder summit
#

2D has shapes that aren't very useful in 3D, and 3D shapes while always having a 2D representation aren't always useful

#

circle vs sphere would be pretty pointless for example

#

Also whats this typed shape stuff? parry has enum-dispatch? πŸ‘€

vestal minnow
#

yeah

#

you can get enums from SharedShape at least

cinder summit
#

I guess it might have some uses in preventing many dynamic dispatch overheads when doing many shape calls πŸ€”

timid holly
cinder summit
#

That really seems to be everyone's favorite feature huh?

vestal minnow
#

seems like it lmao

#

should use that as a big selling point

cinder summit
#

I guess it's just like how Jondolf went like "You got a lot done in a few weeks" about my SDF and BVH stuff .... Guess I should put that in the README πŸ˜‚

vestal minnow
#

although you'd assume it's better to be a veteran in the field

cinder summit
#

Eh if you were a veteran in the field we would only get performance

#

And we'd all be like "Where's our determinism and features????"

vestal minnow
#

and πŸ§ͺ

#

777 errors left

#

I've gained 40 more

cinder summit
#

Now that's some rapid progress πŸ‘€

sleek thicket
vestal minnow
#

hmm, that's true thonk

sleek thicket
#

or you could just make a religion out of it

vestal minnow
#

4 years in high school is becoming increasingly more common though

#

(instead of 3)

#

just because people need more time to think what they want to do and/or don't want to crunch as much through high school

sleek thicket
#

or play more video games

#

let's be real here

mellow orbit
#

Now that it doesn't explode, I'm on to the next problem with my robot: it doesn't settle. Everything all seems to often have very small linear and angular velocities (like, length 0.000005 or so). Even when it eventually all goes to sleep (as indicated by the debug renderer), it blinks back into a waking state after a second or so. I have AngularDamping and LinearDamping on all of the rigid bodies. What could be going wrong here?

vestal minnow
#

small jitter is inevitable when not sleeping

#

are you mutably accessing position or velocity anywhere?

#

that could wake up bodies

mellow orbit
#

No -- only interacting by externalforce

vestal minnow
#

changing forces also wakes up bodies

mellow orbit
#

ah, sorry -- I'm also not doing that πŸ™‚

#

i mean, that is the only way I do interact, but it's only when i press keys. which I'm not

vestal minnow
#

this is the filter

type WokeUpFilter = Or<(
    Changed<Position>,
    Changed<Rotation>,
    Changed<LinearVelocity>,
    Changed<AngularVelocity>,
    Changed<ExternalForce>,
    Changed<ExternalTorque>,
    Changed<ExternalImpulse>,
    Changed<ExternalAngularImpulse>,
    Changed<GravityScale>,
)>;
#

you can also try to increase the sleeping threshold

#

like

.insert_resource(SleepingThreshold {
    linear: 0.4,
    angular: 0.3,
})
mellow orbit
#

hmm, okay. I'll poke.

vestal minnow
#

if that doesn't work, it could be an issue where joints are waking up the bodies when you don't want them to

mellow orbit
#

Ah! I am setting ExternalForce to 0 to stop. I should remove it.

#

except, the filter is changed. I'm not changing it except when a key is released, so that isn't it either

#

I blame the joints. πŸ™‚

vestal minnow
#

set == changed

mellow orbit
#

yeah. to be more precise: when the keys are any_just_released, i set it to 0, so I'm not doing that repeatedly.

#

but that was a good thing to check!

#

on "jitter is inevitable" ... shouldn't damping bring it to 0 eventually?

vestal minnow
#

very close but most likely not exactly

#

especially when many constraints are interacting at once (e.g. cube stacks)

#

I'm at 812 errors now...

cinder summit
#

πŸ“ˆ

vestal minnow
#

components module has no more errors though

#

except docs ofc...

royal helm
#

Any possibility of having CollisionLayers::new() be a const function

#

a bit of a pain making const/static layers

fallen citrus
#

Is there a way to have have colliders on the same joint ignore each other aside from giving them mutually exclusive groups/filters? I am setting up a character's ragdoll and it would be appropriate for all the bone colliders to have the same flags but its best reprsented as capsules that overlap at the joints

vestal minnow
#

For now, collision layers should work

vestal minnow
sleek thicket
# royal helm Any possibility of having `CollisionLayers::new()` be a const function

collisionlayers are easy,
first you make a bit for a layer

const env:    u32 = 1 << 0;
const red:    u32 = 1 << 1;
const green:  u32 = 1 << 2;
const blue:   u32 = 1 << 3;
const player: u32 = 1 << 10;
const unit:   u32 = 1 << 31;

then make the collisionlayers itself

pub const PLAYER: CollisionLayers = CollisionLayers::from_bits(player | unit, PLAYERMASK);
pub const PLAYERMASK: u32 = env | blue | green | red;
subtle epoch
#

@vestal minnow Hi jondolf, I am realy new to xpbd,I want to add a collision body around the character I control. I saw that there are two implementations of xpbd, one is dynamic and the other is kinematic. May I ask which one do you recommend? Thank youπŸ™‚

sleek thicket
mellow orbit
#

I feel like dynamic with dominance as needed should be able to handle what most people reach to kinematic for.

royal helm
#

I don't know how you'd ever make spatial query const

#

or why even

sleek thicket
#

if it's gonna be reused dozens of times then why not

cinder summit
#

Having const spatial query filters could definitely be nicer for structuring in some cases ... Tho in plenty of cases you need to query and pass in Entity or the identical filters all get used in a loop

fallen citrus
#

If the const constructor for spatial query filters didn't include any filtered entities I think it would be fine, it looks like there's no const constructor for an empty HashSet but you could just use a Vec, I don't imagine most spatial query filters will have many entities anyways. Mine tend to be no longer than 5

#

Or of course it could be an Option<HashSet<Entity>>

mellow orbit
vestal minnow
#

why?

#

it would just stop early, before the constraints have been fully satisfied, so the system wouldn't have reached the fully stable state yet

#

the more substeps you have, the more accurate the result should generally be until you hit floating point issues

mellow orbit
#

oh, hmmm -- something fundamental I guess: is the velocity update the sum of all of the substeps?

vestal minnow
#

not really

#

it's part of the substepping loop

#

first in the integrator when applying forces to bodies, and also after the solver based on the position delta before and after solve

mellow orbit
#

I'm assuming that at the early stop, there would be no movement and therefore velocity would be zero

#

But maybe I'm really off base πŸ™‚

vestal minnow
#

movement and constraint errors aren't necessarily related

#

depends on the constraint and situation

mellow orbit
#

The situation I'm thinking of is... well, my robot sitting still, but a stack of cubes is probably a better simple case.

vestal minnow
#

lower substep count => worse convergence, less accuracy => more jitter

mellow orbit
#

I may have to play with this myself more to actually fundamentally understand πŸ™‚

#

it seems like there must be some way to say "pretend it's converged even if it's just kinda close".

vestal minnow
#

It can't be converged if the constraint error is non-zero, that's the idea of convergence

#

Constraints are just mathematical functions that try to minimize the error over several iterations

#

by moving bodies in the direction opposite of the gradient, i.e. in the direction in which the constraint error decreases the most

royal helm
royal helm
#

kinematic is definitely more usable in some cases where you really need complete control

mellow orbit
vestal minnow
#

In the case of e.g. collisions, this would mean that some penetration is allowed before anything is done

#

I believe this is done in some engines (called slop I think?) but would probably require other changes to make it stable

#

but idk if we want bodies to always be overlapping

mellow orbit
#

They're not very overlapping.

vestal minnow
#

Also I got this working with the single bevy_xpbd crate supporting both 2D and 3D at once πŸ‘€

#

no solver or spatial queries yet, but basically everything else works technically

#

meaning that the code is garbage but it compiles πŸ˜…

mellow orbit
#

Ooh that will simplify things a lot!

vestal minnow
#

To make it actually viable without everything duplicated, it'll also force me to make things even more generic

#

Like I already made a generic Collider trait, which could be useful for e.g. @cinder summit's SDF colliders since it'd ideally make it so that all/most existing collision detection systems work with them

#

without having to make a custom narrow phase and stuff

#

but yeah a lot of refactors are still required to make it practical, so it's not coming soon probably... assuming it's even a good idea to begin with

#

just exploring different approaches to 2D/3D for now

vestal minnow
# vestal minnow Like I already made a generic `Collider` trait, which could be useful for e.g. <...

and this is just this atm

pub trait Collider: Component {
    type Vector: Copy + Clone + PartialEq;
    type Rotation: Copy + Clone + PartialEq;
    type Shape;
    type Aabb;
    type MassProperties;

    /// Returns the raw unscaled shape of the collider.
    fn shape(&self) -> &Self::Shape;

    /// Returns the shape of the collider with the scale from its `GlobalTransform` applied.
    fn shape_scaled(&self) -> &Self::Shape;

    /// Returns the global scale of the collider.
    fn scale(&self) -> Self::Vector;

    /// Sets the unscaled shape of the collider. The collider's scale will be applied to this shape.
    fn set_shape(&mut self, shape: Self::Shape);

    /// Set the global scaling factor of this shape.
    ///
    /// If the scaling factor is not uniform, and the scaled shape can’t be
    /// represented as a supported shape, the shape is approximated as
    /// a convex polygon or polyhedron using the number of `subdivisions`.
    ///
    /// For example, if a ball was scaled to an ellipse, the new shape would be approximated.
    fn set_scale(&mut self, scale: Self::Vector, subdivisions: u32);

    /// Computes the [Axis-Aligned Bounding Box](ColliderAabb) of the collider.
    fn compute_aabb(&self, position: Self::Vector, rotation: Self::Rotation) -> Self::Aabb;

    /// Computes the collider's mass properties based on its shape and a given density.
    fn mass_properties(&self, density: Scalar) -> Self::MassProperties;
}
#

doesn't work for actual collision detection yet ofc

#

but Collider2d, Collider3d and so on can give their own shape implementations using the associated types

mellow orbit
vestal minnow
#

Rotation, inertia and angular velocity should be scalar, not quat/matrix/vector

#

All collider shapes for 3D may not work in 2D and vice versa

#

2D simplifies a lot of computations

mellow orbit
#

Yeah, but it's not code simplification if you have to do both.

#

But anyway, not important really

vestal minnow
#

There should be nice APIs for 2D and 3D

#

And if you have the APIs, might as well have separate implementations where necessary

mellow orbit
#

It sure does make things like that normalization hack feel ugly, though.

vestal minnow
#

2D and 3D can also be made to run in parallel if that's desirable

#

(for games that use both)

mellow orbit
#

On a totally different note β€” I was looking at going through the code and adding some more debug! and trace! statements where I think they might be helpful. But, are you in the midst of so much general refactoring right now that none of it will apply in a month?

vestal minnow
#

nah, this isn't happening any time soon

#

mostly trying to get everything to compile, and then seeing what refactors are needed to make the approach viable

#

(if it's viable)

#

so other improvements and things will still apply definitely

cinder summit
vestal minnow
#

I haven't done much in terms of generizing stuff yet, but rn I just add the system variants like this

.add_systems((
    update_collider_scale::<Collider2d>,
    update_collider_scale::<Collider3d>,
))
#

I tried another approach initially but it would've required bevy_trait_query and a ton of dyn

cinder summit
#

If they get passed along on the systems it could later be expanded to have things get passed along on the plugin (should also save some duplication if you just have to register Collider2d vs Collider3d once

#

Overall this definitely looks usable tho ... Much more reasonable than the giant mess I would end up making if I tried to hack 2d support into the sdf collisions ... And since it's all types on a single trait you won't get stupid things like <Dim::Aabb as Aabb>::Pos like all my bvh code πŸ˜‚

#

Shouldn't we get some way to cache scaled shapes tho? πŸ€”

#

Tho I guess that can be handled outside the trait already

vestal minnow
#

the stuff I've done so far is on the unify-dimensions branch in case you want to see it for whatever reason, but again it's rough

#

90% copying things

#

and docs not updated obviously

cinder summit
#

Continue the grand unification Solid commit message, 10/10

vestal minnow
#

yes

#

idk what to name them when most stuff is still broken πŸ˜‚

cinder summit
#

My idea for scaling shapes would definitely be to just scale every modifier and primitive, and act like it was always that size ... But I'm not sure how parry handles it

vestal minnow
#

it just has a scale method for all shapes, and I copied rapier's approach of storing the unscaled and scaled version in Collider

cinder summit
#

On SDFs if the scale is non-uniform I have to make it panic or something anyway, because that wouldn't produce valid results πŸ˜‚

vestal minnow
#

and it's only updated when transform scale changes

cinder summit
#

Storing both in the same component seems a bit odd, usually you'd only need one of the two, except when you're updating the scaled one

vestal minnow
#

not having the original one could cause precision issues when scaling things often

cinder summit
#

Yea you would definitely need to keep both around, can't change the scale later otherwise

vestal minnow
#

like unscaled * scale / scale != unscaled probably

cinder summit
#

Or you would have to impose the arbitrary requirement that you can only do scales that don't introduce floating point errors

#

So powers of two

#

I'd imagine people would really hate that feature πŸ˜‚

vestal minnow
#

yeah, doesn't work since it should match up with mesh πŸ˜‚

cinder summit
#

In comparison the requirement that sdf colliders can't have non-uniform scaling is a lot less problematic

#

Because non-uniform scaling already makes most meshes look like garbage

#

In theory I could have non-uniform scaling, but it would require a constant computational overhead ... Maybe some day as a feature or some market component if any usecases for it exist

vestal minnow
#

usecase is that people using bevy_editor will expect collider to match mesh regardless of scale

#

but shear doesn't work in bevy_xpbd already so

cinder summit
#

Don't worry I'll just make the editor panic too πŸ˜‚

mellow orbit
cinder summit
#

Extruding an elipsoid? Yea that should be possible

mellow orbit
#

then I don't care about non-uniform scaling πŸ™‚

cinder summit
#

The mesh also can't mismatch if both the collider and mesh are based on unscaled SDFs 🧠

mellow orbit
#

Is there a performance advantage in having fewer Components in a Query?

vestal minnow
#

to not cause unnecessary query conflicts with potential user systems

#

since most components in RigidBodyQuery are &mut

#

it's unlikely that people will have systems there, but still nice to make it possible

mellow orbit
#

put pub name: Option<&'static Name>, in RigidBodyQuery...

vestal minnow
#

that's fine

mellow orbit
#

so it could have


    pub fn debug_id(&self) -> String {
        match self.name {
            Some(n) => format!("{:?} ({n})", self.entity),
            None => format!("{:?}", self.entity),
        }
    }
#

and it feels icky to do it again for all the ones in integrator.rs

vestal minnow
#

could also make it a function in utils

mellow orbit
#

looks at the other stuff there

vestal minnow
#

the restitution and dynamic friction should not be there lmao

#

it's kind of a redundant module tbh

mellow orbit
#

A utility function would look something like debug_id(opt_name,entity)?

vestal minnow
#

yeah

mellow orbit
#

that doesn't feel nice to me

vestal minnow
#

you could make a DebugId world query and add a method there if it's nicer, but then the query can't have another Entity component

mellow orbit
#

hmmm.

mellow orbit
royal helm
#

you'd have to modify global transform directly

#

Transform cant shear

pulsar bone
#

But you can end up with shearing on child transforms

royal helm
#

ah true

mellow orbit
#

maybe this is the wrong approach, and I should just have it log entity Name to EntityId mappings whenever a Name is added to an entity, and then just log entity id. That way, it'd be easy to reconstruct and not so annoying throughout the code.

glossy bloom
#

Should contacts between child colliders of the same rigidbody be ignored?

#

They don't seem to be reported as active contacts in rapier

#

I'm happy to make a PR for this if this is not intended

crystal cosmos
#

Is there a built in way to tell if a collision event is based on a sensor vs rigidbody collision, or to tell the layers of the entities?

I think right now querying for those based on entity is the correct option?

glossy bloom
#

querying based on entity id should be plenty fast though, afaik

#

but yea someone else might be able to give you a more informed answer

#

filtering out collisions between entities parented to the same rigidbody gives an order of magnitude speed up to the narrow phase collect_collisions in my game

vestal minnow
cloud jasper
#

Rapier has collision groups and solver groups. If entities exclude each other using collision groups, intersections between them won't generate entries in the contacts graph and won't generate collision events. But if they only exclude each using using solver groups, they'll still generate collisions that can be detected manually, it just won't affect the physics simulation because Rapier will not generate forces based on these collisions.

I've noticed that XPBD only has collision layers. Am I right to assume it works more like Rapier's collision groups? Does XPBD have anything similar to Rapier's solver groups (as is - detect and register collisions but do not act upon them)?

Colliders represent the geometric shapes that generate contacts and collision events when they touch.

cinder summit
#

Collision layers work like rapier's collision groups yea

#

I wonder what the usecase for solver layers is that isn't covered by sensors πŸ€”

vestal minnow
#

usecase is to treat some objects like sensors and some as normal bodies based on the layers

cinder summit
#

That's not a usecase but a description of the functionality πŸ‘€

vestal minnow
#

like A1 can go through door B1 but A2 can't

#

those names don't make sense but whatever

cinder summit
#

With doors you could still make them collision layers

vestal minnow
#

yeah, but you might want to know that A2 tried to go through the door... although you could have a separate sensor for that

cinder summit
#

Yea the main issue here would be that it's annoying to get collision events for both because they will all be grouped up. A1 and A2 both collide with it, but you're either gonna want only A1 (those who can pass trough, which requires a separate sensor that excludes A2) or A2 (those who got blocked, which works fine if A1 doesn't collide with it)

cloud jasper
#

One thing I used them for was pickables. I want to generate a collision event between the player and the pickable so that I can trigger picking up the object, but I don't want the physics engine to act on that collision.

cinder summit
#

Sensors would work here I think?

vestal minnow
#

sensor

#

ya

cinder summit
#

The only thing I can imagine is the mess that is spaceships in spaceships

#

You might need to know who is in a spaceship for correct behavior, but not want smaller ships to collide with it

#

If you always need both anyway it's cheaper to not have two colliders, especially if they get weird shapes

vestal minnow
#

(in some games)

cinder summit
#

Tho realistically I'd make it a separate sensor and rigid body then because I wouldn't want a tiny pickup radius

cloud jasper
#

Yes. So you have to exclude them from the player using a collision groups, but also add another sensor to the player in order to detect them.

cinder summit
#

Yea I can definitely picture some niche usecases for this .... Tho the docs for such a feature should probably suggest looking at sensor first

cloud jasper
#

Another thing I wanted to use this for, which is probably even more niche and I haven't actually tried to do yet, is some sort of "environment radar". Basically create a big cylinder around the player and give it empty solver groups but non-empty sovler groups, and look at the collisions graph to get the shape of the environment around the player. Form there I was going to deduce if there are ledges they can hang from, walls they can wall-run on, etc.

#

With rapier, at least, a sensor will only give me a yes or no answer - was there a collision or not? But it won't tell me the "shape" of the collision.

#

Though it looks like it may be different in XPBD?

vestal minnow
#

The only difference to normal colliders is that they don't cause a collision response

cloud jasper
#

Okay. Thanks.

vestal minnow
#

I would assume there to be a performance reason for why Rapier can't compute contacts for them, but to me it feels like a niche optimization that can be annoying since people will still often want the data

cinder summit
#

Technically rapier gives you those collision events too ... Just not trough the same channel iirc

cloud jasper
#

This is actually for a more advanced feature of Tnua, which I don't know when I'll get to. Right now I'm working on adding XPBD support, and I was wondering how to handle collision layers, but since I have my answer now I should probably focus on that task and worry about these spatial awareness sensors later.

vestal minnow
#

But yeah if we added SolverLayers, we'd have two components for basically the same thing, except SolverLayers is more powerful. Sensor is just an entity with no masks / interaction groups for SolverLayers. It feels like they could be combined

#

Sensor might be more user friendly though

cloud jasper
#

Maybe a way to configure if sensor gives Collision events, or only CollisionStarted and CollisionEnded?

cinder summit
#

I wonder what the overhead from all the collision events is actually πŸ€”

vestal minnow
#

Also if you have a Sensor and SolverLayers on the same entity, should it ignore all contact responses or just do it based on the layers?

cloud jasper
cinder summit
vestal minnow
#

Which is why it'd make sense to combine them imo

#

Just not sure on the API

cinder summit
#

Only difference being that you don't need additional contact manifolds for things that get ignored by the solver

#

Then again the rapier codebase is kind of confusing so maybe there's architectural reasons why it doesn't work as simply as in xpbd

cloud jasper
vestal minnow
#

Time<Physics>::pause is probably the main way

#

doesn't disable absolutely everything though, just the simulation loop (collision detection, integration, solver etc.)

cloud jasper
#

Okay, I just want to have Tnua pause itself as well when XPBD is paused.

cinder summit
#

@vestal minnow Decided to profile my server now that it's running on 0.12 ... Seems like substeps are running fairly fast now unlike before, but I'm still bottlenecked by a bvh ferris_sob

#

Takes about 100 microseconds to update the grounded state of every character now (there's about 50 I think?), vs 100 micros per character with the single shapecast against a trimesh πŸ˜‚

vestal minnow
#

Sounds like a pretty nice improvement πŸ‘€

vestal minnow
cinder summit
#

Here's the numbers for a release build

#

I think that % is just the % of a single core that was used, it's single threaded and uses only 6-8% so 92%-ish doesn't exist πŸ€”

cinder summit
# cinder summit Here's the numbers for a release build

Pretty sure the only benefits xpbd sees there are no more debug assertions, lto=thin, and codegen-units=1 ... My own code would go from opt-level 1 to 3 as well, which is why the bvh gets a decent amount faster (still not fast enough tho, gotta make those incremental updates)

vestal minnow
#

copy parry's incremental updates, surely it'll work πŸ™ƒ

cinder summit
#

I think incremental updates actually shouldn't be too hard to fit into the tree

#

I just need to do some annoying sorting magic and move stuff around in arrays to make it work

#

Zoomed in on a substep, it looks like it's pretty much all schedule/system overhead besides integrate_rot, integrate_pos and collect_sdf_collisions πŸ€”

#

That schedule for post-processing the collisions might be a bit overkill actually πŸ˜‚

vestal minnow
#

the integration systems could also be parallelized with just a par_iter_mut, not sure if it'd help tho

vestal minnow
cinder summit
#

Overall it's running very well considering the whole area is covered in concave colliders

#

Half the rooms have arcs as walls, and their AABBs tend to just cover the whole room .... There's clearly still some room for optimization left tho, since many of them don't get close to touching the wall I could probably make the logic a bit more efficient with the early returns

#

But I'll probably look into that only after I refactor all the SDF stuff to look more like the primitives PR πŸ€”

lime hatch
# cinder summit Is there any research on determinism with physics btw?

Depends on what you mean with research πŸ™‚ I have a branch locally where I've, in a paranoid way, removed everything I think might possibly break determinism. I still get the occasional desync, but much more rare than when I started. Turns out bevy_ggrs had some bugs as well, and I haven't tested with all the latest versions.

The version of bevy_xpbd I started is still deterministic, but missing a lot of features compared to this one, so I'd rather be on the same version as everyone else.

#

Some of it might strictly speaking not be determinism issues, but be related to added/changed queries not taking rollback into account. Latest bevy_ggrs is very different in this area as well

cinder summit
#

Determinism mad science sounds pretty nice too ... It's just a lot harder to weigh decisions if no research paper talks about determinism

#

One of these days I'll definitely need to try to make my SDF collisions and my game in general behave more deterministic. My game slowly drifts over time, but the real issue would be bumping into anything that has server authority ... Best solution would of course be if you can't bump into them ... By building some obstacle avoidance into the character controller, so you run around enemies and players instead of into them

cinder summit
#

Putting it in the character controller would actually be a bad idea, it would need to happen on the client's input handling, otherwise the desync would just get worse πŸ˜‚

civic wadi
#

Curious what the status of CCD/Tunneling in xpbd is? I have a setup where my systems tick relatively slowly (~30/s) and have rigid bodies with quite high velocities.

vestal minnow
#

Not supported yet but substepping can help if the performance hit is fine
#math-and-physics message

cinder summit
glossy bloom
#

Pretty sure this is another big source of weirdness for child colliders. Unless I'm missing something, they seem to be rotating about the Position of the rigidbody they are attached to, instead of the center of mass.

#

repro:``` // floor
commands
.spawn(PbrBundle {
mesh: meshes.add(shape::Box::new(40., 0.3, 40.).into()),
material: materials.add(Color::WHITE.into()),
..default()
})
.insert(RigidBody::Static)
.insert(Collider::cuboid(40., 0.3, 40.));

// cube
commands
    .spawn(SpatialBundle {
        transform: Transform {
            translation: Vec3::new(0.0, 2.0, 0.0),
            ..default()
        },
        ..default()
    })
    .insert(RigidBody::Dynamic)
    .insert(AngularVelocity(Vec3::new(0., 7., 0.)))
    .insert(LinearVelocity(Vec3::new(0., 7., 0.)))
    .with_children(|b| {
        b.spawn(SpatialBundle {
            transform: Transform {
                translation: Vec3::new(1.5, 0., 0.),
                ..default()
            },
            ..default()
        })
        .insert(Collider::cuboid(1., 1., 1.));
    });
cinder summit
#

I think implementing a specific buoyancy approach would probably be a mistake, since there's difference approached based on game design requirements and adjacent systems like water physics

#

It could even be a crate I think. It's mostly just that a built-in solution could be a pretty big footgun

#

Tho I guess we could say the same about the built-in parry support πŸ˜‚

#

Well that's really the main issue, you're probably not gonna put multiple different implementations of the same thing in your crate

#

otherwise jondolf would've stolen my sdf collision code by now

#

Pretty sure you'd need some specific logic to decide which one wins in that case πŸ€”

#

Which in games if very often whatever you were already touching, or whichever you are overlapping with most (tho that one is kind of hard to calculate)

cloud jasper
#

I know this is a help channel, but I think this may interest you: #crates message

#

Not yet. Maybe some day.

cinder summit
#

Not like there's a non-help xpbd channel, could be useful tho

vestal minnow
vestal minnow
#

I'm sure one of the mods can arrange that

#

and xpbd-dev obviously

#

why not xpbd-memes too

#

should make my own server at that point πŸ˜‚ someone suggested that a while ago

cloud jasper
#

xpbd-jam?

cinder summit
#

Can't forget xpbd-determinism

#

It would have like 3 people probably πŸ˜‚

vestal minnow
#

I've only seen like 3 or 4 people caring about determinism for xpbd so far tho

#

and yes it is very important

#

I believe it can be

#

nvm

#
#

but it just does a syncing thing

cinder summit
#

I feel like that's the real issue with things like determinism, many people just change their whole game design when they run into such issue, because even a slight hint of feeling like it is out of your control makes it seem unreachable

#

Switch to 2d for determinism?

cinder summit
#

Ah, switching to 2d because unity is poorly designed enough to make that seem like a normal solution

vestal minnow
#

*locally, not cross-platform based on the FAQ

#

end

#

yeah

#

I still am not even sure if glam with libm is cross-platform deterministic, but I assume so

#

and if not...

cinder summit
vestal minnow
#

well, behaves the same on most processors and architectures

onyx shard
#

added bevy_framepace and disabled vsync to see my max fps. It looks like the provided 3D kinematic character controller in examples is affected by framerate when it comes to movement, although the jump seems fine. I'm new to all this so I might be doing something wrong as well, can someone else confirm this?

vestal minnow
#

ah yeah that looks frame rate dependent

#

LinearDamping uses this to be independent of frame rate

lin_vel.0 *= 1.0 / (1.0 + delta_secs * damping.0);
#

should probably use a similar thing in the examples

#

@onyx shard ^

onyx shard
#

got it, thanks!

sharp badger
#

Hey!

For the simple kinematic controller example, all collisions are looped over: https://github.com/Jondolf/bevy_xpbd/blob/42fb8b21c756a7f4dd91071597dc251245ddaa8f/crates/bevy_xpbd_3d/examples/basic_kinematic_character.rs#L129

I understand that I can use layers to control what collides, but is it possible to also filter what collision events are handled by which systems?

I'll have many entities and I'd like to handle grounding collisions separately from character collisions, and bullet collisions, etc.
With what I know now, I can only do this where each system iterates over all collisions and checks each colliding pair against a query. I'd prefer to instead iterate over only the relevant collisions.

GitHub

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

junior flower
sharp badger
fallen citrus
#

Question about schedules/timestep. So the physics schedule is fixed I see, suppose I want to have a system which will apply whatever velocity would be required to move an object from its position to a given new position which runs every frame. I set the linear velocity to the difference between the old and new position divided by Time<Physics>. When I add this system, do I need to add it to the PhysicsSchedule or do I add it to FixedUpdate and ensure that the fixed update interval matches the physics? I would prefer to have everything be as simple as possible for my grug brain, as in both game logic and physics run on the same fixed schedule so everything updates once per frame.

#

Right but its not supposed to be "move from position A to position B in x seconds" its supposed to have arrived at position B by the next frame. As if you were just setting Position directly, except it can collide with objects in the way and get blocked

stable narwhal
#

is there a general way to make stuff less glitchy?
I made two wheels that roll on a 2d rectangle, but no matter how I try to roll them, at some point they just explode into the air

#

if I set the mass too high, they don't even reach the floor before flying away

stable narwhal
#

adding compliance on joints seems to have helped

merry tide
#

So... Using a circle collider seems simple enough, but if I wanted to use the inside of a circle as a collider, and perhaps only 25% of it, is that also simple?

sharp badger
stable narwhal
#

How do I use PenetrationConstraint? ::new takes ContactData, but that looks like nothing I can fill out

wraith aspen
#

How do I offset cuboid colliders?

glossy bloom
# wraith aspen How do I offset cuboid colliders?

One way is to add them as a child collider, something like this:

commands.spawn(SpatialBundle::default())
    .with_children(|b| {
        b.spawn(SpatialBundle { transform: Transform::from_xyz(3., 0., 0.), ..default() })
            .insert(Collider::cuboid(1., 1., 1.));
    });
wraith aspen
#

i actually found a ColliderTransform component

#

gonna add it and see if it works

vestal minnow
#

no

vestal minnow
wraith aspen
#

what

#

why

wraith aspen
vestal minnow
#

From the docs

The transform of a collider relative to the rigid body it’s attached to. This is in the local space of the body, not the collider itself.

This is used for computing things like contact positions and a body’s center of mass without having to traverse deeply nested hierarchies. It’s updated automatically, so you shouldn’t modify it manually.

wraith aspen
#

oh i didnt read the "updated automatically" part

vestal minnow
#

should probably make the name more daunting to make it clearer

cloud jasper
#

Isn't GlobalTransform also updated automatically? What's the difference?

vestal minnow
#

it's not global, it's relative to the rigid body

#

I believe rapier has a somewhat similar thing, like translation_wrt_parent or something

#

if it used GlobalTransform, it'd cause pretty bad jitter since it'd be constantly recomputed with new values

#

ColliderTransform only changes when the Transform of a collider that is a child of a rigid body changes

#

it's basically just a local transform, but wrt the rigid body, so deeply nested collider hierarchies work

vestal minnow
#

they're added to a PenetrationConstraints resource which is iterated, solved and cleared at every substep

wraith aspen
#

anyways i got the child childer working

vestal minnow
#

cool

#

they might have some stability issues in some cases, but I think the issues are mostly known and we'll try to fix them soon-ish

wraith aspen
#

collision doesnt seem to be working, i am trying to collide a kinematic rigid body with static rigidbodies

#

but nothing happens

vestal minnow
#

kinematic bodies by definition don't get pushed by things by default

#

same in rapier, unity etc.

#

they're user controlled

wraith aspen
#

i am moving them with LinearVelocity

vestal minnow
#

You need to handle collision response separately; many character controllers have something like move_and_slide/move_and_collide, but xpbd doesn't have a built-in character controller yet.

However, the basic character controller examples have a simple collision response system:
https://github.com/Jondolf/bevy_xpbd/blob/7592ed86e2afd85ae11b35a47fbf3512e1b90813/crates/bevy_xpbd_3d/examples/kinematic_character_3d/plugin.rs#L292
how to add it:
https://github.com/Jondolf/bevy_xpbd/blob/7592ed86e2afd85ae11b35a47fbf3512e1b90813/crates/bevy_xpbd_3d/examples/kinematic_character_3d/plugin.rs#L22-L26

#

You can remove the character controller specific components to make it work for all kinematic bodies

wraith aspen
#

kinematic doesnt handle collisions for you?

vestal minnow
#

dynamic does

#

dynamic bodies can hit kinematic bodies, but kinematic bodies are unaffected by default

#

they're like static bodies that can be moved

wraith aspen
#

alr

vestal minnow
wraith aspen
#

i'll take a look at that

fallen citrus
# wraith aspen How do I offset cuboid colliders?

Also a protip in case you find it complicated to keep track of child colliders as I do: you can alternatively make a composite collider for this since each collider in it has its own local translation and rotation.

peak timber
#

Does bevy_xpbd use the built in Transform scale

vestal minnow
#

it scales colliders yeah

peak timber
#

I was thinking of just not using Transform & disabling the SyncPlugin, that way I can use Position as a source of truth since it uses f64

#

And then write my own GlobalTransform updater to base global transforms around the camera

#

But that doesn't account for scale

#

Since there's only Position & Rotation components, not one for manually setting Scale

#

What would you recommend for doing this?

vestal minnow
#

You might be able to disable transform_to_position in SyncConfig and I think scale might still work?

peak timber
#

and just continue using Transform but ignore the translation property?

vestal minnow
#

Hmm, I don't think it works exactly like you'd like. It would ignore updates that you make to Transform translation or rotation, but it would still update Transform automatically based on Position/Rotation changes. You can also disable that with position_to_transform, but I think that also disables scaling currently

#

I could probably move the scale system out of that run condition though

peak timber
#

I wish Bevy had better support for using f64 for positions

#

So that I don't have to ditch support for basically the entire ecosystem of crates to use it lol

vestal minnow
#

something like a DTransform

peak timber
#

or just a float alias that's feature-controlled like xpbd does it, but maybe that's too complex

vestal minnow
#

(like DVec3)

#

here the colliders are scaled, but not affected by transform translation/rotation changes

peak timber
#

is there a way to have more fine-grained control on which things get synced

#

like keeping rotation part of the transform

#

I guess it doesn't matter too much, I can just use the Rotation component

vestal minnow
#

not really, it'd require splitting systems out and make run conditions more annoying

peak timber
#

fair

#

this will probably work pretty well

#

then I would just disable the TransformPlugin and write it myself to position everything relative to the camera for rendering I suppose

vestal minnow
#

@peak timber scale should work with the other options disabled on main now

glacial knot
#

i can't see my rigid body

glacial knot
#

nevermind i found PhysicsDebugPlugin

tacit hinge
#

This may sound like a stupid problem, but I'm really struggling with this.

I recently switched from bevy_rapier2d to bevy_xpbd_2d. I've gotten it to compile, but the platform I had setup to have my character stand on is missing. These are the components for my player:

PlayerBundle {
    marker: Player,
    health: Health(100.0),
    spritesheet: SpriteSheetBundle {
        transform: Transform::from_scale(Vec3::from_array([1.0, 1.0, 1.0])),
        sprite: TextureAtlasSprite::new(0),
        texture_atlas: assets.spritesheet.clone(),
        ..default()
    },
    animation_timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
    input_manager: InputManagerBundle {
        input_map: PlayerBundle::default_input_map(),
        ..default()
    },
    rigid_body: RigidBody::Dynamic,
    collider: Collider::cuboid(10.0, 10.0),
}

And for my platform:

PlatformBundle {
    sprite_bundle: SpriteBundle {
        transform: Transform::from_xyz(5.0, -100.0, 0.0)
            .with_scale(Vec3::from_array([1000.0, 100.0, 0.0])),
        sprite: Sprite {
            color: Color::rgb(255.0, 0.8, 0.8),
            ..default()
        },
        ..default()
    },
    rigid_body: RigidBody::Static,
    collider: Collider::cuboid(1000.0, 1000.0),
}
vestal minnow
tacit hinge
vestal minnow
#

I don't think it does, but wanted to make sure

#

Your collider is quite massive though

sleek thicket
#

yeah, might need to zoom out

vestal minnow
#

1000.0 * 1000.0 pixels wide and 100.0 * 1000.0 px high

sleek thicket
#

player is definitely inside it

vestal minnow
#

yeah

tacit hinge
#

I changed the platform collider to 10x10 and the player to 2x2, and I can see a flash of the platform at the top of the screen when I first start πŸ€”.

sleek thicket
#

collider scales with transform scale

tacit hinge
#

Oh really? Ahhhh, there we go. The transform scale was huge.

upper pivot
#

If I put a fixed joint between a rigid body with a Rotation and another rigid body, it seems like the rotation is undone. Is there a way to keep the rotation?

vestal minnow
vestal minnow
#

A hacky workaround could be to use a RevoluteJoint instead, but set the angle limits to some desired angle

upper pivot
#

Aha, cheers! So is it expected that it will "just work" the way I thought it would?

vestal minnow
#

I think I'll support local frames which would be anchors + rotations

#

so you could specify the desired rotation yeah

tacit hinge
#

And thank you for helping πŸ™‚

vestal minnow
vestal minnow
tacit hinge
#

Ohhh, I see. Thank you.

final dove
#

Question about the order of systems in each physics frame: Are collisions resolved before objects are translated? Or am I reading the setup incorrectly?

vestal minnow
# final dove Question about the order of systems in each physics frame: Are collisions resolv...

First, broad phase collision detection is run, and then the substepping loop starts:

  1. Move based on velocity and forces
  2. Compute contacts (narrow phase)
  3. Resolve contacts (move bodies)
  4. Update velocities based on the change in position before and after solve
  5. Apply dynamic friction and restitution to velocities

To avoid numerical issues at large distances, the solver doesn't operate on positions directly, but instead uses an "accumulated translation" that is applied at the end of the frame. This might eventually be changed if there's a more elegant approach though

final dove
vestal minnow
# final dove Okay, I was seeing that the ApplyTranslation substep was last in the chain, is t...

oh yeah ApplyTranslation is at the end of each substep and not the end of each frame, my bad

Yes, the broad phase is run before integration, and only once per frame, not once per substep. This is what the original XPBD paper suggests. Of course, this by itself could cause missed collisions, but the AABBs are given some extra padding based on their current velocities, so they are unlikely to move outside of the computed AABBs during the substepping loop.

#

Here's the part in the paper for reference

final dove
#

With apply translations being at the end of the substep, is there a chance that the entity could be rendered intersecting with another entity?

vestal minnow
# vestal minnow

we do it slightly more efficiently though by mostly expanding in just the movement direction

vestal minnow
#

(unless it's unable to resolve the contact fully ofc)

final dove
#

Ah I guess I am thinking in terms of a kinematic object where the velocity won't change from the velocity solver necessarily

tacit hinge
#

I'm trying to setup ground detection, and I've been looking at this for help when I need it. I'm getting a bit confused though.

Why does the ShapeCaster shape have to be smaller than the player collider? Also, why is this system constantly getting hits, even if the shapecast isn't hitting anything? Is it hitting the player's collider?

pub(super) fn update_grounded(
    mut commands: Commands,
    query: Query<(Entity, &ShapeHits), With<Player>>,
) {
    for (entity, hit) in query.iter() {
        dbg!(hit);
        // commands.entity(entity).insert(Grounded);
    }
}
PlayerBundle {
    marker: Player,
    health: Health(100.0),
    spritesheet: SpriteSheetBundle {
        sprite: TextureAtlasSprite {
            index: 0,
            custom_size: Some(Vec2::new(2.0, 2.0)),
            ..default()
        },
        texture_atlas: assets.spritesheet.clone(),
        ..default()
    },
    animation_timer: AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
    input_manager: InputManagerBundle {
        input_map: PlayerBundle::default_input_map(),
        ..default()
    },
    rigid_body: RigidBody::Dynamic,
    locked_axes: LockedAxes::ROTATION_LOCKED,
    collider: Collider::cuboid(2.0, 2.0),
    ground_shapecaster: ShapeCaster::new(
        Collider::cuboid(1.9, 1.9),
        Vec2::ZERO,
        0.0,
        Vec2::NEG_Y,
    )
    .with_max_time_of_impact(10.0),
    grounded: Grounded,
}
drifting marsh
#

Is AccumulatedTranslation modified anywhere in SubstepSet::SolveConstraints? I'm trying to track down non-determinism.

#

Obviously the collisions are different here, but I can't find where AccumulatedTranslation is modified in SolveConstraints.

#

Oh, I found it now. PositionConstraint

#

It's very odd. I'm getting a bunch of collisions on one client but none on the other. The desync happens when the players look like they aren't colliding with anything, just falling in the air.

#

Haha, I think I figured it out. My game has a round system and creates a new level every round. I wasn't rolling back the level entities or the resource that keeps track of the current level. That seemed to fix it.

sleek thicket
vestal minnow
#

Spatial queries don't use prediction distance, it's a narrow phase thing

vestal minnow
#

As for getting hits when not actually hitting anything, I'm not sure; in 0.3 it should ignore the players own collider by default

#

(but not in 0.2)

#

Could log the hits and see which entities are being hit

sleek thicket
#

the hit detection from hugging the wall is from prediction_distance though, isn't it

vestal minnow
#

contacts yes, but shape casts no

sleek thicket
#

oh alright, but it's still not the expected behaviour and workaround could cause more bugs

vestal minnow
#

Contact events being sent when not actually in contact is a bug yeah, but having to use a smaller shape for shapecasting in this case isn't really fixable

#

or I guess it kinda should work already, but there's no guarantee

sleek thicket
#

in this scenario it makes sense though, so i'll complain about it when i actually encounter a need for accurate full-sized check πŸ˜…

#

i think i never had any problems because i was using hovering collider in the first place

#

i can imagine it being weird for sprites though, if you want to teleport forward if nothing is hit, but it has a step and you end up being inside ground

#

potentially launching yourself into orbit because of that

vestal minnow
#

The player will inevitably be slightly overlapping objects when moving into them, like in this case hugging a wall. This would also make the shapecaster hit the wall if its size matched the collider perfectly. But I suppose the solver should have solved contacts before spatial queries are run, so technically they shouldn't be touching anymore; but if the solver can't converge perfectly or there are numerical precision issues, it could still register the shapecast hit

sleek thicket
#

either way the explanation of expected bugs is worth adding as comments, even better if there's an example for how things can go wrong

vestal minnow
#

yeah

sleek thicket
#

like ghost collisions...

vestal minnow
#

Ooh, that looks like an amazing tutorial series, covers a ton of stuff in a practical way

#

it'd be cool to make something similar for Bevy

#

would show off physics and overall how to work with the ECS for this type of stuff

#

could be nice even for the Bevy book eventually if it has a "learn by example" version

sleek thicket
#

or the cheatbook @glad abyss πŸ‘€

vestal minnow
#

I feel like the format is a bit different, but yeah would be cool

glad abyss
# sleek thicket or the cheatbook <@574293018249527308> πŸ‘€

in an ideal world where i have infinite time, mental energy, and motivation, my vision for cheatbook is:

  • to have a chapter dedicated to tutorials, that guide you through making various cool things with bevy (anything from a complete "game", to advanced custom rendering) and also with cool ecosystem plugins
  • to have a chapter dedicated to "learning by example" (the "cookbook" chapter) that shows you the code for various specific problems, together with explanation for you to understand it
  • the rest of the book being reference-style, with a page dedicated to each topic, and that page covering the topic extensively, starting with the basics and a practical overview, and then delving into the details. every page should contain lots of links to other pages to help ppl navigate and jump around the book.
#

currently:

  • the "tutorials" chapter does not have any proper tutorials, just one page that links most of the content in the book , roughly ordered by difficulty and importance for someone new to bevy. the intention for the chapter is to make proper tutorials, but i haven't gotten around to that yet.
  • the "cookbook" chapter contains various miscellaneous things, that have been there since the dawn of time, it hasn't really gotten much love or new content in over a year
  • the rest of the book is largely fine, though different pages are in a wildly different state. some pages are great, high quality, up to date. others are outdated or poor quality in comparison (because they were written before i had my current vision for the book). i am gradually working through all of that.
sleek thicket
#

catlikecoding focuses on just one thing, covering every step that's necessary for the next step, and intentionally making errors so that explaining code isn't overwhelming

glad abyss
#

we all have our own teaching styles, and that's why it is very valuable to have a diversity of different sources and different people teaching things πŸ™‚

sleek thicket
#

when something doesn't require any previous knowledge, cheatbook/examples are good

glad abyss
#

cheatbook intends to make it easy for you to jump around and find the knowledge you need. i don't want to teach things step by step, assuming you have no prior knowledge, because then that hampers ppl who already do have some of the prerequisite knowlege. and most ppl have at least some (albeit different) prerequisite knowledge. instead, i want to teach just the topic at hand, but make sure to link you to the places where you can learn any prerequisite knowledge you need.

sleek thicket
#

i still jumped around CLC, it's not as bad as you think

glad abyss
#

everyone can jump around anything. that's besides the point. my point is that a cheatbook page should cover its topic without distractions / tangents / detours.

#

that is my style

sleek thicket
#

but it'd still have distractions, just in the form of links

glad abyss
#

that's exactly what i do though.

#

when a cheatbook page mentions another topic as part of its explanation for something, the page on that other topic is linked

#

you can click on the link to take that detour and learn about that other topic

sleek thicket
#

in that case yeah, a structured tutorial would have to be in another book

glad abyss
#

like i said, my intention is to have structured tutorials in cheatbook. but they would be in a dedicated chapter for that.

#

i agree they are valuable

sleek thicket
#

maybe it's possible to make some kind of a mix between the 2 though

#

structured tutorial that references a single cheatbook page that's self-contained and without any distractions

#

either way i don't think it's really possible to get away from distractions, it's just that in a structured tutorial it stays on topic by omitting unnecessary parts and explaining potential errors, while in a cheatbook it goes too deep into parts that may be completely irrelevant and burying some of the relevant information in links

merry tide
#

I was trying to make a "bumper" of sorts. If I set the restitution to be above 1.0 by quite a bit, wouldn't you expect something to bounce off of it higher every time?

finite blaze
vestal minnow
#

What I would do is have a system detect hits against bumpers and apply an impulse or add velocity in the direction of the contact normal

#

This way you also have more control over the bumper strength, like you could have a max velocity which wouldn't work with just restitution

merry tide
royal helm
#

I think I've found a nice way to organize my games CollisionLayers:

pub trait CollisionLayersGameDefs {
    const PLAYER: CollisionLayers;
    const ABILITY: CollisionLayers;
    const WALL: CollisionLayers;
    const GROUND: CollisionLayers;
    const FLUFF: CollisionLayers;
}

impl CollisionLayersGameDefs for CollisionLayers {
    const PLAYER: CollisionLayers = CollisionLayers::from_bits(PLAYER, u32::MAX);
    const GROUND: CollisionLayers = CollisionLayers::from_bits(GROUND, u32::MAX);
    const WALL: CollisionLayers = CollisionLayers::from_bits(WALL, u32::MAX);
    const ABILITY: CollisionLayers = CollisionLayers::from_bits(ABILITY, u32::MAX);
    const FLUFF: CollisionLayers = CollisionLayers::from_bits(ABILITY, u32::MAX);
}
#

so I can add them like CollisionLayers::PLAYER

sleek thicket
merry tide
#

I have a system that is storing the placement and time of object being controlled by xpbd, and it sometimes looks like this:

#

It feels like it isn't supposed to have same X/Y at different times.

#

And I think I might be doing something completely wrong, because I would obviously love the physics engine to take precedence over rendering, even if it is just a couple of geometric shapes that can render at 9000 FPS.

pulsar bone
#

That makes sense because the physics simulation doesn't run every frame

merry tide
#

Hm.

#

Hm, yes, perhaps it makes sense. I think I thought about it backwards.

#

So I am capturing the state perhaps too often.

#

No, it makes sense to me, thanks!

sleek thicket
#

@merry tide running it in fixedupdate or whatever xpbd uses should fix it

vestal minnow
#

PhysicsSchedule which runs in PostUpdate

merry tide
sleek thicket
#

replay should probably interpolate it though

merry tide
#

Yeah, that is fair, for consistent rendering.

#
thread 'main' panicked at C:\Users\larsd\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.12.0\src\schedule\schedule.rs:290:33:
Error when initializing schedule PhysicsSchedule: Systems with conflicting access have indeterminate run order.
2 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- track_state and run_substep_schedule (in set Substeps)
    conflict on: bevy_ecs::world::World
 -- track_state and wake_on_collider_removed (in set Sleeping)
    conflict on: ["bevy_transform::components::transform::Transform"]

This is a little outside my expertise, is there a simple way to know whether after, before or ambiguous_with is the right way to go?

#

By "expertise" I am sure you all know I am a noob.

#

Running the state tracker after seems correct?

vestal minnow
#

.after(PhysicsStepSet::SpatialQuery) probably

#

the scheduling can be a bit annoying so I'd like to make it a bit more obvious and user-friendly at some point

merry tide
#

Yeah, well, the Discord help is very user friendly at this point. πŸ™‚

merry tide
#

That just worked as expected, it seems, thanks so much for the help.

crystal cosmos
#

Is there a way to clear/reset a rigid body? Gave this a shot but it kinda breaks the car permenantly xD

fn reset_car(
    input_q: Query<&ActionState<input::InputAction>>,
    mut player: Query<
        (
            &mut Transform,
            &mut ExternalForce,
            &mut ExternalTorque,
            &mut AngularVelocity,
            &mut Inertia,
            &mut LinearVelocity,
        ),
        With<car::Car>,
    >,
) {
    let action_state = get_single!(input_q);
    if action_state.just_pressed(input::InputAction::ResetCar) {
        for mut p in player.iter_mut() {
            *p.0 = Transform::from_translation(Vec3::Y * 4.0);
            *p.1 = ExternalForce::default();
            *p.2 = ExternalTorque::default();
            *p.3 = AngularVelocity::default();
            *p.4 = Inertia::default();
            *p.5 = LinearVelocity::default();
        }
    }
}
vestal minnow
#

Inertia::default() gives it 0 angular inertia so it'll kinda just be broken

crystal cosmos
#

Yea, I can see all the inverse components too. Would you recommend I just remvove all xpbd related components and re-add ?

vestal minnow
#

Do you need to specify mass properties manually?

#

I'm not sure why you'd set inertia to 0

crystal cosmos
#

I am adding a Mass component when I create it, is that what you mean?

#

Ah, maybe I misunderstood the intertia component, I assumed it was some kind of velocity

vestal minnow
#

The moment of inertia, otherwise known as the mass moment of inertia, angular mass, second moment of mass, or most accurately, rotational inertia, of a rigid body is a quantity that determines the torque needed for a desired angular acceleration about a rotational axis, akin to how mass determines the force needed for a desired acceleration. It ...

crystal cosmos
#

ahhhhh, that makes sense

#

Oh it seems just resetting angular velocity and linear velocity might be enough

vestal minnow
#

ya

crystal cosmos
#

nice πŸ™‚ works now. I guess with default settings you would also reset ExternalForce but I have persistence disabled for it

sinful spindle
#

How does bevy_xpbd handle parenting?

#

I want a space ship to be able to experience forces at certain locations within itself by having child components control their own ExternalForce

#

i.e., a thruster entity can be a child of the space-ship entity and enact forces (that may also turn the ship if not within the center of gravity) on the parent ship

silk mauve
#

Has anyone had luck getting xpbd working with bevy_mod_picking? I've got the backend written up but I think I'm doing something wrong... the y axis on my cursor is all jittery. To be more specific, when I log the position of my clicks this is what I get for clicking a few times without moving the mouse at all.

Some(Vec3(-1.9197165, 0.0003232956, 0.8540306))
Some(Vec3(-1.9196998, -5.772958e-6, 0.8541736))
Some(Vec3(-1.904909, -5.0872643e-8, 0.85350126))
Some(Vec3(-1.9048692, 6.2942505e-5, 0.85387325))
Some(Vec3(-1.904728, 3.7637913e-6, 0.8540563))
Some(Vec3(-1.9049245, 0.00016212463, 0.8533497))
Some(Vec3(-1.904776, 9.027271e-7, 0.8547515))
Some(Vec3(-1.9044625, 0.00024318695, 0.8542347))
Some(Vec3(-1.904867, 9.059906e-5, 0.85373783))
Some(Vec3(-1.9049906, 0.00029182434, 0.8529415))
Some(Vec3(-1.9050573, 9.027809e-7, 0.8538484))

There is negligible jitter in the x/z, but the y is all over the place. I'm clicking on a static body here.

#

Figured it out. Apparently the inconsistency is caused by the raycast hitting 2 things at the same position. Seems to mess it up somehow

#
commands.spawn((
        PbrBundle {
            mesh: meshes.add(shape::Circle::new(4.0).into()),
            material: materials.add(Color::WHITE.into()),
            transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
            ..default()
        },
    ));
    commands.spawn((
        RigidBody::Static,
        Collider::cylinder(0.5, 4.0),
        Position::from_xyz(0.0, -0.20, 0.0),
    ));

Raycasting into these objects works as expected. The x, y, and z coordinated are consistent frame to frame. However, if I make a slight change and move the rigidbody from a y of -0.20 to a y of -0.25, the y coordinate will become super inconsistent.

sinful spindle
silk mauve
#

I am clicking on world space objects.

pure nebula
#

Hello! Probably a super simple thing but I upgraded my project from Bevy 0.11 to 0.12 and Bevy_XPBD with it.

I'm using FixedUpdate for my physics and I noticed after upgrading that my movement now is frame-bound. It might have been before as well but nothing I noticed at least. Now when using a FixedTime of 60 Hz my character is updating very slowly. Is that correct or something I should set up differently now?

cinder summit
#

I don't think I see the configuration for Time<Physics> anywhere

tacit hinge
#

When using the LinearVelocity component, do I need to multiply it by time.delta_seconds(), or is that already taken into account?

vestal minnow
#

Depends on what you're doing, just like in other engines. Delta time is mostly to make things less frame-rate dependent or to make units more sensical

#

if you're setting velocity, it's probably unnecessary, but for e.g. acceleration you should multiply by delta time

#

(see link)

tacit hinge
#

I think I get it. So if I'm setting velocity like this, velocity.x = move_speed, I wouldn't need to because it's instantaneous?

vestal minnow
#

yeah

tacit hinge
#

Okay, thank you πŸ™‚

sleek thicket
#

setting never feels good though

tacit hinge
#

Why is that?

sleek thicket
#

here's a whole essay explaining char controllers πŸ˜‚

tacit hinge
#

Lol thank you

cinder summit
sleek thicket
#

in which one does it work?

cinder summit
#

Doesn't the essay itself mention a few examples?

sleek thicket
#

idk when i actually watched it lol

cinder summit
#

A fast acceleration usually still feels better

#

Especially on something that's really about the movement itself

sleek thicket
#

yeah, fast deceleration too

#

instant always feels like a car crash or something

cinder summit
#

But even weird things like really slow acceleration can work well, like in sonic

sleek thicket
#

i never liked 2d sonic though, and that slow acceleration might be the cause

cinder summit
#

Yea it's definitely not for everyone ... Instant acceleration can also just be the easier option for some genres, for fighter games or online games you might pick it because it solves certain gameplay or networking issues

sleek thicket
#

if solving the issue outweighs it then yeah, but either way it's better to just test and feel than argue about it.
if camera doesn't have to move i guess there's less reason for it to feel bad too

tacit hinge
junior flower
# pure nebula Hello! Probably a super simple thing but I upgraded my project from Bevy 0.11 to...

What is the value of PHYSICS_HZ there? I can't remember whether it actually got committed or not, but there was talk of a breaking change to from_hz relatively recently, because it was accepting 1/Hz before but would be changed to actually use Hz instead.
Can't remember if that was on main only or whether it's already been released, but if you're moving really really slowly I wonder if maybe it's that?

#

Oh, is that unrelated, maybe? That looks like Bevy's Time.

vestal minnow
#

yeah it was fixed in a patch release pretty quickly after the original release

#

their code has Time::<Fixed> which is normally unrelated to physics

junior flower
#

Yeah, sorry. Completely tunnel visioned in on the from_hz.

vestal minnow
#

but since @pure nebula is running it in FixedUpdate, maybe the physics timestep shouldn't be fixed and should instead be FixedOnce? It would be two fixed timesteps running at once which could cause issues, although I think there should be logic that fixes it

#

could've broken something in the time migration tho

#

might be worth trying Time::new_with(Physics::fixed_once_hz(60.0))

#

or something similar

cinder summit
#

Yea that's what I first noticed too ... Tho idk if that results in frame-dependant behavior ... Tho maybe that issue where it will run N physics steps in each of the N fixed updates

vestal minnow
#

but I might be reaching here

cinder summit
#

Oh actually if it updates Time<Physics> from Time<Virtual> and that happens inside FixedUpdate the behavior being FPS-dependant makes sense

vestal minnow
#

Time<Real> but yeah

#

there was a special-casing for FixedUpdate but it looks like I might've removed it thonk

cinder summit
#

Huh, based on Time<Real>? So slowing the game down doesn't affect physics?

vestal minnow
#

physics has a separate speed and play/pause loop in Time<Physics>

#

for now at least

#

(or Physics to be more accurate)

cinder summit
#

Kinda weird how xpbd does everything on Physics instead of Time<Physics> tbh πŸ˜‚

vestal minnow
#

the API has conflict-ey things if the methods are implemented for Time directly

#

like fixed_hz/from_hz

#

might cause confusion

cinder summit
#

Those are all on Time<Fixed> rather than Time right?

vestal minnow
#

yeah but shows up in autocomplete iirc

cinder summit
#

Tho I guess the long term goal would be to yeet the physics schedule once it becomes a reasonable assumption that everyone uses FixedUpdate

vestal minnow
#

yeah

#

just need to preserve manual stepping/running somehow

cinder summit
#

What if we just upstream those? thonk

vestal minnow
#

upstream what?

cinder summit
#

The manual stepping, no reason you can't step all of FixedUpdate

pure nebula
#

Sorry for the delay. I have updated so I set the Physics Time. I experienced the same issue, but maybe it's me misunderstanding something. It started working more correctly after using .add_plugins(PhysicsPlugins::default()). πŸ‘

I did record two videos just in case, one with Default and one with FixedUpdate as the only difference. Both setting
.insert_resource(Time::<Physics>::new_with(Physics::fixed_hz(60.0))) to see if there's anything there.

cinder summit
#

That should be fixed_once_hz right?

#

At least with xpbd in FixedUpdate

pure nebula
#

I see! I read through the docs (very late at night) and I didn't really see the difference between Fixed and FixedOnce. If my machine was not struggling with keeping up the physics simulation.
But yeah using Fixed_once totally makes it work in FixedUpdate, thank you!

tacit hinge
#

I was curious about two things. Why does the 2D dynamic character example use a shapecast to detect the ground instead of a raycast, and why do the shape and raycasts use a time of impact instead of a detection distance?

junior flower
#

Without looking, I would assume they use shapecasts because a raycast is an infinitesimally thin line, but a shapecast casts the entire source collider.
For a wide collider you probably don't just want the center, but the whole width of the collider, which is what a shapecast will get you.

Re the TOI, I have a feeling this is just how the internal physics library (Parry) does it so they're just following suit

sleek thicket
#

@tacit hinge #math-and-physics message

It’s the actual distance only if direction is a normalized vector.

tacit hinge
#

Without looking, I would assume they use shapecasts because a raycast is an infinitesimally thin line, but a shapecast casts the entire source collider.
For a wide collider you probably don't just want the center, but the whole width of the collider, which is what a shapecast will get you.

Why is a wide collider needed for ground detection?

vestal minnow
#

if you had a player standing in the middle of a tiny gap between two platforms, you probably want to consider that grounded, but a simple ray could go through the gap

#

or if you wanted to detect multiple objects below the player, you'd want to shapecast probably

#

but for simpler cases a ray is fine too, just be aware of potential edge cases like this

#

@tacit hinge ^

tacit hinge
#

That makes perfect sense. Thank you!

royal helm
#

Might have a frame delay bug for ExternalImpulse?

#

idk need to look into this more, I have some movement code in FixedUpdate and it reads the same velocity for multiple frames even after applying an impulse that should completely nullify the velocity

#

never mind I just didn't realize Time::<Physics> also needed to be set to fixed_once_hz

junior flower
sleek thicket
#

yeah, tbh it would be easy to just manually multiply vector by distance, and it'd make it clear enough what can go wrong

#

unless it does something else on the background πŸ€”

junior flower
#

I’m talking mainly about the docs and the name direction β€” it’s actually velocity internally and none of the doc comments suggest that it should be anything other than a unit vector

#

(Going on the information in that thread you linked)

sleek thicket
#

i didn't even check, did jondolf already do renaming on main?

junior flower
#

Ah, I guess I should have read to the very end of that thread πŸ™‚

sleek thicket
#

nope he didn't πŸ₯²

upper crow
#

hi! I am interested in having overlapping colliders form a composite collider, i.e., having a character where none of the colliders will hit any other colliders in the character, but still interact with other entitites. I know collision layers exist but since those have a maximum, I wanted to check if there's any other way to accomplish this?

royal helm
#

although I'm more familiar with how rapier's child colliders work I think it should be the same

upper crow
#

do you have a link to the relevant documentation? i'm not seeing any search results for "child" in xpbd's docs

royal helm
#

basically just add child entities to the parent rigid body and it should act like a single body

upper crow
#

ohhhh