2018-10-06 20:39:40 -07:00
|
|
|
#pragma once
|
2015-04-30 23:31:59 -07:00
|
|
|
|
2015-11-25 18:38:43 -08:00
|
|
|
#include "Global.hpp"
|
2016-03-04 15:03:26 -08:00
|
|
|
#include "zeus/Math.hpp"
|
2018-12-07 17:16:50 -08:00
|
|
|
#include "CVector4f.hpp"
|
|
|
|
|
2015-11-25 18:38:43 -08:00
|
|
|
#if ZE_ATHENA_TYPES
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
#include "athena/FileReader.hpp"
|
|
|
|
#include "athena/FileWriter.hpp"
|
|
|
|
|
2015-11-25 18:38:43 -08:00
|
|
|
#endif
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2015-11-25 17:26:23 -08:00
|
|
|
#include <iostream>
|
2017-12-29 00:06:22 -08:00
|
|
|
#include <cassert>
|
2015-04-30 23:31:59 -07:00
|
|
|
|
2016-09-18 18:03:37 -07:00
|
|
|
#undef min
|
|
|
|
#undef max
|
|
|
|
|
2015-08-11 18:41:28 -07:00
|
|
|
#if BYTE_ORDER == __ORDER_LITTLE_ENDIAN__
|
2018-12-07 21:23:50 -08:00
|
|
|
#define COLOR(rgba) \
|
|
|
|
(unsigned)(((rgba)&0x000000FF) << 24 | ((rgba)&0x0000FF00) << 8 | ((rgba)&0x00FF0000) >> 8 | \
|
|
|
|
((rgba)&0xFF000000) >> 24)
|
2015-08-11 18:41:28 -07:00
|
|
|
#else
|
2015-11-25 17:26:23 -08:00
|
|
|
#define COLOR(rgba) rgba
|
2015-08-11 18:41:28 -07:00
|
|
|
#endif
|
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
namespace zeus {
|
2016-02-22 21:27:51 -08:00
|
|
|
typedef uint8_t Comp8;
|
|
|
|
typedef uint32_t Comp32;
|
2016-07-08 11:42:42 -07:00
|
|
|
constexpr float OneOver255 = 1.f / 255.f;
|
2016-02-22 21:27:51 -08:00
|
|
|
|
2016-07-08 11:42:42 -07:00
|
|
|
typedef union {
|
2018-12-07 17:16:50 -08:00
|
|
|
struct {
|
|
|
|
Comp8 r, g, b, a;
|
|
|
|
};
|
|
|
|
Comp32 rgba;
|
2015-11-25 17:26:23 -08:00
|
|
|
} RGBA32;
|
|
|
|
|
2015-11-25 17:42:24 -08:00
|
|
|
class CVector4f;
|
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
class CColor {
|
2015-04-30 23:31:59 -07:00
|
|
|
public:
|
2018-12-07 17:16:50 -08:00
|
|
|
simd<float> mSimd;
|
|
|
|
static const CColor skRed;
|
|
|
|
static const CColor skBlack;
|
|
|
|
static const CColor skBlue;
|
|
|
|
static const CColor skGreen;
|
|
|
|
static const CColor skGrey;
|
|
|
|
static const CColor skOrange;
|
|
|
|
static const CColor skPurple;
|
|
|
|
static const CColor skYellow;
|
|
|
|
static const CColor skWhite;
|
|
|
|
static const CColor skClear;
|
|
|
|
|
|
|
|
CColor() : mSimd(1.f) {}
|
|
|
|
|
|
|
|
CColor(float rgb, float a = 1.0) { splat(rgb, a); }
|
|
|
|
|
|
|
|
CColor(float r, float g, float b, float a = 1.0f) : mSimd(r, g, b, a) {}
|
2015-05-04 03:00:15 -07:00
|
|
|
|
2015-11-01 04:04:29 -08:00
|
|
|
#if ZE_ATHENA_TYPES
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
CColor(const atVec4f& vec) : mSimd(vec.simd) {}
|
|
|
|
|
2015-11-01 04:04:29 -08:00
|
|
|
#endif
|
2015-11-25 17:26:23 -08:00
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
CColor(Comp32 rgba) { fromRGBA32(rgba); }
|
|
|
|
|
|
|
|
CColor(const Comp8* rgba) { fromRGBA8(rgba[0], rgba[1], rgba[2], rgba[3]); }
|
|
|
|
|
|
|
|
CColor(const CVector4f& other) : mSimd(other.mSimd) {}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
CColor(const simd<T>& s) : mSimd(s) {}
|
2015-05-04 03:00:15 -07:00
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
CColor& operator=(const CVector4f& other) {
|
|
|
|
mSimd = other.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
2015-11-25 17:42:24 -08:00
|
|
|
|
2015-11-01 04:04:29 -08:00
|
|
|
#if ZE_ATHENA_TYPES
|
2016-12-22 12:35:29 -08:00
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
static CColor ReadRGBABig(athena::io::IStreamReader& reader) {
|
|
|
|
CColor ret;
|
|
|
|
ret.readRGBABig(reader);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void readRGBABig(athena::io::IStreamReader& reader) {
|
|
|
|
simd_floats f;
|
|
|
|
f[0] = reader.readFloatBig();
|
|
|
|
f[1] = reader.readFloatBig();
|
|
|
|
f[2] = reader.readFloatBig();
|
|
|
|
f[3] = reader.readFloatBig();
|
|
|
|
mSimd.copy_from(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void readBGRABig(athena::io::IStreamReader& reader) {
|
|
|
|
simd_floats f;
|
|
|
|
f[2] = reader.readFloatBig();
|
|
|
|
f[1] = reader.readFloatBig();
|
|
|
|
f[0] = reader.readFloatBig();
|
|
|
|
f[3] = reader.readFloatBig();
|
|
|
|
mSimd.copy_from(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeRGBABig(athena::io::IStreamWriter& writer) const {
|
|
|
|
simd_floats f(mSimd);
|
|
|
|
writer.writeFloatBig(f[0]);
|
|
|
|
writer.writeFloatBig(f[1]);
|
|
|
|
writer.writeFloatBig(f[2]);
|
|
|
|
writer.writeFloatBig(f[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeBGRABig(athena::io::IStreamWriter& writer) const {
|
|
|
|
simd_floats f(mSimd);
|
|
|
|
writer.writeFloatBig(f[2]);
|
|
|
|
writer.writeFloatBig(f[1]);
|
|
|
|
writer.writeFloatBig(f[0]);
|
|
|
|
writer.writeFloatBig(f[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeRGBA8(athena::io::IStreamWriter& writer) const {
|
|
|
|
simd_floats f(mSimd);
|
|
|
|
writer.writeUByte(atUint8(f[0] * 255));
|
|
|
|
writer.writeUByte(atUint8(f[1] * 255));
|
|
|
|
writer.writeUByte(atUint8(f[2] * 255));
|
|
|
|
writer.writeUByte(atUint8(f[3] * 255));
|
|
|
|
}
|
2015-11-01 04:04:29 -08:00
|
|
|
|
2015-11-25 17:26:23 -08:00
|
|
|
#endif
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
bool operator==(const CColor& rhs) const {
|
|
|
|
return (r() == rhs.r() && g() == rhs.g() && b() == rhs.b() && a() == rhs.a());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const CColor& rhs) const { return !(*this == rhs); }
|
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator+(const CColor& rhs) const { return mSimd + rhs.mSimd; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator-(const CColor& rhs) const { return mSimd - rhs.mSimd; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator*(const CColor& rhs) const { return mSimd * rhs.mSimd; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator/(const CColor& rhs) const { return mSimd / rhs.mSimd; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator+(float val) const { return mSimd + simd<float>(val); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator-(float val) const { return mSimd - simd<float>(val); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator*(float val) const { return mSimd * simd<float>(val); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
CColor operator/(float val) const { return mSimd / simd<float>(val); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
const CColor& operator+=(const CColor& rhs) {
|
|
|
|
mSimd += rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator-=(const CColor& rhs) {
|
|
|
|
mSimd -= rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator*=(const CColor& rhs) {
|
|
|
|
mSimd *= rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator/=(const CColor& rhs) {
|
|
|
|
mSimd /= rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator+=(float rhs) {
|
|
|
|
mSimd += simd<float>(rhs);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator-=(float rhs) {
|
|
|
|
mSimd -= simd<float>(rhs);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator*=(float rhs) {
|
|
|
|
mSimd *= simd<float>(rhs);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CColor& operator/=(float rhs) {
|
|
|
|
mSimd /= simd<float>(rhs);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void normalize() {
|
|
|
|
float mag = magnitude();
|
|
|
|
mag = 1.f / mag;
|
|
|
|
*this *= mag;
|
|
|
|
}
|
|
|
|
|
|
|
|
CColor normalized() const {
|
|
|
|
float mag = magnitude();
|
|
|
|
mag = 1.f / mag;
|
|
|
|
return *this * mag;
|
|
|
|
}
|
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
float magSquared() const { return mSimd.dot4(mSimd); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
float magnitude() const { return std::sqrt(magSquared()); }
|
|
|
|
|
|
|
|
static CColor lerp(const CColor& a, const CColor& b, float t) {
|
|
|
|
return zeus::simd<float>(1.f - t) * a.mSimd + b.mSimd * zeus::simd<float>(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static CColor nlerp(const CColor& a, const CColor& b, float t) { return lerp(a, b, t).normalized(); }
|
|
|
|
|
|
|
|
simd<float>::reference operator[](const size_t& idx) {
|
|
|
|
assert(idx < 4);
|
|
|
|
return mSimd[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
float operator[](const size_t& idx) const {
|
|
|
|
assert(idx < 4);
|
|
|
|
return mSimd[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
void splat(float rgb, float a) {
|
|
|
|
mSimd = simd<float>(rgb);
|
|
|
|
mSimd[3] = a;
|
|
|
|
}
|
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
float rgbDot(const CColor& rhs) const { return mSimd.dot3(rhs.mSimd); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
void fromRGBA8(const Comp8 ri, const Comp8 gi, const Comp8 bi, const Comp8 ai) {
|
|
|
|
mSimd = simd<float>(ri * OneOver255, gi * OneOver255, bi * OneOver255, ai * OneOver255);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromRGBA32(Comp32 rgba) {
|
|
|
|
static RGBA32 tmp;
|
|
|
|
tmp.rgba = COLOR(rgba);
|
|
|
|
fromRGBA8(tmp.r, tmp.g, tmp.b, tmp.a);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Converts a CColor to RGBA8
|
|
|
|
* \param r
|
|
|
|
* \param g
|
|
|
|
* \param b
|
|
|
|
* \param a
|
|
|
|
*/
|
|
|
|
void toRGBA8(Comp8& ro, Comp8& go, Comp8& bo, Comp8& ao) const {
|
|
|
|
ro = Comp8(r() * 255);
|
|
|
|
go = Comp8(g() * 255);
|
|
|
|
bo = Comp8(b() * 255);
|
|
|
|
ao = Comp8(a() * 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Assigns rgba from hsv
|
|
|
|
* @param h[0-1] The hue percentagee of the color.
|
|
|
|
* @param s[0-1] The saturation percentage of the color.
|
|
|
|
* @param v[0-1] The value percentage of the color.
|
|
|
|
* @param a[0-1] The alpha percentage of the color.
|
|
|
|
*/
|
|
|
|
void fromHSV(float h, float s, float v, float _a = 1.0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Converts rgba to hsv
|
|
|
|
* @param h[0-1] The hue percentagee of the color.
|
|
|
|
* @param s[0-1] The saturation percentage of the color.
|
|
|
|
* @param v[0-1] The value percentage of the color.
|
|
|
|
* @param a[0-1] The alpha percentage of the color.
|
|
|
|
*/
|
|
|
|
void toHSV(float& h, float& s, float& v) const;
|
|
|
|
|
|
|
|
void fromHSL(float h, float s, float l, float _a = 1.0);
|
|
|
|
|
|
|
|
void toHSL(float& h, float& s, float& l) const;
|
|
|
|
|
|
|
|
CColor toGrayscale() const { return {std::sqrt((r() * r() + g() * g() + b() * b()) / 3), a()}; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Clamps to GPU-safe RGBA values [0,1]
|
|
|
|
*/
|
|
|
|
void Clamp() {
|
|
|
|
r() = std::min(1.f, std::max(0.f, float(r())));
|
|
|
|
g() = std::min(1.f, std::max(0.f, float(g())));
|
|
|
|
b() = std::min(1.f, std::max(0.f, float(b())));
|
|
|
|
a() = std::min(1.f, std::max(0.f, float(a())));
|
|
|
|
}
|
|
|
|
|
|
|
|
float r() const { return mSimd[0]; }
|
|
|
|
float g() const { return mSimd[1]; }
|
|
|
|
float b() const { return mSimd[2]; }
|
|
|
|
float a() const { return mSimd[3]; }
|
|
|
|
|
|
|
|
simd<float>::reference r() { return mSimd[0]; }
|
|
|
|
simd<float>::reference g() { return mSimd[1]; }
|
|
|
|
simd<float>::reference b() { return mSimd[2]; }
|
|
|
|
simd<float>::reference a() { return mSimd[3]; }
|
2015-04-30 23:31:59 -07:00
|
|
|
};
|
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
static inline CColor operator+(float lhs, const CColor& rhs) { return simd<float>(lhs) + rhs.mSimd; }
|
2015-05-04 03:00:15 -07:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
static inline CColor operator-(float lhs, const CColor& rhs) { return simd<float>(lhs) - rhs.mSimd; }
|
2015-05-04 03:00:15 -07:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
static inline CColor operator*(float lhs, const CColor& rhs) { return simd<float>(lhs) * rhs.mSimd; }
|
2015-05-04 03:00:15 -07:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
static inline CColor operator/(float lhs, const CColor& rhs) { return simd<float>(lhs) / rhs.mSimd; }
|
|
|
|
} // namespace zeus
|