#Avian Physics

1 messages Β· Page 8 of 1

peak timber
#

no fault to you ofc, just complicated

vestal minnow
#

yep

peak timber
#

if I add Position when spawning the component, it works fine

vestal minnow
peak timber
#

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 πŸ˜…)

vestal minnow
#

I'll check tomorrow where the Transform might be getting updated, it's rather late for me atm

#

(2 am)

coarse locust
#

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!

winter cape
#

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

GitHub

A floating origin plugin for worlds larger than the observable universe - austincummings/big_space

peak timber
#

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

winter cape
peak timber
#

it's pretty laggy, I get spikes even with a low render distance of 3

#

but it does seem to work otherwise

winter cape
#

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

peak timber
#

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

winter cape
#

ah lol

peak timber
#

I'll fix that and try again

#

still some stuttering, maybe profiling will reveal it

winter cape
#

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

peak timber
#

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

vestal minnow
#

how many dynamic bodies are there?

peak timber
#

the player

#

all the chunks are static

#

I might be able to get rid of this temporary collider now I guess

#

same thing tho

winter cape
#

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

peak timber
#

I think so yeah

winter cape
#

If there's only one dynamic body though maybe not

peak timber
#

I'll check what the coordinates are when it happens

#

yeah it's when I change cell

vestal minnow
# peak timber

This means that collect_collisions takes a ton of time, right?

peak timber
#

-16 to 16 resets cause lag

peak timber
#

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

vestal minnow
#

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

peak timber
#

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

vestal minnow
#

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)

peak timber
#

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?

winter cape
#

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

peak timber
#

if I were to get xpbd + big_space actually working it would be so amazing πŸ˜„

vestal minnow
peak timber
#

I get the lag with 33 chunks loaded at once..

#

so unless it's collider complexity, it makes no sense lol

vestal minnow
#

did removing the colliders fix it?

peak timber
#

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?

vestal minnow
#

Semantically yes but the engine doesn't actually care currently

peak timber
#

I can upload the project to git if you want

vestal minnow
#

Yeah I could try to debug if I have time

vestal minnow
peak timber
#

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

vestal minnow
#

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)

peak timber
#

do you think this is caused by an issue in the custom sync plugin, xpbd, or unavoidable

vestal minnow
#

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

peak timber
#

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

vestal minnow
#

now just need to figure out why that is

peak timber
#

most entities won't be this complex, so maybe I don't have to worry about it for dynamic things once this is fixed

vestal minnow
#

oh I might know why it's happening, I'll test real quick

#

...if I can use a local patch of xpbd

peak timber
#

had to do this for work as well

orchid olive
#

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

GitHub

Objective
Currently, Rotation changes are triggered every frame for non-sleeping dynamic bodies because of an incorrect quaternion comparison.
Solution
Change the delta != Quaternion::IDENTITY chec...

vestal minnow
#

I'll fix that soon (and test that the case you describe works)

peak timber
#

quaternions are like chinese to me

vestal minnow
vestal minnow
#

I'll make a PR, it's a super simple fix

peak timber
#

πŸŽ‰

#

that's awesome, thanks!

#

what did it end up being

vestal minnow
#

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

peak timber
#

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 πŸ˜‚

vestal minnow
#

floating origin shouldn't affect that case since they're moving anyway

peak timber
#

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

vestal minnow
#

With rapier? Or something else

peak timber
#

probably would still happen at very high speeds since there's no CCD, but still a lot better

peak timber
vestal minnow
#

ah

peak timber
#

like this

#

super fp-error prone especially with the floating origin & a hitbox that was dynamically calculated every frame

vestal minnow
#

some day 🀞

peak timber
#

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 πŸ˜„

vestal minnow
#

I had a productive summer I guess :P

peak timber
#

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 dogkek

#

at least until I run into the next issue lol

vestal minnow
peak timber
#

damn 3 lines πŸ˜‚

vestal minnow
#

mhmm

peak timber
#

yeah perfectly smooth at a render distance of 10 πŸŽ‰

#

thanks so much

vestal minnow
#

No problem! Thanks for giving access to your project for debugging, it was very useful

peak timber
#

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

vestal minnow
#

mainly that chunks take a while to load, and I got this weird chunk below the surface

peak timber
#

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?

vestal minnow
#

