Switch rotation & translation in grid gizmos (#14656)
# Objective - Fixes #14655 ## Solution Rotation should happen first as this is more easier to conceptualize in the mind: We rotate around the coordinate origin `Vec3::ZERO` and then we just shift the geometry so that its center is exactly on the specified position ## Testing && Showcase Code: ```rust gizmos.grid( Vec3::ONE * 10.0, Quat::from_rotation_x(PI / 3. * 2.), UVec2::splat(20), Vec2::new(2., 2.), PURPLE, ); gizmos.sphere(Vec3::ONE * 10.0, Quat::default(), 1.0, PURPLE); ``` Before picture:  After picture:  ## Migration Guide - Users might have to double check their already existing calls to all the `grid` methods. It should be more intuitive now though.
This commit is contained in:
		
							parent
							
								
									313db39912
								
							
						
					
					
						commit
						d7cb781977
					
				| @ -5,7 +5,7 @@ | |||||||
| 
 | 
 | ||||||
| use crate::prelude::{GizmoConfigGroup, Gizmos}; | use crate::prelude::{GizmoConfigGroup, Gizmos}; | ||||||
| use bevy_color::LinearRgba; | use bevy_color::LinearRgba; | ||||||
| use bevy_math::{Quat, UVec2, UVec3, Vec2, Vec3}; | use bevy_math::{Quat, UVec2, UVec3, Vec2, Vec3, Vec3Swizzles}; | ||||||
| 
 | 
 | ||||||
| /// A builder returned by [`Gizmos::grid_3d`]
 | /// A builder returned by [`Gizmos::grid_3d`]
 | ||||||
| pub struct GridBuilder3d<'a, 'w, 's, Config, Clear> | pub struct GridBuilder3d<'a, 'w, 's, Config, Clear> | ||||||
| @ -368,78 +368,71 @@ fn draw_grid<Config, Clear>( | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[inline] | ||||||
|  |     fn or_zero(cond: bool, val: Vec3) -> Vec3 { | ||||||
|  |         if cond { | ||||||
|  |             val | ||||||
|  |         } else { | ||||||
|  |             Vec3::ZERO | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Offset between two adjacent grid cells along the x/y-axis and accounting for skew.
 |     // Offset between two adjacent grid cells along the x/y-axis and accounting for skew.
 | ||||||
|     let dx = spacing.x |     let skew_tan = Vec3::from(skew.to_array().map(f32::tan)); | ||||||
|         * Vec3::new(1., skew.y.tan(), skew.z.tan()) |     let dx = or_zero( | ||||||
|         * if cell_count.x != 0 { 1. } else { 0. }; |         cell_count.x != 0, | ||||||
|     let dy = spacing.y |         spacing.x * Vec3::new(1., skew_tan.y, skew_tan.z), | ||||||
|         * Vec3::new(skew.x.tan(), 1., skew.z.tan()) |     ); | ||||||
|         * if cell_count.y != 0 { 1. } else { 0. }; |     let dy = or_zero( | ||||||
|     let dz = spacing.z |         cell_count.y != 0, | ||||||
|         * Vec3::new(skew.x.tan(), skew.y.tan(), 1.) |         spacing.y * Vec3::new(skew_tan.x, 1., skew_tan.z), | ||||||
|         * if cell_count.z != 0 { 1. } else { 0. }; |     ); | ||||||
|  |     let dz = or_zero( | ||||||
|  |         cell_count.z != 0, | ||||||
|  |         spacing.z * Vec3::new(skew_tan.x, skew_tan.y, 1.), | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     // Bottom-left-front corner of the grid
 |     // Bottom-left-front corner of the grid
 | ||||||
|     let grid_start = position |     let cell_count_half = cell_count.as_vec3() * 0.5; | ||||||
|         - cell_count.x as f32 / 2.0 * dx |     let grid_start = -cell_count_half.x * dx - cell_count_half.y * dy - cell_count_half.z * dz; | ||||||
|         - cell_count.y as f32 / 2.0 * dy |  | ||||||
|         - cell_count.z as f32 / 2.0 * dz; |  | ||||||
| 
 | 
 | ||||||
|     let line_count = UVec3::new( |     let outer_edges_u32 = UVec3::from(outer_edges.map(|v| v as u32)); | ||||||
|         if outer_edges[0] { |     let line_count = outer_edges_u32 * cell_count.saturating_add(UVec3::ONE) | ||||||
|             cell_count.x + 1 |         + (UVec3::ONE - outer_edges_u32) * cell_count.saturating_sub(UVec3::ONE); | ||||||
|         } else { | 
 | ||||||
|             cell_count.x.saturating_sub(1) |     let x_start = grid_start + or_zero(!outer_edges[0], dy + dz); | ||||||
|         }, |     let y_start = grid_start + or_zero(!outer_edges[1], dx + dz); | ||||||
|         if outer_edges[1] { |     let z_start = grid_start + or_zero(!outer_edges[2], dx + dy); | ||||||
|             cell_count.y + 1 | 
 | ||||||
|         } else { |     fn iter_lines( | ||||||
|             cell_count.y.saturating_sub(1) |         delta_a: Vec3, | ||||||
|         }, |         delta_b: Vec3, | ||||||
|         if outer_edges[2] { |         delta_c: Vec3, | ||||||
|             cell_count.z + 1 |         line_count: UVec2, | ||||||
|         } else { |         cell_count: u32, | ||||||
|             cell_count.z.saturating_sub(1) |         start: Vec3, | ||||||
|         }, |     ) -> impl Iterator<Item = [Vec3; 2]> { | ||||||
|     ); |         let dline = delta_a * cell_count as f32; | ||||||
|     let x_start = grid_start + if outer_edges[0] { Vec3::ZERO } else { dy + dz }; |         (0..line_count.x).map(|v| v as f32).flat_map(move |b| { | ||||||
|     let y_start = grid_start + if outer_edges[1] { Vec3::ZERO } else { dx + dz }; |             (0..line_count.y).map(|v| v as f32).map(move |c| { | ||||||
|     let z_start = grid_start + if outer_edges[2] { Vec3::ZERO } else { dx + dy }; |                 let line_start = start + b * delta_b + c * delta_c; | ||||||
|  |                 let line_end = line_start + dline; | ||||||
|  |                 [line_start, line_end] | ||||||
|  |             }) | ||||||
|  |         }) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // Lines along the x direction
 |     // Lines along the x direction
 | ||||||
|     let dline = dx * cell_count.x as f32; |     let x_lines = iter_lines(dx, dy, dz, line_count.yz(), cell_count.x, x_start); | ||||||
|     for iy in 0..line_count.y { |  | ||||||
|         let iy = iy as f32; |  | ||||||
|         for iz in 0..line_count.z { |  | ||||||
|             let iz = iz as f32; |  | ||||||
|             let line_start = x_start + iy * dy + iz * dz; |  | ||||||
|             let line_end = line_start + dline; |  | ||||||
| 
 |  | ||||||
|             gizmos.line(rotation * line_start, rotation * line_end, color); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     // Lines along the y direction
 |     // Lines along the y direction
 | ||||||
|     let dline = dy * cell_count.y as f32; |     let y_lines = iter_lines(dy, dz, dx, line_count.zx(), cell_count.y, y_start); | ||||||
|     for ix in 0..line_count.x { |  | ||||||
|         let ix = ix as f32; |  | ||||||
|         for iz in 0..line_count.z { |  | ||||||
|             let iz = iz as f32; |  | ||||||
|             let line_start = y_start + ix * dx + iz * dz; |  | ||||||
|             let line_end = line_start + dline; |  | ||||||
| 
 |  | ||||||
|             gizmos.line(rotation * line_start, rotation * line_end, color); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     // Lines along the z direction
 |     // Lines along the z direction
 | ||||||
|     let dline = dz * cell_count.z as f32; |     let z_lines = iter_lines(dz, dx, dy, line_count.xy(), cell_count.z, z_start); | ||||||
|     for ix in 0..line_count.x { |     x_lines | ||||||
|         let ix = ix as f32; |         .chain(y_lines) | ||||||
|         for iy in 0..line_count.y { |         .chain(z_lines) | ||||||
|             let iy = iy as f32; |         .map(|ps| ps.map(|p| position + rotation * p)) | ||||||
|             let line_start = z_start + ix * dx + iy * dy; |         .for_each(|[start, end]| { | ||||||
|             let line_end = line_start + dline; |             gizmos.line(start, end, color); | ||||||
| 
 |         }); | ||||||
|             gizmos.line(rotation * line_start, rotation * line_end, color); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -90,6 +90,14 @@ fn draw_example_collection( | |||||||
|         // Light gray
 |         // Light gray
 | ||||||
|         LinearRgba::gray(0.65), |         LinearRgba::gray(0.65), | ||||||
|     ); |     ); | ||||||
|  |     gizmos.grid( | ||||||
|  |         Vec3::ONE * 10.0, | ||||||
|  |         Quat::from_rotation_x(PI / 3. * 2.), | ||||||
|  |         UVec2::splat(20), | ||||||
|  |         Vec2::new(2., 2.), | ||||||
|  |         PURPLE, | ||||||
|  |     ); | ||||||
|  |     gizmos.sphere(Vec3::ONE * 10.0, Quat::default(), 1.0, PURPLE); | ||||||
| 
 | 
 | ||||||
|     gizmos.cuboid( |     gizmos.cuboid( | ||||||
|         Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)), |         Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)), | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Robert Walter
						Robert Walter