mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
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: ![image](https://github.com/user-attachments/assets/7fea2e71-e62b-4763-9f9f-7a1ecd630ada) After picture: ![image](https://github.com/user-attachments/assets/899dad64-010a-4e4b-86ae-53b85fef0bbc) ## 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
2 changed files with 68 additions and 67 deletions
|
@ -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…
Add table
Reference in a new issue