#Avian Physics
1 messages Β· Page 12 of 1
by rewriting i mean barry, just switching nalgebra to glam and bevy math
Reading parry's code does hurt actually π
and yeah i have to agree there
I wasn't even born yet π
I saw Bevy 0.13 has some collision detection built in now??
yes-ish but actually no
Not really collision detection but bounding volumes yea
primitive shapes kinda have some methods like in parry from what i understand
bounding volumes and intersection tests and ray casts against them
not many
almost none
The only one I can think of is getting the aabb 
I guess for primative shaped colliders, collision detection isn't that difficult
it's difficult.
it kinda is unless you do just ball-ball collisions
It is actually ... Torus - Torus is nightmare fuel π
Sphere - Any shape is simple however ... As long as the signed distance function and gradients are known for that shape
being a rust noob shouldn't prevent reading/understanding parry code, but it's difficult.
If we flip this around ... "Rust knowledge is irrelevant when trying to understand parry code"
||yeah because you wouldn't understand it anyway||
Honestly you're better of with geometry knowledge than rust knowledge when trying to understand anything collisions anyway ... Especially if there's not a lot of docs
Also I feel like the biggest help for bevy_xpbd optimization might actually be pinpointing the biggest bottlenecks
I guess there are two things: Are two convex objects touching(not too hard), by how much are they touching(much harder).
well for 1 you need gjk already for a lot of shapes
3: Is a convex object touching a concave object (extremely hard); 4: is a concave object touching a concave object (afaik this is not something you can solve in a general way)
My thought is that you'd break down any non-convex shapes into simpler primatives. Then use some bounding box to avoid testing everything against everything.
contact_manifolds is what physics would typically use
yeah this is convex decomposition
which is how you build more complex shapes
unless you're using trimeshes
or SDFs :P
The most fun part is that you need all of these collisions to function under unreasonable constraints like: It needs to support thousands of entities on a single core at 3GHz
either way, let me repeat myself
if @trail sparrow wants to try then it's a good start even if it's just rays/boxes/balls vs balls/boxes
Watch as someone actually gives me torus gradients and I'll be struggling with this for weeks
Oh no
BOOM
Because I didn't want to find it π
It's someone that publishes a lot of info about shape related stuff
Especially involving raymarching and raytracing
"Painting with Maths" is all about using mathematics with purely artistic goals within the medium of computer graphics. We'll be designing expressions and deriving formulas for things like dolphins, elephants and landscapes. If you like math, computer graphics, shaders, rendering or fractals, but want to peek into the world of art, this channel ...
I'm gonna spend some time on his YouTube today rather than rewriting parry
wait that's the same guy who made the snail image and that Greek temple
I've seen them but never knew it was him
No one should be rewriting parry anyway ... Only @vestal minnow would start such insanity π
I also based my sphere intersection code on iq's articles π
a new SDF convert acquired
Briefly looking at the code it looks like what I'd expect... I would think we just need to improve the performance?
no
What's wrong with Parry?
switch from nalgebra to bevy math and glam
The real thing we need to improve the performance on is probably the part around where bevy_xpbd uses parry
except Qbvh is wack
Tho parry has a few major flaws: The QBVH doesn't like updating ... And there's a lot of dynamic dispatch ... Which I think we can technically work around π€
and the codebase has questionable characteristics like 500+ warnings or errors
But then the code where bevy_xpbd uses parry does a ton of unnecessary allocs, stores things multiple times, probably doesn't have some very basic early out logic, etc ... And it's also ran every substep π
Seems my role here is to kick the hornets nest lol
I have the core of that migration to bevy_math done in my fork already
no, really
^
It was just primitives left right? Which is the more challenging part because it changes the representations ...
yeah that, and fix some potential bugs I caused
@trail sparrow if you start a new library and just handle the basic stuff you can understand, it'll probably already be useful for simpler games
at least inertia is a bit wrong
But yea I'm pretty sure that the quickstart guide to optimizing bevy_xpbd looks like this:
- Create a game where a lot of collisions happen
- Figure out the thing that takes the most frametime
- Fix that thing
this isn't necessarily hard, just a huge pain
about half-done
You mean like a library that supports collisions between spheres/capsules and any arbitrary shape?
^
Ah so you want boxes ... Yea my sdf collisions don't support those yet
we kinda have that with the bounding stuff already
Maybe soon 
except not oriented boxes
and no contact data π
If only spherecasts against AABBs, OBBs and benchmarks so we can do that Vec3A thing
also box-box is very complex already
mhm
Parry uses some kind of SAT, support mapping, point projection and more for it
and closest points stuff (although it's just segment-segment which doesn't require gjk)
The GilbertβJohnsonβKeerthi distance algorithm is a method of determining the minimum distance between two convex sets, first published by Elmer G. Gilbert, Daniel W. Johnson, and S. Sathiya Keerthi in 1988. Unlike many other distance algorithms, it does not require that the geometry data be stored in any specific format, but instead relies sol...
I wish algorithms would be named something more related to their ideas than the authors...
EPA is, it's the "Expanding Polytope Algrorithm"... you just need to know what that means
it's used for computing penetration depth and normals after GJK
(for penetrating contacts)
So, back to the start of this conversation... does parry need to be replaced, reworked or used differently to improve XPBD performance?
Is there a non-ocean burning approach?
for performance specifically, mainly used differently, but there are other unrelated bottlenecks too
but bevy_xpbd does need glam-based collision detection instead of parry if we ever want to upstream official physics
parry is a bottleneck for updates
You mean to become bevy's physics engine?
because we don't want nalgebra in Bevy's dependency tree
You already did that work in a fork though?
not necessarily bevy_xpbd, but whatever physics engine Bevy adopts officially as bevy_physics some day in the future
needs glam-based collision detection
is there anyone else working on native bevy physics though?
yes, but it's not done yet by any means
not really
but it might not be called bevy_xpbd
there's nise but that's more of a fork/extension of xpbd from what i understand
nise uses normal xpbd
Yea, I don't do physics just collisions
yes
so yeah, there's no competition for official bevy physics
Can I just drop that into bevy_xpbd?
By the time bevy is ready for a bevy_physics, bevy_xpbd won't use xpbd anymore anyway with how things are going 
not really, because it has some broken things and might depend on some things I only have locally atm
Gotcha
Well, I was gonna suggest we could all help push barry forward
Maybe could start by making a private repo or something with issues for the major tasks to be accomplished.
I also have bevy_peck which is a very very very WIP collision detection library made from scratch
Support using Bevy's threadpool instead of rayon to unblock threads when using Bevy
wait, parry blocks threads?
that might not be a thing anymore
but iirc rayon used separate threads while bevy used its own task pools
I think they can share now?
not sure
The what now
It normalizes the vector, returning the original length, but returns an error if the length is below the given threshold (new_and_length threshold is just 0 iirc)
A wrapper that ensures the underlying algebraic entity has a unit norm.
but for Bevy's direction types
Parry uses it in e.g. gjk
for safety reasons
wait, it normalizes but returns the original length?
yeah because that's often valuable
the new length would just be 1 :P
it's
let vec = Vec3::X * 2.0;
// In method
let length = vec.length();
let normalized = vec / length;
return (normalized, length);
pub fn try_new_and_get(mut value: T, min_norm: T::Norm) -> Option<(Self, T::Norm)>
where
T::Norm: RealField,
{
let sq_norm = value.norm_squared();
if sq_norm > min_norm.clone() * min_norm {
let n = sq_norm.simd_sqrt();
value.unscale_mut(n.clone());
Some((Unit { value }, n))
} else {
None
}
}
yeah
that's the actual optimized version with the threshold but the idea is the same
is Norm same as Direction3d?
it's a mathematical term
In mathematics, a norm is a function from a real or complex vector space to the non-negative real numbers that behaves in certain ways like the distance from the origin: it commutes with scaling, obeys a form of the triangle inequality, and is zero only at the origin. In particular, the Euclidean distance in a Euclidean space is defined by a nor...
well, i'm not a mathematician so it still doesn't makes sense π₯΄
yeah
specifically, it's the Euclidean norm in this context
but Nalgebra supports complex numbers and stuff too
how does a vector get negative though, doesn't it just flip direction?
or is that not a vector
what are you referring to as a vector
wait, norm is just a positive float?
yes here it's just the length of the vector
pub fn try_new_and_get(mut value: vec3, min_length: f32) -> Option<(Self, f32)>
{
let sq_length = value.length_squared();
if sq_length > min_length.clone() * min_length {
let length = sq_length.sqrt();
value.unscale_mut(length.clone());
Some((Direction3d { value }, length))
} else {
None
}
}
vec.length() is the same as vec.length_squared().sqrt()
so it splits it up to early out if possible
yeah the generic nature of this makes it hard to read
but the length of e.g. a 3D vector mathematically is either:
i mean, i gotta give credit to sebcrozet for coming up with this stuff
but i like simplicity ._.
The length of a vector is
|v| = sqrt(dot(v, v))
which in 3D becomes
|v| = sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
so the sqrt can be split out
hey, i remember that from middle school math
this is for a generic matrix, so it just iterates over the columns (which are essentially vectors) and adds up the squared lengths (or norms)
so ultimately it's pretty simple
a Vector3 is just a single column, i.e. a 3x1 matrix
so it becomes the same as this
this, yes
or no
pub fn dot(self, rhs: Self) -> f32 {
(self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
}
pub fn length_squared(self) -> f32 {
self.dot(self)
}
glam doesn't simd?
it compiles to different code on different architectures, that's just the "basic" rust version intended to be readable
I think this is what the simd version is
/// Calculates the vector 3 dot product and returns answer in x lane of f32x4.
#[inline(always)]
pub(crate) fn dot3_in_x(lhs: f32x4, rhs: f32x4) -> f32x4 {
let x2_y2_z2_w2 = lhs * rhs;
let y2_0_0_0 = simd_swizzle!(x2_y2_z2_w2, [1, 0, 0, 0]);
let z2_0_0_0 = simd_swizzle!(x2_y2_z2_w2, [2, 0, 0, 0]);
let x2y2_0_0_0 = x2_y2_z2_w2 + y2_0_0_0;
x2y2_0_0_0 + z2_0_0_0
}
intrinsics are horrible to read
it's pretty simple when it's not buried behind arcane types and function names
Gotta say, I'm not a fan of the word swizzle even if it's meaningful here.
I can say that it gets a lot worse
Just the word... sounds dirty in a not fun way
lol
But I'm reading about it now and looks like it's a legit industry term
yep
I cannot wait to be finished with this game I'm working on. I've played it too much while debugging it and I wanna play the "lets make a new game" game. π
I hope you'll all play it if you have iPhones though
why iphone
Just what I'm focusing on developing for atm
glam uses different intrinsics for different platforms, with Tera templates, like here's a part of matrix transpose
I don't have an iPhone sadly
Nice clean code
Android?
yeah
i had an iphone for a couple months, never got used to it and went back to android
I wanna port to Android, but I also want to run away from this game atm.
fyi this is probably getting a bit off-topic for a bevy_xpbd crate-help channel π
So I'll drop it in the App store and put up a couple YT videos of gameplay. bevy_xpbd is a huge part of the gameplay though, so I'll be mentioning you and others in the credits
fair π€
nice job tying this back to bevy_xpbd lol
and thanks β€οΈ
lol ofc
Imagine you credit bevy_xpbd nicely, when suddenly NVIDIA be like: π
Erin Catto has now implemented XPBD, so if NVIDIA found it to be an issue and for some reason came after him, they'd indirectly be harming Box2D and therefore Unity 
Isn't that just for Solver2d which is more of a research thing?
Ah yes ... Libraries and games in bevy are just π§ͺ
I need to take enough elements from the TGS soft solver and other solvers into XPBD to make it a novel approach
How possible is it to combine them?
I like that "no velocity" penetration solving from NGS, and TGS soft seems a lot more stable
But then for distance constraints you want XPBD π€
On the Ten Minute Physics Discord Erin was discussing XPBD stuff with others, and someone managed to use a block solver for joints to make them more stable
And you could maybe somehow take the "soft" constraint part
i.e. formulate spring-like damping into the constraints
also solving e.g. x and y for joints separately unlike the XPBD paper can be more stable
based on some test
But yea definitely could be interesting to combine some approaches to make a library that has exactly the properties you'd want in a game engine
SPBD = Soft Position-Based Dynamics
We need Signed Distance Based Dynamics 
SDFBD
yeah lmao
constraints as SDFs...
I guess in a way, constraint functions could be seen as SDFs already
and equality constraints minimize the distance by moving opposite to the gradient
(of course that's not really an SDF tho)
Minimizing error by moving based on gradients ... Is this ... Machine learning? 
GPTBD coming soonβ’
Gradient descent into madness 
It solves 1 collision per minute, with about 20% accuracy. 50% of the time the collisions are halucinated
Why use a physics engine at all? Just generate a continuous video stream of the simulation with AI
Player inputs change the neural network's input parameters
Latency of a few seconds, but I'm sure that's fine
also iq is so well known that the Wikipedia article on SDFs mentions him
Maybe your game will get popular enough to get listed as an example of using SDFs 
I took a robotics control systems class in college... I'll see if I have my textbook, but this stuff is all very much in that domain
@vestal minnow , I'm noticing bevy_hanabi seems to interfere with the debugging visualization plugin
how?
I'm trying to figure it out now. But I have something like this:
if let Some(portal_effect) = &particle_effects.blue_explosion {
println!("creating force ball at: {:?} with portal", world_position);
commands.spawn((
/*
MaterialMesh2dBundle {
mesh: meshes.add(shape::Circle::new(ball_radius)).into(),
material: materials.add(ColorMaterial::from(Color::rgb(3.2, 2.3, 0.4))),
//transform: Transform::from_xyz(world_position.x, world_position.y, 1.0),
transform: Transform::from_xyz(world_position.x, world_position.y, 1.0)
.with_scale( (1. * Vec2::ONE).extend(1.)),
..default()
},
*/
ParticleEffectBundle {
effect: ParticleEffect::new(portal_effect.clone())
.with_z_layer_2d(Some(0.1)),
transform: Transform::from_xyz(world_position.x, world_position.y, 1.0)
.with_scale( (10. * Vec2::ONE).extend(1.)),
..default()
},
//*/
Collider::ball(200.),
RigidBody::Static,
Friction::new(0.0),
Restitution::new(0.0001),
ColliderDensity(1.0),
Controllable,
Sensor,
ForceBall {
start_time: time.elapsed(),
},
));
}
If I use use MaterialMesh2dBundle, the ball collider shows up and stays around, but if I use ParticleEffectBundle the ball collider is only visible for a couple frames.
Everything still works though.
0.13 supports separate gizmo config groups and bevy_xpbd has its own, so hanabi can't change that in any way
unless your version of bevy_xpbd didn't have that yet
Ah, yea that's it.
One other thing...
If I don't have a ParticleEffectBundle or a MaterialMesh2dBundle, but just a Transform, then the ball stays centered at (0,0)
Bevy needs GlobalTransform too
Ah, got it..
Thank you that works now
I enable bevy_sprite in my project and suddenly I get an extra set of gizmos? π€
What is that even drawing? π€
It's drawing all the aabbs, but from a different perspective
I wonder if it's because I have a Camera2d for kayak_ui π€
Maybe?
I think gizmos can be configured to draw to specific cameras only or something
oh my god that's horrifying XD
it used to be macros, that's better
@vestal minnow Have you ever thought about collider assets? I feel like it could be useful for hotreloading later and avoiding having duplicate mesh colliders in memory ... But idk how fast fetching the assets for every entity would be, considering the dynamic dispatch on parry I guess it already has to fetch them from meory tho π€
do you have any idea if soft bodies are part of bevy-xpbd, or how one would even begin to go about implementing them?
they are not, you could simulate soft bodies with some of the constraints in bevy_xpbd though
but depending on the amount of particles you're trying to simulate, probably not very efficiently
I'm hoping to achieve a 2d simulation of metal, being able to pound it and such as in a forge; so it definitely wouldn't be very efficient.
which constraints would you use?
I believe the term for this would be plasticity. I don't know many physics engines that support it, except NPhysics, but that was superseded by Rapier, which doesn't support soft bodies yet.
Soft bodies aren't on the short term roadmap for bevy_xpbd since there are still many other things that are more important for typical gamedev, but I do find soft bodies to be very interesting and want to try and implement them at some point.
For XPBD soft bodies in general, blackedout01 has a really nice YouTube series: https://youtu.be/MgmXJnR62uA?si=Q7yS3UsP9zrPRgqh
There are also several papers on the topic, and Matthias Muller (one of the authors of XPBD) has resources and examples at https://matthias-research.github.io/pages/tenMinutePhysics/index.html
I'm not sure how plasticity is typically handled, but one idea would be to detect when constraint forces exceed some threshold, and to permanently reduce the target distances for the corresponding distance constraints (and target volumes for volume constraints?)
I wrote a simple soft body cube in C/C++ using the extended Position-Based Dynamics method for my first devlog episode.
The mentioned papers (and a lot more)
https://matthias-research.github.io/pages/publications/publications.html
SDL Template
https://github.com/blackedout01/sdl-gl-template
0:00 Introduction
0:41 PBD overview
1:11 Game
1:25 T...
@sacred sigil ^
Yep: #1124043933886976171 message
The current blocker for it is the thing where we'd probably need to derive Reflect for Collider, but... Parry
And yeah I don't know what the cost of doing colliders.get(collider_handle) everywhere would be, but we'll just have to try
Colliders as assets could be nice API-wise with the primitives too, like you could just do
colliders.add(Circle::new(0.5))
i think for blacksmithing you wouldn't even need soft body, just deform mesh by moving verts based on force applied
or see how car crash sims work
bevy heavy nudge nudge
bevy_heavy was mostly meant to be just mass props for Bevy's primitives π
it's a good name for physics in general though
nothing can be heavy without physics
"heavy" can be interpreted as overhead, and that might not be good for physics
but physics are an overhead, maybe that's even a good thing
like who was it that tried to use physics for something that can be done with plain A*
and if everything goes well, calling rapier heavier than heavy would be satisfying
why do i sound like i'm trying to sell a rebrand lmao π
if we switch solvers then we might need a rebrand anyway
(or become solver-agnostic)
and collision lib agnostic
no idea if that's even possible though
or is it already
it is, isn't it? i just remembered nise
good morning btw.
thanks, it's already 12:30 for me tho
my brain is slow in the mornings, evenings and nights. sometimes day too.
Colliders are generic already, so you can pretty easily make custom colliders, but we can't really have a single Collider struct that would support several different collision libs
Collider representations can differ, like with Nise's SDF colliders you can just extrude and cut shapes, which doesn't really work with normal colliders
@vestal minnow on 0.4.0 with feature serialize I get this error
```^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait Deserialize<'_> is not implemented for configuration::ContactGizmoScale
it technically is, but not officially announced because irl stuff got in the way just as I was about to release posts and stuff
turns out it was enough for Nalgebra to update, although I'm not sure why it works because Parry should still be using the old version
oh
I'll make a patch 0.4.1 patch in a bit
If the version change is say 1.25 -> 1.26 that would just allow you to update it, since those should be semver compatible
Released a patch to fix this along with a few other issues
I'm annoyed that CI doesn't catch issues like this at the moment
Does CI not compile with and without serialize?
thanks
thank you for the links! those should be very helpful!
Alright, 0.4 has officially been announced: #crates message
after migrating to 0.4 all my colliders spawn at the origin when the entities they belong to don't, is it a just me issue?
changed nothing from 0.3 besides calling it sphere instead of ball
yes ::default()
added the debug plugin to see what was going on
Weird π€ At least all of the examples are working normally, like this one
Could you show an example of how you're spawning some entity?
What do you get with just something like this?
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.5).mesh().uv(32, 18)),
material: materials.add(Color::rgb(0.1, 1.0, 0.2)),
transform: Transform::from_xyz(5.0, 2.0, -1.0),
..default()
},
Collider::sphere(0.5),
));
For me it's positioned correctly
And these aren't child entities, right?
no, they are each spawned individually
ill try spawning jsut one
collider at origin still
Might be bc I use SystemSets?
Only thing is that it all worked fine in 0.12 with 0.3
Where do you spawn them? Scheduling-wise
In my loading system set that runs when entering gamestate loading
idk if it should interfer with xpbd
Does this happen in Update?
yes
then it shouldn't be an issue...
Well, here's a minimal example that should definitely work if you run this
use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;
fn main() {
App::new()
.add_plugins((
DefaultPlugins,
PhysicsPlugins::default(),
PhysicsDebugPlugin::default(),
))
.add_systems(Startup, setup)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.1).mesh().uv(32, 18)),
material: materials.add(Color::rgb(1.0, 0.75, 0.0)),
..default()
},
Collider::sphere(0.1),
));
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.5).mesh().uv(32, 18)),
material: materials.add(Color::rgb(0.1, 1.0, 0.2)),
transform: Transform::from_xyz(5.0, 2.0, -1.0),
..default()
},
Collider::sphere(0.5),
));
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 2_000_000.0,
range: 50.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(0.0, 15.0, 0.0),
..default()
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-7.0, 9.5, 15.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
should render this
Thanks π
Hmm, okay I can actually reproduce the issue π€
Rad
It is a thing where spawning in Update makes it not work for whatever reason
aha
Makes it hard for me to come up with a work around for now
maybe inserting collider post spawn?
yeah didn't change anything
it's really late for me though so I'll probably fix it tomorrow
Appreciate your help and work
Adding a RigidBody seems to fix it
You can make it kinematic or static for now
np!
I'll still fix the actual issue though, I might have found it
seems to be a scheduling thing
Makes sense
since they did change that apply deferred thing in 0.13
although we didn't have to do anything about it
I think that's unrelated here, I'm just missing a transform propagation thing for colliders without rigid bodies
aha
0.4 had a pretty big rework for how colliders are handled internally and this was just an oversight
cool
Yeah I have not looked too much under the hood on xpbd
I love how easy it is to add to a bevy project
was surprised you migrated so quickly
was planning on maybe going without it xD
Pretty cool
so I mostly needed to finish up some final things and write the announcement and migration guide once 0.13 actually released
Thanks π I appreciate it a lot :)
migrating xpbd wasn't as bad as lwim
once you set it up it's good, this update completely broke my setup though
https://github.com/Leafwing-Studios/leafwing-input-manager/blob/main/examples/action_state_resource.rs
^ this is basically the tl;dr of how to use it (after this update)
Ah
i'm not even done yet and i think i'll just go to sleep
Does 0.4 work fine for you? I.e. have you noticed regressions or did it introduce any new bugs
i fixed the last error 5 mins ago
ah alr
didn't even build it
good night, I also need to go sleep very soon
very soon means like 5 hrs ago?
okay @daring hawk I pushed a quick fix to the main branch, could you maybe try if it works with that now?
[dependencies]
bevy_xpbd_3d = { git = "https://github.com/Jondolf/bevy_xpbd", branch = "main" }
(without RigidBody on the entities)
Is there support for a point collider?
Can https://docs.rs/bevy_xpbd_2d/latest/bevy_xpbd_2d/plugins/collision/struct.Collider.html#method.polyline be used with one point? (what are the indices, anyway?)
A collider used for detecting collisions and generating contacts.
i think point_intersections is the closest thing, what are you trying to make?
I'm trying to reimplement a collider with a bullet hell style "all that matters is if the center is in the bad"
then intersection is probably fine
and makes it even easier since you won't even need to sort out collisions
Could also use a circle collider with a tiny radius
I released a 0.4.2 patch with this fix now, someone also made a GitHub issue for this issue
Then I need to special case it everywhere
This is my current approach
for a bullet hell it's probably still the way i'd do it, you only need 1 system for a single player, and player will always be an exception anyway
not if you have multiple players!
I have a question regarding the simulation of soft bodies. They are fundamentally made up of points/particles/entities, of course, but I'm not sure what to use as particles. is there some sort of bundle or other thing provided by bevy_xpbd or bevy that I could use? or if not, how would I go about creating something to use for this?
So I made a very rough soft body experiment a long time ago: #showcase message
IIRC this was simply using dynamic rigid bodies as particles, with distance constraints connecting them, and a "global volume constraint" to simulate a kind of pressure inside the ball.
Each particle was its own entity with a RigidBody::Dynamic component, and I think I just used ball colliders (there's probably a much better way to handle collisions, I just haven't looked into it much yet).
This is convenient since it Just Worksβ’ with other physics functionality, and it could be fine for a basic 2D simulation without huge amounts of particles. But for proper soft bodies, I'm unsure if using a separate entity for each particle is the ideal approach; it might be more efficient to have something more custom-made where you e.g. store all particles in an array in a SoftBody component and simulate them manually. That's a lot more work though.
But no, bevy_xpbd doesn't really have a component or bundle specifically for particles at the moment. It could be useful when we add some kind of built-in cloth or soft bodies though
Do you know if the code for that is somewhere? It would be super useful to be able to take a look at it.
Not publicly at the moment but I should have it somewhere... it's for an old version of Bevy though and very WIP and messy
I'll try to find it
thanks so much! and thanks for the response! that's super helpful!
Hmm... so the volume constraint that the example is using required some changes to the built-in solver and constraints. It needs to supports constraints for a dynamic number of entities, i.e. you can store the particle entities in a Vec, while in upstream bevy_xpbd the number is fixed, and you need to give the entity count through const generics.
But this shouldn't be an issue if you don't need a volume constraint or if you first "triangulate" (or in 3D, tetrahedralize) the soft body and use a separate area/volume constraint for each triangle/tetrahedron. This typically gives a better result anyway (like what blackedout01 later implements in the video series)
Which part of the code would you like? I could put the entire branch somewhere, but the important parts are probably the volume constraint and the actual soft body logic, would that be enough?
and yeah as I mentioned, that specific volume constraint won't really work in upstream bevy_xpbd
that would be awesome, thanks!
I'll look into triangulating then, thank you!
@sacred sigil Here's the constraint and some logic for how my soft body is initialized and updated. To create a soft body with this, you'd just add SoftBody::default(), and it'd automatically initialize it based on the mesh vertices and indices.
Again, this has lots of issues, is 3D-only, for Bevy 0.11, requires some internal modifications, and isn't very commented so I'm not sure if even I understand what's going on in some places π This was mostly a throw-away thing I made for fun
Oh and this was just in bevy_xpbd itself, so crate refers to bevy_xpbd, and there are some math types like Scalar and Vector which are just type aliases (to support f32/f64 and 2d/3d with the same code)
thank you!
In 0.3.x I could dynamically disable or enable debug rending via PhysicsDebugConfig.
How can I do it now using gizmos?
The GizmoConfig for each gizmo configuration group (in this case, PhysicsGizmos) should have an enabled field
so something like
fn disable_physics_gizmos(mut config_store: ResMut<GizmoConfigStore>) {
let mut config = config_store.config_mut::<PhysicsGizmos>().0;
config.enabled = false;
}
Ah, missed GizmoConfigStore, thanks!
Yep, the new gizmo stuff is here
https://bevyengine.org/news/bevy-0-13/#multiple-gizmo-configurations
although that last system is missing fn and the variables aren't mut 
Thank you so much for sending the code! it's been so useful!
Is it possible for you to send the code for DistanceConstraint?
I'm assuming that it's a custom constraint, as it's not part of upstream bevy_xpbd as far as I can tell. thanks!!
Isn't that just what is now called DistanceJoint? π€
btw @vestal minnow what did you decide on raycast taking ray instead of origin + direction?
Shameless plug for blog: https://joonaa.dev/blog/05/bevy-xpbd-0-4-0#direction-types-for-spatial-queries
(last paragraph in that section)
The 0.4 version of Bevy XPBD has been released!
ohh i didn't realize it's out π
Didn't do that yet, because it wouldn't work with f64 (e.g. ray casting far from origin) and I wasn't fully sure on the API yet
how about
raycast(Ray3d...
raycast_from(origin, direction...
I don't want to duplicate all ray casting and shape casting methods in SpatialQuery for that
_from would just make ray and call raycast, is that still bad?
- cast_ray
- cast_ray_from
- cast_ray_predicate
- cast_ray_predicate_from (name also doesn't make sense)
- ray_hits
- ray_hits_from
- ray_hits_callback
- ray_hits_callback_from
and same for shape casting
yes, it's pretty bad
yeah
but tbh it gets messy with 9 different ways of doing same thing anyway
Hi I get a panic with gizmos when using PhysicsDebugPlugin (no issue without it) in version 0.4.2:
assertion failed: value.is_normalized()
stack backtrace:
0: _rust_begin_unwind
1: core::panicking::panic_fmt
2: core::panicking::panic
3: bevy_math::primitives::dim3::Direction3d::new_unchecked
at /Users/[...]/bevy_math-0.13.0/src/primitives/dim3.rs:40:9
4: <bevy_gizmos::gizmos::SphereBuilder<T> as core::ops::drop::Drop>::drop
at /Users/[...]/bevy_gizmos-0.13.0/src/gizmos.rs:625:21
5: core::ptr::drop_in_place<bevy_gizmos::gizmos::SphereBuilder<bevy_xpbd_3d::plugins::debug::configuration::PhysicsGizmos>>
at /rustc/[...]/library/core/src/ptr/mod.rs:507:1
6: bevy_xpbd_3d::plugins::debug::debug_render_axes
at /Users/[...]/bevy_xpbd_3d-0.4.2/src/plugins/debug/mod.rs:206:14
Which is when drawing a spherical gizmo (in bevy_gizmos::gizmos::SphereBuilder::drop()), self.rotation * axis returns a non-normalized Vec3, which in turn means my rigid body has a weird Quat rotation.
What's happening here? π€
you're drawing gizmo yourself?
I'm on macOS and that might be related to issue #335
no
yeah it's a panic in debug mode
Direction2d::new_unchecked and Direction3d::new_unchecked have debug assertions for normalization
lots of successive rotations (or invalid quaternions) can sometimes cause the value to drift a bit
the normalization check should probably be made a bit more lenient
did it happen because object was spinning too fast?
i think rather than making normalization check lenient, stuff like this could just make a warning about it
We could also normalize in more places, but that's not ideal
yeah I guess it could warn!
you know UV stretching heatmap view in blender? something like that for debugging
for whenever editor comes out
basically "if it's not normalized, log the amount" -> editor -> denormalization log
Maybe we could have something like Nalgebra's renormalize_fast in some places
Source of the Rust file src/base/unit.rs.
most of the time it's probably not necessary
i guess it could be an option
maybe a macro within direction for the check + what to do if it fails
or not macro but feature flag
it could be run once every frame at the end of the substepping loop, which is most likely to cause numerical drift
that way it'd always be normalized for stuff like this
float drift can happen even without physics though
so something to catch it would probably be better long-term
yeah
panic when not normalized is already a bit too much, so until editor is there i think just subsequent check and report about the amount, error if it's clear that it's fubar
and after testing just how much it derails and in which scenarios you can decide between performance and accuracy
for the record I don't have objects spinning too fast but rather a hierarchy of entities with children each with their own rotations
and my game panics as soon as the physics simulation starts
then it's probably a useful catch
but not to the point of panic, yeah
direction will need a second pass because of direction3A anyway, so it'll be a good time to do all that stuff
and hopefully rename to Dir3 ._. and compass + etc from LWIM
@vestal minnow not a huge deal but it seems like only impulses from continuous contacts are being relayed by the collision events, and momentary contacts like when an object with high restitution bounces off the ground don't report any impulse. additionally, there isn't a sudden spike in impulse when an object hits the ground hard. so it seems like maybe the impulse for the first frame of contact is lost for some reason? it looks like that video you posted a few days ago is showing the same thing. do you know how i could get this info out of bounces?
for these kinds of bounces, there is actually a contact event reported, but the impulse is just 0
i actually had this same problem with rapier so i feel like it might even be intentional, but i'd still wonder how to get around it
That's most likely because the impulse in collision events is only from the last substep. That's one of the caveats with the current implementation.
It should be possible to get the impulse at each individual substep using the Collisions resource in a system running in the substepping loop, here for example:
app.add_systems(
SubstepSchedule,
handle_impulses.after(SubstepSet::StoreImpulses),
);
A resource that stores all collision pairs.
I haven't tested if it works, but in theory I think it should
ahhh i see i wouldn't have thought of that, i'll try it!
You'd query collisions like
fn handle_impulses(collisions: Res<Collisions>) {
for collision in collisions.iter() {
// ...
}
}
ok perfect, that's actually what i'm doing now but i didn't have it in the substep schedule
thanks for the help
np, let me know if it works
also, how often do substeps run?
well, what i'd like to do is accumulate the forces into a component for all the substeps of a full step
SubstepCount times within one run of the PhysicsSchedule. The delta time is Time<Substeps>::delta_seconds
The total impulse should already be in the Contacts data returned for collisions though
no way man it's working!
thanks so much this is great
by the way, i have this system
.add_systems(
PhysicsSchedule,
reset_total_forces.ambiguous_with_all(),
)
i had to set it ambiguous with all or i'd get system conflict error
1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
-- reset_total_forces and run_substep_schedule (in set Substeps)
conflict on: bevy_ecs::world::World
is there a better solution than doing ambiguous with all? i don't think run_substep_schedule is publicly exposed so i don't know how to select it specifically
ah k got it!
Hello everyone, currently trying to upgrade my project to the newest version of bevy and this crate.
i'm a bit confused on how to migrate my CollisionLayers to the reworked layers.
I'm using Qevy to create maps, and there i get a number based on what layers i click on, as seen in the image.
and i basically turn that into a Vec of L, L implements PhyiscsLayer:
let layers = props
.get("collision_layers")
.and_then(|cl| cl.parse::<u32>().ok())
.map_or_else(Vec::new, |cl| {
decode_flags(cl)
.iter()
.map(|flag| L::from_flag(*flag))
.collect()
});
let masks = props
.get("collision_masks")
.and_then(|cm| cm.parse::<u32>().ok())
.map_or_else(Vec::new, |cm| {
decode_flags(cm)
.iter()
.map(|flag| L::from_flag(*flag))
.collect()
});
if !layers.is_empty() || !masks.is_empty() {
collider.insert(CollisionLayers::new(layers, masks));
}
the L::from_flag just returns the enum variant
that used to work, but now i get following error:
error[E0277]: the trait bound `std::vec::Vec<L>: PhysicsLayer` is not satisfied
--> src\build.rs:229:62
|
229 | collider.insert(CollisionLayers::new(layers, masks));
| -------------------- ^^^^^^ the trait `PhysicsLayer` is not implemented for `std::vec::Vec<L>`
| |
| required by a bound introduced by this call
|
= help: the trait `PhysicsLayer` is implemented for `&L`
= note: required for `LayerMask` to implement `From<std::vec::Vec<L>>`
= note: required for `std::vec::Vec<L>` to implement `Into<LayerMask>`
note: required by a bound in `CollisionLayers::new`
--> crates\bevy_xpbd_3d\../../src\components\layers.rs:369:34
|
369 | pub fn new(memberships: impl Into<LayerMask>, filters: impl Into<LayerMask>) -> Self {
| ^^^^^^^^^^^^^^^ required by this bound in `CollisionLayers::new`
i can see in the docs that i can give it an array of PhysicsLayer, but it seems a Vec doesnt work?
wouldn't it be easier in this case to just use bitmask directly?
yeah probably, but imma be honest i don't understand the concept of bitmasks
layermask has 32 bits, none is just 0
you checked the first 2 which is same as (1 << 0 | 1 << 1)
i kind of get the idea behind it, but can't quite wrap my head around when it comes to using it in practice
each checkbox is basically a single bit out of i32
so, i just need to give it "3" for example, and xpbd would make out of that the two layers?
yep
that's literally all that layermasks are
first bit is 1, second bit is 2, third bit is 4, fourth bit is 8...
layer 1 is 1, layer 2 is 2, layer 3 is 4, layer 4 is 8...
you basically perform simple bool operations x 32 bits
a | b is same as a || b for bool, if a or b is true, it returns true
a & b is same as a && b for bool, if a AND b is true, it returns true
a & !b is same as a && !b for bool, if both are true, it returns false
single layer operations are easy, and the collisionlayers wrapper is supposed to make the rest easy too
yeah awesome, thanks! figured it out now :)
this thing needs a better documentation, it's supposed to be simple but it's strangely hard to explain despite everyone essentially using it daily
and you should be able to iterate through your stuff just based on 1 << n since it starts at 0 same as vec index
how can i toggle the debug plugin?
i used to be able to just
fn toggle_physics_debug(mut conf: ResMut<PhysicsDebugConfig>, input: Res<Input<KeyCode>>) {
if input.just_pressed(KeyCode::F3) {
conf.enabled = !conf.enabled;
}
}
but i can't find anything to enable/disable it?
this #1124043933886976171 message
ah, thanks!
How can I add custom "collision primitive"? A minercraft style voxel terrain, so collision lookup can be just a "is cell filled" check.
you know A*?
I mean should I create a single entity for this, or multiple? AABB should span the whole terrain?
colliders are overkill for this
idk, collision check should be a simple ultra fast index operation
or you could just get a grid and check adjacent cells, which is ultra-fast in comparison π€·ββοΈ
maybe we are talking about same thing, I've barely worked with xpbd, that grid still should be a collider, or do I need to hook into broad/narrow phase?
you don't need a collider
look at how A* works
a built-in 2d/3d grid would be awesome though @vestal minnow
Sorry, I don't quite understand how A* can help in this case.
your character's bounding box checks if it crossed over to the next cell, then updates player environment collider to exist in that cell if it's empty, or prevent moving in that direction
so when you're moving diagonally, you're essentially zig-zagging along the grid
if you ever played runescape, that's exactly how minecraft works too
since voxels are always on the grid, its' collision is entirely faked in a similar way to A*, and the bounding box on the player just needs to decide which cell player is in and to which one he's crossing over
That should work for general physics entity "roll a bouncy ball"? Thank you for explanation, I'll try to figure this out.
considering how common tiles and voxels are, it's strange that grid isn't built-in into every physics engine by default tbh
A spatial hash to check which cells entities belong to, or an actual collider? Or something else
for the grid most of the data in collider is pointless, it's always axis-aligned square/cube with uniform size
so if edge of bounding box on character moves from 0.9 to 1.1, it checks if grid cell at 1 is filled, and applies collision without thinking about cell's bounding box
i can't find what minecraft actually stores in voxels, block damage is most likely stored outside, so probably just the tile type, and tile durability is just matched against its' type? layer/sensor could also be done by block type.
so they don't need transform aside from grid itself, and might not even need to be entities as long as grid handles lighting and textures
found this instead https://0fps.net/2012/01/14/an-analysis-of-minecraft-like-engines/
i wonder if it's still relevant
β€οΈ bevy_xpbd, grate crate mate.
bevy_framepace makes animation extremely jerky on my system, and bevy_xpbd seems to not like the FixedUpdate schedule. I can only get smooth animation by running the physics at full tilt, which is 1400fps at the moment, not ideal! Is this a known bug with FixedUpdate?
You can configure bevy_xpbd to run in FixedUpdate, but you'd need to change the update mode to fixed_once
Superb, thank you @cinder summit that's now running even smoother than my non-physics code. I was just trying .add_plugins(PhysicsPlugins::new(FixedUpdate)) which exhibits very strange behaviour.
... Why are you running at 1.4k fps?
present_mode: bevy::window::PresentMode::AutoNoVsync,
I mean, yes
I want my game to be smooth and responsive, I'm just trying different stuff right now!
you don't really get that from more fps though
and if you do, then something is probably wrong with your schedules
Interesting, I'm not doing anything exotic with schedules. With default settings, I get what feels like 2 or 3 frames of input lag. With vsync disabled it's responsive.
I've not found a way of limiting FPS without compromising the experience, that's kinda what I'm asking about :D
hello everyone, i'm currently running into the issue that the game crashes when i spawn cubes on top of each other (not in each other, i make sure the distance between them is big enough) while having the debug on.
when i disable the debug before the cubes land on the ground, it works fine. i can also enable debug again after that, as showcased in the gif.
but if i have it enabled from the beginning, it seems to crash as soon as the cubes hit the ground/each other...
thats how i spawn them:
for i in 0..10 {
// cube
commands
.spawn((
Name::new(format!("Cube-{}", i)),
PbrBundle {
mesh: meshes.add(Mesh::from(Cuboid::from_size(Vec3::new(1.0, 1.0, 1.0)))),
material: materials.add(Color::rgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, ((i + i) + 20) as f32, 0.0),
..default()
},
RigidBody::Dynamic,
Collider::cuboid(1.0, 1.0, 1.0),
GravityScale(2.0),
CollisionLayers::new(
[MyPhysicsLayer::Player],
[
MyPhysicsLayer::Ground,
MyPhysicsLayer::WallRunnable,
MyPhysicsLayer::Player,
],
),
));
}
and thats the error message i get:
thread 'Compute Task Pool (7)' panicked at .cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_math-0.13.0\src\primitives\dim3.rs:40:9:
assertion failed: value.is_normalized()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_xpbd_3d::plugins::debug::debug_render_axes`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
the assertion happens in the dim3.rs file of bevy_math, line 40:
pub fn new_unchecked(value: Vec3) -> Self {
debug_assert!(value.is_normalized());
Self(value)
}
@torn hedge #1124043933886976171 message
Hrm, I'm trying to update to bevy_xpbd and I'm running into some compilation errors:
error[E0277]: the trait bound `bevy::prelude::Gizmos<'w, 's, configuration::PhysicsGizmos>: bevy::prelude::GizmoPrimitive2d<bevy_math::primitives::Ellipse>` is not satisfied
--> /Users/jpedrick/.cargo/git/checkouts/bevy_xpbd-87d8ac3552aaa63b/164f252/crates/bevy_xpbd_2d/../../src/plugins/debug/gizmos.rs:442:29
|
441 | self.primitive_2d(
| ------------ required by a bound introduced by this call
442 | ellipse.0,
| ^^^^^^^^^ the trait `bevy::prelude::GizmoPrimitive2d<bevy_math::primitives::Ellipse>` is not implemented for `bevy::prelude::Gizmos<'w, 's, configuration::PhysicsGizmos>`
|
= help: the following other types implement trait `bevy::prelude::GizmoPrimitive2d<P>`:
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Direction2d>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Circle>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Ellipse>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Capsule2d>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Line2d>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Plane2d>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Segment2d>>
<bevy::prelude::Gizmos<'w, 's, T> as bevy::prelude::GizmoPrimitive2d<bevy::prelude::Polyline2d<N>>>
and 6 others
Some errors have detailed explanations: E0277, E0308, E0599.
For more information about an error, try `rustc --explain E0277`.
I'm using bevy from git main as of a couple of weeks ago...
Hm ok, so I'll just go and fix these myself
I can make a fork and PR to help track the API changes needed, so only one of us has to do the work
this is most likely just that you're using a newer version of Bevy than xpbd, so your Ellipse type doesn't work for the gizmos xpbd uses (because they use an older Bevy version)
You mean two versions of bevy? I ran cargo tree -d and I only have one version(I think).
bevy_xpbd uses 0.13 and you use main
Ohh, this is probably the thing:
bevy_math v0.13.0
βββ bevy_xpbd_2d v0.4.2 (https://github.com/Jondolf/bevy_xpbd.git#164f2523) (*)
So i understand right that its nothing from my side, and the Debug rendering is currently, lets say, "unsafe" to use?
not unsafe, overzealous
yeah Bevy's new direction types (which the gizmo uses internally) panic if not normalized, which in this case can happen when the body rotation is degenerate (e.g. not normalized)
degenerate is the proper term for it? i was just calling it denormalized π₯²
degenerate body rotation somehow sounds really metal
degenerate is basically just a math term for cursed things
like a triangle where all points are on the same line (collinear)
quaternions are generally expected to have a unit-length, not sure if unnormalized quats are strictly counted as degenerate in math though
I believe overall they aren't, but for rotations specifically they are
huh
I added an explicit bevy_math = "0.13" as well as an override in .cargo/config.toml and the errors are much more sane
"Due to floating point error, even safe operations like multiplying two quaternions (if both are normalised then the answer will be normalised already in theory) can have slight errors. It won't have a visible effect at first, but if you do something like rotate a character every frame the orientation quaternion can accumulate more errors until it starts to distort your model (it used to happen to the ogre camera, so renormalising was added to some ogre functions to correct it)."
yep
this is such a good description, it needs to be added to the doc for direction itself
they're normalized every frame in the sim loop though
what caused gizmo to fail assert then
not normalized enough in that instance
the normalization doesn't happen at the end of the sim loop iirc, but at the start or middle
on a side note, i had the same error thinking i forgot to normalize somewhere, and it turned out that it was because i multiplied 2 vectors expecting them to be unit, and one turned out to be 0
so adding the length to the warning/error would be super useful for these cases
yeah
and you probably need length anyway to give different warnings depending on how bad the situation is
on a side note, i went to check if ogre is still alive and found this
VET_INT_10_10_10_2_NORM support added
Ogre now supports normalized INT_10_10_10_2 as the vertex format. This packs 3 signed values with 10bit precision and a fourth 2bit value into 4 bytes β the size required by a single float.
If you are using normal-maps, you will notice how this format is perfect to store a tangent with parity, while only requiring 25% of storage compared to 4 floats.
Additionally, you can use it to store normals where storage requirements drop to 33% too.
In both cases the 10bit resolution is typically sufficient.
The format is natively supported by GLES3, GL3+, Vulkan and Metal meaning that you also save bandwidth and VRAM.
can't tell if glam does it by default
@vestal minnow one last follow up. I made zero changes to bevy_xpbd after overriding bevy_math and everything roughly works
Nice!
I'm having an issue where the capsule collider doesn't perfectly align with the collider mesh
I'm going back to the many_shapes example to try and see what's different
Oh, it's simple. I just needed to call capsule.collider() instead of trying to make a new one that maps onto it.
is there a built-in way to change how strongly overlapping objects push against each other?
i'd like to be able to spawn 2 rigid bodies intersecting with each other and let them even themselves out on their own, but at the moment they fly away from each other way too fast
on the other hand if that's a behavior i should implement myself, is there a recommended way of adding a "custom collision solver" or something like that, or should i just write a system for it?
hrm maybe i actually need to think about the concept a little better, in real life a solid that is suddenly at 2x its normal resting density would definitely probably explode
that sounds more like soft body behaviour than rigid body
it's kinda in-between, i don't need the rigid body to deform but i want the repulsive force to scale based on penetration depth
regardless of whether i do the spawning-overlapping thing, i'll still need to implement this custom behavior for this type of body
what's the actual purpose for this?
sph-ey fluids
fluid sim?
i was thinking about making the bodies sensors instead of solid colliders and having my own system to handle these interactions
yeah
with a bit of custom behavior though
mm.. xpbd is supposed to be good for that but not there yet
jondolf sent something about it before but i doubt i'll be able to find it
oh
there you go https://youtu.be/9IULfQH7E90
that's not SPH and doesn't have "soft" collision responses, but yeah that has some optimization things
good watch, thanks
on another note, is there a way to invert colliders?
making a quick bounding box around the screen with 4 half spaces but just being able to do a single inverted rectangle would be cool
Collision detection algorithms (like GJK) are largely based on convexity, and hollow/inverted shapes aren't convex. The only option (at least for traditional colliders) would be to approximate the boundary with multiple shapes, in this case half-spaces
ahh ok makes sense, thanks for answering a silly question lol
np!
Would be nice if SpatialQueryFilter had something like add_excluded_entities
Or really, I think I wanna do something like:
fn some_sys( thing1s: Query<Entity, ...>, thing2s: Query<Entity, ...>, colliders: Query<...>){
SpatialQueryFilter::default().with_entities((thing1s, thing2s));
}
...?
why not from_excluded_entities?
or you mean add tuple to existing, instead of replacing it?
let inners : Vec<Entity> = force_ball_inner.iter().map(|(e,_c,_t)| ->Entity {e}).collect();
SpatialQueryFilter::default().with_excluded_entities(things.iter().chain([force_ball]).chain(inners.clone().into_iter())),
I've got something like this
Yes
what are you actually trying to accomplish with this?
I'm doing a ray-cast and have a bunch of entities I need to exclude for it to work correctly
and you can't use layers?
Hm, maybe I should use a mask
yeah, most of the time mask is just better
especially on raycasts.
it's even better if you don't use raycasts.
I wonder if computationally a .with_entities function would be better for what I'm doing.
probably not
Well, this "force_ball" has a range, and within that range I want to test if walls are blocking the force.
So I can reduce the problem to a much smaller set of entities
so, trigger range?
you're not making a clear explanation so it sounds like either a trigger or plain collision
I'm not sure what you mean by a trigger.
It's kind of like a spell that gets blocked by things and also has a limited range
so, a grenade-like behaviour? xD
lol, yeah, roughly
in that case it makes sense, what about the filter though
Masks can definitely do what I need, but I'm just thinking the number of entities can be reduced by a lot since I use a Sensor to find everything in range to do the ray casting.
why not shape intersections?
You mean a shape-cast?
no, shapecast is like raycast but shape
shape intersections is just intersection check
I'm doing that
in unity it was called overlap sphere/box
But I want the effect to be blocked by walls
it's a spatial query, not a collider/sensor
it finds all entities that match your filter, automatically sorting out everything out of range, then you can do your raycasts
I see. Yeah, that actually is a nicer interface than the Sensor that I'm using
your sensor is just cursed but i had something similar in unity
adding anything that enters to list
keeping it simple with overlap is less buggy and probably better performance anyway
so that's what i did after moving to bevy, i don't do it on every frame anyway
I'm gonna look into bevy 0.13 ray casting too
Idk, it's not even that performance critical. I just have a situation where my game can become unplayable and I'm adding a "spell" that lets the player get the pieces unstuck
i made a system that spawns a collider when click left mouse button, but sometimes it creates normal collider and sometimes it creates those strange colliders. is this normal?
If these are all spheres, then it could be that some of them get some slight non-uniform scaling for some reason. This converts them to a trimesh approximation, because ellipsoids aren't supported as a primitive collider shape yet
huh so it should be fine if i use cuboid collider i guess
(Rapier also does this fwiw)
or figure out why it's not uniform
the non-uniform scaling was a #math-dev topic of the day, we could probably add this as another case of why does it even exist
i'm trying to see how scaling is used in games that couldn't be baked for the mesh/animation, because i can't tell why it exists considering how many problems it brings
i did the raycast and it works perfectly
but what exactly does this pink arrow mean?
it's the surface normal at the hit point
damn like i thought
hit.normal is the one that gives me the surface normal info right?
yea
it should also draw a red line from the ray origin to the hit point (by default), but you probably can't see it since it's going directly forward from the camera
yeap
how can i get the mesh of a gltf/glb model so i can use it to create collider?
so i managed to create collider for gltf model with this
commands.spawn((
SceneBundle {
scene: asset_server.load("models/shooting-range.glb#Scene0"),
..default()
},
AsyncSceneCollider::new(Some(ComputedCollider::TriMesh)),
Name::new("Shooting Range"),
));
but its wrong
so uh, help me pls?
did you apply scale in blender?
Yea
Because i kinda failed to use AsyncCollider with gltf
ah it doesn't use gltf, i'll need to check it out tomorrow
I used asynccollider with gltf before but now i dont remember it and i just tried it with asyncscenecollider
But your deleted message was right, no?
Maybe i messed up the model?
i'm not sure, try loading a gltf sphere
i'll mess around with it tomorrow, i've been delaying it enough already π
hey, sorry to bring this up again but i didn't end up getting enough information last time. i'm wanting to add a custom constraint for sph particles.
got a few questions about this. most importantly, how and when do constraints actually get added into the world? is this done every frame or once?
also, since my particles are technically not really rigid, should i still use a rigidbody component for them, or should i make a new component to represent them specifically? how would i define interactions between particles and normal rigidbodies?
sorry still kinda figuring out what i'm even doing! thanks!
or alternatively, should i run my sph stuff completely separately from xpbd and just have a light integration layer between them, instead of trying to build the whole sph thing within the xpbd framework?
@mossy flume i couldn't remember what the end goal was and found that you were asking about minecraft-like game, are you trying to make a fluid sim in a voxel game?
that sounds like a bad idea then
lol wdym
that's ok, i'm not really held up on whether it's a good idea or not, i'm just seeing what i can do
it is in 2d for now
then look up how terraria did it, the source is essentially open
i thought terraria has a grid based fluid system
xpbd is supposed to work well with fluids but you'd probably need to understand the entire physics engine to write it
and the whole xpbd started off from fluid sim from what i understand
GPU fluid simulation using Position Based Fluids, paper to appear at SIGGRAPH 2013.
it's ok i don't mind studying more about the engine, this is just something i'm interested in
really most importantly i'm just hoping to get more info about adding constraints
then you'll have to wait until jondolf wakes up π
want a link to the stuff that bevy xpbd started from?
haha no worries, i'm not expecting a corporate support level service from bevy discord
hrm sure, wouldn't hurt!
In a sudden and ambitious outburst of not-invented-here syndrome combined with hype-train, I decided there weren't enough physics engines out there and it would be a good idea to write one myself using all the latest buzzwords. In this tutorial series, I'll explain step-by-step how to build an extended position-based dynamics (XPBD) rigid-body p...
also just gonna add a @vestal minnow here in case this gets lost under more msgs
he'll probably read everything anyway
dang, maybe this is corporate level service then lol
i mean, that's his crate so π€·ββοΈ
haha ik ik, i still think it's impressive tbh
oh by the way, i'm having trouble with detecting sleeping bodies. tried adding a sleeping threshold, even set it very high and was able to observe bodies going to sleep midair, but the Sleeping component wasn't getting added. is there some config i need to set for that to work?
I just logged all the components from a xpbd RigidBody π. I'm a bit curious about why all the fields are separate structs instead of grouping Current/Previous in structs
@vestal minnow I think there's a bug in the spatial_query ray-casting logic for child transforms. Collisions for child entities work correctly, but it seems like for ray casting it's using &Transform in the local system coordinates.
This function seems... wrong:
I'm still trying to understand the code, but it looks like you're treating scale, rotation and translation separately. Much easier to apply as a Mat4 containing all three.
from what I understand they need to be treated separately sometimes from the physics engine's perspective
for instance in substepping, the scale will never be changed so we only need to iterate on translation and rotation
the position and rotation components are better as their own components so that they can be adjusted and interpreted easier by the algorithms the physics engines use, like decomposing a quaternion to extract only the z axis of the rotation euler angles and then reconstructing a new quaternion just to update that one value introduces a lot of unneeded overhead, this would be especially prevailent in 2d physics simulations, or 3d simulations which have locked axes
yes
sorry, this became long lol
how and when do constraints actually get added into the world?
This depends; joints are constraints that are just added by the user as components, and never cleared (unless you remove the component or entity).
Penetration constraints (which solve contacts) are stored in a resource, and are currently both initialized and solved in a special penetration_constraints system in SubstepSet::SolveConstraints.This could be split into e.g. prepare_contacts and solved by solve_constraints, but with the current architecture, it's more efficient to do them in the same system since it reduces the amount of iteration. This could change if we ever switch solvers or implement "simulation islands" though.
For custom constraints, you should typically solve them in the SubstepSchedule in SubstepSet::SolveUserConstraints. There, they won't have any system ordering conflicts. There isn't a specific place or time where "constraints get added into the world"; you can handle it however you want. But there's a built-in generic solve_constraint system that can handle some things for you in terms of actually solving constraints, and it currently expects constraints to be components. This is what solves e.g. joints.
There's a bit of docs on custom constraints here:
https://docs.rs/bevy_xpbd_2d/latest/bevy_xpbd_2d/constraints/index.html#custom-constraints
Contains constraints used by the solver.
since my particles are technically not really rigid, should i still use a rigidbody component for them, or should i make a new component to represent them specifically? how would i define interactions between particles and normal rigidbodies?
I'm honestly not sure what the best approach would be, but if you want collisions against rigid bodies to work, you could still make the particles rigid bodies with colliders that have collision layers set up so that they don't collide against each other (since you probably want to handle fluid dynamics manually). But if you don't need collisions against rigid bodies, it could be a bit more efficient to have a custom Particle type and handle velocity integration (i.e. movement in this case) manually.
should i run my sph stuff completely separately from xpbd and just have a light integration layer between them, instead of trying to build the whole sph thing within the xpbd framework?
This is likely to be more efficient and flexible, and how built-in fluid simulation stuff would most likely work. I would expect it to also be more efficient to store particles outside the ECS in a custom data structure (maybe even do fluid sim on the GPU?)
But this can quickly get quite complex, so it might be easier to start within the existing physics framework
They could be in the same struct, but the Previous versions are quite specific to the XPBD algorithm. Position/Rotation also used to be the primary user-facing way of moving bodies before using Transform was supported, and having to access position.current would've been a bit weird (though I guess there could've been a Deref impl and/or getters and setters)
PreviousPosition/PreviousRotation aren't meant to be very user-facing and probably aren't what you'd expect (they're the position/rotation from the previous substep, not frame)
That system specifically is a bit cursed and could definitely be cleaned up, but I'm not sure how Mat4 would be related here. Physics requires position and rotation to be separate; you can't really integrate the laws of motion or solve positional constraints using a Mat4 very nicely and certainly not efficiently.
And physics doesn't really care about scale except for colliders
And there's a ton of other reasons for separate Position/Rotation too
Yeah, I get what you mean here. There obviously could be matrix forms and they might be mathematically more elegant, but then youβll never find someone with a CS degree that would want to work on it.
Iβm sorta thinking though that a little bit of encapsulation would help. Maybe we just make a TransformF64 structure that can easily be synced/chained. Within it rotation/transformation could be separate and you build the Mat4D for applying a parentβs transform to a child transform or to back out the global position
Here are some reasons for separate Position/Rotation
https://docs.rs/bevy_xpbd_3d/latest/bevy_xpbd_3d/#why-are-there-separate-position-and-rotation-components
Bevy XPBD
Anyway, there is a bug π¬ I just donβt know where in the code exactly.
(And yeah I found that later on last night)
I have a parent entity that Iβm using as my world root and Iβm letting bevy do the transformations internally
We could have e.g. a PhysicsTransform to group them, but it wouldn't change things that much, and it'd more accurately be a PhysicsIsometry since it doesn't include scale
Honestly, even though Iβm mentioning it here I donβt think it matters that much. It just would make the code a bit easier to read and interact with.
Iβm just deciding if I need to rework my entity hierarchy or if the problem with child entity transformations in XPBD is easier to fix
Iβll see if I can made a small reproducible
Is this in 0.4, using RayCaster? Some RayCaster transform issues were fixed here
https://github.com/Jondolf/bevy_xpbd/pull/310
||marking spoiler because i don't want this to distract the conversation||
||hi! i'm looking for some help about xpbd but idk if i should ask here or in github discussions page first ^^'||
||what's the process for applying central forces in a FixedUpdate system? namely, i just need to get a Vec3 of the current linear velocity and know how to mimic Godot's apply_torque(vec3) and apply_central_force(vec3).||
||i have more or less found how to apply forces despite not finding examples from the repo, as well as a tiny bit of math to figure out how to apply a central vec3 force, but i don't see anything for applying central torque||
Iβm using 0.4.2 from a git pull
Iβm afk this second, but Iβll get the hash for you
I believe collisions were also incorrect. Iβll try to do a reproducible using many_shapes but make the box the child of an entity and the particles as root entities, then apply a transform to the box
There are the ExternalForce and ExternalTorque components for this; by default they persist across frames, but you can make it clear them automatically using .with_persistence(false)
An external torque applied continuously to a dynamic rigid body.
In a system you'd do
fn apply_forces(mut query: Query<&mut ExternalForce>) {
for mut force in &mut query {
force.apply_force(my_force);
}
}
and similarly for torque
thank you :3
last question for now: is this a central force relative to the center of the object, or is this from world position? i'm asking this because of the implication of the name ExternalForce
also is (linear|angular)Velocity a vec3? i've been having trouble with lsp autocompletion to discover lately x.x
It's relative to the center of the object, but in world-space, so Vec3::Y will always apply an upwards force regardless of the position or rotation of the object
And yeah linear and angular velocity both use a Vec3 in 3D
so if bevy transform would be split into (global) position2d/3d and rotation2d/3d, would it be the best outcome for physics?
@vestal minnow that's perfect! thank you :3
It doesn't really matter that much whether they're grouped or separate. The main things are:
- Physics positions should be global
- Physics should have different position and rotation representations for 2D and 3D
- 2D should use a unit complex or a Mat2 for rotation
- 3D should use a Quat for rotation
- bevy_xpbd ideally wants to support f64
I'm not sure if Bevy would add a GlobalTransform2d
i'm just trying to understand what's going on from different perspectives
transform is a really uncomfortable clash between rendering, physics, ecs, and editing
yep
and nobody's making their position clear
I'm not sure if people have really formed strong opinions on the exact approach yet, so it's kinda hard to have a clear position
There's also the thing where having a separate visual transform and physics transform could be useful for visual interpolation
Like you might want to update the visual position several times in between physics frames
without affecting the actual simulation
yeah, that's what i'd imagine affine would be used for
unity has a dropdown menu for static/dynamic next to transform, so i think it would be simple enough for users once editor is out
We might handle static bodies with a separate Static component that is used by both rendering and physics if the PR gets merged
GUI-wise it could be handled similar to Unity though
Many systems in Unity can precompute information about static GameObjects in the Editor. Because the GameObjects do not move, the results of these calculations are still valid at runtime. This means that Unity can save on runtime calculations, and potentially improve performance.
so basically it does what the whole thing in #math-dev started with
yea, it'd allow some (slight) optimizations on the physics side too since you can skip iterating over static bodies in some cases
I've been thinking of adding a Static component anyway
I could be wrong, but I doubt we'll see a Transform2d or a TransformF64 in bevy. I believe for OpenGL double's are considered overkill
Transform2d is planned and relatively likely to be added, but mainly as an API thing. Rendering would probably remain using 3D types.
for now at least
same for TransformF64, it'd be for e.g. physics, but be converted to f32 for rendering
Although, why not keep doubles on the transform and convert to floats when outputting the Mat4 for opengl
Shouldn't be hard to convert almost everything to Vec4D/Mat4D... Instead of using the glam type just use a type alias
Then convert at the interface between OpenGL and bevy
And by "planned" I mean that there's reasonable consensus that it should exist, and there was a PR already, but some details need to be sorted out still
Got it. Maybe we can poke the bear
@trail sparrow did you see #math-dev ?
I have now ποΈ
#math-dev message i should've sent the pin instead
Thanks. I voted lol, but I wish I could do a .1 vote since I'm not implementing anything at this level.
So it seems for collisions everything is working, even with the parent "TransformBundle" rotating. So, now I'm digging into adding the SpatialQuery mechanisms
Anyone else have the ray_caster example crashing in debug?
Looks like the AngularVelocity is causing the ray vector fail a debug_assert!(ray.is_normalized()) check
@vestal minnow so toying with the ray_caster example is looks like the colliders don't apply the parent scaling
commands.spawn((
AsyncCollider(ComputedCollider::ConvexHull),
PbrBundle {
mesh: asset_server.load("models/shooting-range.glb#Scene0"),
..default()
},
Name::new("Shooting Range"),
));
im using this code to create collider from gltf mesh
but it doesnt work
whats wrong? how can i fix it?
What doesn't work?
it doesnt generate a collider
It should be an AsyncSceneCollider if you're loading a scene
yeah i tried asyncscenecollider yesterday and it looked like this
i guess im not properly scaling in blender
Have you tried options other than ConvexHull? And yeah I think you need to make sure you have applied scale with Ctrl+A -> Apply scale (or something like that)
yeah i tried trimesh too
imma try this after trying default blender objects
default objects worked perfectly
my scaling is wrong
and yeah
Ctrl + A -> All Transforms
this is the fix
so with raycast, in console it says "Hit entity 10v1"
is there any way to give a name to this collider?
wait, no i dont need to give a name, blender mesh name is the collider name
hit.entity is giving me the entity
but i need the name
I think Bevy might add Name components for the meshes spawned based on the glTF scene, maybe you can query for it based on the entity?
fn my_system(query: Query<&Name>) {
// ...
// yay I have the ray hits
if let Ok(name) = query.get(hit.entity) {
// do something with the name
}
}
not 100% sure but I think Bevy adds names
it does have a name
lemme show you
this is the name
but raycast is giving me the entity 10v1
lemme try this one
thank you for the detailed reply, this is extremely useful.
i'll try rigidbody with collision filter mask first, and if that's not performing well enough i'll try writing a separate implementation. my only concern in the latter case would be about duplicating effort on making spatial partitioning code which xpbd has built in. does xpbd expose any utilities for this?
i'll report back later : )
xpbd currently just has a very basic sweep and prune algorithm for the broad phase and a Qbvh (from the Parry crate) for spatial queries
I imagine a spatial grid could maybe be better for fluid sim
it worked!
youre amazing
Thanks π I'm glad it works!
@vestal minnow I tried all manner of ways to reproduce the problem I'm having and haven't been able to do it. At this point I think it's a bug of my own creation. In the process I played around with the ray caster example and did this:
Not sure if you'd be interested in adding that, as I use the SpatialQuery as a system argument here
cast_ray doesn't have a parent so it makes sense that it's not buggy
what about ray_caster though? @trail sparrow
In my game I'm not using a RayCaster component
I found my issue. I was using &transform to compute the ray direction and I needed to use &GlobalTransform instead
I had reworked my entity hierarchy because rotations of my map caused the framerate to drop when I was rotating each entity
how do i recognize players apart from trerrain ground or self-intersections?
tagComponentQuery.contains(entity)
by chance do Collision events get swallowed by higher-level entities in the Bevy entity hierarchy before propagating to lower levels?
these docs are a bit confusing. "distance travelled" would imply the orange line but "distance between origin and point of intersection" implies the blue line
Ah, good catch. It's meant to be just the distance travelled (or time of impact), i.e. the orange line. I'll fix the docs
(I added that image to illustrate the issue if that's fine)
yeah, thanks
was wondering how you guys would recommend creating a "box select" for an RTS game, I basically want to cast a bunch of rays in a rectangle downward to select my units (which all have colliders), just wondering what would be a good way to do this
Should be as simple as a shape intersection with a cuboid made from two corner points
Yeah if you just want the entities in some area, you can use shape_intersections or aabb_intersections_with_aabb on SpatialQuery
A system parameter for performing spatial queries.
shape_intersections will be more accurate since it considers the actual shapes and not just the bounding boxes
awesome, thanks!
It also works a lot better if the camera can be rotated
yeah, true
does that happen to be available in xpbd's collision events? i forgot to ask
the entities are available, but you need to check if they have Player/Ground/Whatever components yourself if you want to distinguish them
fn my_system(mut collisions: EventReader<Collision>, player_query: Query<&Player>) {
for collision in collisions.read() {
// Check if either entity is the player
let is_player = player_query.contains(collision.entity1)
|| player_query.contains(collision.entity2);
// Do whatever, maybe check if the other entity is also terrain
}
if you don't need contact data (contact points and normals) and just want to know when players are colliding with e.g. the ground, you could also query for the CollidingEntities of players directly, and check if they include entities with the Ground component
oh i see :3
so i can just query in the signature and all should work?
yeah
nice! thank you :3
any tips for debugging a faulty sensor? i already logged the globaltransforms of the entities involved and can't see any reason that a collision wouldn't fire.
if layers are fine and one of the colliders has (dynamic i think?) rigidbody then it should just work
I'm setting it up like this:
.with_children(|parent| {
parent.spawn((
Name::new("Door Collider"),
Collider::cylinder(player::HEIGHT / 2., player::RADIUS * 5.),
CollisionLayers::new([CollisionLayer::Sensor], [CollisionLayer::Player]),
Sensor,
));
});
The thing I find weird is that I only get collisions on Sensor 32, which is a child of the "house entity" and not Sensor 34 which is a child of the "door entity". The "door'" entity itself is a child entity of "house". Does the collision detection care about the entity hierarchy at all?
i guess it might've turned into compound collider but i have no idea what the rules are for xpbd
in unity it called parent by default but you could easily access the actual collider causing the hit (from player's perspective)
if it works fine if you unparent it then it's probably similar to that
you generally don't want to make children unless you really need them for something specific anyway, it causes a lot of bugs even outside of physics
It could be useful to visualize the colliders with PhysicsDebugPlugin if you haven't already
yeah transform hierarchies don't use compound colliders as in "one collider with many shapes", but rather each collider is treated separately
i'm not even sure if that's good or not, it's good for me but how easy is it to get parent if you just want to put the damage script on parent to be responsible for the whole body?
actually no, considering how many times i've answered how to get the collider hit and not the parent, it's definitely better
you can get the root rigid body of a collider with the ColliderParent component if that's what you mean
alright, i'll try to make an example for generic modern military shooter for loading model + animations + colliders + getting parent... ... ...eventually...
or actually, maybe i should wait for that gltf collider extension
both ways are useful to show π€·ββοΈ
I think these are all incorrect. I've only tested point1 and normal1 but they don't appear to be in the local space of the collider. (didn't meant to include time_of_impact in the screenshot)
so, maybe this isnt the place to ask, but how would you recommend going from two mouse positions (top left and bottom right of the dragged box) to the required scale for the collider with the shape cast? I found camera::viewport_to_world, but this is on the near plane. maybe I could then use the origin of the rays that gives me, and do some calculation with the camera's fov, to create a cone maybe?
don't use shape cast, use shape intersections
viewport_to_world is just point+dir of cursor your screen in the world, if you raycast using it you will hit the exact point in world, or with ray.intersect_plane() you get it at the intersection
Hmm, you might be right... I recall fixing some documentation error like this in the past though π€
I'll try to find that
I found this which has the descriptions reversed for point1/point2 and normal1/normal2
The issue I'm talking about though is that they aren't in local space but world space
Yeah that might be what I was remembering, although it's unrelated here
So the result being in world-space is interesting
The reason why the docs say it's in local space is because Parry literally says so:
https://docs.rs/parry3d/latest/parry3d/query/details/struct.TOI.html
The result of a time-of-impact (TOI) computation.
ok, I'm getting strange results
point2 appears to be in local space but point1 isn't
huh 
and if I'm not reading the values wrong, both normals appear to be world space
it's just mapped from Parry values like this
ShapeHitData {
entity: query_pipeline.entity_from_index(entity_index),
time_of_impact: hit.toi,
point1: hit.witness1.into(),
point2: hit.witness2.into(),
normal1: hit.normal1.into(),
normal2: hit.normal2.into(),
}
I'm not doing any weird transformations afaik
and Parry says they all should be local
but I'm also getting world-space normals
or normal2 might be local-space?
the one on the cast shape
But how do I do this from the mouse position
2d or 3d?
3d
then... hmm...
The world space coordinates? It's just https://docs.rs/bevy/latest/bevy/prelude/struct.Camera.html#method.viewport_to_world
yeah they mentioned that method
he's trying to make an RTS selection
projecting camera's frustum as a shape to do that
i can't even find if it's an existing shape
Because there isn't one :')
Making a cuboid from the corners in world position and padding them by some arbitrary extra height should be good enogh tho
Camera bundles have a frustum
https://docs.rs/bevy/latest/bevy/render/primitives/struct.Frustum.html
A region of 3D space defined by the intersection of 6 HalfSpaces.
It would need to be a collider for shape_intersections tho
yeah
but maybe you can create some collider based on the frustum
like a convex hull from corners
although that might be a pain to create from the frustum's half-spaces, idk how exactly the API for them works
why is that not in primitives? π
no one has done it yet
we also need a HalfSpace primitive
useful as a collider too
Because I decided it's not very primitive like :)
that's like saying trapezoid isn't a primitive
sooo, what I understand about this is that there isnt a primitive shape for the camera frustum. which means its harder to create the collider for it?
we could have more frusta like a frustum with a regular polygon base, but a view frustum might be a bit rendering-specific and not that primitive-y
The main issue wasn't about the shape but the fact that the representation wouldn't be very primitive like or become S-Controversial π
ah
so the data needed for rendering isn't the same as what would've been in a prim?
Yea, but in an RTS you're quite zoomed out usually so a cuboid is probably a decent enough stand in
nah that depends on FoV
and angle. which gets really skewered in some cases
it'd get really weird if it's not ortho
I was thinking of using a cuboid, and dynamically scaling it based on angle and FoV, but I just hope it looks right
A prism is basically a frustum with the top and bottom always being the same size
primitive
oh I misread lmao
prism would be a neat prim shape though
A prism is just an extruded 2D shape right?
Yea, and there are also some weirder variants of it like twisted or truncated prisms
Upstreaming https://github.com/NiseVoid/bevy_prototype_sdf/blob/main/src/dim3.rs#L243 would be cool, I'm not sure if it would be as easy to support for traditional collision detection as it is for SDFs tho 
extruding a polyline might be cursed
Not as cursed as this one:
type Cylinder3d = Extruded<Circle>
The SDF code is actually the same for extruded and cylinders tho 
Okay so we could pretty easily do
- Circle
- Rectangle
- Regular polygon (becomes a regular prism)
and maybe do
- Ellipse (some weird scaled cylinder?)
- Triangle (just a convex polyhedron probably)
- Plane (should this extrude upwards or along normal?)
and these could be quite cursed
- Lines, line segments
- Polygon (I guess run convex decomp or something?)
- Capsule2d (a cuboid with the ends rounded but a flat top and bottom)
You probably could implement support mapping and have proper collision detection for shapes like the extruded ellipse and extruded 2D capsule, but they might be weird shapes to have support for
Gotta get those SDF collisions into bevy_peck
Yeah we could just use SDFs for all the weirder extruded shapes 
then also add support for revolving shapes because why not
so this is my code now:
let screen_ray_start = camera.viewport_to_world(camera_transform, select_box.start);
let screen_ray_end = camera.viewport_to_world(camera_transform, select_box.end);
if let (Some(ray_start), Some(ray_end)) = (screen_ray_start, screen_ray_end) {
let start = ray_start.origin;
let end = ray_end.origin;
let x = (start * 100.0).x;
let y = (start * 100.0).y;
let end_x = (end * 100.0).x;
let end_y = (end * 100.0).y;
let hits = spatial_query.shape_intersections(
&Collider::cuboid((x - end_x).abs(), (y - end_y).abs(), 100.0),
// what to set position to?
camera_trans.rotation,
SpatialQueryFilter::from_mask(GameLayer::Unit),
);
but I dont know what the shape position should be
Probably Vec3::new(x + end_x, y + end_y, 0.0) / 2.0? At the center of your extents where you want the cuboid to be
assuming you want it to span from x to end_x and y to end_y
it always gets centered on the camera, im probably just too tired for this rn
https://docs.unity3d.com/Packages/[email protected]/manual/workflow-create-predefined.html
https://docs.unity3d.com/Packages/[email protected]/manual/shape-tool.html
i'm guessing there will be a similar tool in the future for the editor, so it might be useful to see how they did it
especially cylinder/pipe/arch because you can set number of sides to 3 to make them triangular
and with arch it's possible to create prism/"pipes"/cylinders so other shapes feel a bit redundant
so, a hollow n-gon with angle would probably make a good primitive
Hey Blender folks! ProBuilder is a great extra tool for doing quick, iterative work inside Unity - level design, prototyping, etc. Here's a tutorial specifically for you all, to get up and running easily! Let me know if you have any questions or need more details on parts of the tooling!
Hollow colliders π©
but yeah we'll probably add a 2D ring shape, a tube would be an extruded version of that
and we could just add a Tube primitive too I guess
it should probably be possible to switch between similar shapes (by the editor itself)
cylinder, pipe/tube(just a hollow cylinder), arc(h) (just a pipe with angle cut), and.. what do you call a cylinder with angle cut? pizza?
n-gon/prism would fit better with 3d mesh though
...ok i'm starting to see why not-primitive-enough is a good argument...
This might be answered somewhere, but what's the story on determinism? Looks like glam supports it but how much thought has been given to it for xpbd?
there were some issues, not sure if resolved
theoretically should be possible (compared to nv physx)
yeah it's not fully deterministic yet, and it's a bit unclear where the source of indeterminism is, but I'm reasonably confident it should be possible
we just need someone with enough determination to come around to fix it π₯²
determinism determination?
determination to make it deterministic
determination to determine what's not deterministic π