#pragma once #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #undef min #undef max namespace M { template constexpr inline T min(T a, T b) { return a < b ? a : b; } template constexpr inline T max(T a, T b) { return a > b ? a : b; } template constexpr inline T clamp(T min, T a, T max) { return M::min(M::max(min, a), max); } template constexpr inline T clamp01(T a) { return clamp((T)0, a, (T)1); } inline float square_root(float a) { return sqrtf(a); } inline float square_root(double a) { return sqrt(a); } inline float reciprocal_square_root(float a) { return 1.0f / square_root(a); } inline double reciprocal_square_root(double a) { return 1.0 / square_root(a); } constexpr float lerp(float a, float b, float t) { return (1.0f - t) * a + t * b; } inline float ilerp(float a, float b, float v) { return (v - a) / (b - a); } inline float remap(float in_a, float in_b, float out_a, float out_b, float v) { float t = ilerp(in_a, in_b, v); return lerp(out_a, out_b, t); } inline float radians(float degrees) { return degrees * (M_PIf / 180.0f); } //----------------------------------------------- //Vektorberechnung 2-dim union V2 { struct { float x; float y; }; struct { float u; float v; }; struct { float width; float height; }; struct { float E[2]; }; float operator [](size_t index) { assert(index < 2); return E[index]; } }; //Negation von 2-dim Vektor inline V2 operator -(V2 a) { return { -a.x, -a.y }; } //Addition 2er 2-dim Vektoren inline V2 operator +(V2 a, V2 b) { return { a.x + b.x, a.y + b.y }; } //Vektor Addition inline V2 operator +=(V2& a, V2 b) { return a = a + b; } //Subtraktion 2er 2-dim Vektoren inline V2 operator -(V2 a, V2 b) { return { a.x - b.x, a.y - b.y }; } //Vektor Subtraktion inline V2 operator -=(V2& a, V2 b) { return a = a - b; } //Skalarmultiplikation -> erst Skalar, dann Vektor inline V2 operator *(float a, V2 b) { return { a * b.x, a * b.y }; } //Skalarmultiplikation -> erst Vektor, dann Skalar inline V2 operator *(V2 a, float b) { return { a.x * b, a.y * b }; } //Skalarmultiplikation -> mit V2 Pointer inline V2 &operator *= (V2 &a, float b) { a = a * b; return a; } //Division mit einem Skalar Oo -> Skalar geteilt durch Vektor inline V2 operator /(float a, V2 b) { return { a / b.x, a / b.y }; } //Division mit einem Skalar Oo -> Vektor geteilt durch Skalar inline V2 operator /(V2 a, float b) { return { a.x / b, a.y / b }; } //Division mit einem Skalar -> 2 Vektoren inline V2 operator /(V2 a, V2 b) { return { a.x / b.x, a.y / b.y }; } //Division mit einem Skalar -> mit V2 Pointer inline V2 &operator /= (V2 &a, float b) { a = a / b; return a; } //Skalarprodukt inline float dot(V2 a, V2 b) { return a.x * b.x + a.y * b.y; } //Hadamard-Produkt inline V2 hadamard(V2 a, V2 b) { return { a.x * b.x, a.y * b.y }; } //Betrag des Vektors quadrieren inline float length_squared(V2 a) { return dot(a, a); } //Betrag eines Vektors inline float length(V2 a) { return square_root(length_squared(a)); } //Reziproke der Länge inline float reciprocal_length(V2 a) { return reciprocal_square_root(length_squared(a)); } //Einheitsvektor inline V2 normalize(V2 a) { return a * reciprocal_length(a); } //Vektor der 90 inline V2 perp(V2 a) { return { -a.y, a.x }; } //clamp für 2-dim Vektor inline V2 clamp01(V2 a) { return { clamp01(a.x), clamp01(a.y) }; } //Vektor mit den kleinsten Werten 2er Vektoren inline V2 min(V2 a, V2 b) { return { min(a.x, b.x), min(a.y, b.y), }; } //Vektor mit den groessten Werten 2er Vektoren inline V2 max(V2 a, V2 b) { return { max(a.x, b.x), max(a.y, b.y), }; } //kleinster Vektor Wert inline float min(V2 a) { return min(a.x, a.y); } //groesster Vektor Wert inline float max(V2 a) { return max(a.x, a.y); } //Lerp mit 2 Vektoren inline V2 lerp(V2 a, V2 b, V2 t) { return V2{ lerp(a.x, b.x, t.x), lerp(a.y, b.y, t.y), }; } // inline V2 ilerp(V2 a, V2 b, V2 v) { return (v - a) / (b - a); } // inline V2 remap(V2 in_a, V2 in_b, V2 out_a, V2 out_b, V2 v) { V2 t = ilerp(in_a, in_b, v); return lerp(out_a, out_b, t); } //----------------------------------------------- //Vektorberechnung 3-dim union V3 { struct { float x; float y; float z; }; //farbvektor struct { float r; float g; float b; }; //texturvektor struct { float u; float v; float s; }; //von V3 zu V2 ohne z struct { V2 xy; float _z; }; //von V3 zu V2 ohne x struct { float _x; V2 yz; }; struct { float E[3]; }; float operator [](size_t index) { assert(index < 3); return E[index]; } }; //Negation von 2-dim Vektor inline V3 operator -(V3 a) { return { -a.x, -a.y, -a.z }; } //Addition 2er 2-dim Vektoren inline V3 operator +(V3 a, V3 b) { return { a.x + b.x, a.y + b.y, a.z + b.z }; } //Subtraktion 2er 2-dim Vektoren inline V3 operator -(V3 a, V3 b) { return { a.x - b.x, a.y - b.y, a.z - b.z }; } //Skalarmultiplikation -> erst Skalar, dann Vektor inline V3 operator *(float a, V3 b) { return { a * b.x, a * b.y, a * b.z }; } //Skalarmultiplikation -> erst Vektor, dann Skalar inline V3 operator *(V3 a, float b) { return { a.x * b, a.y * b, a.z * b }; } //Division mit nem Skalar Oo -> Skalar geteilt durch Vektor inline V3 operator /(float a, V3 b) { return { a / b.x, a / b.y, a / b.z }; } //Division mit nem Skalar Oo -> Vektor geteilt durch Skalar inline V3 operator /(V3 a, float b) { return { a.x / b, a.y / b, a.z / b }; } //Skalarprodukt inline float dot(V3 a, V3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } //Hadamard-Produkt inline V3 hadamard(V3 a, V3 b) { return { a.x * b.x, a.y * b.y, a.z * b.z }; } //Kreuzprodukt inline V3 cross(V3 a, V3 b) { 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 }; } //Betrag des Vektors quadrieren inline float length_squared(V3 a) { return dot(a, a); } //Betrag eines Vektors inline float length(V3 a) { return square_root(length_squared(a)); } //Reziproke der Länge inline float reciprocal_length(V3 a) { return reciprocal_square_root(length_squared(a)); } //Einheitsvektor inline V3 normalize(V3 a) { return a * reciprocal_length(a); } union V4 { struct { float x; float y; float z; float w; }; //farbvektor struct { float r; float g; float b; float a; }; //texturvektor struct { float u; float v; float s; float t; }; //von V4 zu V2 ohne z struct { V2 xy; V2 zw; }; //V2 fuer Teiltexturenausgabe struct { V2 uv0; V2 uv1; }; //von V4 zu V2 ohne x struct { float _x; V2 yz; float _w; }; struct { float E[4]; }; V4(V2 a, V2 b) { xy = a; zw = b; } V4(float a, float b, float c, float d) { x = a; y = b; z = c; w = d; } V4() {} float &operator [](size_t index) { assert(index < 4); return E[index]; } }; //----------------------------------------------- //2x2 Matrix //M2x2 m; //m.E[0][1] //m.V[1] //m[1][0] union M2x2 { struct { float x1; float x2; float y1; float y2; }; struct { float E[2][2]; }; struct { V2 V[2]; }; V2 &operator [](size_t index) { assert(index < 2); return V[index]; } }; //Matrix negieren inline M2x2 operator -(M2x2 a){ return { -a[0][0], -a[0][1], -a[1][0], -a[1][1] }; } //Matrix Addition inline M2x2 operator +(M2x2 a, M2x2 b) { return { a[0][0] + b[0][0], a[0][1] + b[0][1], a[1][0] + b[1][0], a[1][1] + b[1][1] }; } //Matrix Subtraktion inline M2x2 operator -(M2x2 a, M2x2 b) { return { a[0][0] - b[0][0], a[0][1] - b[0][1], a[1][0] - b[1][0], a[1][1] - b[1][1] }; } //Matrix Skalarmultiplikation inline M2x2 operator *(M2x2 a, float b) { return { a[0][0] * b, a[0][1] * b, a[1][0] * b, a[1][1] * b }; } //Matrix Skalarmultiplikation inline M2x2 operator *(float a, M2x2 b) { return { a * b[0][0], a * b[0][1], a * b[1][0], a * b[1][1] }; } //Matrix Multiplikation inline M2x2 operator *(M2x2 a, M2x2 b) { return { a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1], a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1] }; } //Matrix * Vektor inline V2 operator *(M2x2 a, V2 b) { return { a[0][0] * b[0] + a[0][1] * b[1], a[1][0] * b[0] + a[1][1] * b[1], }; } //Matrix Transponieren inline M2x2 transpose(M2x2 a) { return { a[0][0], a[1][0], a[0][1], a[1][1] }; } //Einheitsmatrix (oder Identitätsmatrix) constexpr inline M2x2 identityM2x2() { return { 1.0f, 0.0f, 0.0f, 1.0f }; } //----------------------------------------------- //3x3 Matrix union M3x3 { struct { float x1; float x2; float x3; float y1; float y2; float y3; float z1; float z2; float z3; }; struct { float E[3][3]; }; struct { V3 V[3]; }; V3& operator [](size_t index) { assert(index < 3); return V[index]; } }; //Matrix negieren inline M3x3 operator -(M3x3 a) { return { -a[0][0], -a[0][1], -a[0][1], -a[1][0], -a[1][1], -a[1][2], -a[2][0], -a[2][1], -a[2][2] }; } //Matrix Addition inline M3x3 operator +(M3x3 a, M3x3 b) { return { a[0][0] + b[0][0], a[0][1] + b[0][1], a[0][2] + b[0][2], a[1][0] + b[1][0], a[1][1] + b[1][1], a[1][2] + b[1][2], a[2][0] + b[2][0], a[2][1] + b[2][1], a[2][2] + b[2][2] }; } //Matrix Subtraktion inline M3x3 operator -(M3x3 a, M3x3 b) { return { a[0][0] - b[0][0], a[0][1] - b[0][1], a[0][2] - b[0][2], a[1][0] - b[1][0], a[1][1] - b[1][1], a[1][2] - b[1][2], a[2][0] - b[2][0], a[2][1] - b[2][1], a[2][2] - b[2][2] }; } //Matrix Skalarmultiplikation inline M3x3 operator *(M3x3 a, float b) { return { a[0][0] * b, a[0][1] * b, a[0][2] * b, a[1][0] * b, a[1][1] * b, a[1][2] * b, a[2][0] * b, a[2][1] * b, a[2][2] * b }; } //Matrix Skalarmultiplikation inline M3x3 operator *(float a, M3x3 b) { return { a * b[0][0], a * b[0][1], a * b[0][2], a * b[1][0], a * b[1][1], a * b[1][2], a * b[2][0], a * b[2][1], a * b[2][2] }; } //Matrix Multiplikation inline M3x3 operator *(M3x3 a, M3x3 b) { return { a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0], a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1], a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2], a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0], a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1], a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[0][2] * b[2][2], a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0], a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1], a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[0][2] * b[2][2] }; } //Matrix * V2 inline V2 operator *(M3x3 a, V2 b) { return { b.x * a[0][0] + b.y * a[0][1] + 1.0f * a[0][2], b.x * a[1][0] + b.y * a[1][1] + 1.0f * a[1][2], }; } //Matrix * V3 inline V3 operator *(M3x3 a, V3 b) { return { b.x * a[0][0] + b.y * a[0][1] + b.z * a[0][2], b.x * a[1][0] + b.y * a[1][1] + b.z * a[1][2], b.x * a[2][0] + b.y * a[2][1] + b.z * a[2][2] }; } //Matrix transponieren inline M3x3 transpose(M3x3 a) { return { a[0][0], a[1][0], a[2][0], a[0][1], a[1][1], a[2][1], a[0][2], a[1][2], a[2][2] }; } //Einheitsmatrix (oder Identitätsmatrix) inline M3x3 identityM3x3() { return { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; } //----------------------------------------------- //m128i struct m128i { __m128i val; }; inline __m128i operator &(m128i a, m128i b) { return _mm_and_si128(a.val, b.val); } inline __m128i operator |(m128i a, m128i b) { return _mm_or_si128(a.val, b.val); } inline __m128i operator >>(m128i a, int b) { return _mm_srli_epi32(a.val, b); } inline __m128i operator <<(m128i a, int b) { return _mm_slli_epi32(a.val, b); } //----------------------------------------------- //m128 struct m128 { __m128 val; }; inline __m128 operator +(m128 a, m128 b) { return _mm_mul_ps(a.val, b.val); } inline __m128 operator *(m128 a, m128 b) { return _mm_mul_ps(a.val, b.val); } inline __m128 operator *(float a, m128 b) { return _mm_mul_ps(_mm_set1_ps(a), b.val); } inline __m128 square_root(__m128 a) { return _mm_sqrt_ps(a); } inline __m128 operator /(m128 a, m128 b) { return _mm_div_ps(a.val, b.val); } union M4x4 { struct { float x1; float x2; float x3; float x4; float y1; float y2; float y3; float y4; float z1; float z2; float z3; float z4; float w1; float w2; float w3; float w4; }; struct { float E[4][4]; }; struct { V4 V[4]; }; V4& operator [](size_t index) { assert(index < 4); return V[index]; } }; inline V4 operator*(M4x4 a, V4 b) { return { b.x * a[0][0] + b.y * a[0][1] + b.z * a[0][2] + b.w * a[0][3], b.x * a[1][0] + b.y * a[1][1] + b.z * a[1][2] + b.w * a[1][3], b.x * a[2][0] + b.y * a[2][1] + b.z * a[2][2] + b.w * a[2][3], b.x * a[3][0] + b.y * a[3][1] + b.z * a[3][2] + b.w * a[3][3], }; } inline M4x4 operator*(M4x4 a, M4x4 b) { return { a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0] + a[0][3] * b[3][0], a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1] + a[0][3] * b[3][1], a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2] + a[0][3] * b[3][2], a[0][0] * b[0][3] + a[0][1] * b[1][3] + a[0][2] * b[2][3] + a[0][3] * b[3][3], a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0] + a[1][3] * b[3][0], a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1] + a[1][3] * b[3][1], a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2] + a[1][3] * b[3][2], a[1][0] * b[0][3] + a[1][1] * b[1][3] + a[1][2] * b[2][3] + a[1][3] * b[3][3], a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0] + a[2][3] * b[3][0], a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1] + a[2][3] * b[3][1], a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2] + a[2][3] * b[3][2], a[2][0] * b[0][3] + a[2][1] * b[1][3] + a[2][2] * b[2][3] + a[2][3] * b[3][3], a[3][0] * b[0][0] + a[3][1] * b[1][0] + a[3][2] * b[2][0] + a[3][3] * b[3][0], a[3][0] * b[0][1] + a[3][1] * b[1][1] + a[3][2] * b[2][1] + a[3][3] * b[3][1], a[3][0] * b[0][2] + a[3][1] * b[1][2] + a[3][2] * b[2][2] + a[3][3] * b[3][2], a[3][0] * b[0][3] + a[3][1] * b[1][3] + a[3][2] * b[2][3] + a[3][3] * b[3][3], }; } inline M4x4 transpose(M4x4 a) { return { a[0][0], a[1][0], a[2][0], a[3][0], a[0][1], a[1][1], a[2][1], a[3][1], a[0][2], a[1][2], a[2][2], a[3][2], a[0][3], a[1][3], a[2][3], a[3][3], }; } inline M4x4 projection(float fovy, float aspect, float near) { float g = 1.0 / tanf(fovy * 0.5); return { g / aspect, 0, 0, 0, 0, g, 0, 0, 0, 0, 0, near, 0, 0, 1, 0, }; } inline M4x4 inverse_projection(float fovy, float aspect, float near) { float g = 1.0 / tanf(fovy * 0.5); return { aspect / g, 0, 0, 0, 0, 1 / g, 0, 0, 0, 0, 0, 1, 0, 0, 1 / near, 0, }; } }