#Avian Physics
1 messages Β· Page 8 of 1
yep
if I add Position when spawning the component, it works fine
It doesn't update the Transform?
didn't seem to
though when I update the collider they do get their transform set to 0 and it messes up the chunk position (they get teleported to the origin, basically)
ideally I want the transform to just not be touched at all by xpbd so I can do it myself with the proper relative calculation
(I am worried that constantly re-positioning everything's Position whenever the origin changes will cause issues, but I'm hopeful it won't π )
I'll check tomorrow where the Transform might be getting updated, it's rather late for me atm
(2 am)
no rush
thanks :P
Hi, Jondolf, I was the one who reported the "weird flag" issue some days before. Just now I tried to add debug config(all) resource into the demo, and found the possible source. In the demo, the aabb is much larger than the actual collider, while in the example, the aabb is smaller (or not that large). So I'm wondering if there's any way to force xpbd to recalculate aabb?
Seems like the height of aabbs are incorrect.
And switching to convex_hull solves that!
I've been working at writing a replacement for the SyncPlugin in my fork of big_space that's hopefully compatible with big_space. Seems to be working alright for me but I haven't done very extensive testing on it. Here it is if you want to take a look: https://github.com/austincummings/big_space/blob/xpbd-compat/src/bevy_xpbd/floating_origin_sync.rs

thanks, I'll try it out
Do I just disable the SyncPlugin/Transform plugin, add this FloatingOriginSyncPlugin, and set everything up as I would normally?
FYI it doesn't compile unless you set bevy_xpbd_3d to f64, which is fine for me but thought it might not be intended
Yeah just disable the SyncPlugin and add the FloatingOriginSyncPlugin. There's also the xpbd example too that I used to debug it that should show how it's set up. Right now I've just been making it for my own use so wasn't too worried about it not compiling without f64
it's pretty laggy, I get spikes even with a low render distance of 3
but it does seem to work otherwise
Hm yeah, not sure what could be causing that. Most of the differences from the normal SyncPlugin are in the recenter_positions function so maybe that's eating up some time
oh I forgot to move collider generation back to the background threads/tasks
I was debugging a bunch of stuff trying to get it to work lol
ah lol
yeah lemme know if you find anything. Right now there's also potentially issues with manually updating the transform and having those changes be copied to the Position/Rotation. There's some commented out code at the end of transform_to_position that caused stuff to continuously accelerate that I haven't figured out how to fix yet
seems like a potential breeding ground for floating point errors
lol
yeah when it stutters it takes 190 ms to do run_substep_schedule
my gridcells are tiny (1 chunk = 1 grid cell) if that matters
how many dynamic bodies are there?
should be 1
the player
all the chunks are static
I might be able to get rid of this temporary collider now I guess
same thing tho
Seems like it stutters when you cross grid cell boundaries right?. My first guess is my plugin is messing with change detection that bevy_xpbd is using for the substep stuff
I think so yeah
If there's only one dynamic body though maybe not
This means that collect_collisions takes a ton of time, right?
-16 to 16 resets cause lag
yeah
I guess moving everything's position over and over is slow lol
or rather, the collision detection that happens as a result of change detection
though for 1 dynamic entity that seems excessively long
my guess was that at some point the positions of all bodies is the same for one frame, which makes the dynamic body collide with everything at once
but I'd expect that to cause other very visible issues so idk
I could make my gridcells much larger and just ignore the issue for now but it'd be nice if I didn't have to
static-static collisions shouldn't even be checked, so dynamic-static is the only case we need to care about (player-ground in this case)
maybe I can clone bevy_xpbd locally and use patch.crates-io to patch it as the version everything else depends on
and debug what's taking so long?
Yeah I've only tried it with fewer than a dozen bodies so I think that's why I haven't seen the same issue
if I were to get xpbd + big_space actually working it would be so amazing π
I'm pretty sure triggering change detection shouldn't affect collect_collisions in any way
I get the lag with 33 chunks loaded at once..
so unless it's collider complexity, it makes no sense lol
did removing the colliders fix it?
both removing the colliders and replacing them with a simple cube fixed it, so it must be how complex they are
so I guess it's recomputing a bunch of things every time the position resets
are static colliders not expected to move?
Semantically yes but the engine doesn't actually care currently
I can upload the project to git if you want
Yeah I could try to debug if I have time
I believe only the AABBs would have to be recomputed by broad_phase::update_aabb, but otherwise there shouldn't be much extra computation. And that update is relatively cheap and running outside the substep schedule
I think I added you to this as a collaborator
thanks for the help, I'll see if I can figure anything out by printing how long different xpbd systems take in the meantime
I'd also print BroadCollisionPairs after PhysicsStepSet::BroadPhase to see if the collision count spikes at the chunk edges
(in PhysicsSchedule)
that's really the only thing that would make collect_collisions extra slow
yep a ton more broad phase collisions when the cell changes
(ignore the 257 logs)
do you think this is caused by an issue in the custom sync plugin, xpbd, or unavoidable
Maybe xpbd, apparently there are collisions even when the player doesn't have a collider so I guess it could be between ground colliders even though I'd expect that to be impossible
it does sound like a number similar to 33*6 so maybe yeah
er I guess in this demo theres more than 33 chunks
I also hope this doesn't mean the performance will be much worse when I add actual dynamic entities to the game
yeah it's between several different entities, presumably ground entities (here I just log the first 5 collision pairs)
now just need to figure out why that is
most entities won't be this complex, so maybe I don't have to worry about it for dynamic things once this is fixed
oh I might know why it's happening, I'll test real quick
...if I can use a local patch of xpbd
[patch.crates-io]
bevy_xpbd_3d = { path = "..." }
had to do this for work as well
AngularVelocity and ExternalTorque sometimes don't work. Like a rigidbody with AngularVelocity of Vec3::X won't rotate, it seems to be caused by the check in integrate_rot system, where only the w component of the rotation delta is checked rather than the whole. Changing delta.w != 0. to delta != Quat::IDENTITY makes the body rotate.
https://github.com/Jondolf/bevy_xpbd/pull/272 should be reverted as rotation aren't happening when they should be
Yeah sorry I didn't respond to the dm yet, this floating point issue above caught my eye first.
I don't think we should revert it completely because it breaks change detection, but just make the condition stricter to check that x, y, z, and w are all 0
I'll fix that soon (and test that the case you describe works)
quaternions are like chinese to me
@peak timber Yep silky smooth now
same
I'll make a PR, it's a super simple fix
The broad phase just determined whether a body is active by checking if it's position/rotation had changed, and didn't also check if it was static. So when all ground entities were moved, they collided with all nearby ground entities even though they were static
and trimesh collisions can be relatively expensive
do you think for cuboid or capsule colliders (dynamic entities like animals) this will be an issue with the floating origin? or since they're likely moving anyway and they're much simpler colliders it will be smooth unless there's an excessive amount of them?
basically trying to figure out if mixing physics and floating origin is a mistake or a good idea π
floating origin shouldn't affect that case since they're moving anyway
I'm surprised there aren't any floating point errors like clipping through blocks - I tried doing AABB minecraft-like physics before switching to XPBD and it was miserable
the hitbox kept changing by like 0.00000001 due to error and causing the player to fall into the block lol
With rapier? Or something else
probably would still happen at very high speeds since there's no CCD, but still a lot better
no just basic fp value comparisons
ah
like this
super fp-error prone especially with the floating origin & a hitbox that was dynamically calculated every frame
Yeah CCD would definitely be nice especially with trimeshes, I'd like to Γmplement it eventually but have so many other things that I still need to do...
some day π€
yeah, I'm sure I can get pretty far with my game without it, if I even need it at all - but will definitely be nice when you have time to work on it
impressive how much stuff xpbd already does π
I had a productive summer I guess :P
I think I should be able to just patch the bevy_xpbd_3d version to the PR's branch once it's ready so I don't need to wait for the release
presuming it's backward compatible with the fork of big_space
and hopefully now that this works I can finally work on gameplay instead of worrying about floating point hell 
at least until I run into the next issue lol
@peak timber https://github.com/Jondolf/bevy_xpbd/pull/283
damn 3 lines π
mhmm
No problem! Thanks for giving access to your project for debugging, it was very useful
yeah, it isn't much yet but I've always wanted to make a voxel game and I finally figured out what was giving me such terrible performance in my previous attempts
there's nothing super secret about it, will probably make it open source eventually, just want to get it more complete first :P
@peak timber There appear to be some chunk gen issues at higher render distances
mainly that chunks take a while to load, and I got this weird chunk below the surface
hmm, definitely not supposed to be there π
I also scaled the velocity wrong for movement, but that can be improved later
it seems to work for me, how did you reproduce it?
just changed render distance from 4 to a higher value like 14 and moved around
on Windows if that matters
maybe I should delete my world db and generate fresh chunks
seems to work fine for me, I fall through the world and see the meshes from the bottom since it's generating all of the chunks at once in a random order
but I dont see any chunks in the wrong spot
weird
@peak timber here, starting from initial state

yeah I just reproduced it
wth lol
ChunkPos(IVec3(12, 0, -18)) in grid cell GridCell { x: 18, y: 0, z: -15 }
ChunkPos(IVec3(7, -1, -23)) in grid cell GridCell { x: 8, y: -2, z: -24 }
ChunkPos(IVec3(14, 0, -17)) in grid cell GridCell { x: 22, y: 0, z: -12 }
ChunkPos(IVec3(11, -1, -22)) in grid cell GridCell { x: 15, y: -2, z: -21 }
ChunkPos(IVec3(10, -1, -22)) in grid cell GridCell { x: 13, y: -2, z: -21 }
ChunkPos(IVec3(11, -1, -21)) in grid cell GridCell { x: 15, y: -2, z: -19 }
Somehow some of the grid cells get repositioned
these should be equal
maybe it's a bug with the big_space fork
@winter cape have you run into this issue before?
it seems to only happen if you go pretty fast
Hm I don't think so. It does seem like it would be caused by the custom sync plugin. I'm not seeing a pattern in how they're being repositioned though
it only happens to some of them, and it only happens if you're moving quickly
thanks
I had an issue early on where if an entity crossed grid cell boundaries in the same frame that the floating origin entity crossed a boundary it would get repositioned incorrectly. Maybe that's still happening
I can add you to the project if you'd like to take a look at it
Sure
should be added https://github.com/Rigidity/game-wip
pushed the changes
the repro is load world at 4 chunks distance, set speed to 500, and then increase render distance in the gui and move forward quickly
(escape to lock/unlock cursor)
I could just make a system to hack around it by constantly setting the position back to the chunkpos
but that would be pretty hacky π
and not work for other entities
fyi I merged the broad phase fix so I'll delete the branch tomorrow probably
I have a EventReader<CollisionStarted> but the event occurs before the collision.
- this is 2d physics
- the cube mesh has a cuboid collider, it's static
- the sphere mesh has a ball collider, it's dynamic
Is there a flag or some resource I forgot to setup?
Having some trouble with the DistanceJoint. I'm attempting to create something like a rope, but it appears the joint is completely ignored? I'm doing a raycast to find an entity, then adding a distance constraint between the player and the wall:
cmd.entity(entity).insert(
DistanceJoint::new(ray.entity, entity)
.with_local_anchor_1(Vec2::ZERO)
.with_local_anchor_2(Vec2::ZERO)
.with_limits(0.0, 10.0),
// tried basically every permutation of distance joint properties
);
but it results in this vid example (skip to halfway to start, sorry):
For reference, each block in that video is 1 unit, so I'd assume at ~10 units I'd see the joint take action. Is there something I'm doing wrong?
There was an issue where distance joint limits are ignored and it always just uses the rest length, and that should get fixed by #286. That doesn't seem to be your issue though since it doesn't do anything in your case.
Do both the player and the wall have the RigidBody component? And is the player a dynamic body?
(side note: the local anchors are zero by default, so you don't need to set them explicitly)
It's a bug, related to this
https://github.com/Jondolf/bevy_xpbd/issues/224
using a lower value for NarrowPhaseConfig.prediction_distance should help in the meanwhile
Thanks a lot. github interface is hard to navigate, I should've been able to find that issue.
Trying to run this now, but getting some rather cryptic compile errors from bevy_inspector_egui
also that should probably be in the dev-dependencies and not dependencies since it's only used in examples
got it running by removing bevy_inspector_egui and fixing the ldtk asset path, but I'm not seeing the flag anywhere (there are also white rectangles in the levels)
For me, the AABBs are the correct size in the ldtk example. The physics also works fine-ish, although sometimes it bumps into seemingly non-existent edges
But the player is using a cuboid collider here, I'll test with the convex hull again
It could maybe be this Parry issue since the ground convex hulls can be hundreds of units wide/high, but idk
okay I managed to repro your issue by making everything use cuboid colliders, and now the AABBs also have a smaller height than the actual colliders
I'll try to look into it
thanks, ill check out that branch and see if that resolves! if its any added clues, i am doing something weird with my world - the level is shrunk to 1/16th scale so that 1 tile = 1 unit, as I can't seem to find a scaling with xpbd. so I wonder if that is contributing at all...
@winter cape
if I comment out the line that changes the gridcell it works, but I dont have any entities that move lol
that would probably break other stuff
this is definitely the issue, not sure why it's doing it tho
From GridCell { x: 1, y: -5, z: -9 } to GridCell { x: 2, y: -9, z: -13 }, origin is at GridCell { x: 0, y: -2, z: -5 }
Teleported from ChunkPos(IVec3(1, -5, -9)) to Mut(GridCell { x: 2, y: -9, z: -13 })
here's an example from my log
From GridCell { x: -6, y: -3, z: 6 } to GridCell { x: -9, y: -4, z: 11 }, origin is at GridCell { x: -3, y: -2, z: 2 }
Teleported from ChunkPos(IVec3(-6, -3, 6)) to Mut(GridCell { x: -9, y: -4, z: 11 })
I don't see any patterns here
I'll keep playing around with it
Yeah unfortunately I haven't figured it out yet either. One weird thing I've noticed is it happens less frequently when I removed the perlin noise and just generated a flat world.
whoops! finally figured it out. I was spawning the joint in one of the affected entities instead of spawning a new entity, and it doesn't work that way.
Seems like this is the latest version. I switched to convex_hull in that version and fixed it.
https://github.com/443eb9/bevy_entitiles/tree/46a3ed295946c44a57c15530fc27d65998594246
This commit created is right after I asking you the problem in this thread. And I was using cuboid colliders for grounds.
The asset image for these icons are not allowed to be redistributed and I'm not good at designing levels tbh. So there's only white rects.
Trying to run this now, but getting some rather cryptic compile errors from bevy_inspector_egui
Sorry for the inconvenience. I will move that to dev-deps.
A 2d tilemap library for bevy. With many useful algorithms/tools built in. - GitHub - 443eb9/bevy_entitiles at 46a3ed295946c44a57c15530fc27d65998594246
Heyy, I believe I found the actual issue now. Your AABBs at ldtk/layer.rs lines 179-189 seem to have the min and max Y coordinate the wrong way around, which causes aabb.height() to be negative, and breaks cuboid colliders since they don't work with negative extents. Fixing this makes the cuboid colliders work, and the AABBs also look correct
Here are the incorrect AABBs
But the collider constructor should probably panic/warn with incorrect extents like this to make debugging easier :P
or just .abs() the extents
Oooohhhh, thanks a lot!! After all that's my flaw which causes this issue. XD
No problem! I've made similar issues in the past too
hi, i know that for example for rapier i can enable a debug view that shows the colliders and stuff.
is there something similar for xpbd?
Yep, add PhysicsDebugPlugin::default()
Docs here
https://docs.rs/bevy_xpbd_3d/latest/bevy_xpbd_3d/plugins/debug/struct.PhysicsDebugPlugin.html
A plugin that renders physics objects and properties for debugging purposes. It is not enabled by default and must be added manually.
This requires the debug-plugin feature, but it's enabled by default
aaaah awesome!
thanks for the quick response
"Axis Aligned Bounding Box Box" :P
Trying to run this finally to see if I can find the issue, but it panics with a missing resource, and a system not finding any entities. Initializing the resource manually and disabling a state tracking system removes the errors, but I get a black screen after pressing "Play"
Yeah @coarse locust might want to rename that AabbBox2d π
Oh I didn't notice that. Thanks for your reminding. π€£
Although Bevy is also getting a built-in 2D AABB soon
The name looks really funny XD
yesss I want Transform2d too
this https://github.com/bevyengine/bevy/pull/8268
not sure what's blocking it, I guess render order stuff and reviews
and maybe whether or not it should include skew
It's blocked on my procrastinating on writing an RFC D:
Oh it needs an RFC? alr
I'm currently wondering if 2D rotations should be clockwise or counterclockwise, and experimenting with the idea of an Angle type in bevy
counterclockwise makes a lot more sense for radians, but degrees... idk
counterclockwise also makes sense since 3D transform rotation is counterclockwise because of quats
but clockwise is of course more intuitive for rotation when working with degrees
hope the merge conflicts dont pile up π
I'd definitely prefer clockwise but I'm bad at rotation math so probably not the best person's opinion to use :P
you can only dumb it down so much lol
I think of radian rotations on a unit circle and it makes sin/cos stuff nicer imo
but for degrees, clockwise is nicer yeah
I think Godot's 2D transform uses clockwise degrees
radians are more standard right?
it's super easy to convert between the two at least
radians are used for basically all internal computations in physics etc.
but degrees can be more intuitive for users
so degrees for public API + radians internally would be nice, but it needs to be efficient
you could also represent 2D rotations like this
pub struct Angle {
cos: f32,
sin: f32,
}
where cos and sin are the cosine and sine of the actual angle in radians. This is what bevy_xpbd uses for 2D Rotation because a lot of computations use the sine or cosine instead of the raw angle
so it's more efficient for physics at least
and the complexity can be hidden via helpers and constructors
(I originally got this representation from Johan's XPBD engine tutorial btw, but I've seen it elsewhere too)
Yeah, it is a little more involved now. It is on that feature/egui-branch and you need to paste in the level data. If it is too much of a hassle I understand. If you decide to take it for a spin, there is a file levels/pacman.txt that you just paste into the text-field and click load.
I think it could accumulate floating point errors quicker as well if you keep converting back and forth
hi everyone, just exported a very basic/ugly scene from blender, and am creating colliders for it:
let my_blockout_level = asset_server.load("maps/blockout_level.gltf#Scene0");
commands.spawn((
SceneBundle {
scene: my_blockout_level,
..default()
},
RigidBody::Static,
AsyncSceneCollider::new(Some(ComputedCollider::TriMesh)),
));
Both the Cube and the player are dynamic rigidbody, the player controller is basically a copy from the character controller in the documentation.
was just wondering if anyone knows whats happening here? :)
Could maybe try ComputedCollider::ConvexHull? Strange that it's clipping that easily though
yea already tried the convexhull, it just makes the character fall through the map when spawned inside, or stand on the (non existent) roof when spawned higher up
yes
the whole map was just a single cube in the beginning
and i just created loop cuts and extruded
so all is just a single object in blender
(i'm very new to blender, and not good xD)
yeah a convex hull won't work in that case because it treats the mesh like it's basically filled and not hollow like in your case
I haven't properly tried large triangle meshes like this so it's kinda hard to say
triangle meshes can have clipping problems since they're infinitely thin in a sense, but it seems a bit too easy to clip through things in your demo
I might try to make some kind of basic repro in Blender
well i can also just give you my blender file if you want, its nothing fancy
yep that works too, thanks
hm me seperating the ground, walls and so on might solve it? as a temporary workaround
uhh, maybe?
have you tried ComputedCollider::ConvexDecomposition? or does that have similar issues as a basic convex hull
lemme try
(convex decomp is quite slow at startup though)
AsyncSceneCollider::new(Some(ComputedCollider::ConvexDecomposition(
bevy_xpbd_3d::parry::transformation::vhacd::VHACDParameters::default(),
))),
would the default value for VHACDParameters be enough? not sure what this is :)
ya
it's just configuration for the VHACD algorithm that does the convex decomposition
it should also be re-exported so you can do bevy_xpbd_3d::prelude::VHACDParameters::default()
unless i'm doing something wrong, i don't think this solves the issue xD
or default() to save typing all that lol
yeah :P
the blender file btw
Yeah I think this has the same issue as a normal convex hull and you'd need to split things into several meshes
convex decomposition basically just simplifies meshes into several simpler convex hulls
thanks, I'll try in a bit
yeah no worry :)
mhm, then i'll try to split it into a few more meshes
uhmm... this is crashing Blender for me π
huh
what version are you using? if that matters
alright I think I'm 3.something so I'll update
@torn hedge I have no camera controller rn so this view is garbage, but I don't have clipping issues
interesting
I just copied the dynamic character controller without modifications, and loaded the gltf as a trimesh collider
mhm, i did some smaller modifications to the controller... so maybe that causes some issue... or its the ordering of my systems maybe
just realized something. could it cause major issues if my movement happens in PostUpdate instead of PhysicsSchedule? :)
i'll change that quickly
if it's changing velocity, then I doubt it
i see you're using a character controller plugin, and it even has a Bundle you can spawn?
am i blind or can i not find this on the crate itself?
crates/bevy_xpbd_3d/examples/dynamic_character_3d/plugin.rs
is that behind a feature?
i somehow never even saw the CharacterControllerBundle
wtf
was i drunk when i looked at all this?
yea no seems like a issue on my end
lemme try that now again...
aha no i was not drunk!
i was following the documentation on crate and got to the is there a character controller? part and it linked the basic_dynamic_character controller, but to a very specific commit. and there it was not like this!
https://github.com/Jondolf/bevy_xpbd/blob/42fb8b21c756a7f4dd91071597dc251245ddaa8f/crates/bevy_xpbd_3d/examples/basic_dynamic_character.rs
sorry just had to do a small sanity check for my own sake...
Ah whoops, guess I forgot to update the docs there, thanks for finding that
I'll fix it
Docs fixed on main branch now
great, thanks!
i was still experiencing clipping issues btw, until i decided to change the dependency to the git main branch, instead of version 0.3.2, and now the issues seem to be gone.
so something isnt right with that version, but it seems to be fixed now :)
thanks for the help!
Hmm, it might've been this that fixed it then: https://github.com/Jondolf/bevy_xpbd/pull/238
I noticed that your Blender model has a Z rotation of -180 degrees, and IIRC that produced incorrect contact normals before that fix
Hi again! Don't spend time on this. I think I have an idea what the issue might be. I will let you know if I figure it out. Very likely it is in my code.
Alright, thanks :)
@vestal minnow OK, so in the code I shared, I think there is a very obvious bug where I return from the system instead of doing continue, so sorry about this. I am trying to learn a lot of stuff at the same time, but this is just a total brain-fart on my behalf here. Changing return to continue seems to fix it. Sorry about the arm-flapping and thanks for the help.
No worries :) I make those kinds of mistakes all the time too, can be difficult to catch sometimes
Glad you managed to (hopefully) fix it!
Yes, it looks super solid now.
Is there any documentation or examples about doing analysis on a RayHitData's entity? I'd like to see if the colliding entity has a certain component.
In the system where you're reading the hit data, have another query with the component you want to check, and do query.contains(hit.entity)
Thank you! I feel like I've been googling the wrong stuff for so long lol
Want to thank you for this question, i was wondering the same thing and was literally gonna ask like 10 minutes after you posted lol
I know this may be an issue with the bevy-tnua but I wanted to get a second opinion before I start makeing issues, and if its something I can fix Id rather do that.
I think I may have figured this out at least partly. In recenter_positions, I did some debugging and it appears that the issue (the new grid cells sometimes not matching the old one even though the entity wasn't moved) is due to the fact that the entity's transform.translation is non-zero
I think what's going on might be the following series of events:
- The custom sync plugin sets the Position to a relative value based on the GridCell
- The xpbd prepare plugin sets the Transform based on the Position
- The entity is "recentered" based on this new Transform
So I suppose the PreparePlugin would need to be replaced as well?
@vestal minnow do you have any thoughts on whether this seems like what's happening, or what the best path forward is here?
I'd imagine it happens less without perlin noise because it takes much less time to generate a chunk and there is a lower chance that the chunk would generate while the FloatingOrigin just changed
I'm kind of piecing together several things here and it's late, so wouldn't be surprised if I got some of this wrong, but I think it's progress to a solution at least
Would XPBD work well for a (literally) fine-grained simulation like a Noita-style falling sand game? #showcase message
I'm not sure how the colliders in Noita work, since it surely doesn't have a separate collider for each particle. Probably only for the ones on the surface or something.
The falling sand logic would need to be done manually since it's pixel-perfect and has quite specific rules, but for player movement and collisions, xpbd could be fine
Oh yeah my bad, I shouldβve been more specific. Iβm talking about using XPBD specifically for rigid body physics. Astratomic already has a fully custom sand simulation implemented.
Up next on his roadmap is
Rapier2d rigidbodies (with simulated pixels) for things you can throw!
..and I got the feeling maybe XPBD might work even better.
I can't say that one is objectively better than the other at the moment, both have their tradeoffs. If they prefer rapier, that's fine
I don't think there's anything specific that would make XPBD better specifically for this case, and vice versa for rapier
Although I guess XPBD is more configurable and pluggable if the project needs more custom control over physics
So in that case it could be better, depends on the requirements
I commented this line out and the chunks no longer reposition themselves anymore
maybe the easiest thing to do is to make Transform/Position sync in the PreparePlugin configurable, or part of the SyncPlugin itself?
the init_transforms system specifically
I don't think anything else would conflict with custom coordinate systems and sync plugins
Happy to make a PR for this, if you agree on the solution(s)
I'd rather not have to completely replace the PreparePlugin since it's a lot of code
@vestal minnow Did you have any recommendations on how you wanted to go about solving the negative scale issue. I was debating creating a pull for it.
Does negative scaling mirror meshes?
I don't think I've used negative scaling in Bevy before
I should prob do some more digging on it but it seems to just ignore all collisions.
I have not ether but it happens quite a bit when importing from blender
Yes, but what does a negative scale do to sprites and visual Meshes in Bevy?
I assume it just .abs() them because that is how the render treats the meshes
so no different than if they are postive
At least Godot seems to flip them
which is what I'd expect
but I haven't tried in Bevy yet
It may but idk all my shapes have been solid color so I have not seen if they are flipped
I have also only really been working with cube colliders
The biggest annoyance is that they show up as normal in the debug preview but you just fall through them
Imo the collider should always match the mesh, so if the meshes get flipped with negative scaling, then the same should happen to colliders.
The tricky part here is that you can't just make the values stored in collider shapes negative, since that breaks the support point computation (used by collision detection algorithms). Cuboids are symmetrical, so you could just .abs() the values, but if you had e.g. a cone with a negative Y scale, you'd also need to rotate it to be upside-down.
I think the way we should handle scale for all colliders is to treat it as if it was positive for the actual collider shape, but in the code where the colliders are passed to collision detection, it should rotate the collider to flip it along the axes that have negative scaling
First we need to make sure what negative scaling does though, I'd expect it to flip things
I think it'd be fine to make it configurable similarly to SyncConfig, although ideally this issue wouldn't exist in the first place
So are you specifying Position manually at spawn?
since I think that's the only case where it'd get inside that if branch
if so, have you tried just Transform without specifying Position?
Yep, meshes get flipped like I thought
no, I let xpbd add it automatically
also Ferris why do you look like that π
Ahh I was trying to test that but didnt have any models on hand I could easy test with
THATS FERRIS π
I thought it was the blender monkey model
lol
In Blender it's nice and bright but in Bevy it's like this, not sure why
prob something wack with the mat
Since I add the Collider later, I'm guessing what's happening is the Position gets added, the Collider gets inserted later, which triggers the Added<Collider> part of the query, and by then Position and Transform are both on the component so it "initializes" it even though it's unnecessary
Hmm, that's a bit strange... That system should run just once per body, and if Position doesn't exist yet, it shouldn't get to that part of the code. Are you creating the rigid body first and inserting the collider later?
Oh yep
yes
lol
I think we could just add an extra filter to make sure it's only run once per body by checking if it already has an old rigid body or collider
so I think adding a PrepareConfig & adding equivalent behavior to the FloatingOriginSyncPlugin if necessary would be the way to go?
I was just wondering if not running in FixedUpdate is there any way to get the camera to follow a body without being left behind? I saw the discusion in a issue about this but I was just wondering.
or that, yeah
Probably just this if it's enough
for now at least
I mean, all position->transform and transform->position calculations are going to be incorrect if using any other sort of coordinate system and syncing between the two
so ideally there would be no scenario in which it can happen (for apps with a custom syncplugin)
like if I wanted to add and remove a RigidBody it would do the same thing I think (bit of a niche case that I don't care much about for my game, though)
Actually yeah it could probably just be added as a property to SyncConfig since it's very related to Position <-> Transform syncing
would it be a bad idea to move that system to the SyncPlugin entirely?
I think it doesn't matter either way as long as it's configurable but just curious
SyncConfig might not be initialized if SyncPlugin is disabled, so init::<SyncConfig>() would have to be added to PreparePlugin as well I guess
Yeah it can probably be moved to SyncPlugin
just need to make sure the system order is correct
yeah that seems like the most complicated part of ECS to me
debugging it is.. painful
It might be pretty specific, don't remember details
my favorite part of xpbd so far is how modular and configurable it is.. I think doing stuff like this with Rapier would be pretty challenging at best
but it's definitely a nightmare to plan ahead for every use-case π
If you mean camera jitter when following objects, I don't think there's a way to prevent it other than the system ordering solution in the issue (this). The jitter occurs because of transfom propagation reasons, and transform propagation runs at the end of the frame
I guess you could maybe hide the issue with some kind of interpolation, but that's not ideal
also I still need to add that camera jitter thing to the FAQ in the docs
Yeah, modularity is one of my top priorities for bevy_xpbd. It's one of Bevy's core design philosophies, and I try my best to align with them where possible. The ECS and plugin system are amazing for modularity
love it for sure
I like that you can just add a random system anywhere in the schedule (assuming the surrounding systems or system sets are public)
and components are also really nice for abstracting implementation details
since the logic is separate from data
I mean more like the camera falling behind the rigid body at high speeds
I'm not sure if I remember that issue
Right now Iβm doing what is mentioned in that issue and it works fine but I was just wondering
Doing everything in that issue and then removing the fixed update causes the players camera to fall behind the position of the object in the world. Itβs not that big of a deal cause it works fine with the fixed update, but I was just wondering.
Yeah I don't have a solution to that right now unfortunately, might try it when I have time though
Sorry for the simple question but do raycasters use the transform on the entity or dose it just care about the starting dir and pos
They use the transform
You can also nest them in entity hierarchies to have more than one RayCaster or ShapeCaster on the same root entity
This is a bit strange
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
I have attached the raycaster to my camera entity
commands.spawn((
Camera3dBundle {
transform: Transform::default(),
projection: Projection::Perspective(PerspectiveProjection{
fov: f32::to_radians(100.0),
..default()
}),
..default()
},
PlayerCameraSettings::default(),
RayCaster::new(Vec3::ZERO, Vec3::X).with_ignore_self(true)
));
}```
18v3 is the floor
but the normal being [0, 0, 0] is confuseing me
Idk that's probably a parry issue
parry is the lib used for collision detection and spatial queries internally
hmm
If your floor is like a flat plane with a Y coordinate of 0, then your ray is basically skimming right on the surface since it's going in the X direction
Should the debug plugin show rays?
Yes, for RayCaster
Well if it is locked to the camera it should be a few units above the ground
an arrow, the hit point, and the normal as an arrow
your camera's initial transform is Transform::default()
do you only get the log once or several times?
Yea but it gets moved to another pos by another system and it seems to be doing it every frame
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
Hit entity 18v3 at [0, 0, 0] with normal [0, 0, 0]
can you print ray.global_origin()?
Vec3(0.0, 0.0, 0.0) ig that would make sence becasue it would put it inside the floor
Hmm, it should match the camera's GlobalTransform though
Oh I think there might be an issue where it currently relies on components that only exist on rigid bodies and colliders... Just to test, could you give the camera a RigidBody::Static?
If that's the issue, I think I can fix it though
Yep that did it
alright, I'll try to fix that, tomorrow probably
Nice as long as I keep the camera without a collider is should be fine to leave the comp there i assume
I think you can just keep RigidBody::Static on the camera for now, even though it's kinda strange
ya
π ty
In principle what is the difference between an entity with a Collider and no RigidBody and an entity with a Collider and RigidBody::Static? They both seem to behave the same. Is the former a footgun?
I may be wrong here but im pretty sure that the RigidBody is just a flag to tell the engine what to do with it
I believe a Collider without a RigidBody doesn't currently trigger collision response, so it's actually the same as a sensor collider
And I'm not sure if this is the expected behavior or not
@vestal minnow would you like me to open a issue about the raycast thing for tracking or is it just gonna be a quiet fix?
Yeah that'd be nice, thanks :)
My logic here is that if you were to separate collision detection and rigid body dynamics into two separate crates, all a Collider is is just a way to get data about intersections (and spatial queries). It's not a physics object because it's not aware of physics.
When you add a RigidBody to a collider, it becomes a physics object and therefore interacts with other bodies through the physics engine. In my mind, an entity shouldn't have any physics interactions unless it itself is a physics object.
I think Rapier and Unity do trigger collision response between non-rigid body colliders and rigid bodies, so maybe my approach isn't the expected one. But it does make more sense to me personally.
All that matters to me is that there is a meaningful difference that's handled consistently, that logic makes sense to me π
My expectation is that there shouldn't be two ways to do the (exact) same thing in an ECS, so we're all good
Or more generally, that in an ECS you want to avoid invalid combinations of components
Adding a Sensor to a RigidBody::Static + Collider combo is basically the same as just a Collider without a RigidBody, but I'm not sure how we'd avoid that
Sensor is just a way to disable the collision response of a RigidBody
That way you could have e.g. a dynamic body with collision detection but no collision response, but a RigidBody::Static isn't supposed to really move anyway so for the sensor case it's redundant
But yeah it's not an invalid combination either way, just a mostly useless component for this specific case
Oh boy I found another weird bug
@vestal minnow
This is all im doing there
pub fn transform_valve(
mut valve_query: Query<(&mut Valve, &mut Transform)>
){
for (mut valve, mut transform) in valve_query.iter_mut() {
valve.visible_angle = valve.visible_angle.lerp(&valve.current_angle, &0.1);
transform.rotation = valve.starting_rot * Quat::from_rotation_z(valve.visible_angle);
}
}
pub fn handle_valve_interaction(
mut scroll_evr: EventReader<MouseWheel>,
query: Query<(&RayCaster, &RayHits)>,
mut valve_query: Query<&mut Valve>
) {
for (ray, hits) in &query {
// For the faster iterator that isn't sorted, use `.iter()`
for hit in hits.iter() {
let Ok(mut valve) = valve_query.get_mut(hit.entity) else { continue; };
for ev in scroll_evr.iter() {
valve.current_angle += ev.y * valve.step_size;
}
}
}
}```
What if RigidBody::Static was removed? Thus static bodies are just anything with a Collider, if you want a sensor you can use the Sensor component. Or the inverse, where they are sensors by default and you have a Solid component, this was the basis of that automatic collision flags example I shared with you
There also seems to be significant lag between when the raycast start location and where the transform actually is
Yeah this could be possible, but it'd go against my logic of "colliders aren't physics objects without RigidBody"
mostly a viewpoint thing though
IIRC I was personally confused that Unity treated raw colliders as static bodies when I initially used it
Also a Solid component would just be painful to add to all colliders, usually just a fraction of them are sensors
@vestal minnow any idea what might be causing this?
Not really, it's weird that it's broken at the start but seems to work later on
The only thing i can think of is a sign mult error someone
My guesses would be (1) a rotation that isn't normalized or (2) a negative scale, but it's probably not 2 since you don't seem to be changing scale
and an unnormalized rotation seems unlikely to be the issue either
Well that is what it was lol
Alright, lol
pub fn transform_valve(
mut valve_query: Query<(&mut Valve, &mut Transform)>
){
for (mut valve, mut transform) in valve_query.iter_mut() {
valve.visible_angle = valve.visible_angle.lerp(&valve.current_angle, &0.1);
transform.rotation = valve.starting_rot * Quat::from_rotation_z(valve.visible_angle);
transform.rotation = transform.rotation.normalize();
}
}
this fixed it no idea why but whatever
Using a rotation that isn't normalized makes meshes go wack
I'm pretty sure colliders don't care as much
which is why the debug rendering doesn't match the mesh
or did I get that the wrong way round 
@vestal minnow Sorry for all the questions today but do you think the transform fix will resolve the lag with the raycast?
@vestal minnow I can help make the PR to move init_transforms into SyncPlugin and make it respect the SyncConfig if it would help
Yeah that'd be useful, thanks!
does this mean that physics bodies can be sensors too?
Yes, that's the idea of Sensor
It just disables collision response so that the body passes through things while still triggering collision events
cool cool, I wasn't sure if they would just behave like "areas" in godot, then it makes sense
Yep
some engines call them triggers too
I think it's a sensor in bevy_xpbd, Rapier, and Jolt, a trigger in PhysX/Unity, and an area in Godot
Not sure if PhysX allows them to be rigid bodies too though
Hey, is it possible to have a Collider be a child of a RigidBody without simulating physics on it
For ground detection
Make only the child collider a sensor
Or check only the bottom of the player collider, that works too
oh, it's called a Sensor
thanks, missed that in the docs
does it need a RigidBody::Static like it shows here
https://docs.rs/bevy_xpbd_3d/latest/bevy_xpbd_3d/components/struct.Sensor.html#example
A component that marks a Collider as a sensor, also known as a trigger.
No
this
and message above
and below xd
No worries, it happens π
maybe a shapecast is better for this
right now I have to pick between accidentally allowing wall climbing because the collider is too big, or jumping not working on the edges of blocks because it's too small
though I guess with a cuboid shapecast I could run into the same issue?
You could check the normal to see if the slope is "jumpable"
I basically want "the ground must be vertically below the player and overlap with the bottom of the player's collider"
can you get this with CollidingEntities?
No, but you could use the Collisions resource and do collisions.collisions_with_entity(my_entity) to iterate over the actual contacts
or listen to Collision events and check the entity manually
or just use a shapecaster
The dynamic_character_3d example handles slope angle limits for jumping like this
https://github.com/Jondolf/bevy_xpbd/blob/f4a58035e3de0ae5fe4bf0e4c1e3962f5a580960/crates/bevy_xpbd_3d/examples/dynamic_character_3d/plugin.rs#L203
yeah that looks pretty good, thanks
I think that could also be -hit.global_normal2(rotation) but anyway
Why are compound colliders with a bunch of cubes much much much slower than a trimesh?
slower to initialize, I suppose
I'm trying to make it so you get pushed out of blocks if you somehow find yourself in one instead of falling through the world
I guess it's a lot larger of a shape than with a trimesh since even blocks underneath the surface are part of it
maybe what I want is a convex decomposition or something but it seems to smooth out the collider, making physics really weird lol
ConvexHull probably smooths it out too?
I wonder if it'd be possible to use cuboid colliders, but merge flat surfaces to be bigger boxes
might be a bit hard to implement though
so is it normal to be that slow?
I haven't tested compound colliders much, it'd probably be more of a parry thing
random thought... do you have debug rendering on?
no
alright, just wondering
I can stick with trimesh and just hope and pray nobody finds a way to get into a block for now π
Increase the number of substeps π
well, physics seems to be working perfectly fwiw
it'd just be gameplay things like placing a block while you're standing on it
ah yeah
fwiw I believe cuboid collisions are more expensive than you'd think, but I'm pretty sure trimeshes should still be more expensive
maybe it's just because my meshes are so optimized compared to adding every single block in every single chunk
does it add them even below the surface if they're cuboids?
yeah, I was doing it for every solid block so that if you get stuck anywhere you get pushed out or suffocate
If you have spatial queries then that could be making it slow maybe
I have a raycast on click & the player is a shapecaster, but I think it's the generation only since once all of the chunks are loaded it's back to max FPS
If you disable the BroadPhasePlugin, does that help? (collisions will break though ofc)
nope, just as slow
okay interesting
I was thinking that it could be that when you add a bunch of colliders at once, it has to sort them all for the sweep and prune algorithm but I guess insertion sort is still fast enough for it
Idk why it'd only be slow at startup π€
it's probably something like 67 million cubes (rough math)
Okay well that's a lot
things add up fast lol
nope
Nvm it's colliders
to see if it's just the collider constructor?
it's still just as slow to generate them if I do that, but it doesn't slow down the FPS
so I think it just takes a while to create the collider, and then the processing done by xpbd is synchronous and also takes a while
this isn't really a blocker, so if this is just a limitation/I'm just using too many colliders, I'm fine with that
I guess it could be PreparePlugin? Though you can't really disable that to test since it'd probably make everything else stop running too
also side note, when the game is lagging, the physics simulation runs slower than normal
yeah I tried removing that before and it just panics
I don't think there's anything else that would run substantial extra things when entities are added
Yeah
Lmao
Yeah that's kinda what I was thinking, it's one of the more expensive parts of PreparePlugin probably
Although surely it should be super fast for cuboids π€
Maybe we could do some parallelization there or something
Although it might be a bit annoying to do par_iter there since it needs to get the collider parent, and many colliders could have the same parent
Wait is it doing all of that parry dynamic dispatch overhead 67 million times in only 87ms?
no
it's only adding a maximum of 25 chunks per frame
and the colliders themselves are constructed in async tasks
Could maybe do two passes, one for colliders without parents (parallel) and one for colliders with parents (serial)
actually I guess I don't batch mesh generation the same way I do chunk generation
but still not all at once
just limited that to 25 tasks at a time and it's still pretty slow
Either way I can't imagine having a box for every solid voxel would end well ... You'd need to do greedy meshing but with boxes I'm pretty sure ... So a 2x2 grid that's filled becomes a bigger box
yeah
I think it might actually be fairly cheap computationally but it does sound like a pain to build π
I don't even do normal greedy meshing for rendering, it doesn't seem worth it tbh
it's like a 15% performance gain and it wouldn't work as well with non-cube blocks
at least from what I've seen
Yea on non-cube blocks that would be hard yea. It would make a bigger difference for the volume tho, since there you get the speedup of culling all the solid-solid faces
Couldn't you just check for entities intersecting a cuboid where a block was just placed and push those out however you want? You can keep the ground as a trimesh, but use convex cuboids for the checks
I can get like a render distance of 14 with decent fps, which I believe is equivalent to 28 or so in Minecraft since my chunks are twice as wide (not to mention vertically as well, but I might optimize that later)
yeah or I can just prevent anything from ever being placed if an entity would be colliding with it
but if there's a will there's a way, someone will find a way out of the world lol
future problem I guess
I mainly want to focus on adding some gameplay mechanics atm
I wonder it'd be possible to efficiently use SDFs for blocky voxel terrain π€
SDFs and cubes aren't great friends tbh π
I'm definitely sticking with xpbd for now, I still have PTSD from the floating origin and I just got it to work π
It might beat a trimesh, but only if the rest of the world is spheres
The only SDF collisions in bevy are for xpbd afaik ... Really need to make a version based on bevy primitives and opensource it 
I realized today that I think I could technically remove basically all remaining Parry and Nalgebra stuff from the public API with the primitives
nice
implementation detailβ’οΈ
I like how this happens for a few seconds and then just goes away due to how my chunk loading works
As in remove any parts of the public API that are parry and nalgebra types?
I could make Collider APIs convert Parry's shapes to primitives in getters, accept primitives instead of Parry shapes in setters, and impl From<MyPrimitive> for Collider
Once the API has no parry types we just need a feature flag to use sdf collisions instead 
And reimplement helpers for AABBs and spatial query stuff for Collider
Reimplement helpers for AABBs?
Surely you mean ... Use the bounding types on the primitives? 
And then make an optional feature in xpbd to use bounding spheres to make your performance worse in basically every case except when everything is almost a sphere π
just make it the default 
First we need to actually implement Bounded2d/Bounded3d
Also idk if it'd be helpful here since the internal collider shape would still be a parry shape
Just need to give xpbd the worst defaults ... Where it'll default to using sdf collisions except you can totally just provide it bound sdfs which require all sorts of inefficient workarounds, a solver that doesn't create realistic physic responses, and using the parry qbvh with incremental updates while also building another bvh every frame
That's definitely a good point
I wonder if it would be doable to keep an internal type that holds mostly bevy primitives and enum dispatch everything to work around parry's dynamic dispatch π€
That's what I'm planning to do for my sdf collisions at least ... The sdf type is already a huge enum anyway, just without bevy primitives
Some collision pairs have custom collision implementations that don't necessarily use GJK/EPA, so we can't just impl SupportMap for the primitives and pass those to Parry
Or we could, but it wouldn't be as efficient
Unless we copy those special cases to use primitives
Also I was wondering... We (mainly me and @cinder summit, probably) might not be the biggest fans of Parry, but it is the best collision detection library we have at the moment. Making a collision detection library from scratch like I've been planning would be cool of course, but reaching feature-parity would be a pretty huge task that would probably take a lot of time and effort. I feel like it also isn't wise to just ignore the effort that has been put into Parry.
One of the main issues that makes Parry bad for Bevy is that it uses Nalgebra, but Parry is open source, so we could just... fork it? I feel like it'd be relatively straightforward and quick to make everything use Glam types instead of Nalgebra, and we could also remove Parry's shapes in favor of Bevy's primitives.
Of course, Parry has other issues, like poor docs, BVH issues, and perhaps the dynamic dispatch stuff, but I'd imagine it to be easier to fix those in the fork than to build everything from the ground up and face a whole bunch of new bugs and issues in the process. If there's a specific part of Parry that sucks, we could just remove and rewrite that part and keep all the stuff that does work well enough.
I'll call this library... Barry! (Bevy Parry)
For now.
So basically:
- Fork Parry as Barry
- Replace Nalgebra with Glam
- Replace Parry shapes with Bevy's primitives
- I'll work my magic on the docs in some cave
- Fix the dang BVH, maybe make a new one (ploc-bvh??)
As a result:
- We'd have a fully featured collision detection library using Glam and Bevy's primitives, could be upstreamed
- The effort put into Parry wouldn't go to waste
- Things fixed and improved in the fork would also benefit Parry, and vice versa
- We/I can focus more on physics stuff
I'm not sure why I'm only now considering this lol
One issue would be that Parry only has Apache-2.0 and not MIT, so we might need to do the thing where we get permission from contributors to add MIT
Hey, I noticed part of the documentation on collision events is using the deprecated .iter() function on an EventReader instead of .read().
Are y'all open to PRs on that?
Yep!
Weird if the doc test doesn't give an error there π€ unless it's specified to be ignored
oh maybe it's because iter still exists but is just deprecated
and doc tests don't care about warnings, only errors
Yeah I did a search on the rest of the repo and it looks like this is the only instance of .iter that got left behind.
I could also just be wrong lol. Just thought I'd try and save ya a bit of time.
No you're correct, thanks for the PR!
Happy to help!
Separate note,
I'm working on a 2D platformer and I'm seeing a pretty consistent issue where I'll have my player entity falling into a platform (just a few pixels) for a frame or so before the position is corrected.
I'm using the one_way_platform_2d example as a base with some ray casting for better ground detection, but this is starting to annoy me a bit.
I can add some code examples if necessary, but maybe this is something others have noticed?
Started experimenting with this a bit, Parry always surprises me with weirdness...
It has both of these types:
/// The vector type with dimension `SpatialDim Γ 1`.
pub type SpatialVector<N> = Vector6<N>;
/// A vector with a dimension equal to the maximum number of degrees of freedom of a rigid body.
pub type SpacialVector<N> = Vector6<N>;
Spacial isn't even a word π
Just enum dispatch on the pairs of colliders so you can pick the right way to do it π€
went from eating to fork suspended midair in disbelief looking at this
π€£
Wait that's also SpatialDim x 1... That's just SpatialDim??
or a cross product with 1 but that makes even less sense
Not sure if sebcrozet has a habit of drinking while coding, or if we should be worried about them 
True
The over 500 clippy warnings also exist still
I don't get how you can live without clippy
or ignore it like that
I've worked on crates where the warnings got ignored, I didn't even want to try running clippy π
Also I'm not sure how I should even represent these with Glam... (Vec3, Vec3) I guess?
and I'm not sure if Affine3 and Isometry3 are the same, I think they are? at least almost
I wonder if there's any optimizations that can be had with a Vec6 implementation that you can't get with (Vec3, Vec3) π€
hmm I might need to make custom Iso2/Iso3 types
The docs suggest it works like Transform but without the scale 
Affine3A has a matrix for rotation+scale+shear, but we want just rotation
Yea that's why it's just a translation and a Quat
Not a very complex type ... Except of course the fact that quaternions make no sense π
yeah it should be very easy to make
just
pub struct Iso3 {
translation: Vec3,
rotation: Quat,
}
and impl the needed operations
and 2D version with angle
technically I think I could also use Affine3A and treat the matrix as a rotation matrix, which is also valid for Nalgebra's Isometry, but quats are probably more efficient
bevy_barry would be a fun name lol
barry makes more sense tho
not that it's the best name
Gotta get that S-Controversial issue approved first 
I feel like it wouldn't have been controversial if it was just a type called Radians that has a From<f32> 
yeah but allowing/disallowing the implicit convertion is a part of the controvertiality too
one of the main goals was to go for explicitness
same
it's a godsend
aside from type_complexity and too_many_arguments 
Bigger one for me is that it's very confusing when functions just take some f32 and having to read the docs just to verify that it is in fact radians
Doesn't help that I apparantly don't even know which way the rotations go π
it's inconsistent tbh
doesn't LSP just show you the name of the param or the docs?
gizmos take clockwise radians for some reason
Radians & Degrees newtypes are superior though
If the param has a name and it doesn't go off screen, yea
Yea that's what Jondolf made
yea I think that's where I saw it tbh 
Radians & Degrees would be almost perfect if type inference for the math ops like Degrees + Radians worked
Idk if I like the idea of thinks taking impl Angle tho 
Imo the first operand being the type of the output makes the most sense
you can always cast with t.into() and ::from(T) if nothing else
not too bad
Yeah I think I'll change it to that
I mean you can make it so that Degrees + Radians gives Degrees and Radians + Degrees gives Radians ... Tho you might run into issues with making those ops efficient because const stuff in rust is still kinda jank
yes that's what I mean
shouldn't newtypes and unnecessary math operations be completely optimized out? especially if you mark them #[inline]
the conversion between units is just one multiplication so it's not too bad tbh
+ Degrees(90.) would be a lot nicer than + std::f32::consts::PI / 2. tho 

you think I remember middle school level math? lol
oh that's high school
yea that's how little I remember
I never learned useful things like radians and quaternions at school at all 
radians are high school, quaternions are never
Lessons about quaternions are imaginary 
quaternions were created as an alternative to Chinese water torture
The physics I learned at school also never prepared me for writing SDF collisions ... Which is clearly a major failure of the educational system
I'd say that's more math than physics
yeah SDF is so useful for everything on a day to day basis
Sure but it already failed me by not preparing me for SDFs 
It'd be cool to know your exact distance from things at all times
*signed distance
Someone needs to make the missile knows where it is at all times meme but with SDFs
It's crazy how we can have complte XPBD physics, just by knowing the exact distance to things
And by exact I mean very inaccurate because floats suck π
somehow I havent gotten a single issue due to floating point errors with xpbd so far
even with the floating origin integration
it's like magic 
you have f64, right?
yeah
yeah well that's super precise in comparison
it goes back and forth between f32 and f64, but I guess since it uses change detection it doesn't lose precision unless necessary
Until you try to make a BVH, and still need to add 2 ULPs if you want to support arbitrary unnormalized direction vectors
I don't even know what a BVH or ULP is lol
There's also this weird AccumulatedTranslation component so that the integrator doesn't have precision issues regardless of the distance from origin
BVH is a bounding volume hierarchy, it's the data structure you use to speed up things like raycasting
idk ULP either
And a ULP is a Unit in the Last Place, which is a term I see pop up occasionally because the value of that changes in a float
I did this now btw, it was also suggested in the PR as an option and there's an existing angle crate that does this
I think ULP relates to the whole epsilon thing
speaking of PRs I need to actually make that init_transforms PR
and remove it from my procrastination list lol
Speaking of PRs I need to fix the bounding PR ... Because padded and shrunk are bad names 
Yo I feel like I've never seen ULP before and now I immediately stumbled on it in some crate's code, wtf
there's a name for this phenomenon but I don't remember it
The ULPs can never be unseen now 
We should make a list of the names used by all AABBs known to man
scrape GH with some bot to look for AABBs
If the names aren't in past tense I feel like grow/shrink would be decent tbh
AabbBox is my favorite so far
please no
SS-Controversial
Probably ... Might work for the other Self thing tho π€
But I've also been thinking that maybe we can just not do the Self thing
S-Unsee
And just make AabbCast and SphereCast intersection tests π€
isn't this just a cuboid shape-cast
lol
axis-aligned
Yea, can't rotate an AABB, but you can rotate a cuboid
Also funny we call it cuboid because Rust just has the unfortunate situation where Box is super cursed π
if you rotate an AABB, it becomes an OBB
LockedAxes isn't respected by shapecasts?
no...?
If you rotate an AABB you clearly need to get help 
fair
yeah, better than rectangular_prism lol
ExtrudedRectangle π
we also need to do something about the fact that Bevy now has Quad, Rectangle, a bunch of Rect types, and Aabb2d
or is Quad a thing, I don't remember
Quad is a thing in 3D, it's just not very useful outside of rendering
yeah it should vanish with the meshing impl
TruncatedTesseract
Rectangulon
Looks like there's a long line of chained together systems here
Maybe it's simpler to keep it in PreparePlugin but make it respect the SyncConfig?
I'm not sure how you'd add a custom one though
yeah that's what I meant with a potential "specific order"
Would this work .after(update_collider_parents).after(apply_deferred).before(propogate_collider_transforms)?
I don't think it would necessarily refer to that specific apply_deferred..
time to research system ordering more lol
it wouldn't refer to that one specifically
it'd be any apply_deferred after any update_collider_parents
inside PhysicsSet::Prepare
if you put it in the config with in_set
Actually with the existing setup, I think you could just put init_transforms at the end of PrepareSet::Init as long as you run apply_deferred right after it
propogate_collider_transforms doesn't depend on it?
nvm it probably does, I was just thinking that init_transforms only uses commands (which aren't applied before the end of the set anyway), but it can also modify stuff
does after(system) still work if system doesn't meet its run condition(s)
I think we could do this, and custom implementations of it can just do .after(init_transforms).before(propogate_collider_transforms) to make sure it happens at the same time as the built in one
This leaks implementation details though
If the ordering or structure of the library were to change it could break that unexpectedly
I'd also be fine with just adding a PrepareConfig for now (or config in the PreparePlugin struct?) and maybe moving it elsewhere later if it makes more sense
with something like initialize_transforms: bool, initialize_positions: bool?
yeah, something like that
ok, I'll submit a PR rq and see what you think
I think it's better than relying on the specific system structure in another plugin
unless we added more system sets
well you'd still need to do that to override it right?
like if I needed to add my own init_transforms in the floating origin sync plugin
yeah, true
I almost wish you could use trait methods for systems :P
to make it easier to override things without worrying about order
hmm
pub enum InitSet {
RigidBodies,
MassProperties,
Colliders,
Transforms // or Positions?
}
that would be nice
something like this could maybe make it a bit nicer
ACollectionOfEightPointsWhereEachPointIsAlignedWithThreeAdjacentPoints feels a bit more right I think 
Java devs be like
Hey that looks like a Parry type!
That's what I thought while typing it π
no that would be ACollationOfAtePointsWareEachPointIsAlinedWithThreeAjasentPoints
It just needs some "DepthFirst" or something in the name I feel 
I still can't get over Parry's names like
TOICompositeShapeShapeBestFirstVisitor
TOI isn't even acceptable rust naming π
Without clippy nothing matters, there is only depression π
Wait None can have generics?
let mut best_hit = None::<TOI>;
Idk if I like that or not
Well None is just a variant of Option, which does have a type, so the variant also has a type
Kinda nice but feels cursed somehow
You can do this on all your generic enums by just useing the variants into your scope
yeah I learned that a few days ago
I don't think it's very common to need this tho ... And I feel like I'd rather just do Option::<Toi>::default()
some angle crates have an Angle enum but re-export Radians and Degrees variants
Imagine thinking you have a f32 newtype but it's actually an enum and takes up more memory than you thought π
lmaoo true
there's a sneaky trimesh in there
if you could add arrays with const generics, could you make an infinitely large type?
or until you run out of numbers
It would be limited by usize at the very least π€
Const generic array sizes are kind of hard to actually use tho
Only usecase I can really think of is with things like ndshape, or more end user facing types like primitives
MyStruct<[[f64; 18446744073709551615]; 18446744073709551615]>(f32)
You'd probably need to Box that because on windows builds stack size is limited to something like 1 MB
Well in this case I guess you don't actually use the generic π
Just generic size for arrays? bevy_xpbd constraints currently use that for XpbdConstraint trait because the number of entities/bodies must be known
or there's an entities method
Oof ... Just the inner array would be a few hunderd exabytes π
I assume you can't make types recursive in Rust unfortunately
Ah yea, constraints between a variable number of things sound reasonable yea
You can make types recursive, but they can't contain theirselves because then they aren't Sized and can't be stored in theirselves because they aren't Sized
Yeah this probably doesn't work
type A = [B; 10000000000];
type B = [A; 10000000000];
Like this recursive type is valid:
pub enum Sdf3d {
Tree {
ops: Box<[SdfOperation]>,
sdfs: Box<[Sdf3d]>,
},
...
}
But if I made a variant that just contained Sdf3d directly it wouldn't work
Also, yes, my sdf code is really the first thing that came to mind π
Can you Reflect that? I'm pretty sure you can't
iirc it's why you can't Reflect colliders yet, compound colliders are kinda recursive
Not sure tbh ... I've never actually used bevy's reflect magic
I couldn't reflect the angle types because bevy_math doesn't have bevy_reflect and the macros used for implementing it externally don't support tuple structs yet
I have no idea how any of it works or what it really does tbh
I just know that it should generally be derived for public components, and that's the extent of my knowledge lol
and it makes things show up in inspectors because it can access type data somehow
Reminds me of the Go Proverbs thing ... "Reflection is never clear."
I like that too
I know π I think I left a comment about that above the function
More Parry fun... why does it have stuff like this everywhere
let _2: Real = na::convert::<f64, Real>(2.0);
It's just 2.0, it can infer the type...
Also Clippy: consider choosing a more descriptive name
_2 is a perfectly descriptive name for 2 
I think it's only for valid identifiers that happen to be reserved words
like r#struct
tho I'd only ever use that for C bindings, I'd rather not type r#
like I usually just use 'kind' instead of 'type'
same
#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PrepareSet {
PreInit,
PropogateTransforms,
InitRigidBodies,
InitMassProperties,
InitColliders,
InitTransforms,
Finalize,
}
impl Plugin for PreparePlugin {
fn build(&self, app: &mut App) {
app.configure_sets(
self.schedule,
(
PrepareSet::PreInit,
PrepareSet::PropogateTransforms,
PrepareSet::InitRigidBodies,
PrepareSet::InitMassProperties,
PrepareSet::InitColliders,
PrepareSet::InitTransforms,
PrepareSet::Finalize,
)
.chain()
.in_set(PhysicsSet::Prepare),
);
app.init_resource::<ColliderStorageMap>()
.init_resource::<PrepareConfig>()
.register_type::<PrepareConfig>()
.add_systems(
self.schedule,
(
apply_deferred,
// Run transform propagation if new bodies or colliders have been added
(
bevy::transform::systems::sync_simple_transforms,
bevy::transform::systems::propagate_transforms,
)
.chain()
.run_if(any_new_physics_entities),
)
.chain()
.in_set(PrepareSet::PropogateTransforms),
)
.add_systems(
self.schedule,
init_rigid_bodies.in_set(PrepareSet::InitRigidBodies),
)
.add_systems(
self.schedule,
init_mass_properties.in_set(PrepareSet::InitMassProperties),
)
.add_systems(
self.schedule,
(
init_colliders,
apply_deferred,
update_collider_parents,
apply_deferred,
)
.in_set(PrepareSet::InitColliders),
)
.add_systems(
self.schedule,
(
init_transforms,
(
sync::propagate_collider_transforms,
sync::update_child_collider_position,
)
.chain()
.run_if(any_new_physics_entities),
)
.in_set(PrepareSet::InitTransforms),
)
.add_systems(
self.schedule,
(
update_mass_properties,
clamp_collider_density,
clamp_restitution,
// All the components we added above must exist before we can simulate the bodies.
apply_deferred,
)
.in_set(PrepareSet::Finalize),
);
app.add_systems(
PhysicsSchedule,
(
update_collider_storage.before(PhysicsStepSet::BroadPhase),
handle_collider_storage_removals.after(PhysicsStepSet::SpatialQuery),
handle_rigid_body_removals.after(PhysicsStepSet::SpatialQuery),
),
);
#[cfg(all(feature = "3d", feature = "async-collider"))]
app.add_systems(Update, (init_async_colliders, init_async_scene_colliders));
}
}```
@vestal minnow what do you think of this?
the many_shapes example still works, let me know if there's a better way to test this
ok the dynamic_character_3d example gives me "Dynamic rigid body 1v0 has no mass or inertia. This can cause NaN values. Consider adding a MassPropertiesBundle or a Collider with mass." so I must have missed something lol
It's Propagate and not Propogate, otherwise I think it looks fine
Hmm, could check if this was happening before too. IIRC that example has AsyncCollider stuff, which might give false warnings for that I believe
I'll add some doc comments to this before I make the PR
waiting for the new 10 GB target folder to be created and the 5 minute compilation to finish to see
gotta love Rust :P
looks like main doesn't have that issue
I've been changing parry math types and fixing clippy warnings for a few hours now, got below 500 errors for the first time
Started with over 1000
issue is, Rust does that fun thing where fixing errors creates new ones
exactly xd

the main downside to what you're doing is it makes it virtually impossible to sync upstream changes
Well luckily that's not a big deal considering Parry's activity π
Watch parry suddenly get super active again, just to spite you
last commit 4 months ago
parry sees a fraction of the number of changes of rapier, and rapier sees a fraction of the number of changes of bevy_rapier
I'll fix parry so they'll reverse fork barry
Exactly π
Watch as rapier suddenly depends on ploc-bvh and I'm just confused when someone opens an issue about using it in rapier
100,000,000 lines changed
PR name: "Thank me later"
Watch me, I'll do it
Luckily parry isn't that big π
It will be once I do docs
I'm not even sure if you can make a 100m line PR on the linux kernel π
100m is rookie numbers
Running cargo test will be terrifying once I've fixed these errors
no shot it'll work
0/1000 tests passing
I watched the xpbd intro video you linked in the docs
pretty fascinating stuff
Your todo list must have a million items already π
I feel that
it's not in priority order at all and probably not up to date
I actually haven't had a single case of tunneling even with my 6 substeps π
I think the most important change that isn't missing features would be speeding up the broad phase π€
it's pretty fast for me but I do only have 1 dynamic entity
After that more parrallelization maybe? Idk I don't even have it enabled π
It might be that other engines do integration just once per frame and only solve constraints with multiple iterations/substeps
not sure tho
XPBD does integration in substepping loop
so things advance in smaller increments
Normally there are only iterations and no substeps. Which means only 1 narrow phase ... While bevy_xpbd expands AABBs and does multiple narrow phase runs iirc
yep
I do remember having more high speed issues with rapier
the sequential impulses test I made did this
experimenting more with that is also on my todo list :P
the todo list for my game is overwhelming at best
I also basically can't get tunneling in my game anymore
Because SDF colliders have volume, unlike trimesh colliders π
there's a terminal velocity right?
no

unless you make one
I set one up myself, gotta limit things like fall speed or it'll be very disorienting for the user
so gravity just keeps getting larger? I figured there's some sort of drag
you can add LinearDamping
I'm mainly concerned about players falling from extremely high distances into unloaded chunks
but that'll also affect xz velocity
I guess I could add some MaxVelocity, but you could do it manually too
yeah last time I did that I was annoyed by the fact that it uses a scalar
maybe I should make a PR to make it a Vec
yeah I'd probably accept that, it's just scalar in almost all other engines too
but yeah it's pretty simple to do myself as well
because air resistance isn't really direction-dependent unless you consider the shape of the object
like for x and z motion for the player controller I just multiply by 1.0 - delta_time / 4.0 or whatever every frame
probably a bad way to do it but I'm too lazy to improve that code atm lol
fair
I need to start using fixedupdate
I'm going to dogfood the hell out of this fork to improve Bevy's primitives, there are so many methods that Parry needs them to have
speaking of that, how do I get xpbd to use a fixed timestep so it doesn't get slower based on framerate? Is that what the self.schedule value is for?
self.schedule is just so that you can run the systems in that plugin in whatever schedule you want, like rollback networking might want GgrsSchedule and many projects might want FixedUpdate
Maybe I should finish up the last issue in the bounding PR so you can also dogfood that 
FixedUpdate is how I fix it I suppose?
There's two approaches, but the better one generally is using FixedUpdate yea
I dont like my game's physics coming to a crawl if you have low frames lol
This might just make it freeze or do something weird but you could try this
.insert_resource(Time::<Physics>::from_timestep(TimestepMode::Fixed {
delta: Duration::from_secs(1.0 / 60.0),
max_delta_overstep: Duration::from_secs(1.0),
..default()
}))
also ew that formatting, I wrote it here
I shall try soonβ’οΈ
I think the fixed timestep has this thing where it can (by default) only advance by 1.0 / 60.0 seconds during a single frame to avoid "death spirals"
with that change it might indeed death spiral π
Only 1 per frame seems like a bad way to avoid death spirals π€
I think bevy by default allows like 250ms worth of ticks
yeah but iirc it worked better than other things I tried
move_marbles basically froze with larger overstep I think
It also really depends on the desired behavior
In a single player game, getting a slowdown because of lag spikes isn't a big deal, it's probably more fair even
But in an online game you can't just stop updating, because then you go way out of sync
yeah

