Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scale_around_center method to BoundingVolume trait #12142

Merged
merged 7 commits into from
Mar 11, 2024

Conversation

chompaa
Copy link
Member

@chompaa chompaa commented Feb 26, 2024

Objective

Add a scale_around_center method to the BoundingVolume trait, as per #12130.

Solution

Added scale_around_center to the BoundingVolume trait, implemented in Aabb2d, Aabb3d, BoundingCircle, and BoundingSphere (with tests).

Copy link
Contributor

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

@Jondolf Jondolf added C-Feature A new feature, making something new possible A-Math Fundamental domain-agnostic mathematical operations labels Feb 26, 2024
@alice-i-cecile alice-i-cecile added C-Usability A targeted quality-of-life change that makes Bevy easier to use and removed C-Feature A new feature, making something new possible labels Feb 26, 2024
@alice-i-cecile
Copy link
Member

Nice docs and tests :) Thanks!

@Jondolf
Copy link
Contributor

Jondolf commented Feb 27, 2024

This looks good implementation-wise, but we might need to think more about what the scaling should actually do.

This scales bounding volumes in each direction relative to their centers, right? So the center remains the same, but just the size changes. The Parry collision detection library actually scales the min and max of AABBs directly, which also affects the center (this is consistent with how rotation for bounding volumes works, see #11681).

I believe one reason for doing scaling like that is that you can e.g. scale entire Bounding Volume Hierarchies without having to separately scale the AABB sizes and center coordinates. BVHs can even be used to accelerate colliders like polylines and trimeshes, and scaling them requires scaling the BVH, which in turn requires scaling the center coordinates of the bounding volumes.

The kind of scaling in this PR isn't generally as useful in my opinion; if you want to expand AABBs for e.g. speculative contacts or CCD, you'd typically want to expand them by a specific amount, and we have grow for that.

@Jondolf
Copy link
Contributor

Jondolf commented Feb 27, 2024

@unknownue
Copy link
Contributor

The meaning of "scale" is controversial.
I would like to use another name like scale_around_center instead of scale to allow user scale the BoundingVolume relative to center.

@Jondolf
Copy link
Contributor

Jondolf commented Feb 27, 2024

For scaling with respect to the center, you can also just do this: aabb.grow(aabb.half_size() * 0.1) (this expands the AABB by 10%). Not exactly the same as a separate scaling method, but can accomplish the same thing in a pretty simple way.

I haven't seen any libraries with scaling wrt the center yet, but if we do want a separate method for it, some naming ideas:

  • scale_around_center (as suggested by @unknownue)
  • scale_wrt_center (explicit, but wrt might be unfamiliar for some people, and abbreviations aren't ideal in names)
  • scale_local (i.e. in the local space of the volume, which means the center of the volume is considered to be at the origin)
  • scale_size (clearly implies changing the size only)
  • resize_scale (similar to previous)

@alice-i-cecile
Copy link
Member

scale_around_center is my preferred name here :)

@chompaa
Copy link
Member Author

chompaa commented Feb 27, 2024

I agree the naming isn't precise. Renaming scale to scale_around_center seems most appropriate. Alternatively, what about keeping scale but having the point to scale around be chosen, something like:

fn scale(&self, scale: Self::HalfSize, point: Self::Position) {
    let b = Self {
        min: (self.min - point) * scale + point,
        max: (self.max - point) * scale + point,
    };
    debug_assert!(b.min.x <= b.max.x && b.min.y <= b.max.y);
    b
}

would work. In this way, we could also have the component-wise scaling mentioned by @Jondolf, by choosing to scale around zero. My only issue is that I'm not really sure this makes sense for BoundingCircle and BoundingSphere.

Copy link
Contributor

@Jondolf Jondolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few suggestions, otherwise everything looks good in terms of code.

Personally, "scaling around X" sounds kind of weird to me, since "around" often implies some kind of rotational or orbiting motion like in the case of Transform::translate_around and Transform::rotate_around. This is why I'm not 100% sold on the name scale_around_center. But I don't have a clear favorite in terms of naming, so I probably wouldn't block over it

Comment on lines 481 to 486
Self {
center: self.center,
sphere: Sphere {
radius: self.radius() * scale,
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be cleaner and what the BoundingCircle version already does

Suggested change
Self {
center: self.center,
sphere: Sphere {
radius: self.radius() * scale,
},
}
Self::new(self.center, self.radius() * scale)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think I missed this since grow and shrink don't use Self::new.

@@ -43,6 +43,9 @@ pub trait BoundingVolume {

/// Decrease the size of the bounding volume in each direction by the given amount
fn shrink(&self, amount: Self::HalfSize) -> Self;

/// Scale the size of the bounding volume around the center by the given amount
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the center" could be confused with the global origin, i.e. (0, 0, 0). It should explicitly refer to the center of the bounding volume.

Suggested change
/// Scale the size of the bounding volume around the center by the given amount
/// Scale the size of the bounding volume around its center by the given amount

Comment on lines 297 to 298
assert!((scaled.min - Vec2::new(-2., -2.)).length() < std::f32::EPSILON);
assert!((scaled.max - Vec2::new(2., 2.)).length() < std::f32::EPSILON);
Copy link
Contributor

@Jondolf Jondolf Feb 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a matter of preference, but you can use splat when every element is the same

Suggested change
assert!((scaled.min - Vec2::new(-2., -2.)).length() < std::f32::EPSILON);
assert!((scaled.max - Vec2::new(2., 2.)).length() < std::f32::EPSILON);
assert!((scaled.min - Vec2::splat(-2.)).length() < std::f32::EPSILON);
assert!((scaled.max - Vec2::splat(2.)).length() < std::f32::EPSILON);

same for 3D

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed the style choices for the above tests here, since they choose to not use splat. There's a mix of both though overall, and I think I also prefer splat.

Comment on lines 293 to 294
min: Vec2::new(-1., -1.),
max: Vec2::new(1., 1.),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to the previous comment, there are constants for this:

Suggested change
min: Vec2::new(-1., -1.),
max: Vec2::new(1., 1.),
min: Vec2::NEG_ONE,
max: Vec2::ONE,

Copy link
Contributor

@Jondolf Jondolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fully sold on the name scale_around_center (see my comment #12142 (review)), but I don't have a clearly better suggestion right now and the code looks good, so I'm content with this. We can always rename later if a better name pops up.

Note: You should probably update the PR title and description to match the new name :)

@chompaa chompaa changed the title Add scale method to BoundingVolume trait Add scale_around_center method to BoundingVolume trait Feb 28, 2024
@NthTensor
Copy link
Contributor

Code looks good but I'd like to understand the motivation before I approve. What's the use-case for this?

@unknownue
Copy link
Contributor

unknownue commented Mar 9, 2024

@NthTensor In my use case, I need to scale the y-direction of a 2D bullet asset's Transform to simulate a laser effect, and the scaling value is dynamically calculated during game. scale_around_center can directly adjust the bounding box size of the laser, while using the grow/shrink method requires more steps, including:

  1. Comparing the original bounding box size and the new bounding box size to determine whether to call grow or shrink in each direction (xyz).
  2. Manually calculating the parameters for grow/shrink based on the scaling value.

Copy link
Contributor

@NthTensor NthTensor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I think this is worth adding.scale_around_center name seems pretty clear. Nice tests!

@Jondolf Jondolf added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Mar 11, 2024
@alice-i-cecile
Copy link
Member

@chompaa once you've resolved merge conflicts I'll merge this in :)

@chompaa
Copy link
Member Author

chompaa commented Mar 11, 2024

@alice-i-cecile All should be good now :)

@alice-i-cecile
Copy link
Member

Awesome thanks. I tried doing this on the web client and git was very confused about the #[test] annotations.

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 11, 2024
Merged via the queue into bevyengine:main with commit 686d354 Mar 11, 2024
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Math Fundamental domain-agnostic mathematical operations C-Usability A targeted quality-of-life change that makes Bevy easier to use S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants