Skip to content
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
196 changes: 196 additions & 0 deletions include/gkit/math/color.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
#pragma once

#include <cstdint>
#include <array>


namespace gkit::math {

// ------------------------------
// Predefined Color Constants
// ------------------------------
namespace colors {
// Basic 8-color palette (BGRA format: 0xAABBGGRR)
inline constexpr std::array<uint32_t, 8> palette_8 = {
0xFF000000, // 0: Black
0xFF0000FF, // 1: Red
0xFF00FF00, // 2: Green
0xFF00FFFF, // 3: Yellow
0xFFFF0000, // 4: Blue
0xFFFF00FF, // 5: Magenta
0xFFFFFF00, // 6: Cyan
0xFFFFFFFF // 7: White
};

// Basic colors
inline constexpr auto black() { return std::array<float, 3>{ 0.0f, 0.0f, 0.0f }; }
inline constexpr auto white() { return std::array<float, 3>{ 1.0f, 1.0f, 1.0f }; }
inline constexpr auto red() { return std::array<float, 3>{ 1.0f, 0.0f, 0.0f }; }
inline constexpr auto green() { return std::array<float, 3>{ 0.0f, 1.0f, 0.0f }; }
inline constexpr auto blue() { return std::array<float, 3>{ 0.0f, 0.0f, 1.0f }; }
inline constexpr auto yellow() { return std::array<float, 3>{ 1.0f, 1.0f, 0.0f }; }
inline constexpr auto cyan() { return std::array<float, 3>{ 0.0f, 1.0f, 1.0f }; }
inline constexpr auto magenta() { return std::array<float, 3>{ 1.0f, 0.0f, 1.0f }; }

// Grayscale
inline constexpr auto gray() { return std::array<float, 3>{ 0.5f, 0.5f, 0.5f }; }
inline constexpr auto dark_gray() { return std::array<float, 3>{ 0.25f, 0.25f, 0.25f }; }
inline constexpr auto light_gray() { return std::array<float, 3>{ 0.75f, 0.75f, 0.75f }; }

// HTML color names
inline constexpr auto coral() { return std::array<float, 3>{ 1.0f, 0.5f, 0.31f }; }
inline constexpr auto tomato() { return std::array<float, 3>{ 1.0f, 0.39f, 0.28f }; }
inline constexpr auto gold() { return std::array<float, 3>{ 1.0f, 0.84f, 0.0f }; }
inline constexpr auto orange() { return std::array<float, 3>{ 1.0f, 0.65f, 0.0f }; }
inline constexpr auto purple() { return std::array<float, 3>{ 0.5f, 0.0f, 0.5f }; }
inline constexpr auto violet() { return std::array<float, 3>{ 0.93f, 0.51f, 0.93f }; }
inline constexpr auto pink() { return std::array<float, 3>{ 1.0f, 0.75f, 0.8f }; }
inline constexpr auto brown() { return std::array<float, 3>{ 0.65f, 0.16f, 0.16f }; }
inline constexpr auto olive() { return std::array<float, 3>{ 0.5f, 0.5f, 0.0f }; }
inline constexpr auto navy() { return std::array<float, 3>{ 0.0f, 0.0f, 0.5f }; }
inline constexpr auto teal() { return std::array<float, 3>{ 0.0f, 0.5f, 0.5f }; }
inline constexpr auto silver() { return std::array<float, 3>{ 0.75f, 0.75f, 0.75f }; }
} // namespace colors


// ------------------------------
// Color Operation Functions
// ------------------------------
// Format conversion
inline auto rgb_to_rgba(uint32_t rgb, uint8_t alpha = 255) noexcept -> uint32_t {
return (static_cast<uint32_t>(alpha) << 24) | (rgb & 0x00FFFFFF);
}

inline auto rgba_to_rgb(uint32_t rgba) noexcept -> uint32_t {
return rgba & 0x00FFFFFF;
}

inline auto rgba_to_alpha(uint32_t rgba) noexcept -> uint8_t {
return static_cast<uint8_t>(rgba >> 24);
}

// Extract RGB components
inline auto get_r(uint32_t rgb) noexcept -> uint8_t {
return static_cast<uint8_t>((rgb >> 16) & 0xFF);
}
inline auto get_g(uint32_t rgb) noexcept -> uint8_t {
return static_cast<uint8_t>((rgb >> 8) & 0xFF);
}
inline auto get_b(uint32_t rgb) noexcept -> uint8_t {
return static_cast<uint8_t>(rgb & 0xFF);
}

// Brightness adjustment
inline auto brightness(uint32_t rgb, float factor) noexcept -> uint32_t {
float r = ((rgb >> 16) & 0xFF) * factor;
float g = ((rgb >> 8) & 0xFF) * factor;
float b = (rgb & 0xFF) * factor;
return (static_cast<uint32_t>(std::min(255.0f, r)) << 16) |
(static_cast<uint32_t>(std::min(255.0f, g)) << 8) |
static_cast<uint32_t>(std::min(255.0f, b));
}

// Contrast adjustment
inline auto contrast(uint32_t rgb, float factor) noexcept -> uint32_t {
float r = (((rgb >> 16) & 0xFF) - 128.0f) * factor + 128.0f;
float g = (((rgb >> 8) & 0xFF) - 128.0f) * factor + 128.0f;
float b = ((rgb & 0xFF) - 128.0f) * factor + 128.0f;
return (static_cast<uint32_t>(std::max(0.0f, std::min(255.0f, r))) << 16) |
(static_cast<uint32_t>(std::max(0.0f, std::min(255.0f, g))) << 8) |
static_cast<uint32_t>(std::max(0.0f, std::min(255.0f, b)));
}

// Grayscale conversion
inline auto grayscale(uint32_t rgb) noexcept -> uint32_t {
auto gray = static_cast<uint8_t>(0.299f * ((rgb >> 16) & 0xFF) +
0.587f * ((rgb >> 8) & 0xFF) +
0.114f * (rgb & 0xFF));
return (gray << 16) | (gray << 8) | gray;
}

// Color inversion
inline auto invert(uint32_t rgb) noexcept -> uint32_t {
return 0xFF000000 | (~rgb & 0x00FFFFFF);
}

// Set color components
inline auto set_r(uint32_t rgb, uint8_t r) noexcept -> uint32_t {
return (rgb & 0x00FFFFFF) | (static_cast<uint32_t>(r) << 16);
}
inline auto set_g(uint32_t rgb, uint8_t g) noexcept -> uint32_t {
return (rgb & 0xFFFF00FF) | (static_cast<uint32_t>(g) << 8);
}
inline auto set_b(uint32_t rgb, uint8_t b) noexcept -> uint32_t {
return (rgb & 0xFFFFFF00) | static_cast<uint32_t>(b);
}
inline auto set_a(uint32_t rgb, uint8_t a) noexcept -> uint32_t {
return (static_cast<uint32_t>(a) << 24) | (rgb & 0x00FFFFFF);
}


// ------------------------------
// HSV <-> RGB Conversion
// ------------------------------
struct HSV {
float h; // 0-360 Hue
float s; // 0-1 Saturation
float v; // 0-1 Value
};

auto rgb_to_hsv(uint32_t rgb) noexcept -> HSV;
auto hsv_to_rgb(const HSV& hsv) noexcept -> uint32_t;


// ------------------------------
// RGB <-> HSL Conversion
// ------------------------------
struct HSL {
float h; // 0-360 Hue
float s; // 0-1 Saturation
float l; // 0-1 Lightness
};

auto rgb_to_hsl(uint32_t rgb) noexcept -> HSL;
auto hsl_to_rgb(const HSL& hsl) noexcept -> uint32_t;


// ------------------------------
// Color Blending
// ------------------------------
auto alpha_blend(uint32_t src, uint32_t dst) noexcept -> uint32_t;
auto premultiplied_blend(uint32_t src, uint32_t dst) noexcept -> uint32_t;


// ------------------------------
// Utility Functions
// ------------------------------
// Color rounding (for antialiasing)
inline auto nearest_color(uint32_t color) noexcept -> uint32_t {
auto r = static_cast<uint8_t>((((color >> 16) & 0xFF) + 127) / 255);
auto g = static_cast<uint8_t>((((color >> 8) & 0xFF) + 127) / 255);
auto b = static_cast<uint8_t>(((color & 0xFF) + 127) / 255);
return (r << 16) | (g << 8) | b;
}

// Linear interpolation
inline auto lerp_color(uint32_t a, uint32_t b, float t) noexcept -> uint32_t {
float inv_t = 1.0f - t;
auto r = static_cast<uint8_t>(((a >> 16) & 0xFF) * inv_t + ((b >> 16) & 0xFF) * t);
auto g = static_cast<uint8_t>(((a >> 8) & 0xFF) * inv_t + ((b >> 8) & 0xFF) * t);
auto b_r = static_cast<uint8_t>((a & 0xFF) * inv_t + (b & 0xFF) * t);
auto a_a = static_cast<uint8_t>(((a >> 24) * inv_t + (b >> 24) * t));
return (static_cast<uint32_t>(a_a) << 24) |
(static_cast<uint32_t>(r) << 16) |
(static_cast<uint32_t>(g) << 8) |
static_cast<uint32_t>(b_r);
}

// Check if colors are similar
inline auto is_similar(uint32_t a, uint32_t b, int tolerance = 3) noexcept -> bool {
int dr = ((a >> 16) & 0xFF) - ((b >> 16) & 0xFF);
int dg = ((a >> 8) & 0xFF) - ((b >> 8) & 0xFF);
int db = (a & 0xFF) - (b & 0xFF);
return (dr * dr + dg * dg + db * db) <= tolerance * tolerance * 3;
}

} // namespace gkit::math
3 changes: 2 additions & 1 deletion include/gkit/math/vector2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ namespace gkit::math {
public: // Properties
[[nodiscard]] inline auto length() const -> float { return std::sqrt(x * x + y * y); }
[[nodiscard]] inline constexpr auto length_sq() const -> float { return x * x + y * y; }
inline auto properties() -> auto { return std::tie(x, y); }
[[nodiscard]] inline auto properties() const -> auto { return std::tie(x, y); }
[[nodiscard]] inline auto properties() -> auto { return std::tie(x, y); }

public: // Operations
inline static auto zero() noexcept -> Vector2 { return {0.0f, 0.0f}; }
Expand Down
103 changes: 74 additions & 29 deletions include/gkit/math/vector3.hpp
Original file line number Diff line number Diff line change
@@ -1,44 +1,89 @@
#pragma once

#include <cstdint>
#include "gkit/math/vector2.hpp"

#include <cmath>
#include <tuple>


namespace gkit::math {
class Vector3 final {
class Vector3 {
public:
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;

Vector3() noexcept = default;
Vector3(float x, float y, float z) noexcept;
Vector3(const Vector3& other) noexcept;
explicit Vector3(float v) noexcept;
Vector3(float x, float y, float z) noexcept;
Vector3(const Vector2& v, float z) noexcept;
Vector3(const Vector3& other) noexcept = default;
Vector3(const Vector3&& other) noexcept;
~Vector3() noexcept = default;

public: // Arithmetic operators
inline auto operator=(const Vector3& other) noexcept -> Vector3& { this->x = other.x; this->y = other.y; this->z = other.z; return *this;};
inline auto operator=(const Vector3&& other) noexcept -> Vector3& { this->x = other.x; this->y = other.y; this->z = other.z; return *this;}
inline auto operator==(const Vector3& other) noexcept -> bool { return (this->x == other.x) && (this->y == other.y) && (this->z == other.z);}
inline auto operator!=(const Vector3& other) noexcept -> bool { return (this->x != other.x) || (this->y != other.y) || (this->z != other.z);}
inline auto operator+(const Vector3& other) noexcept -> Vector3 { return Vector3(x + other.x, y + other.y, z + other.z); }
inline auto operator-(const Vector3& other) noexcept -> Vector3 { return Vector3(x - other.x, y - other.y, z - other.z);}
inline auto operator=(const Vector3& other) noexcept -> Vector3& = default;
inline auto operator==(const Vector3& other) noexcept -> bool { return (this->x == other.x) && (this->y == other.y) && (this->z == other.z); }
inline auto operator!=(const Vector3& other) noexcept -> bool { return (this->x != other.x) || (this->y != other.y) || (this->z != other.z); }
inline auto operator+(const Vector3& other) noexcept -> Vector3 { return Vector3(this->x + other.x, this->y + other.y, this->z + other.z); }
inline auto operator-(const Vector3& other) noexcept -> Vector3 { return Vector3(this->x - other.x, this->y - other.y, this->z - other.z); }
inline auto operator+=(const Vector3& other) noexcept -> const Vector3& { this->x += other.x; this->y += other.y; this->z += other.z; return *this; }
inline auto operator-=(const Vector3& other) noexcept -> const Vector3& { this->x -= other.x; this->y -= other.y; this->z -= other.z; return *this; }
inline auto operator*(const int32_t n) noexcept -> Vector3 { return Vector3(x * n, y * n, z * n);}
inline auto operator/(const int32_t n) noexcept -> Vector3 { return Vector3(x / n, y / n, z / n);}
inline auto operator*=(const int32_t n) noexcept -> const Vector3& { this->x *= n; this->y *= n; this->z *= n; return *this;}
inline auto operator/=(const int32_t n) noexcept -> const Vector3& { this->x /= n; this->y /= n; this->z /= n; return *this;}

public:
static auto zero() -> const Vector3&;
auto normalization() -> void;
#ifdef _MSC_VER
inline auto length() const -> float { return std::sqrt(x * x + y * y + z * z); }
#else
inline constexpr auto length() const -> float { return std::sqrt(x * x + y * y + z * z); }
#endif
inline auto properties() -> auto { return std::tie(x, y, z);}

private:
float x = 0.f,
y = 0.f,
z = 0.f;
inline auto operator*(float s) noexcept -> Vector3 { return {this->x * s, this->y * s, this->z * s}; }
inline auto operator/(float s) noexcept -> Vector3 { return {this->x / s, this->y / s, this->z / s}; }
inline auto operator*=(float s) noexcept -> const Vector3& { this->x *= s; this->y *= s; this->z *= s; return *this; }
inline auto operator/=(float s) noexcept -> const Vector3& { this->x /= s; this->y /= s; this->z /= s; return *this; }
inline auto operator-() noexcept -> Vector3 { return {-this->x, -this->y, -this->z}; }

public: // Properties
inline static auto zero() noexcept -> Vector3 { return {0.0f, 0.0f, 0.0f}; }
inline static auto one() noexcept -> Vector3 { return {1.0f, 1.0f, 1.0f}; }

[[nodiscard]] inline auto length() const -> float { return std::sqrt(x * x + y * y + z * z); }
[[nodiscard]] inline constexpr auto length_sq() const -> float { return x * x + y * y + z * z; }
[[nodiscard]] inline auto properties() const -> auto { return std::tie(x, y, z); }
[[nodiscard]] inline auto properties() -> auto { return std::tie(x, y, z); }

public: // Operations
static inline auto dot(const Vector3& a, const Vector3& b) noexcept -> float { return a.x * b.x + a.y * b.y + a.z * b.z; }
static inline auto cross(const Vector3& a, const Vector3& b) noexcept -> Vector3 {
return {
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x
};
}
static inline auto normalize(const Vector3& v) noexcept -> Vector3 {
float len = v.length();
return (len > 0.0f) ? Vector3{v.x / len, v.y / len, v.z / len} : Vector3{0.0f, 0.0f, 0.0f};
}
static inline auto lerp(const Vector3& a, const Vector3& b, float t) noexcept -> Vector3 {
return {a.x + t * (b.x - a.x), a.y + t * (b.y - a.y), a.z + t * (b.z - a.z)};
}
static inline auto min(const Vector3& a, const Vector3& b) noexcept -> Vector3 {
return {(a.x < b.x) ? a.x : b.x, (a.y < b.y) ? a.y : b.y, (a.z < b.z) ? a.z : b.z};
}
static inline auto max(const Vector3& a, const Vector3& b) noexcept -> Vector3 {
return {(a.x > b.x) ? a.x : b.x, (a.y > b.y) ? a.y : b.y, (a.z > b.z) ? a.z : b.z};
}
static inline auto reflect(const Vector3& v, const Vector3& n) noexcept -> Vector3 {
float d = 2.0f * dot(v, n);
return {v.x - d * n.x, v.y - d * n.y, v.z - d * n.z};
}
static inline auto distance(const Vector3& a, const Vector3& b) noexcept -> float {
float dx = b.x - a.x;
float dy = b.y - a.y;
float dz = b.z - a.z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
static inline auto angle(const Vector3& a, const Vector3& b) noexcept -> float {
float d = Vector3::dot(a, b);
float len_a = a.length();
float len_b = b.length();
return (len_a * len_b > 0.0f) ? std::acos(d / (len_a * len_b)) : 0.0f;
}
static inline auto component_mul(const Vector3& a, const Vector3& b) noexcept -> Vector3 {
return {a.x * b.x, a.y * b.y, a.z * b.z};
}
}; // class Vector3
} // namespace gkit::math
Loading
Loading