just changed render distance from 4 to a higher value like 14 and moved around

#

on Windows if that matters

peak timber
#

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

vestal minnow
peak timber
#

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

winter cape
#

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

peak timber
#

it only happens to some of them, and it only happens if you're moving quickly

orchid olive
#

thanks

winter cape
#

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

peak timber
winter cape
#

Sure

peak timber
#

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

vestal minnow
#

fyi I merged the broad phase fix so I'll delete the branch tomorrow probably

peak timber
#

imagine a game with terrain like this because there's no height limit πŸ˜‚

indigo scarab
#

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?
past escarp
#

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?

vestal minnow
#

(side note: the local anchors are zero by default, so you don't need to set them explicitly)

vestal minnow
#

using a lower value for NarrowPhaseConfig.prediction_distance should help in the meanwhile

indigo scarab
#

Thanks a lot. github interface is hard to navigate, I should've been able to find that issue.

vestal minnow
#

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)

vestal minnow
#

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

past escarp
peak timber
#

@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

winter cape
# peak timber <@215643402585243648>

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.

past escarp
coarse locust
# vestal minnow For me, the AABBs are the correct size in the ldtk example. The physics also wor...

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.

GitHub

A 2d tilemap library for bevy. With many useful algorithms/tools built in. - GitHub - 443eb9/bevy_entitiles at 46a3ed295946c44a57c15530fc27d65998594246

vestal minnow
#

But the collider constructor should probably panic/warn with incorrect extents like this to make debugging easier :P

#

or just .abs() the extents

coarse locust
vestal minnow
#

No problem! I've made similar issues in the past too

torn hedge
#

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?

vestal minnow
#

This requires the debug-plugin feature, but it's enabled by default

torn hedge
#

aaaah awesome!
thanks for the quick response

peak timber
#

"Axis Aligned Bounding Box Box" :P

vestal minnow
#

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"

vestal minnow
coarse locust
vestal minnow
#

Although Bevy is also getting a built-in 2D AABB soon

coarse locust
#

The name looks really funny XD

peak timber
#

2d transform would be nice too, I hate quaternions

#

I just want angle: f32 Sadge

vestal minnow
#

not sure what's blocking it, I guess render order stuff and reviews

#

and maybe whether or not it should include skew

pulsar bone
#

It's blocked on my procrastinating on writing an RFC D:

vestal minnow
#

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

peak timber
peak timber
#

you can only dumb it down so much lol

vestal minnow
#

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

peak timber
#

radians are more standard right?

#

it's super easy to convert between the two at least

vestal minnow
#

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)

merry tide
peak timber
torn hedge
#

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? :)

vestal minnow
torn hedge
#

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

vestal minnow
#

Are the ground and walls a single mesh?

#

and not separate

torn hedge
#

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)

vestal minnow
#

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

torn hedge
#

well i can also just give you my blender file if you want, its nothing fancy

vestal minnow
#

yep that works too, thanks

torn hedge
vestal minnow
#

uhh, maybe?

#

have you tried ComputedCollider::ConvexDecomposition? or does that have similar issues as a basic convex hull

torn hedge
#

lemme try

vestal minnow
#

(convex decomp is quite slow at startup though)

torn hedge
#
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 :)

vestal minnow
#

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()

torn hedge
#

unless i'm doing something wrong, i don't think this solves the issue xD

peak timber
vestal minnow
torn hedge
vestal minnow
#

convex decomposition basically just simplifies meshes into several simpler convex hulls

vestal minnow
torn hedge
#

yeah no worry :)

torn hedge
vestal minnow
torn hedge
#

huh

vestal minnow
#

what version are you using? if that matters

torn hedge
#

4.0

#

newest from steam

vestal minnow
#

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

torn hedge
#

interesting

vestal minnow
#

I just copied the dynamic character controller without modifications, and loaded the gltf as a trimesh collider

torn hedge
#

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

vestal minnow
#

if it's changing velocity, then I doubt it

torn hedge
#

oh

#

:(

vestal minnow
#

movement is inverted though, sry :)

torn hedge
#

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?

vestal minnow
torn hedge
#

is that behind a feature?

vestal minnow
#

Oops wrong path initially

#

It's just an example

torn hedge
#

