Skip to content
Snippets Groups Projects
Commit 6464d0e7 authored by Joseph Walton-Rivers's avatar Joseph Walton-Rivers
Browse files

some of the more useful hex-grid features from HexBoard

parent 52d2df90
No related branches found
No related tags found
No related merge requests found
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 27/11/22.
//
#ifndef FGGL_GRID_HEX_HPP
#define FGGL_GRID_HEX_HPP
#include <array>
#include <vector>
#include <cmath>
#include <fggl/math/fmath.hpp>
/**
* Hexagonal Grid Implementation.
* Based largely off Amit's incredible grid documentation.
*/
namespace fggl::grid {
enum class HexDirPointy {
RIGHT = 0, TOP_RIGHT = 1, TOP_LEFT = 2, LEFT = 3, BOTTOM_LEFT = 4, BOTTOM_RIGHT = 5
};
enum class HexDirFlat {
BOTTOM_RIGHT = 0, TOP_RIGHT = 1, TOP = 2, TOP_LEFT = 3, BOTTOM_LEFT = 4, BOTTOM = 5
};
constexpr std::array< std::array<int, 2>, 6> HEX_DIRECTIONS {{
{1, 0}, {1, -1}, {0, 1},
{-1, 0}, {-1, 1}, {0, 1}
}};
constexpr std::array< std::array<int, 2>, 6> HEX_DIAGONALS {{
{2, -1}, {+1, -2}, {-1, -1},
{-2, 1}, {-1, 2}, {1, 1}
}};
template<typename T>
struct HexPointT {
constexpr HexPointT(T q, T r) : m_pos({q, r}) {}
constexpr explicit HexPointT(const std::array<int, 2>& pos) : m_pos(pos[0], pos[1]) {}
inline T q() const {
return m_pos[0];
}
inline T r() const {
return m_pos[1];
}
inline T s() const {
return -m_pos[0]-m_pos[1];
}
inline HexPointT neighbour(HexDirPointy dir) {
return this + HexPointT<T>(HEX_DIRECTIONS[(int)dir]);
}
inline HexPointT neighbour(HexDirFlat dir) {
return this + HexPointT<T>(HEX_DIAGONALS[(int)dir]);
}
HexPointT operator+(const HexPointT<T>& other) const {
return { m_pos[0] + other.m_pos[0], m_pos[1] + other.m_pos[1] };
}
HexPointT operator-(const HexPointT<T>& other) const {
return { m_pos[0] - other.m_pos[0], m_pos[1] - other.m_pos[1] };
}
T distance(const HexPointT& other) const {
auto vec = *this - other;
return (
::abs(vec.q())
+ ::abs(vec.q() - vec.r())
+ ::abs(vec.r()) / 2
);
}
std::vector<HexPointT<T>> hexesInRange(int range) const {
std::vector<HexPointT<T>> results;
for ( auto q = -range; q <= range; ++q ) {
auto stopCount = std::min(range, -q+range);
for ( auto r = std::max(-range, -q-range); r <= stopCount; ++r ) {
results.push_back( this + HexPointT<T>(q, r) );
}
}
return results;
}
private:
std::array<T, 2> m_pos;
};
using FloatHex = HexPointT<float>;
using IntHex = HexPointT<int>;
template<typename T>
constexpr FloatHex hexLerp(const HexPointT<T>& start, const HexPointT<T>& end, float t) {
return {
math::lerp(start.q(), end.q(), t),
math::lerp(start.r(), end.r(), t)
};
}
constexpr IntHex round(const FloatHex& hex) {
// see https://observablehq.com/@jrus/hexround for original JS implementation
float xGrid = std::round( hex.r() );
float yGrid = std::round( hex.q() );
float x = hex.q() - xGrid;
float y = hex.r() - yGrid;
auto dx = std::round(x + 0.5F*y) * (x*x >= y*y);
auto dy = std::round(y + 0.5F*x) * (x*x < y*y);
return { (int)(xGrid + dx), (int)(yGrid + dy) };
}
std::vector<IntHex> lineTo(const IntHex& start, const IntHex& end) {
int distance = start.distance(end);
std::vector<IntHex> line;
for (auto i=0; i < distance; ++i) {
line.push_back( round(hexLerp(start, end, 1.0F/distance * i)) );
}
return line;
}
} // namespace fggl::grid
#endif //FGGL_GRID_HEX_HPP
...@@ -84,6 +84,14 @@ namespace fggl::math { ...@@ -84,6 +84,14 @@ namespace fggl::math {
return valueOrMin > max ? max : valueOrMin; return valueOrMin > max ? max : valueOrMin;
} }
constexpr float lerpImprecise(float start, float end, float t) {
return start + t * (end - start);
}
constexpr float lerp(float start, float end, float t) {
return (1 - t) * start + t * end;
}
} // namespace fggl::math } // namespace fggl::math
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment