#Avian Physics

1 messages · Page 7 of 1

upper crow
#

thanks!

royal helm
#

lemme check

#

ragdolls are usually done via joints though

#

compound colliders aren't really meant to be disjointed, but I guess you could

upper crow
#

for further context, i have a lizard/snake that i don't want objects to be able to squeeze through its individual colliders

royal helm
#

hmm

royal helm
#

by that description I'd assume the colliders would be "dragged" behind the head of the snake

upper crow
royal helm
#

I'd suggest joints in that case

upper crow
#

Oh I'm already using joints! How do they help here?

#

Just applying enough force to keep things from pushing the circles apart?

royal helm
#

ah sorry 1 sec my internet isnt good right now

#

haven't seen the thing you sent

upper crow
#

no worries!

#

I am also interested in the overlapping circle colliders because I think those produce the best lizard shape aesthetically

royal helm
#

I think you should be able to make it so joints let you overlap with the things it is jointed to

#

or maybe not?

#

I guess you could do it through collision layers

#

but idk how you'd deal with multiple snakes in that case

upper crow
#

ohhhh yeah that's exactly what i need

#

well maybe not exactly but can do 90% of what i need

vestal minnow
#

I'll do this next week, I have an exam week rn so I'm kinda busy unfortunately

#

Yep it's a bit misleading. I originally mostly followed the naming used in parry/rapier, and they also seem to use direction for raycasts despite it actually being velocity

junior flower
#

Ahh fair enough. I'd considered making a PR but looking at #math-and-physics message this conversation it looks like you're planning on changing the API anyway

Good luck with your exams. Hope it goes well!

zinc talon
#

I'm not seeing examples in the brain repo. Apologies if that's been asked a million times but are there available examples?

junior flower
#

What examples are you looking for? Anything specific or just anything about using bevy_xpbd?

zinc talon
#

Ah, I was looking for an example dir in the root

#

Thanks!

sleek thicket
fervent crescent
#

Is there an elegant solution for multiple ShapeCasters on 1 Entity or am I restricted to 1 ShapeCaster in 1 direction and any more will need to be manually done via a SpatialQuery? I'm looking for collisions along -Y, -X, and +X in a platformer setting.

vestal minnow
#

You'll just need to handle queries a bit more annoyingly if you want to do something to the parent when one of the child shape casters detects a hit

fervent crescent
#

Gotcha, thank you!

zinc talon
# fervent crescent Gotcha, thank you!

That would actually be a really good use for bevy_event_listener, it allows you to send events to a child, but handle them in a parent with "bubbling"

tacit hinge
#

I'm trying to setup a movement system where there can be acceleration and deceleration with different values. This is what I have so far:

pub(super) fn walk(
    mut walk_event: EventReader<WalkEvent>,
    mut query: Query<(
        &mut LinearVelocity,
        &WalkSpeed,
        &WalkAcceleration,
        &WalkDeceleration,
    )>,
    time: Res<Time>,
) {
    for event in walk_event.read() {
        for (mut velocity, speed, acceleration, deceleration) in query.iter_mut() {
            // NOTE: Acceleration: 50.0, Deceleration: 100.0

            // walk_event's value will be either -1, 1, or 0 depending on whether the user
            // is trying to move left, right, or not at all.
            let direction = event.0;

            // Increase x velocity by acceleration value
            velocity.x += direction * acceleration.0 * time.delta_seconds();

            // If no movement direction, but entity is still moving, apply deceleration
            if direction == 0.0 && velocity.x != 0.0 {
                velocity.x -= deceleration.0 * time.delta_seconds();
                dbg!(velocity.x);
            }

            // Make sure velocity doesn't exceed walk speed
            velocity.x = velocity.x.clamp(-speed.current(), speed.current());
        }
    }
}