oh.
i never saw the plugin.rs, only the main.rs in the example. tunnelvision i guess

#

i somehow never even saw the CharacterControllerBundle

#

wtf

#

was i drunk when i looked at all this?

vestal minnow
#

I added that stuff like a month ago

#

The old example was a lot simpler

torn hedge
#

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

GitHub

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

#

sorry just had to do a small sanity check for my own sake...

vestal minnow
#

Ah whoops, guess I forgot to update the docs there, thanks for finding that

#

I'll fix it

vestal minnow
torn hedge
#

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!

vestal minnow
#

I noticed that your Blender model has a Z rotation of -180 degrees, and IIRC that produced incorrect contact normals before that fix

merry tide
merry tide
#

@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.

vestal minnow
#

Glad you managed to (hopefully) fix it!

merry tide
#

Yes, it looks super solid now.

red gulch
#

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.

vestal minnow
red gulch
#

Thank you! I feel like I've been googling the wrong stuff for so long lol

vale thunder
abstract forge
#

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.

abstract forge
peak timber
#

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

turbid sigil
#

Would XPBD work well for a (literally) fine-grained simulation like a Noita-style falling sand game? #showcase message

vestal minnow
turbid sigil
#

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.

vestal minnow
#

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

peak timber
#

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

abstract forge
#

@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.

vestal minnow
#

I don't think I've used negative scaling in Bevy before

abstract forge
abstract forge
vestal minnow
abstract forge
#

so no different than if they are postive

vestal minnow
#

At least Godot seems to flip them

#

which is what I'd expect

#

but I haven't tried in Bevy yet

abstract forge
#

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

vestal minnow
#

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

vestal minnow
#

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?

vestal minnow
peak timber
vestal minnow
abstract forge
abstract forge
#

I thought it was the blender monkey model

vestal minnow
#

Lmaooo

#

The lighting is real bad here, looks a bit better from the front

abstract forge
#

lol

vestal minnow
#

In Blender it's nice and bright but in Bevy it's like this, not sure why

abstract forge
#

prob something wack with the mat

peak timber
#

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

vestal minnow
# peak timber no, I let xpbd add it automatically

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?

peak timber
#

yes

vestal minnow
#

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

peak timber
#

so I think adding a PrepareConfig & adding equivalent behavior to the FloatingOriginSyncPlugin if necessary would be the way to go?

abstract forge
#

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.

vestal minnow
#

for now at least

peak timber
#

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)

vestal minnow
#

Actually yeah it could probably just be added as a property to SyncConfig since it's very related to Position <-> Transform syncing

peak timber
#

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

peak timber
vestal minnow
#

Yeah it can probably be moved to SyncPlugin

#

just need to make sure the system order is correct

peak timber
#

yeah that seems like the most complicated part of ECS to me

#

debugging it is.. painful

vestal minnow
peak timber
#

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 πŸ˜…

vestal minnow
#

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

vestal minnow
peak timber
#

love it for sure

vestal minnow
#

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

abstract forge
vestal minnow
#

I'm not sure if I remember that issue

abstract forge
#

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.

vestal minnow
#

Yeah I don't have a solution to that right now unfortunately, might try it when I have time though

abstract forge
#

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

vestal minnow
#

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

abstract forge
#

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

vestal minnow
#

Idk that's probably a parry issue

#

parry is the lib used for collision detection and spatial queries internally

abstract forge
#

hmm

vestal minnow
#

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

abstract forge
#

Should the debug plugin show rays?

vestal minnow
#

Yes, for RayCaster

abstract forge
#

Well if it is locked to the camera it should be a few units above the ground

vestal minnow
#

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?

abstract forge
#

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]
vestal minnow
#

can you print ray.global_origin()?

abstract forge
#

Vec3(0.0, 0.0, 0.0) ig that would make sence becasue it would put it inside the floor

vestal minnow
#

Hmm, it should match the camera's GlobalTransform though

abstract forge
#

Hold on I got a vid I just forced it up out of the ground it is strange

vestal minnow
#

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

abstract forge
#

Yep that did it

vestal minnow
#

alright, I'll try to fix that, tomorrow probably

abstract forge
#

Nice as long as I keep the camera without a collider is should be fine to leave the comp there i assume

vestal minnow
#

I think you can just keep RigidBody::Static on the camera for now, even though it's kinda strange

