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

Use grid size based arithmetics for offsets in hex tile layout #463

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
67 changes: 17 additions & 50 deletions src/helpers/hex_grid/axial.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Code for the axial coordinate system.

use crate::helpers::hex_grid::consts::{DOUBLE_INV_SQRT_3, HALF_SQRT_3, INV_SQRT_3};
use crate::helpers::hex_grid::cube::{CubePos, FractionalCubePos};
use crate::helpers::hex_grid::neighbors::{
HexColDirection, HexDirection, HexRowDirection, HEX_OFFSETS,
Expand All @@ -9,7 +8,7 @@ use crate::helpers::hex_grid::offset::{ColEvenPos, ColOddPos, RowEvenPos, RowOdd
use crate::map::HexCoordSystem;
use crate::tiles::TilePos;
use crate::{TilemapGridSize, TilemapSize};
use bevy::math::{Mat2, Vec2};
use bevy::math::Vec2;
use std::ops::{Add, Mul, Sub};

/// A position in a hex grid labelled according to [`HexCoordSystem::Row`] or
Expand Down Expand Up @@ -184,34 +183,6 @@ impl From<ColEvenPos> for AxialPos {
}
}

/// The matrix for mapping from [`AxialPos`], to world position when hexes are arranged
/// in row format ("pointy top" per Red Blob Games). See
/// [Size and Spacing](https://www.redblobgames.com/grids/hexagons/#size-and-spacing)
/// at Red Blob Games for an interactive visual explanation, but note that:
/// 1) we consider increasing-y to be the same as "going up", while RBG considers increasing-y to be "going down",
/// 2) our vectors have magnitude 1 (in order to allow for easy scaling based on grid-size)
pub const ROW_BASIS: Mat2 = Mat2::from_cols(Vec2::new(1.0, 0.0), Vec2::new(0.5, HALF_SQRT_3));

/// The inverse of [`ROW_BASIS`].
pub const INV_ROW_BASIS: Mat2 = Mat2::from_cols(
Vec2::new(1.0, 0.0),
Vec2::new(-1.0 * INV_SQRT_3, DOUBLE_INV_SQRT_3),
);

/// The matrix for mapping from [`AxialPos`], to world position when hexes are arranged
/// in column format ("flat top" per Red Blob Games). See
/// [Size and Spacing](https://www.redblobgames.com/grids/hexagons/#size-and-spacing)
/// at Red Blob Games for an interactive visual explanation, but note that:
/// 1) we consider increasing-y to be the same as "going up", while RBG considers increasing-y to be "going down",
/// 2) our vectors have magnitude 1 (in order to allow for easy scaling based on grid-size)
pub const COL_BASIS: Mat2 = Mat2::from_cols(Vec2::new(HALF_SQRT_3, 0.5), Vec2::new(0.0, 1.0));

/// The inverse of [`COL_BASIS`].
pub const INV_COL_BASIS: Mat2 = Mat2::from_cols(
Vec2::new(DOUBLE_INV_SQRT_3, -1.0 * INV_SQRT_3),
Vec2::new(0.0, 1.0),
);

pub const UNIT_Q: AxialPos = AxialPos { q: 1, r: 0 };

pub const UNIT_R: AxialPos = AxialPos { q: 0, r: -1 };
Expand All @@ -238,14 +209,17 @@ impl AxialPos {
(*self - *other).magnitude()
}

/// Project a vector representing a fractional axial position (i.e. the components can be `f32`)
/// into world space.
/// Project a vector, representing a fractional axial position (i.e. the components can be `f32`)
/// on a row-oriented grid ("pointy top"), into world space.
///
/// This is a helper function for [`center_in_world_row`](`Self::center_in_world_row`),
/// [`corner_offset_in_world_row`](`Self::corner_offset_in_world_row`) and
/// [`corner_in_world_row`](`Self::corner_in_world_row`).
#[inline]
pub fn project_row(axial_pos: Vec2, grid_size: &TilemapGridSize) -> Vec2 {
let unscaled_pos = ROW_BASIS * axial_pos;
Vec2::new(
grid_size.x * unscaled_pos.x,
ROW_BASIS.y_axis.y * grid_size.y * unscaled_pos.y,
grid_size.x * (axial_pos.x + axial_pos.y / 2.0),
grid_size.y * axial_pos.y * 0.75,
)
}

Expand Down Expand Up @@ -297,10 +271,9 @@ impl AxialPos {
/// [`corner_in_world_col`](`Self::corner_in_world_col`).
#[inline]
pub fn project_col(axial_pos: Vec2, grid_size: &TilemapGridSize) -> Vec2 {
let unscaled_pos = COL_BASIS * axial_pos;
Vec2::new(
COL_BASIS.x_axis.x * grid_size.x * unscaled_pos.x,
grid_size.y * unscaled_pos.y,
grid_size.x * axial_pos.x * 0.75,
grid_size.y * (axial_pos.y + axial_pos.x / 2.0),
)
}

Expand Down Expand Up @@ -350,12 +323,9 @@ impl AxialPos {
/// * The world position corresponding to `[0.0, 0.0]` lies on the hex grid at index `(0, 0)`.
#[inline]
pub fn from_world_pos_row(world_pos: &Vec2, grid_size: &TilemapGridSize) -> AxialPos {
let normalized_world_pos = Vec2::new(
world_pos.x / grid_size.x,
world_pos.y / (ROW_BASIS.y_axis.y * grid_size.y),
);
let frac_pos = FractionalAxialPos::from(INV_ROW_BASIS * normalized_world_pos);
frac_pos.round()
let r = world_pos.y * 4.0 / grid_size.y / 3.0;
let q = world_pos.x / grid_size.x - r / 2.0;
FractionalAxialPos { q, r }.round()
}

/// Returns the axial position of the hex grid containing the given world position, assuming that:
Expand All @@ -364,12 +334,9 @@ impl AxialPos {
/// * The world position corresponding to `[0.0, 0.0]` lies on the hex grid at index `(0, 0)`.
#[inline]
pub fn from_world_pos_col(world_pos: &Vec2, grid_size: &TilemapGridSize) -> AxialPos {
let normalized_world_pos = Vec2::new(
world_pos.x / (COL_BASIS.x_axis.x * grid_size.x),
world_pos.y / grid_size.y,
);
let frac_pos = FractionalAxialPos::from(INV_COL_BASIS * normalized_world_pos);
frac_pos.round()
let q = world_pos.x * 4.0 / grid_size.x / 3.0;
let r = world_pos.y / grid_size.y - q / 2.0;
FractionalAxialPos { q, r }.round()
}

/// Try converting into a [`TilePos`].
Expand Down
13 changes: 0 additions & 13 deletions src/helpers/hex_grid/consts.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/helpers/hex_grid/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub mod axial;
pub mod consts;
pub mod cube;
pub mod neighbors;
pub mod offset;
8 changes: 1 addition & 7 deletions src/render/shaders/column_even_hex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@

// Gets the screen space coordinates of the bottom left of an isometric tile position.
Copy link
Contributor

Choose a reason for hiding this comment

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

Not related to this PR, but all the comments seem to be copy and paste... Haha.

fn hex_col_tile_pos_to_world_pos(pos: vec2<f32>, grid_width: f32, grid_height: f32) -> vec2<f32> {
let SQRT_3: f32 = 1.7320508;
let HALF_SQRT_3: f32 = 0.8660254;
let COL_BASIS_X: vec2<f32> = vec2<f32>(HALF_SQRT_3, 0.5);
let COL_BASIS_Y: vec2<f32> = vec2<f32>(0.0, 1.0);

let unscaled_pos = pos.x * COL_BASIS_X + pos.y * COL_BASIS_Y;
return vec2<f32>(COL_BASIS_X.x * grid_width * unscaled_pos.x, grid_height * unscaled_pos.y);
return vec2<f32>(grid_width * pos.x * 0.75, grid_height * (pos.y + pos.x / 2.0));
}

fn col_even_to_axial(offset_pos: vec2<f32>) -> vec2<f32> {
Expand Down
8 changes: 1 addition & 7 deletions src/render/shaders/column_hex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@

// Gets the screen space coordinates of the bottom left of an isometric tile position.
fn hex_col_tile_pos_to_world_pos(pos: vec2<f32>, grid_width: f32, grid_height: f32) -> vec2<f32> {
let SQRT_3: f32 = 1.7320508;
let HALF_SQRT_3: f32 = 0.8660254;
let COL_BASIS_X: vec2<f32> = vec2<f32>(HALF_SQRT_3, 0.5);
let COL_BASIS_Y: vec2<f32> = vec2<f32>(0.0, 1.0);

let unscaled_pos = pos.x * COL_BASIS_X + pos.y * COL_BASIS_Y;
return vec2<f32>(COL_BASIS_X.x * grid_width * unscaled_pos.x, grid_height * unscaled_pos.y);
return vec2<f32>(grid_width * pos.x * 0.75, grid_height * (pos.y + pos.x / 2.0));
}

fn get_mesh(v_index: u32, vertex_position: vec3<f32>) -> MeshOutput {
Expand Down
8 changes: 1 addition & 7 deletions src/render/shaders/column_odd_hex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@

// Gets the screen space coordinates of the bottom left of an isometric tile position.
fn hex_col_tile_pos_to_world_pos(pos: vec2<f32>, grid_width: f32, grid_height: f32) -> vec2<f32> {
let SQRT_3: f32 = 1.7320508;
let HALF_SQRT_3: f32 = 0.8660254;
let COL_BASIS_X: vec2<f32> = vec2<f32>(HALF_SQRT_3, 0.5);
let COL_BASIS_Y: vec2<f32> = vec2<f32>(0.0, 1.0);

let unscaled_pos = pos.x * COL_BASIS_X + pos.y * COL_BASIS_Y;
return vec2<f32>(COL_BASIS_X.x * grid_width * unscaled_pos.x, grid_height * unscaled_pos.y);
return vec2<f32>(grid_width * pos.x * 0.75, grid_height * (pos.y + pos.x / 2.0));
}

fn col_even_to_axial(offset_pos: vec2<f32>) -> vec2<f32> {
Expand Down
8 changes: 1 addition & 7 deletions src/render/shaders/row_even_hex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@

// Gets the screen space coordinates of the bottom left of an isometric tile position.
fn hex_row_tile_pos_to_world_pos(pos: vec2<f32>, grid_width: f32, grid_height: f32) -> vec2<f32> {
let SQRT_3: f32 = 1.7320508;
let HALF_SQRT_3: f32 = 0.8660254;
let ROW_BASIS_X: vec2<f32> = vec2<f32>(1.0, 0.0);
let ROW_BASIS_Y: vec2<f32> = vec2<f32>(0.5, HALF_SQRT_3);

let unscaled_pos = pos.x * ROW_BASIS_X + pos.y * ROW_BASIS_Y;
return vec2<f32>(grid_width * unscaled_pos.x, ROW_BASIS_Y.y * grid_height * unscaled_pos.y);
return vec2<f32>(grid_width * (pos.x + pos.y / 2.0), grid_height * pos.y * 0.75);
}

fn row_even_to_axial(offset_pos: vec2<f32>) -> vec2<f32> {
Expand Down
8 changes: 1 addition & 7 deletions src/render/shaders/row_hex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@

// Gets the screen space coordinates of the bottom left of an isometric tile position.
fn hex_row_tile_pos_to_world_pos(pos: vec2<f32>, grid_width: f32, grid_height: f32) -> vec2<f32> {
let SQRT_3: f32 = 1.7320508;
let HALF_SQRT_3: f32 = 0.8660254;
let ROW_BASIS_X: vec2<f32> = vec2<f32>(1.0, 0.0);
let ROW_BASIS_Y: vec2<f32> = vec2<f32>(0.5, HALF_SQRT_3);

let unscaled_pos = pos.x * ROW_BASIS_X + pos.y * ROW_BASIS_Y;
return vec2<f32>(grid_width * unscaled_pos.x, ROW_BASIS_Y.y * grid_height * unscaled_pos.y);
return vec2<f32>(grid_width * (pos.x + pos.y / 2.0), grid_height * pos.y * 0.75);
}

fn get_mesh(v_index: u32, vertex_position: vec3<f32>) -> MeshOutput {
Expand Down
8 changes: 1 addition & 7 deletions src/render/shaders/row_odd_hex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@

// Gets the screen space coordinates of the bottom left of an isometric tile position.
fn hex_row_tile_pos_to_world_pos(pos: vec2<f32>, grid_width: f32, grid_height: f32) -> vec2<f32> {
let SQRT_3: f32 = 1.7320508;
let HALF_SQRT_3: f32 = 0.8660254;
let ROW_BASIS_X: vec2<f32> = vec2<f32>(1.0, 0.0);
let ROW_BASIS_Y: vec2<f32> = vec2<f32>(0.5, HALF_SQRT_3);

let unscaled_pos = pos.x * ROW_BASIS_X + pos.y * ROW_BASIS_Y;
return vec2<f32>(grid_width * unscaled_pos.x, ROW_BASIS_Y.y * grid_height * unscaled_pos.y);
return vec2<f32>(grid_width * (pos.x + pos.y / 2.0), grid_height * pos.y * 0.75);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think naming these in variables as before would help, e.g.

Suggested change
return vec2<f32>(grid_width * (pos.x + pos.y / 2.0), grid_height * pos.y * 0.75);
let ROW_BASIS_X: f32 = 0.5;
let ROW_BASIS_Y: f32 = 0.75;
return vec2<f32>(grid_width * (pos.x + pos.y * ROW_BASIS_X), grid_height * pos.y * ROW_BASIS_Y);

}

fn row_odd_to_axial(offset_pos: vec2<f32>) -> vec2<f32> {
Expand Down