I'm having a bit of trouble though. After I've pressed a movement key, my character starts sliding to the left, I think I understand why (the if direction == 0.0 && velocity.x != 0.0 isn't right), but I don't know what condition to use to make this work.

sleek thicket
#

or just the variable?

brisk bay
#

So I'm having some general stability/behavior issues with bevy_xpbd_3d in a new XR project. There's a few different specific issues:

  • First, generally, collisions between dynamic bodies are being weird. They're sleeping really aggressively, and when they get woken up by other collisions they tend to jump/hop in random directions. This got worse when I tried f64 precision.
  • Second, I am trying to make some velocity-tracked 'physics hands' by controlling a dynamic rigidbody hand's velocity based on its position relative to the controller, like so:
fn move_hands(
    mut hands: Query<
        (&PhysicsHand, &GlobalTransform, &mut LinearVelocity),
        Without<OpenXRController>,
    >,
    controllers: Query<&GlobalTransform, With<OpenXRController>>,
) {
    for (hand, hand_global_transform, mut hand_local_transform, mut velocity) in hands.iter_mut() {
        let controller_transform = controllers.get(hand.controller).unwrap();
        let delta_position =
            controller_transform.translation() - hand_global_transform.translation();
        velocity.0 = (delta_position * hand.follow_strength).into();
    }
}

However said hands don't interact with other objects in a reasonable way. Instead of pushing them out of the way, they phase through, with some resistance. They do bump the other objects slightly, in random ways, sometimes. If the hand ever fully overlaps another object they both disappear to NaN-land.

They do have a collider, and if I take the same objects but just don't modify their velocity, they collide as normal.

sleek thicket
#

that reminds me of this #1124043933886976171 message @brisk bay

#

no idea if it got resolved though

brisk bay
brisk bay
#

This would be a basic way to implement it

let drag_constant = 2.0; // Tune this to control the behavior

// If no movement direction, but entity is still moving, apply deceleration
if direction == 0.0 && velocity.x != 0.0 {
    let drag_acceleration = -velocity.x * drag_constant;
    velocity.x += drag_acceleration * time.delta_seconds();
    dbg!(velocity.x);
}

Good initial value for drag_constant would be (desired deceleration at top speed) / (walk speed)

#

If the deceleration speed is good initially but it takes too long to come to a complete stop, or vice versa, you could raise the velocity to an exponent (like 1/2, or 2) to change the shape of the deceleration curve

#

But there might also just be a built in drag mechanism in bevy_xpbd

vestal minnow
#

there's a LinearDamping component

#

ya

#

but it's applied uniformly in all directions

#

whch probably isn't what is desired here

sleek thicket
#

@vestal minnow i didn't check, did you end up fixing that framerate-dependent drag issue? because knexer just handed out the solution to it there

vestal minnow
#

@sleek thicket this?

sleek thicket
#

yes

vestal minnow
#

not yet, that issue is just in the example afaik

#

LinearDamping uses a different formula that should be framerate-independent I believe

sleek thicket
sleek thicket
#

wouldn't it be possible to just change lin_damping into a vec2 btw

vestal minnow
#

yes

sleek thicket
#

that way you can configure it for sideways and custom gravity

vestal minnow
#

usually it's just a scalar value though

#

like in unity, rapier...

sleek thicket
#

in unity i ended up making everything custom though

vestal minnow
#

same could be done in xpbd with a custom system

sleek thicket
#

yeah that's what i'm doing here too 🥲

#

especially because of different movement slowing effects, idk if changing lindamp would be good for that

vestal minnow
#

drag as a vector is just kinda weird physically, like why would it be different when going forwards/backwards vs. left/right (assuming that shape doesn't affect things)

sleek thicket
#

but for gameplay purposes it'd probably be good

#

esp for hovering collider

#

gravity and spring handle Y, but not X

#

unless i check ground for friction 🤔

#

i'm still not done transferring the whole movement system though, so i might have a better opinion later anyway

#

and btw

#

#math-and-physics message

#

i was constantly switching layers in unity, is doing that bad in xpbd for some reason?

vestal minnow
#

are you trying to add the filter as a component or smth?

#

it's not a component

sleek thicket
#

wait did i brainfart

vestal minnow
#

that's what the error is basically suggesting, it's not a component so you can't query for it

#

it's stored in RayCaster/ShapeCaster or given in SpatialQuery methods

#

that way you could also have different filters for the different casters if they were on the same entity

sleek thicket
#

i'm still brainfarting, changed to collisionlayers but can't figure out how to replace it

#

i guess i'd have to start using physicslayer and just add/remove instead of replacing group/mask

#

but why not just replace them ._.

tacit hinge
#

Yet I see it hitting 0.0 eventually, so I guess I'm just confused how that's happening.

vestal minnow
#

it'll be practically zero, plus floating point precision will eventually cut it to 0.0

#

and also bodies can be marked as sleeping if they're still long enough, which will set velocity to 0

sleek thicket
#

just tested knexer's one, and it definitely ends up stopping

#

or i can't tell, my char doesn't sleep because of spring anyway

tacit hinge
#

Yeah, it definitely does stop, I was just asking how, but floating point precision cutting it off makes sense.

#

Oh sorry, were you talking about something else @sleek thicket ?

vestal minnow
#

floating point precision + sleeping + it'll be close enough to zero that any movement would be unnoticeable anyways

sleek thicket
#

nope, other than the previous topic of CollisionLayers' mask/group not being pub

vestal minnow
#

should expose some more APIs for that probably

sleek thicket
#

or make it pub.

vestal minnow
#

yeah

sleek thicket
#

all that API does is bitshiftflip so i don't see a reason why i can't just swap the whole thing

vestal minnow
#

you can probably do *collision_layers = CollisionLayers::from_bits(...) or whatever

sleek thicket
#

i'm a unity monkey so i like stuff braindead simple 🐒

#

err

vestal minnow
#

or *collision_layers = old_layers.add_layer(...) or smth

sleek thicket
#

yeah let me try

#

oooh yeah that works

#

i guess i didn't understand how deref works on components

#

i can actually continue working now ty \o/

vestal minnow
#

no worries

sleek thicket
#

although i probably shouldn't work at night

vestal minnow
#

ideally you could just add/remove individual groups/masks without replacing and copying things ofc

#

but for now replacing the component value should work

sleek thicket
#

in unity it was basically replacing just the groups

#

except in unity it was literally just 1 layer, not groups

vestal minnow
brisk bay
# brisk bay So I'm having some general stability/behavior issues with bevy_xpbd_3d in a new ...

btw @vestal minnow any brief thoughts on this issue? Basically I'm seeing:

  1. lots of penetration when I'm setting the velocity every frame during Update (which should be before physics runs in PostUpdate by default right?)
  2. chaotic behavior around sleeping, e.g. bumps when waking or sleeping really early

Mostly wondering if there are any tweakables I should try tweaking, or maybe if I should be scheduling the velocity setting differently, or if there's just something basic I'm missing

#

I could record a video next time I have a headset with me if that'd be helpful

vestal minnow
#
  1. sleeping can be disabled

Sleeping can be disabled for specific entities with the SleepingDisabled component, or for all entities by setting the SleepingThreshold to a negative value.

#
  1. You could try increasing the SubstepCount but I'm not sure if that'll help much. Your scheduling looks fine since you're modifying velocity; if you were updating the position directly, running in `SubstepSchedule´ could be more stable, but that shouldn't be needed here
#

could also enable debug rendering to see the hand colliders in case you don't already

brisk bay
#

Thanks, okay, I'll try those! I could probably be ok with sleeping disabled across the board as there shouldn't be too many bodies at once in what I'm doing

#

Substep counts I've already bumped to... 30 I think? I can try going higher

vestal minnow
#

hmm that should definitely be enough I believe

#

what kind of collider(s) is the hand made of?

brisk bay
#

For the colliders, I can confirm in game that they line up nicely with the rendered mesh, like if I gently touch the hands to one another they respond reasonably

vestal minnow
#

like trimesh, convex hull, etc.

brisk bay
#

Cubes

#

veeeeeery prototype right now haha

vestal minnow
#

hmm yeah I don't see why that would have any clipping issues or other stability issues

#

kinda weird

#

what if the follow strength is a lot weaker?

brisk bay
#

then the hands follow behind the controllers very slowly, but still penetrate other objects in the same way

vestal minnow
#

could try giving them a constant velocity and see how collisions behave with that

brisk bay
#

like set the initial velocity and let the sim go?

vestal minnow
#

yeah

brisk bay
#

I am doing something similar with 'press b to spawn a cube' which then falls under gravity to the ground

#

that's where some of the other weird collision/sleeping behavior is coming from

#

but they do mostly behave sensibly-ish, like there's not the same kind of penetration happening at all

#

could it be an issue with the scale of the numbers I'm using somehow? I know that can be an issue with physics engines, if they expect certain sizes/masses they can be weird outside that domain

vestal minnow
#

closer to 1 would be ideal but I doubt it

brisk bay
#

The cubes are .1 meters each way, hands have a mass of 1kg, default cubes have... probably much less mass now that I think about it

#

At least I assume Mass(1.0) means 1kg?

vestal minnow
#

yes

#

assuming SI units

#

setting mass explicitly could maybe cause some issues tho

brisk bay
#

oh? interesting

vestal minnow
#

or most likely not, but I believe it means that your angular inertia values could be off unless you specify them as well

#

not entirely sure

brisk bay
vestal minnow
#

ooh they don't have any inertia right?

#

that'd mess collisions up

brisk bay
#

oh

#

hmmm

#

lol that would though

#

I assumed that was being added like Position/Rotation/LinearVelocity were

vestal minnow
#

it is, but it's zero since collider density is 0 and you don't specify it

brisk bay
#

huh, I'd expect the nonzero mass to still mean it has inertia, but i guess not angular inertia?

vestal minnow
#

inertia == angular inertia in this case

brisk bay
#

Okay I'll have to try this - wish I had my headset on me, oof

vestal minnow
#

yeah tested cubes example and it definitely explodes without inertia

brisk bay
#

okay yeah, that does make sense. Thanks for all the help!

#

I'll report back once I try out these fixes

vestal minnow
#

if you want to add Inertia explicitly then something like Inertia(Mat3::from_diagonal(Vec3::ONE)) seems to work

#

scale the diagonal vec to increase it

#

alternatively, you could compute mass props from a collider shape with MassPropertiesBundle::new_computed

brisk bay
#

initializing multiple interrelated components seems like a hard thing to do API-design-wise without this kind of footgun / rough edge sneaking in somewhere, huh

#

easy to do something that's in some sense invalid / not internally consistent

vestal minnow
#

yeah there's the MassPropertiesBundle but it doesn't help that much with that issue currently

brisk bay
#

I guess that's why computing from the collider is the well-lit path, it guarantees things are sensible

vestal minnow
#

in general the easiest way is to just use a collider with some density yeah

#

specifying them manually can be inherently error-prone and unphysical since e.g. inertia depends on the shape and offset of the object and also the mass

brisk bay
#

it might be nice to have an alternate new_computed that takes a mass instead of density, in a lot of cases that's the more fundamental number game design wise

vestal minnow
#

yep

brisk bay
#

I would often find it really unexpected if I shrunk a collider to make something easier to dodge or whatever and it suddenly weighed 1/3 as much

vestal minnow
#

I believe that should be possible, although parry's mass property method just takes a density

#

would probably need to compute the volume first somehow

#

parry's shapes should have volume methods, but I'm not sure if there's one for the dynamic shape so maybe I'd need to handle all of the variants separately... idk I'll have to check

#

ouch that looks painful

brisk bay
#

yikes. well for now it's not hard to calculate densities on a case by case basis, as long as I know that I need to, haha

#

and tbh thinking in terms of densities actually helps a fair amount in setting realistic masses, like it prompts me to think in terms of what material the object is composed of and go from there

vestal minnow
#

or it might be doable, I think I can just compute some valid inertia and then scale that based on the mass

#

but I don't think I can compute the correct one directly since I'd need the volume which is annoying to handle

brisk bay
#

isn't there already volume calculation happening to get the mass from the density + collider?

vestal minnow
#

yes but it's handled by parry, and it's complex enough that it has an entire folder for the different shapes

#

I couldn't find a singular shared volume method, instead it does stuff like this

let (cyl_vol, cyl_unit_i) = Self::cylinder_y_volume_unit_inertia(half_height, radius);
let (ball_vol, ball_unit_i) = Self::ball_volume_unit_angular_inertia(radius);
#

(for capsule)

#

weird how the shapes don't have volume methods 🤔

#

they're pretty straightforward for the most part, I already implemented them for Bevy's shape primitives

brisk bay
#

yeah it is odd that it doesn't have a uniform interface

royal helm
brisk bay
vestal minnow
#

the other one is just casually reading a book or something lmao

#

this is fine

brisk bay
#

and disabling sleeping made the other cubes much better behaved as well

warm gulch
#

How do we make this answer the first google search result? You should add this to a notice or special bullet in the ReadMe... Thanks anyways, solved all my issues!

sleek thicket
warm gulch
#

Yep

vestal minnow
# warm gulch How do we make this answer the first google search result? You should add this t...

Yeah I'll try to remember to add docs or an example for this. There's also an issue with the fix
https://github.com/Jondolf/bevy_xpbd/issues/211#issuecomment-1789342920

GitHub

Hi, I'm trying to make the camera follow a physics object using this system: pub fn camera_follow_player( mut camera_query: Query<&mut Transform, With<MainCamera>>, player_query...

warm gulch
#

Is there a convenient way of controlling the model's rotations and offset inside bevy. I downloaded som models and I notice that their "origin" and "base rotation", or whatever you would call them, are not where I would want them. I can adjust this by changing the model in Blender, but I feel it would be nice to control it by just setting some offsets in code instead. My problem is that the loaded scene and the model do not have the same center. Or is it perhaps advisable to go with a child entity with some transform of its own?

#

The reason I ask here is because it pertains to xpbd which I use...

crystal cosmos
warm gulch
#

It seems to me that the origin for the colliders cannot be set to anything but the center / origin of the entity, which is what I'm getting at. Maybe I just don't understand all this well enough. I will try to just change the origin in Blender, should work well enough for me.

#

I just found the answer, maybe, in the code, regarding child entities and colliders. I think I might have what I need now.

small flower
#

Why same colliders are rendered with different wireframe?
These are all Collider::ball(0.2)

vestal minnow
#

are you sure? those other ones look like trimesh colliders

small flower
#

I spawn then in a for cycle with same spawn command

                            let ball = Collider::ball(
                                        collider.radius,
                                    );
                            info!("Spawning {:#?}", ball);
                            let rg_entity = commands
                                .spawn((
                                    Name::new(format!("COLLIDER_{:?}", *bone_id)),
                              TransformBundle::from_transform(transform.compute_transform()),
                                    VisibilityBundle::default(),
                                    RigidBody::Dynamic,
                                    ball,
                                    Restitution::new(0.7),
                                    *bone_id,
                                    CollisionLayers::new(
                                        [collider.layer],
                                        [RagdollLayer::Floor, collider.layer],
                                    ),
                                ))
                                .id();

In the logs:

2023-11-27T00:27:48.822403Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
2023-11-27T00:27:48.822499Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
2023-11-27T00:27:48.822573Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
2023-11-27T00:27:48.822657Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
2023-11-27T00:27:48.822714Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
2023-11-27T00:27:48.822779Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
2023-11-27T00:27:48.822890Z  INFO main::ragdoll: Spawning Ball { radius: 0.1 }
vestal minnow
#

hmm, could you log the transform scale?

#

ball colliders are currently turned into convex hull colliders if they have non-uniform scaling, because ellipsoids aren't supported as a built-in shape at the moment (same in rapier)

#

so if your transform.compute_transform() scale isn't perfectly uniform (x, y and z have the same exact value) it won't be counted as a real ball anymore

small flower
#

Well yeah, it is not uniform
Almost all of them have value similar to this... except the root which is not touched

scale: Vec3(
        0.9999999,
        1.0,
        0.9999996,
    ),

I'll try to fix, thanks a lot.
Trimesh balls are spawned in infinity with joints sometimes 😄

vestal minnow
#

yeah 😄 you can probably just round the values or use something like Vec3::splat(scale.x) to make sure it's uniform

#

and yeah GlobalTransform::compute_transform can have numerical issues because global transforms use an Affine3A which basically has scale and rotation in one matrix and it needs to do some math things to compute the scale

royal helm
#

tbh I think xpbd and rapier should clamp to uniform scaling within a threshold by default

#

having a non-uniform scale is already a weird concept for physics and having it be off by a minor amount shouldn't really matter all that much

vestal minnow
#

Yeah it should probably use some small threshold

#

I think for the ball case we could technically add support for ellipses and ellipsoids too 🤔 at least ellipses seem to have a pretty trivial support map

fiery mortar
#

Hello, I recently switched to bevy_xpbd to try things out, and I was wondering if there was a crate for picking, similar to bevy_mod_picking with its backends, or if there's a reason for there being none (such as having xpbd handle it itself with some ergonomic plugin). I could write it up myself but I figured I don't have to reinvent the wheel if I can.

Also, is there a way to search for text in posts such as this? I tried using the search bar at the top right of the Discord client but I don't seem to be able to filter through messages in this particular post, it just shows me all of them.

cinder summit
#

I think the only thing you cando is filter to crate-help 🙃

#

Looks like you could also provide your own backend (or even upstream an xpbd one?)

fiery mortar
merry tide
#

Hello. Sorry, I think I have asked this before but I didn't understand my own question and/or answer. If I want to make a bounding box... It is just a box? How does it know whether to be inside or outside?

vestal minnow
# merry tide Hello. Sorry, I think I have asked this before but I didn't understand my own qu...

I'm not sure if I fully understand the question, but a bounding box is just a box that fully contains some shape. An AABB is an Axis-Aligned Bounding Box, meaning that it's orientation aligns with the world's axes (i.e. it's not rotated). For example, if you had a square shape rotated by 45 degrees, the AABB would be a box where each side is at the furthermost parts of the shape, in this case the corners. I'm not sure what you're trying to do with bounding boxes though, they're mostly a thing used for internal acceleration structures

#

For colliders, you can compute the AABB with collider.compute_aabb(position, rotation)

merry tide
#

Yeah, I am not that smart. I guess I am going to try asking in a way that makes it apparent what I do and do not know.

#

I understand I can make a box collider and a circle collider.

#

But can I make it so that if I need to frame my level, I use a single bounding box?

#

And something can happen inside of a circle collider instead of a bunch of balls colliding?

winter cape
#

Colliders are meant to keep things out of them if im not mistaken. So to frame your level, you'd have something like a cube collider for the floor, each wall, and roof. Something like that

feral citrus
feral citrus
#

wow that's exactly the problem, thank you

sharp badger
#

Hey!

I have a sword slash that I'm modeling as a box collider moving along an arc. I need to detect when the sword hits other colliders (but will pass through them). What is the best way to handle the movement here?

  • just put collider on and use transform directly? (Would be my preferred, but unsure if collisions handled okay with other rigid bodies)
  • have a kinematic rigid body and do angular vel + linear Vel to control movement? (A bit tricky to ensure the correct movement)
  • use a revolutejoint constraint and kinematic rigid body (again, unsure how accurate I can get the movement speed along the arc)
  • a custom implementation of the first idea collision carefully
vestal minnow
# sharp badger Hey! I have a sword slash that I'm modeling as a box collider moving along an a...

3 won't work because kinematic rigid bodies aren't affected by joints, forces etc. since they're user-controlled. It'd need to use a dynamic rigid body

If the sword should detect collisions but just pass through everything (not cause a collision response), you could make it a sensor collider and move it manually with transforms. To make it rotate around a specific point (like the sword "handle") you could make the collider a child entity that is offset, and move the parent instead

#

so I would probably do your first idea if I interpreted it correctly

sharp badger
#

Yes, it sounds like it.

But basically I can use a non-rigidbody collider and still have all collisions detected correctly?

vestal minnow
#

yeah I'm pretty sure it should still detect collisions

sharp badger
#

Thanks! I'll implement that and update if I run into trouble

abstract tendon
#

Hello. I have a player that can rotate and move. I need to add velocity to my character but when i give velocity, lets say velocity to x, it goes to world x but i need it to go local x. Does bevy_xpbd have local_x velocity or something like that? if it doesnt, how can i implement this?

vestal minnow
#

If you're using 2D then you just need to convert between Vec2/Vec3

winter cape
vestal minnow
#

Yeah you can use rotation.rotate(...) as well

#

Transforms might generally be considered more idiomatic/familiar in Bevy which is why I often use them in examples, but Rotation will give the most accurate result since it is what is actually used for physics. The difference for users should be basically negligible in most cases tho

feral citrus
feral citrus
#

well, that simplified things a lot

#[derive(Component, Default, Reflect)]
struct CanInteract(pub HashSet<Entity>);

#[allow(clippy::type_complexity)]
fn can_interact_update(
    mut commands: Commands,
    mut button_query: Query<(Entity, &CollidingEntities), With<MyButton>>,
) {
    for (button_entity, button_touchers) in button_query.iter_mut() {
        if button_touchers.0.is_empty() {
            commands.entity(button_entity).remove::<CanInteract>();
        } else {
            commands.entity(button_entity).insert(CanInteract(button_touchers.0.clone()));
        }
    }
}

fn reset_interaction_color(mut query: Query<&mut Sprite, With<MyButton>>) {
    for mut sprite in query.iter_mut() {
        sprite.color = Color::rgb(0.0, 0.0, 0.0);
    }
}

fn update_interaction_color(
    mut query: Query<&mut Sprite, (With<MyButton>, With<CanInteract>)>,
) {
    for mut sprite in query.iter_mut() {
        sprite.color = Color::rgb(0.0, 1.0, 0.0);
    }
}
#

oh wait

#

it still does the thing where it stops detecting at zero velocity

#

rip

feral citrus
peak timber
#

Hey, when combining RigidBody and AsyncSceneCollider I get a warning about it not having mass during the period where the model isn't loaded

#

Is there a better way to do this? i.e. loading the model(s) on startup, and spawning the entities later?

sleek thicket
vestal minnow
#

I believe it's zero velocity because the broad phase ignores collisions between bodies that aren't moving and the events don't handle that correctly

#

(but sleeping can also set velocity to 0 so it's somewhat connected)

vestal minnow
#

I made a PR for renaming cast_ray to raycast and so on
https://github.com/Jondolf/bevy_xpbd/pull/269

However, changing time_of_impact to distance requires normalizing direction, and we probably don't want to do that for each raycast. I guess we could just mention in docs that it must be normalized, but it'd be nice if it "just worked".

I think ideally the methods would take Bevy's Ray2d/Ray3d primitives (just noticed, they're not added yet despite being in the RFC lol). That way, it wouldn't need to normalize as often because users can reuse the same ray for multiple casts or even bypass normalization if the provided direction is known to be normalized

sleek thicket
vestal minnow
#

What exactly do you mean? What would the result of a raycast be

sleek thicket
#

normalized dir with 10 distance is same as normalized dir * 10, which is same as e.g. non-normalized dir with magnitude of 10

vestal minnow
sleek thicket
#

yeah, getting distance is just getting magnitude

vestal minnow
#

I haven't seen any engine handle it like that

sleek thicket
#

yeah, but it makes sense, doesn't it?

#

e.g. i often need to send a ray towards target, there could be a linecast, or i could just get dir towards target and without normalizing just use it for raycast without needing extra distance

#

basically that gives more control so i'm curious if it would actually be good in practice

#

also i didn't check what raycast does to get toi, does it just return a fraction of a distance if vector isn't normalized?

vestal minnow
#

toi is basically direction.length() * distance

#

(direction is velocity currently, which is unintuitive)

sleek thicket
#

so i guessed right?

#

the main problem is wording but removing distance as parameter makes it mostly intuitive anyway

vestal minnow
#

returning a vector is more expensive technically

#

if you had 1000 hits, that'd be 1000 vectors vs. 1000 scalar distances

#

RayHitData only needs to store the distance since the direction is stored in the ray itself

sleek thicket
#

don't have to return a vector, i mean it doesn't really change the result if you normalize before and input distance, or just do it afterwards knowing that nothing is normalized

#

you don't even have to normalize, it's just length, isn't it

vestal minnow
#

both involve sqrt which is the expensive part

#

("expensive" in the micro-optimization sense)

vestal minnow
sleek thicket
#

raycast(dir*dist..)
instead of raycast(dir, dist)

#

and returned result.length instead of direction.length * dist? i don't know what's going in on the background

vestal minnow
#

In that case you mean max_distance? raycast doesn't have a distance

#

and that'd just be confusing

sleek thicket
#

oh, is there a difference?

vestal minnow
#

max_distance is an argument controlling where to stop the raycast, i.e. a collider 2 units away from the origin wouldn't be detected with 1

#

distance (currently time_of_impact) is the actual distance from the origin to some hit point, stored in RayHitData

sleek thicket
#

just call it toi, i get what you mean <_<

#

instead of returning correct distance instead of toi, you wanted to normalize direction and then multiply it by distance, then return direction.length() just hitDistance, correct?

#

how do you get hitDistance?

vestal minnow
#

it's just time_of_impact if the direction is normalized

sleek thicket
#

yeah, i basically don't understand the difference between that, and removing max_distance and just using non-normalized vector pre-multiplied, then returning hitDistance

vestal minnow
#

If you remove max_distance, you'd need to have a vector like Vec3::X * f32::MAX to get all hits in the X direction

#

the vector representation would be confusing imo

sleek thicket
#

you mean (dir * dist)

#

instead of (dir, dist)

vestal minnow
#

yes

#

but making the direction be a line segment is more confusing in my opinion than having it be just a direction and storing the max distance separately

sleek thicket
#

it's essentially just moving a number around for users, but it's very clear that it's a velocity and not direction that needs to be normalized

vestal minnow
#

This is kinda the API I was imagining

let ray = Ray2d::new(Vec2::ZERO, Vec2::X);
let result = spatial.raycast(&ray, f32::MAX, true, default());
println!("Point: {:?}", ray.point_at(result.distance));
sleek thicket
#

and you get a choice of using something vectors of correct length that don't need to be multiplied

#

or you already have a normalized vector and multiply it as usual anyway

#

there won't be a need to double-check if it's normalized either

#

so in my mind it'd be better if nothing on the background gets worse because of that

vestal minnow
#

so 3 things

sleek thicket
#

pretty much

vestal minnow
#

then all of the toi results are kinda wack

#

if you use Vec3::X * f32::MAX for the vector, time of impact would always be 0 or close to 0

#

so you wouldn't be able to query for all hits in a direction and get toi values that make sense

#

(to query for all hits in the direction, the vector length in that direction must be f32::MAX if the vector also controls the max toi)

sleek thicket
#

i'm not sure how often it's needed though

#

it makes sense to get a fraction of path and then just multiply by length as return

#

might not even be a point to multiplying by length actually

#

i can actually think of a case where damage is multiplied by distance, and 0~1 is way more useful for that

#

aka damage falloff... a really common mechanic for shooters.

vestal minnow
#

idk that approach just seems overly complicated with no significant benefits, people find velocity and time of impact for raycasts confusing

#

direction and distance are more intuitive

sleek thicket
#

i can confirm it's confusing, but only because you have both the velocity AND max distance

#

dir * dist just makes it more obvious that you don't have to normalize, and the results will vary if you don't

vestal minnow
#

Velocity and max distance control two very separate things, with max distance being more important to have configurable than the velocity magnitude

vestal minnow
#

I assume you mean dir * speed = velocity

#

but also |velocity| = max distance somehow

sleek thicket
#

yeah, pretty much

#

i can't think of any case where it wouldn't be interchangeable though

#

e.g. line-of-sight raycast (assuming there's no linecast added) is basically just velocity * 1 right now

#

trying to think of anything else where max_distance varies but i think i'll need to look through the code

vestal minnow
#

Your model represents a line segment more than a ray

#

so a linecast, not a raycast

sleek thicket
#

yeah, i just can't think of a raycast case that needs variable max_distance

vestal minnow
#

almost everything?

sleek thicket
#

ground/wall-check ray/shapecast is a fixed distance, guns are all fixed, vision checks are either lines or fixed

vestal minnow
#

with a grounded cast, you probably want to get the distance to the ground, but restrict the raycast to a max distance of something like 0.1

#

and having to divide the result by 0.1 to get the real distance would be annoying

sleek thicket
#

in my case i had an anti-gravity char controller with a spring, so at least here i can confidently say it wouldn't matter to me

vestal minnow
#

what would the vector even be called, velocity_with_max_toi?

sleek thicket
#

does it really matter? it's easy to document as direction * speed

vestal minnow
#

but also max_toi

sleek thicket
#

a line.

vestal minnow
#

a line segment

sleek thicket
#

a vector representing a line segment, where 0 is the origin.

vestal minnow
#

velocity doesn't imply that the ray ever stops

indigo scarab
#

Hello peeps,
Is there a way to have a 2D physics sim, but then ouput positions on (x,z) axes instead of (x,y) axes? To better suit a top down game.
Probably related to altering SyncPlugin somehow.

sleek thicket
#

yeah, velocity is confusing

#

direction implies being normalized

#

speed doesn't really imply that it's the end

vestal minnow
#

if it's a line segment, it's no longer a ray

#

so it's a linecast

sleek thicket
#

linecast is between 2 points though

vestal minnow
#

which is a line segment

#

origin and whatever the end point is

sleek thicket
#

i can't think of any real use case for infinite rays in a game at least

#

and anything that isn't infinite is a line by that definition

sleek thicket
indigo scarab
#

Yessir

sleek thicket
#

🤔 coordinate problems stike again

#

i think it'd be easier to just change the 3d perspective, should be more comfortable to have Z-up

indigo scarab
#

totally, but I'm not comfortable with Z-up 🤮

sleek thicket
#

it makes more sense than -Z forward though 😂

indigo scarab
#

As the saying goes, y to sky. Not z to the sky

sleek thicket
#

never heard of that but i like it

#

i don't particularly like Z pointing out of my ass though

#

you didn't get any bugs with Z being reversed yet?

indigo scarab
#

I haven't started. What do you mean z is reversed?

sleek thicket
indigo scarab
#

I can cope with that. That chart is really funny, Unreal is sticking it out there by itself.

vestal minnow
#

Swapping translation coords is relatively easy but rotation is more of a pain

#

oh @indigo scarab are you using bevy_xpbd_2d?

#

in that case it'd be easy I think

indigo scarab
#

yes i am

vestal minnow
#

alr I'll test it real quick

vestal minnow
indigo scarab
#

estimated time: 2 seconds
actual time: errrrr

sleek thicket
vestal minnow
#

I think it's working? This is a horrible demo, but the camera is looking down towards the XZ plane and the cubes are only moving in XY directions physics-wise

#

and they bump into a wall but I just didn't position things logically so it looks weird

#

and the cubes can be offset in the Y plane which is like the Z depth in 2D

#

I'll post code in a bit, will just clean it up a little

sleek thicket
#

is it for any coordinate system or just an option for XY->XZ?

vestal minnow
#

XY->XZ but it's easy to make generic I think

sleek thicket
#

might be useful to make it generic considering how many people came out speaking for different systems

vestal minnow
#

or not generic as in some arbitrary [0.1, 0.5, 0.3] axis but on the XYZ axes

vestal minnow
#

@indigo scarab

Here is a plugin for the top-down physics thing. Haven't tested much, so idk how well it actually works. I can try more tomorrow if it has issues

Annoyingly, I think it's necessary to replace the entire SyncPlugin because too many things in it are private. I might make more of them public so that you'd only need to replace specific systems

#

you can just copy that file somewhere

#

and then configure plugins like

.add_plugins((
    DefaultPlugins,
    PhysicsPlugins::default().build().disable::<SyncPlugin>(),
    TopDownSyncPlugin::default(),
))
#

the actual changed parts are in position_to_transform lines 502-512

#

that just swaps y and z around for translation and handles conversion from Rotation to Quat differently (rotate around Y instead of Z)

#

could easily change the axes too

indigo scarab
#

Thank you so much

tacit hinge
#

Is with_max_time_of_impact framerate dependent? It appears to be acting differently on my 165Hz monitor than on my 60Hz one.

royal helm
#

everything is frame rate dependent on variable timing instead of fixed timestep

#

but overall it shouldn't have massive differences

#

unless you mean differences of objects in the simulation itself over time

tacit hinge
#

My shapecast is acting weird on my 165Hz monitor. It's detecting the ground at odd times, when that doesn't happen on my 60Hz monitor.

pub(super) fn update_grounded(
    mut commands: Commands,
    query: Query<(Entity, &ShapeHits), Without<Grounded>>,
) {
    for (entity, hits) in query.iter() {
        // If the ShapeCaster detects a ground hit, the entity is grounded
        if !hits.is_empty() {
            commands.entity(entity).insert(Grounded);
        }
    }
}
#
ground_shapecaster: ShapeCaster::new(
    // Shapecaster should be slightly smaller than the
    // player, to prevent colliding when hugging a wall.
    Collider::cuboid(1.9, 1.9),
    Vec2::ZERO,
    0.0,
    Vec2::NEG_Y,
)
// Max distance it will travel to detect the ground
.with_max_time_of_impact(0.05),
winter pebble
#

Is there some plugin to draw 2d colliders for debug?

sleek thicket
winter pebble
#

I see, thanks

winter pebble
#

Hello, what is a good way to convert a vector of trianlges to a trimesh?

#

Do I need to care about duplicate vertices, or can I just slap TriMeshFlags::MERGE_DUPLICATE_VERTICES and don't care about it?

winter pebble
#

Automatic collider generator: mostly done

winter pebble
#

I wish physics debug options had some sort of "collider fill color" so I can see what's inside and what's outside the tri-mesh

cinder summit
#

@vestal minnow Is this change detection prevention for 3D rotations really correct?
https://github.com/Jondolf/bevy_xpbd/blob/main/src/plugins/integrator.rs#L229-L233
I'm getting Changed<Rotation> every frame despite having every axis locked and all code that modifies it disabled. If Quat::IDENTITY was the "no rotation" value, wouldn't that (rot.0 + delta).normalize() always drift you back to the default rotation, since + is not how you apply rotation and all 🤔

vestal minnow
vestal minnow
wraith aspen
#

how do i check if a RigidBody::Dynamic is touching the ground?

cinder summit
#

Usual solution would be checking what it touches and seeing if anything it touches has a normal that could be considered up

#

Alternatively you could specifically mark the ground and see if it's touching that, or shapecasting down to see if it's close enough to the ground

wraith aspen
#

also, for an unrelated issue, how do i do raycasting?

cinder summit
#

There's two approaches, you could spawn a RayCaster/ShapeCaster component which will do a ray/shapecast each frame and update the component with the results, or you can use the SpatialQuery system param to do raycasts/shapecasts on demand

vestal minnow
wraith aspen
#

component seems easier

#

wait its not working how i thought it would

#

i thought it would tell me if theres something inside the collider

tawny comet
#

Tried to search for this answer but not sure I'm using the right keywords... Is it possible to prevent a collider from inheriting a sprite's rotation? (I'm trying to animate the player with a tween , but I want the capsule to remain vertical)

cinder summit
#

Making the sprite a child of the collider is the usual approach I think

tawny comet
#

Ahh that makes sense lol, ty!

wraith aspen
#

Is it possible to make it so when 2 dynamic rigidbodies collide they despawn?

fiery mortar
#

I'm getting motion blur when moving my player with velocity instead of transform (camera follow)

fiery mortar
#

the player itself looks fine but other objects are blurry when it moves

fiery mortar
wraith aspen
#

thanks

fiery mortar
#

you'll have to filter based on what components you want to actually disappear

wraith aspen
#

i know, the hard part is finding a cool explosion effect

vestal minnow
#

I'm not that invested in quaternion math but I think checking delta.w != 0.0 is enough? Since it's the angle around a rotation axis

#

it seems to work at least

#

and logging the quat, it's always [0, 0, 0, 0] when the rotation shouldn't change

#

the math is kinda confusing anyways since idk what adding quats with + even semantically means

cinder summit
#

I think w is supposed to be some magnitude of the rotation or something like that ... But I'm not really sure on the specifics either, I always ask in off-topic and @plain lion explains how it works 🙃

vestal minnow
#

ya it's the angle around some axis I belive

#

or probably not mathematically, but for rotation quaternions it's an intuitive-ish way to think about it

#

(and how Unity describes it)

plain lion
#

gonna be honest - my entire understanding of quaternions is based on multiplication being composition
i have not put in the time to understand any other part of quaternions 🙃

cinder summit
vestal minnow
#

I've mentioned quaternions to several people with CS degrees and they hadn't even heard of them before

#

apparently uni doesn't talk about them

#

or not CS degrees but some engineering degrees

#

I had a math book that mentioned their existence in some tiny aside tho

lavish laurel
#

Does anyone that had classes on quats remember what course they took for them? Only thing I skipped was phys with calculus, is it like abstract algebra or some other physics class that teaches them?

shell ermine
#

I thought linear algebra but I don't remember

merry tide
#

Sorry for being lazy, I have done so much tonight. And it is a Sunday. Is there an example of doing hit-testing for 2D with a camera projection? As in, just clicking the screen to select an object?

warm agate
#

Are there any benchmarks comparing bevy_rapier to bevy_xpbd for large-scale collision handling?

cinder summit
vestal minnow
#

If you need data like the exact point where the cursor is intersecting, you can instead use spatial_query.project_point()

#

bevy_mod_picking is also great for this stuff if checking hits against meshes is enough

#

(it's primarily 3D but I think 2D works too?)

merry tide
#

BTW, my game is up, using xpbd.

#

I was wanting to make an advent-thing, but it is really hard making interesting levels.

#

So I am working on the level editor, so I need to punch that through the camera.

merry tide
#

I guess I want to cast a ray from the camera given the coordinates I got after converting, into the world, right?

#

Sorry, I didn't mean to be badgering you guys, but I got this far:

#

But the transform to the ray_hits just turns out like jibberish in my mind.

wraith aspen
#

How do I check if the player is inside a specific Collider? (the player is a RigidBody::Dynamic and the collider is just a Collider and a TransformBundle without a RigidBody)

vestal minnow
#

The code example in the docs uses bevy_xpbd_3d but it's basically the same in 2D

#

Raycasting might not make sense here because you probably want to just check a specific 2D point and not cast an actual ray in some direction

vestal minnow
#

Or if you don't know the specific collider's entity but it has some marker component, you can iterate through CollidingEntities and check if collider_query.contains(entity)

#

There's also a Collisions resource where you can access all collisions and/or collision pairs

tacit hinge
#

So, if with_max_time_of_impact is framerate dependent, should I multiply it's argument by Time.delta_seconds?

merry tide
#

Can I just run a piece of code by you guys, because it feels a little off. It does work, I am just curious if I am doing something wrong. Is this "the right way" do check for collisions? It feels like using contains is not very effective, but it is just a feeling. This code is trying to see if the player entity collides with a crystal entity. And it works both in app and on WASM.

vestal minnow
#

this will count all collisions, not just the ones that started, but since you're despawning the crystals I don't think it matters much

merry tide
#

OK, but you are still leaning on contains. It is just my reptilian OO-brain that gets into fight/flight when I see that, because it looks like an O(n) thing.

vestal minnow
#

yes but a lot less contains

#

and query.contains(entity) is O(1) just like query.get(entity)

#

because it's not just iterating a vec

merry tide
#

Ah, perfect. Exactly what I wanted to hear, thanks again.

vestal minnow
#

It doesn't explicitly mention contains, but looking at the code, it's essentially sugar for query.get(entity).is_ok() (but with some unsafe for performance)

#

so it's O(1) like get

merry tide
merry tide
#

I have a problem that isn't necessarily xpbd-related, but I am asking you first because I like you more. And also, you know my situation. I got the selection stuff to work and also the moving-part, but I cannot seem to understand how to make it relate to the camera transform. It looks like this.

#

And I am already taking the camera transform into account, but perhaps not correctly.

#

The "whoops" is TimBeaudet, I was watching his stream.

vestal minnow
#

Are you snapping the rectangle position to the cursor position or doing some interpolation?

merry tide
#

No, this is just super simple translating deltas from the mouse to objects.

#

I can mess with the values to make it overshoot and undershoot, but ideally it would just be correct screen-space translated to the physics world.

vestal minnow
#

You could even have a resource like MousePos and a system that updates it so that you don't have to handle the camera stuff in every system that needs the position

merry tide
#

That sounds good. I am all for making it more streamlined, but I feel I just need to get a bunch of stuff to work first.

#

Can I share that code, tho? It isn't super much.

vestal minnow
#

Translating by mouse deltas seems like it could cause problems in some cases, at least I think I had similar issues in some web dev stuff but I don't remember

merry tide
#

I just need to flip branches. And that means I need to also flip the version of the Rust compiler. 🙂

#

It is just this:

pub fn move_selected_entity(
    camera_query: Query<&mut Transform, (With<Camera2d>, Without<LevelObject>)>,    
    mut entity_transform_query: Query<(Entity, &mut Transform), With<LevelObject>>,
    ui_state: Res<UiState>,
    mut motion_event_reader: EventReader<MouseMotion>,
) {
    if ui_state.dragging {
        let camera_transform = camera_query.single();

        // Iterate the selected entities
        for (entity, mut transform) in entity_transform_query.iter_mut() {
            // Check to see if this is the selected entity
            if ui_state.selected_entity == Some(entity) {
                // Iterate the motion events
                for ev in motion_event_reader.read() {
                    // Move the entity
                    transform.translation.x += ev.delta.x * (camera_transform.scale.x / 2.);
                    transform.translation.y -= ev.delta.y * (camera_transform.scale.y / 2.);
                }
            }                        
        }       
    }
}
#

And me dividing it by 2. is just an act of desperation, really. 🙂 I tried all of it.

#

But you see, I am getting better at splitting the systems up.

vestal minnow
#

so that wouldn't work in a super simple way

merry tide
#

No, but given how you can select and go into dragging, you would think that the translation in X/Y would be a relatively simple function of the camera projection.

#

If I just do this transform.translation.x += ev.delta.x * camera_transform.scale.x; it overshoots by a bit all the time, no matter the zoom level.

vestal minnow
#

camera_transform.scale is probably 1 so it's not actually doing anything there

merry tide
#

Ah, cool. I am not alone in this cold winterscape.

#

Let me know if you figure it out. I am going to try a little on my own, but I am going to look at something else. Because I cannot even get the asset server to work on WASM.

merry tide
pulsar bone
merry tide
#

This makes me very uncertain. Is the EventReader not deterministic?

pulsar bone
#

It is, but you need to mark events as read by reading them or clearing them. You're not reading the events when you're not dragging

merry tide
#

It seems like it is a math problem. Because it consistently moves stuff too much or too little.

pulsar bone
#

Won't solve your problem entirely
I know

merry tide
#

Sorry, I am not being a Negative Nelly. I am just trying to say that it is odd that what I consider "everyday things" are often a little more difficult that I thought. 🙂

#

But when you know them it is all simple and the waveform collapses into pure consciousness.

#

Then again, a lot of the things I envision as almost unreachable are done in a couple of lines of code.

vestal minnow
#

ah this #engine-dev message

pulsar bone
#

Bevy doesn't yet have a convenient method for converting vectors from viewport to world space(only positions) but it's possible to hack around it.

pub fn move_selected_entity(
    camera_query: Query<(&Camera, &GlobalTransform), (With<Camera2d>, Without<LevelObject>)>,    
    mut entity_transform_query: Query<(Entity, &mut Transform), With<LevelObject>>,
    ui_state: Res<UiState>,
    mut motion_event_reader: EventReader<MouseMotion>,
) {
    if ui_state.dragging {
        let (camera, camera_transform) = camera_query.single();
        
        // Remove the translation component from the camera transform
        let mut affine = camera_transform.affine();
        affine.translation = Vec3A::ZERO;
        let camera_transform = affine.into();

        // Iterate the selected entities
        for (entity, mut transform) in entity_transform_query.iter_mut() {
            // Check to see if this is the selected entity
            if ui_state.selected_entity == Some(entity) {
                // Iterate the motion events
                for ev in motion_event_reader.read() {
                    // Convert viewport vector to world space vector
                    let Some(world_space_delta) = camera.viewport_to_world_2d(&camera_transform, ev.delta) else {
                        return;
                    };
                    
                    // Move the entity
                    transform.translation += world_space_delta.extend(0.);
                }
            }                        
        }       
    }
    motion_event_reader.clear();
}

I've done this before but haven't tested this code here c:

pulsar bone
vestal minnow
#

ahh yeah the world space conversion is different for delta vector vs. position, makes sense

merry tide
#

Ah, sorry, I forgot to watch history. 🙂

vestal minnow
#

the camera transform in the above code doesn't quite work right it seems

#

the world_space_delta is always down and to the left even if camera_transform and ev.delta are zero/default

#

so idk if camera also requires some modification or smth

#

hhhh I figured that out but now the original issue of overshooting is back

#

and @pulsar bone it required this btw

let Some(world_space_delta) = camera.viewport_to_world_2d(
                    &GlobalTransform::from(Transform::from_translation(
                        camera.logical_viewport_size().unwrap().extend(0.0)
                            * 0.5
                            * Vec3::new(1.0, -1.0, 0.0),
                    )),
                    ev.delta,
                ) else {
                    return;
                };
#

wow that formatting

#

or wait no that's kinda wrong

#

@pulsar bone this

let mut affine = camera_transform.affine();
affine.translation = Vec3A::from(
    camera.logical_viewport_size().unwrap().extend(0.0) * Vec3::new(0.5, -0.5, 0.5),
);
let camera_transform = affine.into();
#

the camera transform needs to have the viewport center coordinates apparently, but with y reversed

#

it makes the thing mostly work, but the original overshooting isn't fixed

#

and I don't think it's entirely related to the camera anyway like I originally suggested

#

If you move the mouse slowly, the platform moves faster in relation to the mouse, but with fast movements the mouse can skip ahead

#

I had similar issues with web drag APIs at some point

#

with event.movementX/event.movementY I think

#

or velocity, I don't remember

#

I was making some board-based notataking app with draggable cards iirc and they were moving at the wrong speed

#

probably a different issue tho

merry tide
#

But is it me being a dumbass, or might it be somewhere else?

vestal minnow
#

I have the same issue so idk

pulsar bone
#

Oof, you're right. It's like MouseMotion itself is buggered when you move the mouse quicly

kindred charm
#

Is there any way to rotate the collider of an entity without also rotating it's sprite, other than making the collider a child of the entity?

vestal minnow
#

you could use Collider::compound(vec![(position, rotation, collider)]) but idk if that's ideal

kindred charm
#

Yeah that sounds worse than having to deal with Parent/Children components in the query 😄

vestal minnow
#

seems like a weird oversight if it is a bug though

#

maybe there should be a mouse input example with dragging or something

pulsar bone
#

Might be good to track the issue on our side as well though

vestal minnow
#

yeah, maybe make a winit issue + a Bevy issue that links to it with S-Blocked

pulsar bone
#

Sounds good c:

pulsar bone
#

Now this should actually work ™️
@merry tide

pulsar bone
#

(updated: now handles cursor leaving the window properly betterer)

#

@vestal minnow ^ In case you're interested.

vestal minnow
#

ya I was trying to make something similar but didn't bother to finish it lol

#

cool if it works

merry tide
#

Or right now.

brisk bay
merry tide
#

I think it is solid, let me test @pulsar bone thing first. But it should be simpler, perhaps?

pulsar bone
#

(Why the hell would you call it "enhance pointer precision" Windows? :V)

merry tide
#

Wait, what. Are we finding something simpler?

pulsar bone
#

Nope. It's just that the MouseMotion event is not bugged.

#

There's just no guarantee it matches the cursor movement, which makes sense thinking about it now

#

I guess we need CursorMotion events 😔

vestal minnow
#

I like that there's "mouse", "cursor" and "pointer" which are all subtly different but can also mean the same thing

peak timber
#

Hey, is there a way to make a regular polygon collider?

#

And/or create a collider from a Mesh

#

I'm creating a Mesh::from(shape::RegularPolygon { sides, radius }) for my 2d game and I need a collider for it, basically

#

It looks like there's features for this, but only for 3d?

#

I don't see why it wouldn't also work in 2d

peak timber
#

I copy pasted the code and it seems to work fine, so it should be possible to implement for 2d as well. Might be a bit harder from a library perspective though

#

Maybe I can contribute a PR sometime for this

vestal minnow
#

As for regular polygon colliders, I think we could easily just add that as a built-in collider type

#

It's not built-in to Parry, but we could use custom shapes to support it since the support map (used by collision detection algorithms) for regular polygons is very simple

merry tide
#

I had a pretty good day yesterday, I had a bunch of people from Microsoft playing my game.

vestal minnow
#

Not yet in 2D, but we could maybe do it for trimeshes

merry tide
#

And Ryan Reynolds and Taylor Kitsch liked my comment.

#

Ah, OK, cool.

vestal minnow
merry tide
vestal minnow
#

Yes

merry tide
#

OK, so this is going to make no sense unless I take you back in time a little. But see this.

#

But a couple of years ago I made a joke that would really work in a Deadpool-movie.

#

This is the comment. 😄

#

I pitched it years ago on Twitter or whatever.

#

But the likes seem to be actual accounts.

vestal minnow
#

if they're real accounts then that's really cool

merry tide
#

This is almost as good as Reuben Bond from Microsoft working to set a time in Ponkatris.

#

And he did that yesterday.

#

I already have players from Microsoft playing the game, shaving off time introduced because the backend is in Microsoft Orleans.

#

We'll see when the movie comes out. God damn, I hope they do it.

#

But I think it is simple to see my issue with making new levels all the time.

#

The help I got will be super helpful, tho.

vestal minnow
merry tide
peak timber
#

My 2d shapes keep exploding apart randomly

glossy bloom
#

I've been trying to solve this for longer that I'd like to admit... Is there any way to force collider translations (i.e. manually changing Position) to take effect for the purpose of spatial queries while Time<Physics> is paused? For some context, I'm using raycasts for a 3d ship editor sort of thing, but would rather keep the physics paused in the background.

#

Just checking that I haven't missed something obvious

vestal minnow
#

Does spatial_query.update_pipeline() help?

#

Probably won't update child colliders though because that requires transform propagation

glossy bloom
#

That worked perfectly, thanks 🙂 There's no child colliders in the editor setup, just a few static colliders that I move around depending on which layer of a grid should be editable

zinc talon
#

Is there a built-in way to get the velocity at a specific point on a rigid body? Meaning factoring in angular velocity

vestal minnow
#

no but it's pretty easy

#

2D or 3D?

vestal minnow
zinc talon
#

I guess the information for that is split across components

vestal minnow
#

yeah if they were under Velocity component then you could have a helper

zinc talon
#

So not sure how you'd add that as a function somewhere... you could do AngularVelocity::velocity_at_point(&self, Vec3)

#

Then just add that to linear

vestal minnow
#

Originally I felt like separate components are more ECS-like, and it'd also make it possible to have e.g. particles without rotational properties like angular velocity, but I'm open to combining them under Velocity if people prefer that

zinc talon
#

I was just thinking about that

#

Kinda reminds me of when Transform was originally Translation, Rotation, and Scale

#

Which was maybe a good idea in theory, but less usable in practice

#

That's not to say it's the exact same problem, tbh I find the way it works in bevy xpbd to be fine

vestal minnow
#

Yeah I'll have to think about the API more, grouping things like linear/angular velocity and different mass properties would make some nicer APIs possible and also help with docs

#

The main cons are that it technically reduces parallelizability and not all entities need e.g. angular velocity, but in practise the difference is negligible

tacit hinge
#

I'm trying to work my way through understanding the code in the 2D kinematic character example's kinematic_controller_collisions function. This (https://github.com/Jondolf/bevy_xpbd/blob/7bc9883251cf9a2a60776ebddf63ba38f5fef96b/crates/bevy_xpbd_2d/examples/kinematic_character_2d/plugin.rs#L297C2-L297C2) part in particular is tripping me up a bit:

// Get the rigid body entities of the colliders (colliders could be children)
let Ok([collider_parent1, collider_parent2]) =
    collider_parents.get_many([contacts.entity1, contacts.entity2])
else {
    continue;
};

What does it mean by "colliders could be children." I'm assuming that's why we're using the entity ID's from the ColliderParents instead of just using contacts.entity1 and 2 directly.

GitHub

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

vestal minnow
#

I think originally the code was different and doing this was more important but it's probably rare for character controllers to have child colliders

tacit hinge
#

Okay, that makes sense. Thank you.

I had another question about it. For this line (https://github.com/Jondolf/bevy_xpbd/blob/7bc9883251cf9a2a60776ebddf63ba38f5fef96b/crates/bevy_xpbd_2d/examples/kinematic_character_2d/plugin.rs#L319), why does the rigid body being kinematic need to be verified? Wouldn't it always be kinematic if it's on an entity with a CharacterController?

GitHub

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

vestal minnow
#

IIRC the code mostly works for both kinematic and dynamic rigid bodies, so nothing stops you from making a CharacterControllerBundle with a dynamic body. There's also a dynamic version of that example in the repo

If there happened to be a CharacterController on a dynamic body, it could cause duplicate collisions

#

but you don't need to verify if you already know it's kinematic ofc

#

also fyi, the character controller examples are definitely not production-ready and have some issues, for a proper controller I recommend bevy_tnua

#

mostly they just showcase how to handle some common things like basic input and grounded checks

tacit hinge
#

Does bevy_tnua have a kinematic body example? I could only find dynamic ones.

vestal minnow
#

only dynamic yeah

tacit hinge
#

Ah okay. Well, I'm only having trouble with the collision part anyway. In that case, are the examples here fine?

vestal minnow
#

It should be fine for most things yeah

tacit hinge
#

That's some beautiful jankiness right there. I might try fixing it if I ever get a grasp on collisions.

vestal minnow
#

It's mostly because the kinematic body is treated like it has infinite mass, so in general it can't get pushed by anything

#

So if the cube gets pushed to clip the ground, it can't push the player up, so it's just stuck there getting pushed further to some point

#

until the player moves away

tacit hinge
#

Interesting. Is there any way to allow dynamic rigid bodies to push back against the player?

#

I wonder how Godot's KinematicBody deals with this, or if they even do.

vestal minnow
#

The collision code kinda does that but not very well

#

I believe character controllers usually use raycasts or shapecasts for collisions instead of actual colliders

#

and try to maintain a small margin (extra space) between the character and its environment

#

it's mostly for numerical stability though

#

for example when walking over two cubes, you shouldn't hit the edge between them

tacit hinge
#

Oh, so have the player hover just a bit?

vestal minnow
#

yeah

tacit hinge
vestal minnow
carmine sluice
# merry tide This is the comment. 😄

Remarks that violate the community standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner).

Mod hat: This is both off-topic and in violation of the rules. Don't do it again.

merry tide
# pulsar bone

I just tried this and it also seems to have the same issue for me. Hm.

light vessel
#

You solving all my problems with this idea ty

junior flower
#

Eyyy glad to be of help 😄

royal helm
#

I'm running into some weirdness with different tick rates

#

128 hz with 1 velocity will move faster than a 32hz one

#

which shouldn't be happening

#

the higher the hz the faster the speed

vestal minnow
#

there was an issue with that but I thought I fixed it

royal helm
#

lemme try updating then

vestal minnow
#

are you running in PostUpdate or somewhere else?

royal helm
#

FixedUpdate with

        let tick_hz = 300.0;
        app.insert_resource(Time::<Fixed>::from_hz(tick_hz))
            .insert_resource(Time::<Physics>::new_with(Physics::fixed_once_hz(tick_hz)));
vestal minnow
vestal minnow
#

but 300.0 Hz for Time<Fixed>

royal helm
#

still seem to have the issue on 0.3.2, I'll check

#

yeah that seems to work but that's a bit weird

#

at least, it is moving at the same rate as I modify the Time::<Physics> hz

#

but I'd expect the opposite here

royal helm
#

hmm

#

works in the latest main

vestal minnow
#

huh

royal helm
#

I think that'd be the issue then

#

makes sense to me at least

#

I was adding the Time::<Physics> before I added the plugin

#

so it was probably overwriting my fixed hz with the default

#

ya, works perfectly now 🙂

tacit hinge
#

And the reason you can with Update is because the frame is being rendered while the object is simaltaneously moved out of the colliding object?

vestal minnow
# tacit hinge Just to clarify, does `SubstepSchedule` run before the next frame is rendered, s...

I believe rendering runs independently of app scheduling in a separate SubApp.

SubstepSchedule runs in a loop in PhysicsSchedule which by default runs in PostUpdate.

Collision detection and the solver are run in the substepping loop, so if you instead run in Update (or elsewhere outside SubstepSchedule), you wont handle all collisions, which can cause jitteriness like what you experienced. There could be other factors that contribute to it too though

tacit hinge
#

Dang, that's much more confusing than I assumed.

vestal minnow
#

Physics engines typically use iterative solvers to be able to handle multiple simultaneous collisions or other interactions in a stable way. This just means running some parts of physics multiple times a frame

#

and substepping is a form of this iteration

#

which the SubstepSchedule handles

tacit hinge
#

Does bevy_xpbd have physics interpolation, or something similar, so physics running at a lower framerate than the monitor won't look choppy?

verbal cloud
tacit hinge
#

I suppose a more apt question would be, how does bevy_xpbd keep the physics looking smooth at high framerates?

vestal minnow
# tacit hinge Does bevy_xpbd have physics interpolation, or something similar, so physics runn...

There's a 3rd party plugin for this but it requires using separate entities for the rendered mesh and the actual physics object
https://github.com/rubengrim/bevy_xpbd_interp

GitHub

A simple library for interpolation of bevy_xpbd rigidbodies - GitHub - rubengrim/bevy_xpbd_interp: A simple library for interpolation of bevy_xpbd rigidbodies

vestal minnow
#

Note that this might impact performance a bit because it's running physics more frequently. You can lower SubstepCount to gain back some performance, but lower values can make the simulation a bit less accurate

tacit hinge
#

Thank you!

final dove
#

I went the lazy way and set the physics time step to variable

vestal minnow
#

yeah that works too, just makes it frame rate dependent

royal helm
#

I don't love variable because it isn't great for networking or consistency

#

physics will also more likely explode with variable

#

e.g. if you move a window it'll stutter the program

#

and if you don't have a good cap on it then it'll explode because the delta is high

final dove
#

You can set a cap with xpbd and luckily my game isn't very focused on physics so it should be fine for me

tacit hinge
vestal minnow
#

hopefully yes

#

not entirely sure how it'd work though, haven't looked into it much yet

#

ideally it would Just Work™ with some setting without requiring separate entity shenanigans

#

I believe it should be possible though, especially because there are separate physics Position and Rotation components that can work independently of visual Transforms

#

just need to keep it possible for users to also use Transforms directly for most physics stuff

tacit hinge
#

Awesome 🙂

merry tide
#

BTW, I solved that problem I had with moving the objects with the mouse by converting to world space and tracking the deltas. If anyone is interested in that code, I am happy to share it. But it is strange that it was hard to just use the mouse deltas as some function of the camera transform. I feel the code I ended up with so far is a little clunky, Sorry, again a little off-topic, but might be relevant to some previous discussion.

vestal minnow
#

Working on an ECS-ified joint and constraint rework, going pretty smoothly 👀

Joints are split into components like ConstraintEntities, JointDamping, JointAnchors, and then the actual joint type like DistanceJoint. Previously, each joint stored all of this in its own massive struct that contained several properties that are only important for outside usage.

This required a bunch of annoying trait methods and impls, and some systems had to include generics like joint_damping::<DistanceJoint>. With the new component approach, none of that is required and everything is much more reusable and composable! In the future we should also be able to neatly add e.g. joint motors, joint breakage and so on via components without having to handle each joint separately.

API-wise, it might even look nicer and more Bevy-like than the old one that required builders (because the actual struct was massive):

// Before
commands.spawn(
    DistanceJoint::new(entity1, entity2)
        .with_local_anchor_1(Vec2::NEG_Y)
        .with_local_anchor_2(Vec2::ONE)
        .with_rest_length(1.5)
        .with_limits(0.75, 2.5),
);

// After (WIP)
commands.spawn(JointBundle {
    entities: [entity1, entity2].into(),
    joint: DistanceJoint::new(1.5).limits(0.75, 2.5),
    anchors: JointAnchors::new(Vec2::NEG_Y, Vec2::ONE),
    ..default()
});
#

This also removes a ton of constraint code duplication that has been haunting me for a while

#

Need to update docs and examples but otherwise PR should be ready soon

#

Also I've locally implemented collision disabling for joints (#274), it basically requires this component approach because otherwise we'd have to run the same system separately for each joint type (because generics were previously needed) and iterate over collisions an unnecessary amount

untold summit
#

I am spawning a SceneBundle with a scale of 0.2. This has a children entity with a ball collider. The issue is that, on spawn, the collider is enormous, probably because it does not get the scale. You can view it in the debugger, and also because it also causes collisions. Then, after a frame, it properly resizes and works as intended. Am I doing something wrong?

merry tide
#

How would I do something like this for the colliders?

#

Disregard the code at the bottom, it is just "for fun", but it seems to change the scale for a frame or something, then it reverts.

#

Is there anything like the sprite-code to do something like this?

#

Should I grab it back as a Shape and set a new one?

fair fractal
#

Hi, I'm curious about the broadphase collision detection optomizations in bevy_xbpd. Do you use a bounding volume hierarchy like rapier does? I think parry provides some utilities for it, but from what I understand, the responsibility still lies on the developer to implement the details, and I'm wondering if those broadphase collision sweeps are implemented into bexy_xbpd like they are for rapier

vestal minnow
cinder summit
#

Any idea why it doesn't use a BVH anymore? I think bepu uses a BVH so I can't imagine it's a slow approach

vestal minnow
vestal minnow
cinder summit
#

I mean I guess I can kind of see that when you have a broken bvh thonk

vestal minnow
#

yeah 😂

junior flower
#

I don't have much to compare it against, but I was honestly surprised just how fast bevy_xpbd's SAP is

vestal minnow
#

yeah based on tracy I think it barely takes any frame time in most cases

#

solver is mostly the issue

#
  • the large amount of query.get_many(...)
cinder summit
#

Depends a bit on your usecase too. Having 10k entities that don't overlap doesn't run super great, but if you have less entities but they're all touching it won't be the bottleneck

#

Biggest optimization that could be done would be if the things looking for collisions are only the non-sleeping dynamic/kinematic bodies and sensors. Chances are if you have 10k entities that don't touch they're all asleep

vestal minnow
junior flower
#

Yeah, once they start overlapping a lot even the broadphase starts to crawl. The early out when X has passed over the limit is doing a lot of the heavy lifting until things start overlapping

merry tide
#

Are there any examples of changing the collider size? I have a version that compiles and runs here, but "nothing happens". This is the basic code:

if let Some(cuboid) = cuboid_shape {
    info!("Cuboid");
    let new_shape = SharedShape::cuboid(
        cuboid.half_extents.x + 100.0,
        cuboid.half_extents.y,
    );                                                                       
    collider.set_shape(new_shape);
} else {
    info!("Not a cuboid");
} 
vestal minnow
merry tide
vestal minnow
#

Yeah, that's a bug then, set_shape should just work; I'll try to fix this later today

merry tide
#

Great, thanks for the quick reply!

devout sail
#

Couple questions wrt sensors:

  1. Is there a way to filter shapecasts to ignore sensor collisions? From what I see I could filter by the sensor entity, but I don't have access to that at that point.
    I tried filtering out according to the hit entity if it has a sensor attached, but that then removed every shape hit. Are sensors attached to more things than I expect them to be on?

  2. Is there a reason why colliders made from TriMesh or ConvexHull asyncscenecolliders seem to show up in a query like: Query<&ColliderParent, Without<Sensor>>? Directly creating the collider by hand seems to work as I'd expect.

vestal minnow
# devout sail Couple questions wrt sensors: 1. Is there a way to filter shapecasts to ignore s...
  1. Not yet, but I can try to add flags for this like the ones in Rapier's query filters. You could add some sensor collision layer for the sensors and filter by that for now. Sensors are only on entities you add them to.

  2. Bevy scenes loaded from e.g. glTFs create multiple entities, each with their own meshes and transforms. AsyncSceneCollider creates colliders for these entities, but doesn't attach any other configuration by default. If you have a Sensor on the root/parent entity, it only applies to that entity, not the child entities.

AsyncSceneCollider has some options for specifying the layers or densities of the spawned entities, but no such option for "sensorness" yet. I could add that if it'd be useful? Ideally, we'd have something like bevy_scene_hook built into Bevy for this though

devout sail
#

I see, thanks for the fast reply!
For 2: Just to make sure, the children created are attached to the same parent? So if the mesh creates two children, they both have a collider on their own, but their ColliderParent would still be the same? I.e. it would be possible to iterate over the collision children and add a sensor if the parent has one?

vestal minnow
devout sail
#

Perfect, I think that'll work for my case then. scene hook would indeed be the cleanest way though.
Though if there were a way to pass arbitrary components that should be attached to every child made through asyncscenecollider that'd also work very well.

#

Not sure if that'd make much sense tho in a general

vestal minnow
#

I think arbitrary components would require us to wrap it in a Box or something since it needs to be stored in AsyncSceneCollider and the size and type is unknown

#

could be viable though

#

idk I might test if that works, I'm not a huge fan of the current approach that we use

vestal minnow
#

(once CI compiles and I hit merge)

merry tide
#

Just to be clear, this isn't supposed to work in 0.3.2, right?

vestal minnow
fiery mortar
#

Does xpbd have a collider similar to Rapier's heightfield?

fiery mortar
merry tide
#

I like asking before I read the docs. You make more frenemies that way.

#

Also, I think I might be able to contribute to docs in the future. But I still feel like that toddler in that movie 2001.

#

Sorry, wrong channel!

lavish orbit
#

hey, I want to make a fluid simulation that interacts with xpbd, short term I will just make fluids that flow over colliders, but long term I also want the interaction the other way around (like drag inside a fluid), if anyone has any advice (specifically for the long term goal) let me know!

vestal minnow
#

My response was way too thorough for what the issue was made for 🙈 I felt kinda bad after lol

#

got nerd sniped real hard

cinder summit
vestal minnow
#

Yeah 😂 I knew the person who made the issue didn't require anything super thorough and broad like that, but for an issue titled "Fluid Simulation" I felt like I needed to give some proper answer that covers different approaches, first steps, etc., mainly for people wanting to see if we support fluid sim

cinder summit
last panther
#

@vestal minnow btw the fixed grid thing (in your gh link) definitely isn't an issue
it might be somewhat a problem on the GPU but a basic hashmap of grids would be able to fix it

#

also I'm implementing a bevy gpu sph fluid sim although it's a bit opiniated

vestal minnow
#

Ooh that sounds exciting 👀

#

hmm, I'll see if I can find the fixed grid thing

#

I think it was specifically FLIP

#

but I'd expect a hashmap to work yeah

last panther
#

there's also things like SPGrid
although I think that's eulerian?

#

and whatever complex magic taichi does

vestal minnow
#

taichi?

#

tai chi is a martial art lol

last panther
vestal minnow
#

ah, looks pretty cool

#

one-billion-particle MPM, whoa

last panther
#

Also:
Getting SPH to not randomly just explode is surprisingly hard

#

although it's kinda neat how you can just like
randomly staple one pressure solver to a surface tension by another person and viscosity bu a third author and it generally works

#

and then you touch it wrong and it explodes

vestal minnow
# last panther <@545959292281552928> btw the fixed grid thing (in your gh link) definitely isn...

I think I got the fixed grid thing from this
https://youtu.be/i4KWiq3guRU?si=IAQgdAw2gk0aETGo&t=70

❤️ Check out Weights & Biases and sign up for a free demo here: https://www.wandb.com/papers

The shown blog post is available here:
https://www.wandb.com/articles/visualize-lightgbm-performance-in-one-line-of-code

📝 The paper "Fast Fluid Simulations with Sparse Volumes on the GPU" and some code samples are available here:

▶ Play video
#

the vid shows FLIP sim clips

#

but maybe the sparse approach is algorithm agnostic, idk

last panther
#

its basically algorithm agnostic

#

there's no reason you can't just splat a hashmap onto it

vestal minnow
#

yeah

#

Excited to see your sim in action though if/when you release it

#

Running on GPU is also really cool, I'd like to try some GPU stuff eventually

#

maybe something like NVIDIA's FleX 🤔

#

Although particles for rigid bodies is annoying, but maybe they could still be modeled as "normal" rigid bodies somehow

last panther
#

@vestal minnow you don't need to simulate the rigid bodies using particles
just like put particles on the edges
but if you wnat it to be easily parallelizable using gpu you kinda need some sort of discretization. I guess you could use voxels but eh

vestal minnow
#

yeah the particles are mostly for GPU parallelization

#

(plus unified solver)

prime shadow
#

@vestal minnow If I was going to create a moving platform where my character is kinematic

#

could I keep my moving platform static

#

and then change the position of it

#

then I would of course do things to find the players riding it

#

so they follow it correctly

#

but would I be breaking anything by directly changing the position

#

(I ask this because in Rapier you can't but upon some light testing it seems to work?)

vestal minnow
prime shadow
#

Wouldnt I have to handle the collisions for it then?

vestal minnow
#

Kinematic bodies affect dynamic bodies normally but they themselves aren't affected by collisions by default. The same thing is true for static bodies

#

Kinematic bodies are basically just static bodies that can move and have velocity

#

And semantically, static bodies aren't meant to move, but for now you could do it if you wanted to (idk if we could later do some optimisations by disallowing it tho)

#

So I'm not sure what the difference would be if you were to use a kinematic body instead

prime shadow
#

I see okay

#

ill use a kinematic

vestal minnow
#

Alright 👍 and again you can use static if you want to but I think kinematic just feels more "correct" for a moving platform

prime shadow
#

got it working

#

pretty nice

dull violet
#

how would i query for one face of a 3d mesh containing the entire face of another 3d mesh? i see the Aabb.contains method but i'm missing how to get the bounding boxes for individual mesh faces

dull violet
dull violet
#

would it make sense to add a AsyncSceneCollider::from_collider method so non computed colliders can be added to scenes? i was able to copy the system for computed colliders but perhaps it should be added to the api? i was thinking of adding a scene collider enum with computed and non-computed

prime shadow
#

I am writing a ground checker and I can get it to find the ground

#

but it does not detect walls at all

#

Why is this exactly?

vestal minnow
prime shadow
#

Yes I am

vestal minnow
#

So you're trying to cast a shape at a wall but it's not returning any hits?

prime shadow
#

well I was trying to reuse my ground shapecast

#

to also check for walls

vestal minnow
#

Yeah but does it cast the shape at the wall and not directly downwards like for ground checks

prime shadow
vestal minnow
#

Huh, why's the arrow there 🤔

prime shadow
#

I am not sure why

#

my small block on the right is kinematic

#

the ground is static

vestal minnow
#

I'll try to make a super quick repro of this

prime shadow
#

want me to send what I have?

vestal minnow
#

Yeah that'd be nice

vestal minnow
# prime shadow

Can your character jump? I think the issue could actually be that the shapecaster only gets the closest hit by default, and when it's hitting both the ground and the wall, it just always chooses the ground

#

for ShapeCaster, you can use with_max_hits to allow more hits

#

it's 1 by default because shapecasts can be quite expensive with many hits and I'm not sure what a sane default would otherwise be

prime shadow
#

Oooh I see that makes sense

#

I think 1 is probably sane for a default

#

I think what got me is that in the example for the character it’s looping and one thinks it probably has more then one in the data structure lol

#

thank you

vestal minnow
#

ah yeah

#

np

prime shadow
#

What about the arrow thing

vestal minnow
#

It's correct when the shape isn't intersecting at the origin (i.e. the time of impact is greater than zero), but I'm not sure why that is yet

#

maybe parry doesn't compute the hit points properly for the origin intersection case

#

or maybe the debug rendering logic just does something weird, I'll test

vestal minnow
# dull violet would it make sense to add a `AsyncSceneCollider::from_collider` method so non c...

Do you mean that you could manually specify the collider used for meshes in a scene instead of always computing it from the mesh automatically?

Something like this:

// Every mesh in the scene will have a cuboid collider
AsyncSceneCollider::from_collider(Collider::cuboid(1.0, 1.0))

// Every mesh in the scene will have an automatically computed
// trimesh collider except the "Statue" mesh that has a cuboid
AsyncSceneCollider::new(Some(ComputedCollider::TriMesh))
    .with_collider("Statue", Collider::cuboid(1.0, 2.5))
prime shadow
#

So adding with_max_hits

#

didnt seem to help

#
ShapeHits { vector: 
[ShapeHitData { entity: 2v0, time_of_impact: 0.0, point1: Vec2(400.0, -45.0), point2: Vec2(15.347168, 133.99568), normal1: Vec2(-0.0, 1.0), normal2: Vec2(0.0, -1.0) }, ShapeHitData { entity: 1v0, time_of_impact: 0.0, point1: Vec2(0.0, -200.0), point2: Vec2(-384.65283, -21.004318), normal1: Vec2(-0.0, 1.0), normal2: Vec2(0.0, -1.0) }
], 
count: 2 
}
#

It seems to have the wall in its shapehits

#

but the normal is very wrong

dull violet
prime shadow
#

When I get in the corner I can get the normal to be: [-0.000008588889, -1]

prime shadow
#

I suppose this could be happening because the the impact on the y-axis occurs first?

#

yeah something must be wrong

#

I know my ShapeHits has two items in it like I showed in the last screenshot

#

I suppose the issue is that the direction is going downwards

prime shadow
#

Hm the ShapeCaster its self needs some work

#

One issue is that if I wanted to run multiple casts

#

I am unable to atm because I would need to create a new entity

wraith oriole
#

can't you use child entities for that

prime shadow
#

shape_intersections() might actually be better

#

for what I need

sleek lance
#

Is it possible to turn off collision for a collider in bevy_xpbd, like turning off visibility for a sprite? Without just removing it from the entity?

vestal minnow
sleek lance
vestal minnow
prime shadow
#

@vestal minnow For two way platforms I was thinking of using sensors

#

however I noticed you had an example of them in the 2d_examples

#

however you say that your example is not "robust"

#

what other methods could you think of doing two way platforms

#

there are sensors

#

maybe using some ColliderDisabled component when that gets added

vestal minnow
#

@prime shadow I didn't make that example, so I'm not entirely sure why it wouldn't be robust. I can't think of a nicer approach right now, maybe there are existing tutorials or other resources somewhere?

Sensors or ColliderDisabled wouldn't really work since it'd allow everything to pass through when the collider is in a pass-through state, not just the player

#

Also ColliderDisabled wouldn't work because you need to detect when the player exits the platform's collider

coarse locust
#

Hi, why the little flag in the video bounces and flies away?

// flag
Collider::convex_hull(vec![
    Vec2::new(-0.5, 0.) * size,
    Vec2::new(0.5, 0.) * size,
    Vec2::new(0.5, 1.) * size,
    Vec2::new(-0.5, 1.) * size,
])
.unwrap(),
RigidBody::Dynamic,
Friction {
    dynamic_coefficient: 0.5,
    static_coefficient: 0.5,
    ..Default::default()
},
Mass(100.),

// the ground
collider.insert((
    Collider::cuboid(aabb.width(), aabb.height()),
    RigidBody::Static,
));
if let Some(coe) = physics.frictions.as_ref().and_then(|f| f.get(&i)) {
    collider.insert(Friction {
        dynamic_coefficient: *coe,
        static_coefficient: *coe,
        ..Default::default()
    });
}
#

and the gravity: ```rust
Gravity(Vec2::new(0., -98.))

vestal minnow
#

Hmm, it looks like the flag is initially going through the ground and detects the collision super late

#

Maybe try with the flag as a Collider::cuboid? Just to see if that works

vestal minnow
#

That's really weird

fiery mortar
#

Is there a way to get global space normal from a shapecast hit instead of local. I'm trying to get kinematic bodies to slide against other colliders but the rotation of the entity makes the normal wrong

vestal minnow
# coarse locust

Could you insert the PhysicsDebugConfig::all() resource so that it shows all debug info including AABBs?

coarse locust
vestal minnow
fiery mortar
#

I dont this there a way to get components from entity ids

coarse locust
vestal minnow
# fiery mortar But i would need a way to get the collider that was hits rotation

I think you can also get the negated version of the normal on the shape that you're casting

// Or if you're using ShapeCaster, you'd just query ShapeHits
let hit = spatial_query.cast_shape(&shape, pos, rot, ...).unwrap();
let global_normal = rot * -hit.normal2;

Not entirely sure if this will always match the normal on the collider that was hit, but I'm pretty sure it should.

To get the rotation of the collider that was hit, you can just have another query in your system

fn my_system(q: Query<&Transform, With<Collider>>, spatial: SpatialQuery) {
    // ...
    let transform = q.get(hit.entity).unwrap();
}
vestal minnow
#

My guess would be mass or scale related somehow

#

But it's weird that it's just going through the ground for a couple of frames

#

Does it detect the collision at the initial ground intersection even though it does nothing? Could check e.g. CollidingEntities for that

#

or print Collision events

#

and maybe lower gravity to make it slower

coarse locust
vestal minnow
#

Could you see if you can make a minimal reproduction? I have no idea why it wouldn't detect the collision in that case

#

unless there's some negative scaling or something, haven't tested that though

coarse locust
vestal minnow
#

Ah yeah this is bevy_entitiles, I can try it in a bit

#

thanks

coarse locust
#

cargo run --example ldtk --features="debug serializing physics_xpbd" in the dev branch btw

#

In serializing/ldtk/layers.rs at line 196, I instantiated the colliders for grounds and walls.

coarse locust
prime shadow
#

Have rays that sit only one the two way platform layer and make the player go off the two way platforms layer when they need to ignore the platform

peak timber
#

(mb, posted in wrong channel)

fiery mortar
#

Is there a way to make kinematic bodies behave sort of like dynamic bodies when it comes to interacting with other other kinematic bodies and static bodies? At the moment there are no physics interactions between kinematic bodies and between kinematic and static bodies. I the kinematic bodies to slide off walls and other bodies while not being affected by external forces.

#

A kinematic body would just go through instead

vestal minnow
#

Just make sure to add the system to the SubstepSchedule as shown in the example

#

@fiery mortar Re books: I haven't read books on physics engines but I've heard that this is decent
https://www.amazon.com/gp/product/0123819768/ref=as_li_ss_tl?ie=UTF8&linkCode=sl1&tag=haroldserrano-20&linkId=56751a95680e54b77828297329e548d9&language=en_US
And for collision detection, this is the most popular and comprehensive one afaik
https://www.amazon.com/gp/product/1558607323/ref=as_li_ss_tl?ie=UTF8&psc=1&linkCode=sl1&tag=haroldserrano-20&linkId=e775edabb16bb41e92f9d6559301fb55&language=en_US
There are good online resources too though, Erin Catto (author of Box2D) has a lot of good slides

fiery mortar
vestal minnow
#

For XPBD specifically, I started with Johan Helsing's tutorial and continued with the XPBD papers and taking reference from other engines

junior flower
# prime shadow however you say that your example is not "robust"

Is this about https://github.com/Jondolf/bevy_xpbd/blob/main/crates/bevy_xpbd_2d/examples/one_way_platform_2d.rs ?

If so, one issue with that example is if you have a bunch of boxes in a line to form a floor, it can fall through because of I assume float inaccuracies: when going from one collider to the following one, it sometimes detects that you hit it sideways instead of from the top so it cancels the collision. You can get around that by merging the colliders into one long wide one.

GitHub

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

#

That behaviour improved with one of the latest versions of xpbd, so it’s possible that it’s been completely resolved by changes in the underlying engine. If so, it may be good enough as-is.

I’m using the example code as-is in a relatively simple run-and-gun platformer but have always been merging colliders so I’m not sure whether it’s still an issue or not, tbh

lean sable
#

This project is so cool, any idea on how much work is needed to get joint motors working?

vestal minnow
prime shadow
sleek lance
# vestal minnow Yeah I think that's a good example of a use case where a `ColliderDisabled` comp...

Hi, I hope you're having a nice holiday if you celebrate. I tried using collision layers and something weird is happening: In the below code, it never asks for collision_layers to be mutable (I had it all marked mutable before removing it to show), and it doesn't seem to have any effect when running. Any idea what's going on? I'm very new, so I'm sure I just missed something obvious. Thanks and cheers!

pub fn collision_damage(
    p_query: Query<(Entity, &CollidingEntities, &DamageEffect, &DespawnsOnCollision, &CollisionLayers), With<Projectile>>,
    mut despawn_event_writer: EventWriter<Despawn>,         // despawn the projectile
    mut damage_event_writer: EventWriter<Damage>,           // and apply its damage effect to the other entity.
) {
    for (
        projectile,
        colliding_entities,
        damage_effect,
        DespawnsOnCollision(despawns),
        collision_layers
    ) in p_query.iter() {
        if !colliding_entities.is_empty() {
            // deactivate the collider on the projectile
            collision_layers.remove_group(Layer::Projectile);
            collision_layers.add_group(Layer::Inactive);

            // if the projectile despawns on collision, mark it for despawn
            if *despawns {
                despawn_event_writer.send(Despawn(projectile));
            }

            // trigger the damage event on the colliding entities
            for entity in colliding_entities.iter() {
                damage_event_writer.send(Damage { entity: *entity, damage_effect: *damage_effect });
            }
        }
    }
}
pulsar bone
#

This is a very unfortunate combo of add_group taking self by value and the type being Copy.

*collision_layers = collision_layers
    .remove_group(Layer::Projectile)
    .add_group(Layer::Inactive);

This is how you need to use the API, but you'll also need to change the query to ask for &mut CollisionLayers and use iter_mut instead

#

@vestal minnow I'd recommend marking these methods on CollisionLayers as #[must_use]

sleek lance
#

Ah thanks! I'm not sure I really understand how it happens but is it that it is just silently copying it and then adding/removing on the copy?

#

With that change it works, thanks!

vestal minnow
#

But then I believe the methods would need to return a &mut, which means you can't use them when initially creating the component unless you move it onto a separate line

#

i.e. you wouldn't be able to do this

commands.spawn((
    // ...
    CollisionLayers::default().add_group(...),
));
#

I suppose there could be a with_group when initializing and an add_group when mutably adding layers later

sleek lance
vestal minnow
vestal minnow
#

but with_children takes a closure with a builder

sleek lance
#

By the way, I think just using an "inactive" collision layer was a perfectly fine solution for "disabling" a collider, so I'm not sure it's really worth adding another way. Thanks for the suggestion! And the crate 🙂

peak marsh
#

This might be one of those obscure Nix errors, but anyone know why this is happening:

       >     Checking bevy_xpbd_2d v0.3.2 (https://github.com/Jondolf/bevy_xpbd.git#db224138)
       > error: couldn't read /nix/store/zg2avqgns1hl5hmjmgyb0jn3bdcdskf0-vendor-cargo-deps/583744e0486b5f34e5bf97e225074f254339834801fd96c4fa627719ab14eb1d/bevy_xpbd_2d-0.3.2/../../src/lib.rs: No such file or directory (os error 2)

The error only happens on bevy_xpbd_2d's check, but not in the others for some reason.

peak marsh
#

Alright, I can now reproduce the issue in a non-Nix environment. It looks like that bevy_xpbd's workspace relative paths breaks when you use cargo vendor. To reproduce:

  1. Run cargo vendor in a project that depends on bevy_xpbd (I'm using the git dependency, not sure if it matters)
  2. Follow the instructions in the end of the output and modify your .cargo/config.toml accordingly
  3. Run cargo check
    The check will fail on bevy_xpbd with errors like these:
error[E0433]: failed to resolve: use of undeclared crate or module `bevy_mod_picking`
 --> /home/$USER/Documents/rust/bevy/rope_test/vendor/bevy_xpbd_2d/../../src/pointer.rs:3:5
  |
3 | use bevy_mod_picking::{
  |     ^^^^^^^^^^^^^^^^ use of undeclared crate or module `bevy_mod_picking`

error[E0433]: failed to resolve: use of undeclared crate or module `bevy_mod_picking`
  --> /home/$USER/Documents/rust/bevy/rope_test/vendor/bevy_xpbd_2d/../../src/retro.rs:14:5
   |
14 | use bevy_mod_picking::{picking_core::PickSet, pointer::InputMove};
   |     ^^^^^^^^^^^^^^^^ use of undeclared crate or module `bevy_mod_picking`

(truncated)

#

I'm (optimistically) guessing that this is not a cargo bug, but I'm not sure how you'd fix this.

#

Never mind, it looks like I'm not reading the output correctly 🤔. It looks like it's a lot more broken that I thought.

merry tide
#

Hey, guys! I am messing around with a small level in my game, and I am seeing upping the substeps makes it make sensible. What's a good substepcount? I added it to 30 without it fixing my issues, but upping it to 130 seems to make it consistent. Does 130 substeps mean that it does 130 times as much processing?

vestal minnow
merry tide
#

I can show you quickly, I already made a video.

#

Well, I am about to with the parameters I am talking about.

vestal minnow
#

130 substeps means that it runs integration (moving bodies based on velocity and forces), narrow phase collision detection, and the solver (collision response etc.) 130 times per physics frame. Some things like broad phase collision detection (a "rough" collision check for optimization) are still run just once per frame

#

but yeah, having more substeps corresponds to more processing

merry tide
#

This is without substeps at all. You can see the ball running over the things and leaving some of them behind.

#

at 12 seconds.

#

And it seems super odd, I am probably doing something wrong here, because the collision object is over it for multiple frames.

#

And again at 50 seconds-ish.

vestal minnow
#

Yeah the one at 12 seconds is very odd, it should definitely be colliding with it based on the video

merry tide
#

But I have something here I can reproduce, let me make a video with 30 substeps.

#

There is something seriously wrong here, it must be in my code.

vestal minnow
#

How are you despawning them on collision?

merry tide
#

Well, this is my crystal despawner:

pub fn crystal_despawner(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    players: Query<&Player>,
    crystals: Query<&Crystal>,
    last_crystals: Query<&LastCrystal>,
    mut ev_collision: EventReader<CollisionStarted>,
    mut ev_crystal_collected: EventWriter<CrystalCollected>,
    score: ResMut<Score>,
    audio_state: Res<AudioState>,
    crystal_count: Res<CrystalCount>,
) {
    for CollisionStarted(e1, e2) in ev_collision.read() {
        let (_player, crystal) = if players.contains(*e1) && crystals.contains(*e2) {
            (*e1, *e2)
        } else if players.contains(*e2) && crystals.contains(*e1) {
            (*e2, *e1)
        } else {
            return;
        };

        let mut play_audio = false;

        if last_crystals.contains(crystal) {
            if score.0 == crystal_count.0 - 1 {
                info!("Last crystal collected!");
                commands.entity(crystal).despawn();
                play_audio = true;
                ev_crystal_collected.send(CrystalCollected);
            } 
            info!("Last crystal!");
        } else {
            info!("Normal crystal!");
            commands.entity(crystal).despawn();
            ev_crystal_collected.send(CrystalCollected);
            play_audio = true;
        }

        if play_audio == true && audio_state.play_sound_effects == true {
            info!("Playing crystal capture sound");
            // Play sound
            commands.spawn(AudioBundle {
                source: audio_state.pickup.clone().into(),
                ..default()
            });
        }
    }
}
#

Sorry, all the code is messy. I am a noob still and will be for another year or so.

vestal minnow
#

The code looks fine based on a quick look, not sure what's going wrong here

#

I guess it could be some weird edge case where CollisionStarted doesn't always fire

merry tide
#

Well, if it is helpful, it is simple to reproduce in this codebase.

vestal minnow
#

yeah

merry tide
#

Would you want to look at it? I think you already have access to the repo, I have been yapping here constantly for 5 months now. 🙂

#

And thanks for indulging me.

#

I have it running on web also, I can make it reproducible there also, I think.

#

But it feels like it should be working without substeps, right?

merry tide
#

Also, having two crystal accidentally stacked in the same place should be OK?

#

I am not trying to remake pacman, it is a test level.

vestal minnow
merry tide
pulsar bone
#

I noticed CollisionStarted and CollisionEnded are separate events. This could be problematic if it's possible to get both events for the same entities in one frame.

vestal minnow
#

They're sent based on whether a collision is/was marked as active in the Collisions resource

#

I feel like the event logic is currently unnecessarily complex though so I'd like to clean it up eventually

peak timber
#

It appears that when you add RigidBody or Collider to a component, it updates the Transform, even if the SyncPlugin is disabled..

#

Is there any way around this?

vestal minnow
#

I'm on mobile rn so it's hard to read the code

peak timber
#

How would it know when it should change it or not?

#

I guess it could check the SyncConfig values, but that's in a different plugin

#

This definitely seems like the place

#

I tried just disabling PreparePlugin but it panics 😅

#

fwiw I sort of worked around it by adding a Collider::cuboid(0.0, 0.0, 0.0) but of course I get a flood of warnings since they're all in the same position (I'm trying to integrate big_space so they're all technically at 0, 0, 0)

#

Since it only checks if Added<Collider> not on startup

vestal minnow
peak timber
#

so I might be able to just initialize the Position relative to the origin before the physics systems run to fix the warnings and get them positioned correctly

#

I can definitely tell mixing floating origin and xpbd is going to be a frustrating process :P