Skip to content

Commit 2b11202

Browse files
committed
fix mul_vec3 tranformation order: should be scale -> rotate -> translate (#3811)
# Objective Lets say we need to rotate stretched object for this purpose we can created stretched `Child` and add as child to `Parent`, later we can rotate `Parent`, `Child` in this situation should rotate keeping it form, it is not the case with `SpriteBundle` currently. If you try to do it with `SpriteBundle` it will deform. ## Solution My pull request fixes order of transformations to scale -> rotate -> translate, with this fix `SpriteBundle` behaves as expected in described rotation, without deformation. Here is quote from "Essential Mathematics for Games": > Generally, the desired order we wish to use for these transforms is to scale first, then rotate, then translate. Scaling first gives us the scaling along the axes we expect. We can then rotate around the origin of the frame, and then translate it into place. I'm must say when I was using `MaterialMesh2dBundle` it behaves correctly in both cases with `bevy main` and with my fix, don't know why, was not able to figure it out why there is difference. here is code I was using for testing: ```rust use bevy::{ prelude::*, render::render_resource::{Extent3d, TextureDimension, TextureFormat}, sprite::{MaterialMesh2dBundle, Mesh2dHandle}, }; fn main() { let mut app = App::new(); app.insert_resource(ClearColor(Color::rgb(0.1, 0.2, 0.3))) .add_plugins(DefaultPlugins) .add_startup_system(setup); app.run(); } fn setup( mut commands: Commands, mut images: ResMut<Assets<Image>>, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>, ) { let mut c = OrthographicCameraBundle::new_2d(); c.orthographic_projection.scale = 1.0 / 10.0; commands.spawn_bundle(c); // note: mesh somehow works for both variants // let quad: Mesh2dHandle = meshes.add(Mesh::from(shape::Quad::default())).into(); // let child = commands // .spawn_bundle(MaterialMesh2dBundle { // mesh: quad.clone(), // transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.0)) // .with_scale(Vec3::new(10.0, 1.0, 1.0)), // material: materials.add(ColorMaterial::from(Color::BLACK)), // ..Default::default() // }) // .id(); // commands // .spawn_bundle(MaterialMesh2dBundle { // mesh: quad, // transform: Transform::from_rotation(Quat::from_rotation_z(0.78)) // .with_translation(Vec3::new(0.0, 0.0, 10.0)), // material: materials.add(ColorMaterial::from(Color::WHITE)), // ..Default::default() // }) // .push_children(&[child]); let white = images.add(get_image(Color::rgb(1.0, 1.0, 1.0))); let black = images.add(get_image(Color::rgb(0.0, 0.0, 0.0))); let child = commands .spawn_bundle(SpriteBundle { texture: black, transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.0)) .with_scale(Vec3::new(10.0, 1.0, 1.0)), ..Default::default() }) .id(); commands .spawn_bundle(SpriteBundle { texture: white, transform: Transform::from_rotation(Quat::from_rotation_z(0.78)) .with_translation(Vec3::new(0.0, 0.0, 10.0)), ..Default::default() }) .push_children(&[child]); } fn get_image(color: Color) -> Image { let mut bytes = Vec::with_capacity((1 * 1 * 4 * 4) as usize); let color = color.as_rgba_f32(); bytes.extend(color[0].to_le_bytes()); bytes.extend(color[1].to_le_bytes()); bytes.extend(color[2].to_le_bytes()); bytes.extend(1.0_f32.to_le_bytes()); Image::new( Extent3d { width: 1, height: 1, depth_or_array_layers: 1, }, TextureDimension::D2, bytes, TextureFormat::Rgba32Float, ) } ``` here is screenshot with `bevy main` and my fix: ![examples](https://user-images.githubusercontent.com/816292/151708304-c07c891e-da70-43f4-9c41-f85fa166a96d.png)
1 parent 244687a commit 2b11202

File tree

2 files changed

+2
-2
lines changed

2 files changed

+2
-2
lines changed

crates/bevy_transform/src/components/global_transform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ impl GlobalTransform {
213213
/// Returns a [`Vec3`] of this [`Transform`] applied to `value`.
214214
#[inline]
215215
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
216-
value = self.rotation * value;
217216
value = self.scale * value;
217+
value = self.rotation * value;
218218
value += self.translation;
219219
value
220220
}

crates/bevy_transform/src/components/transform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ impl Transform {
223223
/// Returns a [`Vec3`] of this [`Transform`] applied to `value`.
224224
#[inline]
225225
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
226-
value = self.rotation * value;
227226
value = self.scale * value;
227+
value = self.rotation * value;
228228
value += self.translation;
229229
value
230230
}

0 commit comments

Comments
 (0)