#Avian Physics
1 messages Β· Page 6 of 1
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...
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.
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)
My general intuitive understanding of matrix math is very low, It hadn't really come up in my life since high school, except suddenly now everywhere in AI.
@vestal minnow it's integrating the quaternions I believe
From angular velocity maybe?
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
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?
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)
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
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?
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
this is kind of a wild joint
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?
the anchor is offset
but it also has translational limits along the x axis
which is why it slides around
I'm trying to think what kind of thing that might correspond to usefully π
it's just a prismatic joint, except the rotational DOFs are free
(or one of them was slightly limited as well actually)
I think that might be a "slot joint"?
no idea π
searching for that just gives me casinos
It does sound like some slang for casino π
these angular limits are a pain though, I'm just switching around axes to try to fix things
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 π€
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
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 π
Not other papers or sources doing specifically more complex joint stuff?
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
also this is a monster of a PBD/XPBD paper in case you're interested, covers a bit of everything
http://mmacklin.com/2017-EG-CourseNotes.pdf

You need to make your own XPBD SDF paper and patent the idea
ECS XPBD SDF BVH paper, that's a nice and clear name
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" π
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.
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
Just write it in France, patents are non-enforceable there among other places
So right now its basically assuming Quat::IDENTITY for local rotation?
the XPBD paper only mentioned the attachment points explicitly so I didn't even think about rotations originally
yea
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?)
I'd consider that to be pretty much fully featured in terms of joints
yeah I know that exists
Furthermore we use our own library:
Discregrid to generate cubic signed distance fields for the collision detection
Rapierbros... we're so back ||Dimforge is located in France||
it says π
OH yeah it has that, I forgot
for fancy cloth things probably
and soft bodies maybe
it's a bit off-topic but i'm curious if/how -z being forward affects development
I always feel like it's backwards for cameras and movement
same
need to subtract z
linear_velocity.x += direction.x * movement_acceleration.0 * delta_time;
linear_velocity.z -= direction.y * movement_acceleration.0 * delta_time;
i feel like the best solution would just be adding option of choosing it as a feature
idk that'll be annoying for 3rd party plugins probably
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
-z : I thought it was weird for about 60 seconds and then got used to it
yeah it's not too bad imo, but can be a bit weird sometimes
and sounds unintuitive to have [x, y, -z]
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
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
Oh yeah I got around that one with asset preprocessing
Oh wow, I assumed you meant that you were just working on the PR, but it's basically done already π (apart from the future things ofc)
looks very nice based on a quick look, just needs more shapes and helpers
can't use preprocess for gameplay code though
@vestal minnow Does this help? It's the "explained in detail" paper referenced at the end there... https://www.cs.cmu.edu/~spiff/moedit99/expmap.pdf
page 11
Thanks, looks useful; a bit math heavy, but I can probably grasp the main things with more thought
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
zlib license β osi approved and non-copyleft.
meaning it's copyrighted?
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
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)
If they get angry at you you can just tell them to come look for you if you ever visit america, and then just never go there π
exactly
I do know zlib has some particular issues that can make it annoying in some cases, but overall it's fairly permissive
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
Finland, close enough
Gray slush? Is this one of those cases where they should ban cars because they ruin snow?
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
i just call it mud
If you come to Boston in January or February you will feel right at home
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
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
they dont even have a rigidbody component, and no debug rendering
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
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
should have mentioned, I'm using the big_space library - which may be causing the issues
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)
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
Might be worth running a profiler to see what system is creating the load π€
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..
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
@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.
^ I second this
Third this!
i'm pretty sure everyone agrees though
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.
I think I was using this: https://www.youtube.com/watch?v=7QMRYddFeME
Ferr2D Terrain is available on the Unity Asset Store!
https://www.assetstore.unity3d.com/en/#!/content/11653
If you'd like to see more Ferr2D Terrain documentation, examples, or demos, go here:
http://ferrlib.com/page/Ferr2D_Terrain_Tool
Made with the upcoming 1.0.8 release!
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. π
hmm.. systems added to PostProcessCollisions don't seem to run for me. Is there some gotcha?
Not that I'm aware of... the one_way_platform_2d example works with it
ok, I found out directly after posting... It's because I add one of my plugins before physicsplugins, and physics plugins overwrites the schedule... I see some other bevy plugins changed from add_schedule to init_schedule and edit_schedule when going from bevy 0.12, perhaps we should do the same in bevy_xpbd? Should I make a PR?
Yes please :) didn't even know those were added
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?
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
for referecne, Unity has APIs that does this, you have to call a function every time to ignore collisions with specific other colliders
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
we just make sure to add a performance warning and link to layers?
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
yeah, the ideal would probably be something like SmallVec, but for sets... not sure if such a thing exsits?
haven't seen one
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
seems kinda small/inactive, though... maybe better to just go with a hashset?
maybe inactive because it's abandoned. maybe it's just simple enough that it's done
true
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
yeah good catch... I thought I fixed this already but I guess not
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
I'm dumb, SolverLayers isn't needed here since I can just make the cloth a sensor...
is there an easy way to apply torque off-center? I'm trying to make a joint that applies torque to itself
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
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!
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?
Do the colliders line up with the borders of the meshes when you enable the debug-plugin feature?
they do
yes
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...
Thank you for looking into it! I'll try to look into this more tmr as well
Or it's actually such a simple and quick fix that I'll do it rn
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
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
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.
I suppose a plugin with constraints could be better? But no idea how to tackle forces at the constraint level
Except, if I create the collider as a scaled cylinder, now when I scale the body to be oblong, it'll get extra squished.
And https://docs.rs/bevy/latest/bevy/prelude/shape/struct.Cylinder.html doesn't have a corresponding scale method. Because of course it doesn't.
A cylinder which stands on the XZ plane
This is a fancy way of hoping for that shared primitive shape thing to happen
You could test if it works on the fix-child-collider-contact-normals branch
So the issue is that you want to scale the collider with some subdivision count, but you can't scale both the shape and the transform because the mesh will no longer match?
yeah. at least not without a bunch of fussing around which would be avoided if the apis were not so different
I can think of at least two ways to get around that:
- 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
- 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
Also NiseVoid got the wheel rolling already in case you missed it
https://github.com/bevyengine/bevy/pull/10466
Sounds cool! I also recall seeing some XPBD thing that could handle at least realistic paper airplanes, I can try to find it if you want
I don't think it had code available though
nice!
That sounds cool! I would be glad to read that
||by NVIDIA||
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
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
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
For now, I'll go back to convex_decomposition_from_mesh because that happens to make a much rounder cylinder than the default. And when @cinder summit's stuff lands I can use that instead.
The models already factor control surfaces and flaps
Paper planes sounds easier* because the density of the material and geometry is well known π
Forces are kinda weird at the XPBD constraint level, since the constraints are position-based. At least for joints, I believe you can apply a specific force f by using a specific compliance Ξ± which corresponds to the inverse of the stiffness of the constraint
@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?
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
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?
arbitrarily
heh
good enough performance to have a decent amount of bodies, but they're also not squishy when stacked
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. π
The substep count kinda is the time budget
Yeah, that's what got me thinking of it. Why not express that in actual (game engine) time?
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
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.
Do you mean that the engine would use less substeps if the previous frame took too long? and vice versa
yes exactly.
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
yeah
LOL what is happening now. this is with 200 substeps
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);
could make the frame rate a bit more smooth, but it'd probably cause "unexpected" behavior as well
The smaller substeps become the more floating point error contributes to the output too right? π€
Yes
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 π
because more substeps = delta time closer to 0
also on the above, const JOINT_SPACING: f32 = 1. / 96.; -- there's not supposed to be a meaningful gap at all
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 
*a highly arbitrary estimate that depends a lot on the use case
That's a bit different
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 π
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)
seems to fix it, thanks!
But I haven't seen this done before, and it's not that complex of an idea, so surely there must be serious caveats...
...because if not, JPBD incoming π
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
I'll add the idea to my list of π§ͺ experiments
I think maybe a lot of the research is focused on doing a lot of things in parallel (like on a gpu).
you could still do it in parallel
Optimization is definitely a common topic of research
just skip solving a constraint if the error is small enough
Every single paper about SDF collisions is just about optimizing it for X usecase for example. And all BVH stuff is the same
that seems like that would reduce a lot of jitter too
and maybe other possible explosions π
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
Box2D ignores determinism I'm pretty sure
Which is probably why a lot of MMOs straight up don't have physics, like at all
I haven't seen research, but idk if it's that complicated algorithmically unless you make things massively parallel
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
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
Tho sadly I don't have a fancy enough usecase with my single threaded server instances 
Depending on the usecase bit-level determinism might be necessary, or it just needs to drift very slowly
Can you explain-it-like-I-have-little-math-grounding exactly what those are?
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
this mostly
#1124043933886976171 message
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
oh yeah -- thanks. i remember you saying that before.
this also might solve the normalization issue π
jacobi approach I mean
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
For numerical reasons ... And quaternion reasons probably
because the corrections could be applied in a different order which could have slight impact numerically
yeah
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 π
fun
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
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
I wonder how it would compare to removing parry from your Cargo.toml 
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
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
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
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
yeah that'd be cool
also maybe some way to get e.g. child colliders working without Collider
probably requires traits tho
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 π
I'd like to change the API to some extent anyways
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)
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
not as wet as world query DI
I mean have you seen the primitives PR? Some of the code there is literally copy paste between 2D and 3D ... Just with Vec2 vs Vec3
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>;
Ah yea gotta love the big enum functions with types
Also would I have duplicate docs for Collider2d and Collider3d? I guess so
Should they even really be the same in 2d vs 3d tho?
could break it up and link to docs that aren't specific to dimension tho
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? π
I guess it might have some uses in preventing many dynamic dispatch overheads when doing many shape calls π€
can you believe he's in highschool? awesome!
That really seems to be everyone's favorite feature huh?
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 π
although you'd assume it's better to be a veteran in the field
yes definitely π
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????"
Now that's some rapid progress π
you'd have to repeat a year to delay it becoming a deprecated feature though 
hmm, that's true 
or you could just make a religion out of it
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
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?
small jitter is inevitable when not sleeping
are you mutably accessing position or velocity anywhere?
that could wake up bodies
No -- only interacting by externalforce
changing forces also wakes up bodies
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
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,
})
hmm, okay. I'll poke.
if that doesn't work, it could be an issue where joints are waking up the bodies when you don't want them to
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. π
set == changed
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?
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...
π
Any possibility of having CollisionLayers::new() be a const function
a bit of a pain making const/static layers
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
Not yet but I might add this as part of the joint updates
For now, collision layers should work
This is blocked on a Rust feature I believe
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;
@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π
depends on game, dynamic is generally easier to work with
I feel like dynamic with dominance as needed should be able to handle what most people reach to kinematic for.
you can do similar with PhysicsLayer using as u32
I don't know how you'd ever make spatial query const
or why even
spatial query filter*
if it's gonna be reused dozens of times then why not
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
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>>
It seems like maybe "short circuit substeps if the change is under a threshold" approach would also effectively stop this.
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
oh, hmmm -- something fundamental I guess: is the velocity update the sum of all of the substeps?
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
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 π
movement and constraint errors aren't necessarily related
depends on the constraint and situation
The situation I'm thinking of is... well, my robot sitting still, but a stack of cubes is probably a better simple case.
lower substep count => worse convergence, less accuracy => more jitter
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".
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
Ah
depends I think, kinematics and dynamic are just slightly different design philosophies for character controllers
kinematic is definitely more usable in some cases where you really need complete control
right, I get that part. And right now the constraint is satisfied when it is zero. What if it were considered satisfied if it is within Β± [some small value] of zero instead?
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
They're not very overlapping.
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 π
Ooh that will simplify things a lot!
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
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
I wonder how well "2d is just 3d with no translation allowed in the Y axis; let the compiler optimize stuff out if it wants" would work
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
Yeah, but it's not code simplification if you have to do both.
But anyway, not important really
There should be nice APIs for 2D and 3D
And if you have the APIs, might as well have separate implementations where necessary
It sure does make things like that normalization hack feel ugly, though.
2D and 3D can also be made to run in parallel if that's desirable
(for games that use both)
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?
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
Will this be used with a generic on a plugin that gets passed along to the systems, so it can all happen without silly stuff like Colliders needing to be boxed and getting more layers of dynamic dispatch?
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
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
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
Actually that would require scaled_shape to either pass a copy, or Self::Shape to have a Clone requirement π€
Continue the grand unification Solid commit message, 10/10
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
it just has a scale method for all shapes, and I copied rapier's approach of storing the unscaled and scaled version in Collider
On SDFs if the scale is non-uniform I have to make it panic or something anyway, because that wouldn't produce valid results π
and it's only updated when transform scale changes
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
not having the original one could cause precision issues when scaling things often
Yea you would definitely need to keep both around, can't change the scale later otherwise
like unscaled * scale / scale != unscaled probably
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 π
yeah, doesn't work since it should match up with mesh π
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
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
Don't worry I'll just make the editor panic too π
Will you have a way to make non-circular cylinders?
Extruding an elipsoid? Yea that should be possible
then I don't care about non-uniform scaling π
The mesh also can't mismatch if both the collider and mesh are based on unscaled SDFs π§
Is there a performance advantage in having fewer Components in a Query?
Specifically, why doesn't integrate_pos() https://github.com/Jondolf/bevy_xpbd/blob/2eb34922acfe8f757cc002553a5b0fcbfbdb2bc4/src/plugins/integrator.rs#L50 use RigidBodyQuery?
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
that's fine
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
could also make it a function in utils
looks at the other stuff there
the restitution and dynamic friction should not be there lmao
it's kind of a redundant module tbh
A utility function would look something like debug_id(opt_name,entity)?
yeah
that doesn't feel nice to me
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
hmmm.
yeah, okay, better than other options π
Shear isn't really possible normally
you'd have to modify global transform directly
Transform cant shear
But you can end up with shearing on child transforms
ah true
oh no sleeping.rs has a bunch of other queries that have Entity.
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.
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
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?
I think so, the collision are used in the broad phase to filter out collisions, but don't seem to be copied into the Contacts struct: https://github.com/Jondolf/bevy_xpbd/blob/main/src/plugins/collision/narrow_phase.rs#L113
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
Ah yeah it would be good to ignore those contacts by default; the solver already does, but the check should be in the broad phase to not run collision detection at all
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.
Collision layers work like rapier's collision groups yea
I wonder what the usecase for solver layers is that isn't covered by sensors π€
usecase is to treat some objects like sensors and some as normal bodies based on the layers
That's not a usecase but a description of the functionality π
like A1 can go through door B1 but A2 can't
those names don't make sense but whatever
With doors you could still make them collision layers
yeah, but you might want to know that A2 tried to go through the door... although you could have a separate sensor for that
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)
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.
Sensors would work here I think?
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
or I guess if pickables are physical objects like coins, guns etc. you might still want them to lie on the ground but not exert forces to players
(in some games)
Maybe they can get shoved around by non-players ...
Tho realistically I'd make it a separate sensor and rigid body then because I wouldn't want a tiny pickup radius
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.
Yea I can definitely picture some niche usecases for this .... Tho the docs for such a feature should probably suggest looking at sensor first
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?
Do sensors send Collision events?
A collision event that is sent for each collision.
Sensor collisions are just normal collisions at the moment in that they compute intersection data
The only difference to normal colliders is that they don't cause a collision response
Okay. Thanks.
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
Technically rapier gives you those collision events too ... Just not trough the same channel iirc
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.
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
Maybe a way to configure if sensor gives Collision events, or only CollisionStarted and CollisionEnded?
I wonder what the overhead from all the collision events is actually π€
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?
Not really. Both sensors and regular colliders in Rapier give CollisionEvent, which has not manifold data. For colliders, that manifold data can be retrieved with contact_pair, but sensors only give you intersection_pair which has no manifold data.
I feel like Sensor would have to be the same as SolverLayers::none π€
Yea this
Which is why it'd make sense to combine them imo
Just not sure on the API
Yea this distinction just doesn't really make sense. If you can check for intersections you probably already have the contact points
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
Rapier has a physics_pipeline_active setting that can be used to disable physics. Does XPBD have something similar?
A resource for specifying configuration information for the physics simulation
Time<Physics>::pause is probably the main way
doesn't disable absolutely everything though, just the simulation loop (collision detection, integration, solver etc.)
Okay, I just want to have Tnua pause itself as well when XPBD is paused.
@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 
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 π
Sounds like a pretty nice improvement π
3,31% doesn't sound like a ton though, what's the 96%?
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 π€
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)
copy parry's incremental updates, surely it'll work π
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 π
the integration systems could also be parallelized with just a par_iter_mut, not sure if it'd help tho
yeah, it's just so that you don't need to worry about substeps and system sets
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 π€
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
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
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 π
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.
Not supported yet but substepping can help if the performance hit is fine
#math-and-physics message
What kind of high velocity rigid bodies are we talking here?
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.));
});
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)
I know this is a help channel, but I think this may interest you: #crates message
Not yet. Maybe some day.
Not like there's a non-help xpbd channel, could be useful tho
Ooh that's amazing, thanks! I might have to update docs and/or examples to mention it as a compatible character controller, it's the first one that's been released
xpbd-general, xpbd-help, xpbd-showcase, xpbd-crates, xpbd-tutorials, xpbd-off-topic...
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
Don't forget the xpbd-sdf 
xpbd-jam?
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
I was remembering this https://gafferongames.com/post/networked_physics_in_virtual_reality/
Introduction About a year ago, Oculus approached me and offered to sponsor my research. They asked me, effectively: βHey Glenn, thereβs a lot of interest in networked physics in VR. You did a cool talk at GDC. Do you think could come up with a networked physics sample in VR that we could share with devs? Maybe you could use the touch controllers...
but it just does a syncing thing
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?
Ah, switching to 2d because unity is poorly designed enough to make that seem like a normal solution
*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...
"cross-platform" is a bit broad too
well, behaves the same on most processors and architectures
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?
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 ^
got it, thanks!
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.
Might be more complex than what you're looking for, but this is what I use: #1124043933886976171 message
this looks perfect actually. Exactly what I'm after. Thanks!
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
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
adding compliance on joints seems to have helped
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?
I'm not sure what you mean by the inside of a circle. But beyond the built-in colliders, you can use triangle meshes too,
Or the wonderful thing about PBD is that you can implement custom colliders via a constraint. Though I'm not sure how to integrate that well into the existing collider system.
How do I use PenetrationConstraint? ::new takes ContactData, but that looks like nothing I can fill out
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.));
});
no
that's different
what does that do then
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.
oh i didnt read the "updated automatically" part
should probably make the name more daunting to make it clearer
Isn't GlobalTransform also updated automatically? What's the difference?
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
PenetrationConstraint is mostly an internal thing, one is created for each contact. So it's not really meant to be used by people, although it probably is possible
they're added to a PenetrationConstraints resource which is iterated, solved and cleared at every substep
anyways i got the child childer working
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
collision doesnt seem to be working, i am trying to collide a kinematic rigid body with static rigidbodies
but nothing happens
kinematic bodies by definition don't get pushed by things by default
same in rapier, unity etc.
they're user controlled
i am moving them with LinearVelocity
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
kinematic doesnt handle collisions for you?
dynamic does
dynamic bodies can hit kinematic bodies, but kinematic bodies are unaffected by default
they're like static bodies that can be moved
A non-deformable body used for the simulation of most physics objects.
alr
(side-note: bevy_tnua is a character controller that has bevy_xpbd support)
i'll take a look at that
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.
Does bevy_xpbd use the built in Transform scale
it scales colliders yeah
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?
You might be able to disable transform_to_position in SyncConfig and I think scale might still work?
and just continue using Transform but ignore the translation property?
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
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
something like a DTransform
or just a float alias that's feature-controlled like xpbd does it, but maybe that's too complex
(like DVec3)
I'm pretty sure it works now, will make a PR soon
here the colliders are scaled, but not affected by transform translation/rotation changes
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
not really, it'd require splitting systems out and make run conditions more annoying
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
@peak timber scale should work with the other options disabled on main now
i can't see my rigid body
nevermind i found PhysicsDebugPlugin
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),
}
there's a z scale of 0.0
.with_scale(Vec3::from_array([1000.0, 100.0, 0.0]))
I set that to 1.0 and then 100.0 but it didn't fix it. Does the z-scale matter for 2D in xpbd?
I don't think it does, but wanted to make sure
Your collider is quite massive though
yeah, might need to zoom out
1000.0 * 1000.0 pixels wide and 100.0 * 1000.0 px high
player is definitely inside it
yeah
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 π€.
collider scales with transform scale
Oh really? Ahhhh, there we go. The transform scale was huge.
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?
yeah transforms scale colliders, same in rapier, unity, godot etc.
I believe fixed joints currently just align the rotations of the bodies, but this among other joint things will hopefully be improved for the next release
A hacky workaround could be to use a RevoluteJoint instead, but set the angle limits to some desired angle
Aha, cheers! So is it expected that it will "just work" the way I thought it would?
I think I'll support local frames which would be anchors + rotations
so you could specify the desired rotation yeah
Is there somewhere I can read about how this works? I'm just inputting random values until it works right now.
And thank you for helping π
The collider size is just multiplied by the transform scale, so if you have a collider with a size of [100.0, 100.0] and a transform scale of [2.5, 1.0], the resulting size is [250.0, 100.0]
I think Sprite also has a custom_size property that you could use instead of scaling with transform
Ohhh, I see. Thank you.
Question about the order of systems in each physics frame: Are collisions resolved before objects are translated? Or am I reading the setup incorrectly?
First, broad phase collision detection is run, and then the substepping loop starts:
- Move based on velocity and forces
- Compute contacts (narrow phase)
- Resolve contacts (move bodies)
- Update velocities based on the change in position before and after solve
- 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
Okay, I was seeing that the ApplyTranslation substep was last in the chain, is that changed somewhere else? https://github.com/Jondolf/bevy_xpbd/blob/main/src/plugins/setup/mod.rs#L176
And interesting, the broad phase is ran before entities are displaced based on velocity and forces?
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
With apply translations being at the end of the substep, is there a chance that the entity could be rendered intersecting with another entity?
we do it slightly more efficiently though by mostly expanding in just the movement direction
No, the solver will have run before that
(unless it's unable to resolve the contact fully ofc)
Ah I guess I am thinking in terms of a kinematic object where the velocity won't change from the velocity solver necessarily
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,
}
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.
probably because prediction_distance gets weird
#1124043933886976171 message
you can also look at bevy_tnua (and soon bevy_wanderlust) to see what they're doing
Spatial queries don't use prediction distance, it's a narrow phase thing
The shape should be slightly smaller because if you hugged a wall for example, it shouldn't detect hits. If it's exactly the size of the collider, it could sometimes detect unwanted hits
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
the hit detection from hugging the wall is from prediction_distance though, isn't it
contacts yes, but shape casts no
oh alright, but it's still not the expected behaviour and workaround could cause more bugs
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
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
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
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
yeah
like ghost collisions...
might be a little off-topic, but i really like this way of doing a tutorial.
going step by step, encountering common problems and then solving them.
https://catlikecoding.com/unity/tutorials/movement/
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
or the cheatbook @glad abyss π
I feel like the format is a bit different, but yeah would be cool
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.
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
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 π
when something doesn't require any previous knowledge, cheatbook/examples are good
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.
i still jumped around CLC, it's not as bad as you think
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
but it'd still have distractions, just in the form of links
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
in that case yeah, a structured tutorial would have to be in another book
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
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
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?
Do you know about https://diataxis.fr or "divio" system for docs? I think it's quite powerful, and a lot of projects follow it. Sorry for offtopic
The DiΓ‘taxis framework solves a problem of quality in technical documentation, describing an information architecture that makes it easier to create, maintain and use.
It's clamped to always be in the [0, 1] range because larger values were considered to be a footgun by e.g. Alice: https://github.com/Jondolf/bevy_xpbd/issues/114
This is also what Unity does. It's mentioned in docs:
The coefficient is between 0 and 1
but I should definitely add anassert!to panic if the given coefficient is invalid
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
Yeah, that sounds reasonable, thanks!
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
@royal helm i just have layer::PLAYER ^
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.
That makes sense because the physics simulation doesn't run every frame
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!
@merry tide running it in fixedupdate or whatever xpbd uses should fix it
PhysicsSchedule which runs in PostUpdate
That sounds ideal, to map the replay to the physics.
replay should probably interpolate it though
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?
.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
Yeah, well, the Discord help is very user friendly at this point. π
That just worked as expected, it seems, thanks so much for the help.
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();
}
}
}
Inertia::default() gives it 0 angular inertia so it'll kinda just be broken
Yea, I can see all the inverse components too. Would you recommend I just remvove all xpbd related components and re-add ?
Do you need to specify mass properties manually?
I'm not sure why you'd set inertia to 0
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
nah it's this https://en.wikipedia.org/wiki/Moment_of_inertia
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 ...
ahhhhh, that makes sense
Oh it seems just resetting angular velocity and linear velocity might be enough
ya
nice π works now. I guess with default settings you would also reset ExternalForce but I have persistence disabled for it
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
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.
This is my take on the backend for bevy_mod_picking
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
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.
Why use xpbd? bevy_mod_picking for clicking my manual 2d ui works fine with other backends
I am clicking on world space objects.
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?
I don't think I see the configuration for Time<Physics> anywhere
When using the LinearVelocity component, do I need to multiply it by time.delta_seconds(), or is that already taken into account?
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
The clock representing physics time, following Time. Can be configured to use a fixed or variable timestep.
if you're setting velocity, it's probably unnecessary, but for e.g. acceleration you should multiply by delta time
(see link)
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?
yeah
Okay, thank you π
setting never feels good though
Why is that?
Lol thank you
Not necessarily true, instant acceleration can feel fine, but it's definitely not for every game
in which one does it work?
Doesn't the essay itself mention a few examples?
idk when i actually watched it lol
A fast acceleration usually still feels better
Especially on something that's really about the movement itself
But even weird things like really slow acceleration can work well, like in sonic
i never liked 2d sonic though, and that slow acceleration might be the cause
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
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
Sorry for this ridiculous delay. I guess I just had to modify max_time_of_impact to something really small like 0.1.
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.
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
Yeah, sorry. Completely tunnel visioned in on the from_hz.
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
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
It could be this too actually, maybe they assumed Time::<Fixed> corresponds to the physics timestep (in the FixedUpdate case I guess it is related?) but used the old incorrect 1.0 / hz value for PHYSICS_HZ
but I might be reaching here
Oh actually if it updates Time<Physics> from Time<Virtual> and that happens inside FixedUpdate the behavior being FPS-dependant makes sense
Time<Real> but yeah
there was a special-casing for FixedUpdate but it looks like I might've removed it 
Huh, based on Time<Real>? So slowing the game down doesn't affect physics?
physics has a separate speed and play/pause loop in Time<Physics>
for now at least
(or Physics to be more accurate)
Kinda weird how xpbd does everything on Physics instead of Time<Physics> tbh π
the API has conflict-ey things if the methods are implemented for Time directly
like fixed_hz/from_hz
might cause confusion
Those are all on Time<Fixed> rather than Time right?
yeah but shows up in autocomplete iirc
Tho I guess the long term goal would be to yeet the physics schedule once it becomes a reasonable assumption that everyone uses FixedUpdate
What if we just upstream those? 
upstream what?
The manual stepping, no reason you can't step all of FixedUpdate
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.
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!
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?
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
(TOI is just "distance" in this case, see: https://docs.rs/bevy_xpbd_2d/latest/bevy_xpbd_2d/plugins/spatial_query/struct.ShapeCaster.html#structfield.max_time_of_impact)
@tacit hinge #math-and-physics message
Itβs the actual distance only if direction is a normalized vector.
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?
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 ^
That makes perfect sense. Thank you!
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
Ah, thanks. And that explains why the name sounded to me like it should have a velocity component. Seems to me like direction is a misnomer in that case
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 π€
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)
i didn't even check, did jondolf already do renaming on main?
Ah, I guess I should have read to the very end of that thread π
nope he didn't π₯²
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?
Should be possible via child colliders
although I'm more familiar with how rapier's child colliders work I think it should be the same
do you have a link to the relevant documentation? i'm not seeing any search results for "child" in xpbd's docs
basically just add child entities to the parent rigid body and it should act like a single body
ohhhh