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

Center aligned meshes #139

Merged
merged 6 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ nodes instead of one, allowing for more use cases (#130, #128)
* Bumped `bevy_inspector_egui` dependency (#129)
* Added a `sprite_sheet` bevy example (#135)
* Added `HexLayout::rect_size` method (#135)
* Added `ColumnMeshBuilder::center_aligned` option (#139)
* Added `PlaneMeshBuilder::center_aligned` option (#139)
* Deprecated `MeshInfo::hexagonal_plane` in favor of `PlaneMeshBuilder` (#139)

## 0.12.0

Expand Down
1 change: 1 addition & 0 deletions examples/3d_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ fn hexagonal_column(hex_layout: &HexLayout) -> Mesh {
let mesh_info = ColumnMeshBuilder::new(hex_layout, COLUMN_HEIGHT)
.without_bottom_face()
.with_scale(Vec3::splat(0.9))
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
Expand Down
1 change: 1 addition & 0 deletions examples/a_star.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.with_scale(Vec3::splat(0.9))
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
Expand Down
1 change: 1 addition & 0 deletions examples/chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.with_scale(Vec3::splat(0.9))
.facing(Vec3::Z)
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
Expand Down
5 changes: 4 additions & 1 deletion examples/field_of_movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,10 @@ fn setup_grid(

/// Compute a bevy mesh from the layout
fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout).facing(Vec3::Z).build();
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, mesh_info.normals)
Expand Down
1 change: 1 addition & 0 deletions examples/field_of_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.with_scale(Vec3::splat(0.9))
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
Expand Down
1 change: 1 addition & 0 deletions examples/hex_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.with_scale(Vec3::splat(0.95))
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
Expand Down
1 change: 1 addition & 0 deletions examples/merged_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ fn setup_grid(
let info = ColumnMeshBuilder::new(&layout, height)
.at(c)
.without_bottom_face()
.center_aligned()
.build();
mesh.merge_with(info);
mesh
Expand Down
5 changes: 4 additions & 1 deletion examples/scroll_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ fn handle_input(

/// Compute a bevy mesh from the layout
fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout).facing(Vec3::Z).build();
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, mesh_info.normals)
Expand Down
5 changes: 4 additions & 1 deletion examples/wrap_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ fn handle_input(

/// Compute a bevy mesh from the layout
fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout).facing(Vec3::Z).build();
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.center_aligned()
.build();
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, mesh_info.normals)
Expand Down
16 changes: 12 additions & 4 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,21 @@ pub struct HexLayout {
}

impl HexLayout {
#[allow(clippy::cast_precision_loss)]
#[must_use]
/// Computes hexagonal coordinates `hex` into world/pixel coordinates
pub fn hex_to_world_pos(&self, hex: Hex) -> Vec2 {
self.hex_to_center_aligned_world_pos(hex) + self.origin
}

#[allow(clippy::cast_precision_loss)]
#[must_use]
pub(crate) fn hex_to_center_aligned_world_pos(&self, hex: Hex) -> Vec2 {
let matrix = self.orientation.forward_matrix;
Vec2::new(
matrix[0].mul_add(hex.x() as f32, matrix[1] * hex.y() as f32),
matrix[2].mul_add(hex.x() as f32, matrix[3] * hex.y() as f32),
) * self.hex_size
* self.axis_scale()
+ self.origin
}

#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
Expand All @@ -77,15 +81,19 @@ impl HexLayout {
])
}

#[allow(clippy::cast_precision_loss)]
#[must_use]
/// Retrieves all 6 corner coordinates of the given hexagonal coordinates
/// `hex`
pub fn hex_corners(&self, hex: Hex) -> [Vec2; 6] {
let center = self.hex_to_world_pos(hex);
self.center_aligned_hex_corners().map(|c| c + center)
}

#[must_use]
pub(crate) fn center_aligned_hex_corners(&self) -> [Vec2; 6] {
Direction::ALL_DIRECTIONS.map(|dir| {
let angle = dir.angle_pointy() + self.orientation.angle_offset;
center + Vec2::new(self.hex_size.x * angle.cos(), self.hex_size.y * angle.sin())
Vec2::new(self.hex_size.x * angle.cos(), self.hex_size.y * angle.sin())
})
}

Expand Down
19 changes: 18 additions & 1 deletion src/mesh/column_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub struct ColumnMeshBuilder<'l> {
pub sides_uv_options: UVOptions,
/// UV mapping options for top and bottom faces
pub caps_uv_options: UVOptions,
/// If set to `true`, the mesh will ignore [`HexLayout::origin`]
pub center_aligned: bool,
}

impl<'l> ColumnMeshBuilder<'l> {
Expand All @@ -81,6 +83,7 @@ impl<'l> ColumnMeshBuilder<'l> {
bottom_face: true,
sides_uv_options: UVOptions::quad_default(),
caps_uv_options: UVOptions::cap_default(),
center_aligned: false,
}
}

Expand Down Expand Up @@ -190,6 +193,15 @@ impl<'l> ColumnMeshBuilder<'l> {
self
}

#[must_use]
#[inline]
/// Ignores the [`HexLayout::origin`] offset, generating a mesh centered
/// around `(0.0, 0.0)`.
pub const fn center_aligned(mut self) -> Self {
self.center_aligned = true;
self
}

#[must_use]
#[allow(clippy::cast_precision_loss)]
#[allow(clippy::many_single_char_names)]
Expand All @@ -198,9 +210,14 @@ impl<'l> ColumnMeshBuilder<'l> {
// We compute the mesh at the origin to allow scaling
let cap_mesh = PlaneMeshBuilder::new(self.layout)
.with_uv_options(self.caps_uv_options)
.center_aligned()
.build();
// We store the offset to match the `self.pos`
let pos = self.layout.hex_to_world_pos(self.pos);
let pos = if self.center_aligned {
self.layout.hex_to_center_aligned_world_pos(self.pos)
} else {
self.layout.hex_to_world_pos(self.pos)
};
let mut offset = Vec3::new(pos.x, 0.0, pos.y);
// We create the final mesh
let mut mesh = MeshInfo::default();
Expand Down
27 changes: 27 additions & 0 deletions src/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ impl MeshInfo {
/// * rotation
/// * etc
#[must_use]
#[deprecated(since = "0.13.0", note = "Use `PlaneMeshBuilder` instead")]
pub fn hexagonal_plane(layout: &HexLayout, hex: Hex) -> Self {
let corners = layout.hex_corners(hex);
let corners_arr = corners.map(|p| Vec3::new(p.x, 0., p.y));
Expand All @@ -160,6 +161,32 @@ impl MeshInfo {
}
}

#[must_use]
pub(crate) fn center_aligned_hexagonal_plane(layout: &HexLayout) -> Self {
let corners = layout.center_aligned_hex_corners();
let corners_arr = corners.map(|p| Vec3::new(p.x, 0., p.y));
Self {
vertices: vec![
corners_arr[0],
corners_arr[1],
corners_arr[2],
corners_arr[3],
corners_arr[4],
corners_arr[5],
],
uvs: vec![
corners[0], corners[1], corners[2], corners[3], corners[4], corners[5],
],
normals: [Vec3::Y; 6].to_vec(),
indices: vec![
0, 2, 1, // Top tri
3, 5, 4, // Bot tri
0, 5, 3, // Mid Quad
3, 2, 0, // Mid Quad
],
}
}

/// Computes cheap mesh data for an hexagonal column facing `Vec3::Y`
/// without the bottom face.
///
Expand Down
23 changes: 20 additions & 3 deletions src/mesh/plane_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub struct PlaneMeshBuilder<'l> {
pub rotation: Option<Quat>,
/// UV mapping options
pub uv_options: UVOptions,
/// If set to `true`, the mesh will ignore [`HexLayout::origin`]
pub center_aligned: bool,
}

impl<'l> PlaneMeshBuilder<'l> {
Expand All @@ -47,6 +49,7 @@ impl<'l> PlaneMeshBuilder<'l> {
offset: None,
scale: None,
uv_options: UVOptions::cap_default(),
center_aligned: false,
}
}

Expand Down Expand Up @@ -102,13 +105,26 @@ impl<'l> PlaneMeshBuilder<'l> {
self
}

#[must_use]
#[inline]
/// Ignores the [`HexLayout::origin`] offset, generating a mesh centered
/// around `(0.0, 0.0)`.
pub const fn center_aligned(mut self) -> Self {
self.center_aligned = true;
self
}

/// Comsumes the builder to return the computed mesh data
#[must_use]
pub fn build(self) -> MeshInfo {
// We compute the mesh at the origin to allow scaling
let mut mesh = MeshInfo::hexagonal_plane(self.layout, Hex::ZERO);
// We compute the mesh at the origin and no offset to allow scaling
let mut mesh = MeshInfo::center_aligned_hexagonal_plane(self.layout);
// We store the offset to match the `self.pos`
let pos = self.layout.hex_to_world_pos(self.pos);
let pos = if self.center_aligned {
self.layout.hex_to_center_aligned_world_pos(self.pos)
} else {
self.layout.hex_to_world_pos(self.pos)
};
let mut offset = Vec3::new(pos.x, 0.0, pos.y);
// **S** - We apply optional scale
if let Some(scale) = self.scale {
Expand All @@ -122,6 +138,7 @@ impl<'l> PlaneMeshBuilder<'l> {
if let Some(custom_offset) = self.offset {
offset += custom_offset;
}
mesh = mesh.with_offset(offset);
self.uv_options.alter_uvs(&mut mesh.uvs);
mesh
}
Expand Down