#

ya

abstract forge
#

πŸ‘ ty

fallen citrus
#

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?

abstract forge
#

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

vestal minnow
#

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

abstract forge
#

@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?

vestal minnow
vestal minnow
# vestal minnow I believe a `Collider` without a `RigidBody` doesn't currently trigger collision...

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.

abstract forge
fallen citrus
#

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

vestal minnow
#

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

abstract forge
#

Oh boy I found another weird bug

#

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;
            }
        }
    }
}```
fallen citrus
abstract forge
vestal minnow
#

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

abstract forge
vestal minnow
abstract forge
#

The only thing i can think of is a sign mult error someone

vestal minnow
#

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

abstract forge
vestal minnow
#

Alright, lol

abstract forge
#
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

vestal minnow
#

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 thonk

abstract forge
#

I think the mesh was going the wrong way

#

but whatever it works alright

abstract forge
#

@vestal minnow Sorry for all the questions today but do you think the transform fix will resolve the lag with the raycast?

peak timber
#

@vestal minnow I can help make the PR to move init_transforms into SyncPlugin and make it respect the SyncConfig if it would help

vestal minnow
dense ridge
vestal minnow
#

Yes, that's the idea of Sensor

#

It just disables collision response so that the body passes through things while still triggering collision events

dense ridge
#

cool cool, I wasn't sure if they would just behave like "areas" in godot, then it makes sense

vestal minnow
#

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

peak timber
#

Hey, is it possible to have a Collider be a child of a RigidBody without simulating physics on it

#

For ground detection

vestal minnow
#

Make only the child collider a sensor

peak timber
#

Or check only the bottom of the player collider, that works too

#

oh, it's called a Sensor

#

thanks, missed that in the docs

vestal minnow
#

No

vestal minnow
#

and message above

#

and below xd

peak timber
#

oh I didn't even read the question above mine πŸ˜‚

#

derp

vestal minnow
#

No worries, it happens πŸ˜‚

peak timber
#

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?

vestal minnow
#

You could check the normal to see if the slope is "jumpable"

peak timber
#

I basically want "the ground must be vertically below the player and overlap with the bottom of the player's collider"

peak timber
vestal minnow
#

or listen to Collision events and check the entity manually

#

or just use a shapecaster

peak timber
#

yeah that looks pretty good, thanks

vestal minnow
#

I think that could also be -hit.global_normal2(rotation) but anyway

peak timber
#

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

vestal minnow
#

ConvexHull probably smooths it out too?

peak timber
#

yeah

vestal minnow
#

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

peak timber
#

so is it normal to be that slow?

vestal minnow
#

I haven't tested compound colliders much, it'd probably be more of a parry thing

#

random thought... do you have debug rendering on?

peak timber
#

no

vestal minnow
#

alright, just wondering

peak timber
#

I can stick with trimesh and just hope and pray nobody finds a way to get into a block for now πŸ˜‚

vestal minnow
#

Increase the number of substeps πŸ™ƒ

peak timber
#

well, physics seems to be working perfectly fwiw

#

it'd just be gameplay things like placing a block while you're standing on it

vestal minnow
#

ah yeah

peak timber
vestal minnow
#

fwiw I believe cuboid collisions are more expensive than you'd think, but I'm pretty sure trimeshes should still be more expensive

peak timber
#

maybe it's just because my meshes are so optimized compared to adding every single block in every single chunk

vestal minnow
#

does it add them even below the surface if they're cuboids?

peak timber
#

yeah, I was doing it for every solid block so that if you get stuck anywhere you get pushed out or suffocate

vestal minnow
#

If you have spatial queries then that could be making it slow maybe

peak timber
#

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

vestal minnow
peak timber
#

nope, just as slow

vestal minnow
#

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 πŸ€”

peak timber
#

it's probably something like 67 million cubes (rough math)

vestal minnow
#

Okay well that's a lot

peak timber
#

things add up fast lol

vestal minnow
#

Disable SpatialQueryPlugin maybe?

#

eventually we'll hit the correct plugin

peak timber
#

nope

vestal minnow
#

??

#

Hell, disable all of physics

peak timber
#

didn't work

#

I mean

vestal minnow
#

Nvm it's colliders

peak timber
#

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

vestal minnow
#

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

peak timber
#

also side note, when the game is lagging, the physics simulation runs slower than normal

peak timber
vestal minnow
#

I don't think there's anything else that would run substantial extra things when entities are added

#

Yeah

peak timber
#

I'll try profiling it

#

lol

vestal minnow
#

Lmao

peak timber
#

it looks like prepare::update_mass_properties is taking the longest

vestal minnow
#

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

cinder summit
#

Wait is it doing all of that parry dynamic dispatch overhead 67 million times in only 87ms?

peak timber
#

no

#

it's only adding a maximum of 25 chunks per frame

#

and the colliders themselves are constructed in async tasks

vestal minnow
peak timber
#

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

cinder summit
#

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

peak timber
#

that would take a lot of computation Sadge

#

I'll just stick with trimeshes for now

cinder summit
#

I think it might actually be fairly cheap computationally but it does sound like a pain to build πŸ˜‚

peak timber
#

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

cinder summit
#

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

vestal minnow
#

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

peak timber
#

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)

peak timber
#

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

vestal minnow
#

I wonder it'd be possible to efficiently use SDFs for blocky voxel terrain πŸ€”

cinder summit
#

SDFs and cubes aren't great friends tbh πŸ˜‚

peak timber
cinder summit
#

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 thonk

vestal minnow
#

I realized today that I think I could technically remove basically all remaining Parry and Nalgebra stuff from the public API with the primitives

peak timber
#

nice

#

implementation detailℒ️

#

I like how this happens for a few seconds and then just goes away due to how my chunk loading works

cinder summit
vestal minnow
#

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

cinder summit
#

Once the API has no parry types we just need a feature flag to use sdf collisions instead thonk

vestal minnow
#

And reimplement helpers for AABBs and spatial query stuff for Collider

cinder summit
#

Reimplement helpers for AABBs?

#

Surely you mean ... Use the bounding types on the primitives? thonk

#

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 πŸ˜‚

peak timber
#

just make it the default troll

vestal minnow
#

Also idk if it'd be helpful here since the internal collider shape would still be a parry shape

cinder summit
# peak timber just make it the default <:troll:1104472638694375437>

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

cinder summit
cinder summit
#

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

vestal minnow
#

Or we could, but it wouldn't be as efficient

#

Unless we copy those special cases to use primitives

vestal minnow
#

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:

  1. Fork Parry as Barry
  2. Replace Nalgebra with Glam
  3. Replace Parry shapes with Bevy's primitives
  4. I'll work my magic on the docs in some cave
  5. 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

red gulch
#

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?

vestal minnow
#

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

red gulch
#

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.

vestal minnow
#

No you're correct, thanks for the PR!

red gulch
#

Happy to help!

red gulch
#

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?

vestal minnow
cinder summit
peak timber
#

🀣

vestal minnow
#

Wait that's also SpatialDim x 1... That's just SpatialDim??

#

or a cross product with 1 but that makes even less sense

cinder summit
#

Not sure if sebcrozet has a habit of drinking while coding, or if we should be worried about them thonk

vestal minnow
#

True

#

The over 500 clippy warnings also exist still

#

I don't get how you can live without clippy

#

or ignore it like that

cinder summit
#

I've worked on crates where the warnings got ignored, I didn't even want to try running clippy πŸ˜‚

vestal minnow
#

and I'm not sure if Affine3 and Isometry3 are the same, I think they are? at least almost

cinder summit
vestal minnow
#

hmm I might need to make custom Iso2/Iso3 types

cinder summit
vestal minnow
#

Affine3A has a matrix for rotation+scale+shear, but we want just rotation

cinder summit
#

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 πŸ˜‚

vestal minnow
#

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

cinder summit
vestal minnow
#

Yep

#

I keep changing my opinion

#

I don't know what I think

cinder summit
#

I feel like it wouldn't have been controversial if it was just a type called Radians that has a From<f32> thonk

vestal minnow
#

yeah but allowing/disallowing the implicit convertion is a part of the controvertiality too

#

one of the main goals was to go for explicitness

peak timber
#

it's a godsend

#

aside from type_complexity and too_many_arguments KEKW

cinder summit
#

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 πŸ˜‚

vestal minnow
#

it's inconsistent tbh

peak timber
vestal minnow
#

gizmos take clockwise radians for some reason

peak timber
#

Radians & Degrees newtypes are superior though

cinder summit
cinder summit
peak timber
#

yea I think that's where I saw it tbh KEKW

vestal minnow
#

Radians & Degrees would be almost perfect if type inference for the math ops like Degrees + Radians worked

cinder summit
#

Idk if I like the idea of thinks taking impl Angle tho thonk

peak timber
#

you can always cast with t.into() and ::from(T) if nothing else

#

not too bad

vestal minnow
#

Yeah I think I'll change it to that

cinder summit
#

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

peak timber
#

yes that's what I mean

#

shouldn't newtypes and unnecessary math operations be completely optimized out? especially if you mark them #[inline]

vestal minnow
#

the conversion between units is just one multiplication so it's not too bad tbh

cinder summit
#

+ Degrees(90.) would be a lot nicer than + std::f32::consts::PI / 2. tho thonk

peak timber
#

you think I remember middle school level math? lol

#

oh that's high school

#

yea that's how little I remember

cinder summit
#

I never learned useful things like radians and quaternions at school at all ferris_sob

vestal minnow
#

radians are high school, quaternions are never

cinder summit
#

Lessons about quaternions are imaginary thonk

peak timber
#

quaternions were created as an alternative to Chinese water torture

cinder summit
#

The physics I learned at school also never prepared me for writing SDF collisions ... Which is clearly a major failure of the educational system

vestal minnow
#

I'd say that's more math than physics

peak timber
#

yeah SDF is so useful for everything on a day to day basis

cinder summit
vestal minnow
#

*signed distance

cinder summit
#

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 πŸ˜‚

peak timber
#

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 thonk

vestal minnow
#

you have f64, right?

peak timber
#

yeah

vestal minnow
#

yeah well that's super precise in comparison

peak timber
#

it goes back and forth between f32 and f64, but I guess since it uses change detection it doesn't lose precision unless necessary

cinder summit
#

Until you try to make a BVH, and still need to add 2 ULPs if you want to support arbitrary unnormalized direction vectors

peak timber
vestal minnow
#

There's also this weird AccumulatedTranslation component so that the integrator doesn't have precision issues regardless of the distance from origin

cinder summit
#

BVH is a bounding volume hierarchy, it's the data structure you use to speed up things like raycasting

vestal minnow
#

idk ULP either

cinder summit
#

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

vestal minnow
cinder summit
#

I think ULP relates to the whole epsilon thing

peak timber
#

speaking of PRs I need to actually make that init_transforms PR

#

and remove it from my procrastination list lol

cinder summit
#

Speaking of PRs I need to fix the bounding PR ... Because padded and shrunk are bad names thonk

vestal minnow
#

there's a name for this phenomenon but I don't remember it

cinder summit
#

The ULPs can never be unseen now thonk

vestal minnow
#

scrape GH with some bot to look for AABBs

cinder summit
#

If the names aren't in past tense I feel like grow/shrink would be decent tbh

peak timber
vestal minnow
#

Would implementing Add/Sub be weird

#

math with AABBs lmao

peak timber
#

please no

vestal minnow
#

SS-Controversial

cinder summit
#

But I've also been thinking that maybe we can just not do the Self thing

peak timber
cinder summit
#

And just make AabbCast and SphereCast intersection tests πŸ€”

peak timber
#

lol

vestal minnow
#

axis-aligned

cinder summit
#

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 πŸ˜‚

vestal minnow
#

if you rotate an AABB, it becomes an OBB

peak timber
#

LockedAxes isn't respected by shapecasts?

vestal minnow
#

no...?

cinder summit
peak timber
#

fair

peak timber
cinder summit
#

ExtrudedRectangle πŸ˜‚

vestal minnow
#

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

cinder summit
#

Quad is a thing in 3D, it's just not very useful outside of rendering

vestal minnow
#

yeah it should vanish with the meshing impl

vestal minnow
peak timber
#

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

vestal minnow
#

yeah that's what I meant with a potential "specific order"

peak timber
#

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

vestal minnow
#

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

vestal minnow
# peak timber

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

peak timber
#

propogate_collider_transforms doesn't depend on it?

vestal minnow
#

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

peak timber
#

does after(system) still work if system doesn't meet its run condition(s)

vestal minnow
#

yes

#

I'm 98% sure

peak timber
#

If the ordering or structure of the library were to change it could break that unexpectedly

vestal minnow
#

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

peak timber
#

with something like initialize_transforms: bool, initialize_positions: bool?

vestal minnow
#

yeah, something like that

peak timber
#

ok, I'll submit a PR rq and see what you think

vestal minnow
#

I think it's better than relying on the specific system structure in another plugin

#

unless we added more system sets

peak timber
#

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

vestal minnow
#

yeah, true

peak timber
#

I almost wish you could use trait methods for systems :P

#

to make it easier to override things without worrying about order

vestal minnow
#

hmm

pub enum InitSet {
    RigidBodies,
    MassProperties,
    Colliders,
    Transforms // or Positions?
}
peak timber
#

that would be nice

vestal minnow
#

something like this could maybe make it a bit nicer

cinder summit
peak timber
#

Java devs be like

vestal minnow
#

Hey that looks like a Parry type!

cinder summit
peak timber
#

no that would be ACollationOfAtePointsWareEachPointIsAlinedWithThreeAjasentPoints

cinder summit
#

It just needs some "DepthFirst" or something in the name I feel thonk

vestal minnow
#

I still can't get over Parry's names like
TOICompositeShapeShapeBestFirstVisitor

cinder summit
#

TOI isn't even acceptable rust naming πŸ˜‚

vestal minnow
#

I think they used to have AABB too

#

but without clippy, doesn't matter

cinder summit
#

Without clippy nothing matters, there is only depression πŸ™ƒ

vestal minnow
#

Wait None can have generics?

let mut best_hit = None::<TOI>;
#

Idk if I like that or not

cinder summit
#

Well None is just a variant of Option, which does have a type, so the variant also has a type

vestal minnow
#

Kinda nice but feels cursed somehow

cinder summit
#

You can do this on all your generic enums by just useing the variants into your scope

vestal minnow
#

yeah I learned that a few days ago

cinder summit
#

I don't think it's very common to need this tho ... And I feel like I'd rather just do Option::<Toi>::default()

vestal minnow
#

some angle crates have an Angle enum but re-export Radians and Degrees variants

cinder summit
#

Imagine thinking you have a f32 newtype but it's actually an enum and takes up more memory than you thought πŸ‘€

vestal minnow
#

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

cinder summit
#

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

vestal minnow
#

MyStruct<[[f64; 18446744073709551615]; 18446744073709551615]>(f32)

cinder summit
#

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 πŸ˜‚

vestal minnow
#

or there's an entities method

cinder summit
vestal minnow
#

I assume you can't make types recursive in Rust unfortunately

cinder summit
cinder summit
vestal minnow
#

Yeah this probably doesn't work

type A = [B; 10000000000];
type B = [A; 10000000000];
cinder summit
#

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 πŸ˜‚

vestal minnow
#

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

cinder summit
#

Not sure tbh ... I've never actually used bevy's reflect magic

vestal minnow
#

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

cinder summit
#

Reminds me of the Go Proverbs thing ... "Reflection is never clear."

peak timber
#

I'm losing my mind

#

this code definitely needs a refactor lol

vestal minnow
vestal minnow
#

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

cinder summit
vestal minnow
#

hmm, I wonder if r#2 works

#

doesn't seem to

#

sad

peak timber
#

I think it's only for valid identifiers that happen to be reserved words

#

like r#struct

vestal minnow
#

yep

#

and multiline strings

peak timber
#

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'

vestal minnow
#

same

peak timber
#
#[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

vestal minnow
peak timber
#

ah

#

I should go contribute to Parry then :P /s

vestal minnow
peak timber
#

I'll add some doc comments to this before I make the PR

peak timber
#

gotta love Rust :P

#

looks like main doesn't have that issue

vestal minnow
#

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

peak timber
#

just wait until the second compiler error phase

#

"9,999,999+ errors remaining"

vestal minnow
#

issue is, Rust does that fun thing where fixing errors creates new ones

#

exactly xd

peak timber
vestal minnow
#

can't wait to see the diff at the end though

#

"50,000+ lines changed"

peak timber
#

the main downside to what you're doing is it makes it virtually impossible to sync upstream changes

vestal minnow
#

Well luckily that's not a big deal considering Parry's activity πŸ˜‚

cinder summit
#

Watch parry suddenly get super active again, just to spite you

vestal minnow
#

last commit 4 months ago

peak timber
#

lol

#

fair

cinder summit
#

parry sees a fraction of the number of changes of rapier, and rapier sees a fraction of the number of changes of bevy_rapier

peak timber
#

and bevy_rapier sees a fraction of the changes of bevy_xpbd

vestal minnow
#

I'll fix parry so they'll reverse fork barry

cinder summit
#

Exactly πŸ˜‚

#

Watch as rapier suddenly depends on ploc-bvh and I'm just confused when someone opens an issue about using it in rapier

peak timber
#

100,000,000 lines changed
PR name: "Thank me later"

vestal minnow
cinder summit
#

Luckily parry isn't that big πŸ˜‚

vestal minnow
#

It will be once I do docs

cinder summit
#

I'm not even sure if you can make a 100m line PR on the linux kernel πŸ‘€

peak timber
#

100m is rookie numbers

vestal minnow
#

Running cargo test will be terrifying once I've fixed these errors

#

no shot it'll work

peak timber
#

0/1000 tests passing

#

I watched the xpbd intro video you linked in the docs

#

pretty fascinating stuff

vestal minnow
#

yeah physics stuff is cool

#

I kinda want to make my own videos and/or tutorials

peak timber
#

the 10 minute physics video

#

I'm not an academic paper kinda person lol

cinder summit
peak timber
#

I feel that

vestal minnow
#

I just took a look at a rough list I have

#

it's pretty long yeah

peak timber
#

hopefully CCD isn't being pushed down

vestal minnow
#

it's not in priority order at all and probably not up to date

cinder summit
#

I actually haven't had a single case of tunneling even with my 6 substeps πŸ‘€

peak timber
#

same

#

but

#

CCD sounds cool

#

so its probably important

cinder summit
#

I think the most important change that isn't missing features would be speeding up the broad phase πŸ€”

peak timber
#

it's pretty fast for me but I do only have 1 dynamic entity

cinder summit
#

After that more parrallelization maybe? Idk I don't even have it enabled πŸ˜‚

vestal minnow
#

not sure tho

#

XPBD does integration in substepping loop

#

so things advance in smaller increments

cinder summit
vestal minnow
#

yep

peak timber
#

I do remember having more high speed issues with rapier

vestal minnow
#

experimenting more with that is also on my todo list :P

peak timber
#

the todo list for my game is overwhelming at best

cinder summit
#

I also basically can't get tunneling in my game anymore

#

Because SDF colliders have volume, unlike trimesh colliders πŸ˜‚

peak timber
#

there's a terminal velocity right?

vestal minnow
#

no

peak timber
vestal minnow
#

unless you make one

cinder summit
vestal minnow
#

terminal velocity is Vec3::MAX

#

or infinity

peak timber
#

so gravity just keeps getting larger? I figured there's some sort of drag

vestal minnow
#

you can add LinearDamping

peak timber
#

I'm mainly concerned about players falling from extremely high distances into unloaded chunks

vestal minnow
#

but that'll also affect xz velocity

#

I guess I could add some MaxVelocity, but you could do it manually too

peak timber
#

maybe I should make a PR to make it a Vec

vestal minnow
#

yeah I'd probably accept that, it's just scalar in almost all other engines too

peak timber
#

but yeah it's pretty simple to do myself as well

vestal minnow
peak timber
#

probably a bad way to do it but I'm too lazy to improve that code atm lol

peak timber
#

I need to start using fixedupdate

vestal minnow
#

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

peak timber
#

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?

vestal minnow
#

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

cinder summit
peak timber
cinder summit
#

There's two approaches, but the better one generally is using FixedUpdate yea

peak timber
#

I dont like my game's physics coming to a crawl if you have low frames lol

vestal minnow
#

also ew that formatting, I wrote it here

peak timber
#

I shall try soonℒ️

vestal minnow
#

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 πŸ˜‚

cinder summit
#

I think bevy by default allows like 250ms worth of ticks

vestal minnow
#

yeah but iirc it worked better than other things I tried

#

move_marbles basically froze with larger overstep I think

cinder summit
#

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

vestal minnow
#

yeah