Created
October 11, 2017 10:57
-
-
Save wortelstoemp/9b4eafb62b62faae040a20e5cc6088db to your computer and use it in GitHub Desktop.
Math library for 2D and 3D games
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| // Math library for 2D and 3D games | |
| // Coordinate systems are exclusively right-handed! | |
| // SIMD optimization might be added in the future. | |
| // | |
| // Author: Tom Quareme | |
| #include <cmath> | |
| namespace tqMath | |
| { | |
| const float PI = 3.14159265358979323846; | |
| /************* | |
| * Datatypes * | |
| *************/ | |
| union Vec2 | |
| { | |
| float values[2]; | |
| struct | |
| { | |
| float x; | |
| float y; | |
| }; | |
| struct | |
| { | |
| float u; | |
| float v; | |
| }; | |
| inline static Vec2 Right() | |
| { | |
| const Vec2 result = { 1.0f, 0.0f }; | |
| return result; | |
| } | |
| inline static Vec2 Left() | |
| { | |
| const Vec2 result = { -1.0f, 0.0f }; | |
| return result; | |
| } | |
| inline static Vec2 Up() | |
| { | |
| const Vec2 result = { 0.0f, 1.0f }; | |
| return result; | |
| } | |
| inline static Vec2 Down() | |
| { | |
| const Vec2 result = { 0.0f, -1.0f }; | |
| return result; | |
| } | |
| inline static Vec2 Zero() | |
| { | |
| const Vec2 result = { 0.0f, 0.0f }; | |
| return result; | |
| } | |
| }; | |
| union Vec3 | |
| { | |
| float values[3]; | |
| struct | |
| { | |
| Vec2 xy; | |
| float z; | |
| }; | |
| struct | |
| { | |
| Vec2 uv; | |
| float w; | |
| }; | |
| struct | |
| { | |
| float x; | |
| float y; | |
| float z; | |
| }; | |
| struct | |
| { | |
| float u; | |
| float v; | |
| float w; | |
| }; | |
| struct | |
| { | |
| float r; | |
| float g; | |
| float b; | |
| }; | |
| inline static Vec3 Right() | |
| { | |
| const Vec3 result = { -1.0f, 0.0f, 0.0f }; | |
| return result; | |
| } | |
| inline static Vec3 Left() | |
| { | |
| const Vec3 result = { 1.0f, 0.0f, 0.0f }; | |
| return result; | |
| } | |
| inline static Vec3 Up() | |
| { | |
| const Vec3 result = { 0.0f, 1.0f, 0.0f }; | |
| return result; | |
| } | |
| inline static Vec3 Down() | |
| { | |
| const Vec3 result = { 0.0f, -1.0f, 0.0f }; | |
| return result; | |
| } | |
| inline static Vec3 Backward() | |
| { | |
| const Vec3 result = { 0.0f, 0.0f, -1.0f }; | |
| return result; | |
| } | |
| inline static Vec3 Forward() | |
| { | |
| const Vec3 result = { 0.0f, 0.0f, 1.0f }; | |
| return result; | |
| } | |
| inline static Vec3 Zero() | |
| { | |
| const Vec3 result = { 0.0f, 0.0f, 0.0f }; | |
| return result; | |
| } | |
| }; | |
| union Vec4 | |
| { | |
| float values[4]; | |
| struct | |
| { | |
| Vec2 xy; | |
| float z; | |
| float w; | |
| }; | |
| struct | |
| { | |
| Vec3 xyz; | |
| float w; | |
| }; | |
| struct | |
| { | |
| float x; | |
| float y; | |
| float z; | |
| float w; | |
| }; | |
| struct | |
| { | |
| float r; | |
| float g; | |
| float b; | |
| float a; | |
| }; | |
| struct | |
| { | |
| Vec3 rgb; | |
| float a; | |
| }; | |
| }; | |
| union Matrix2x2 | |
| { | |
| float values[4]; | |
| struct | |
| { | |
| float a11; | |
| float a12; | |
| float a21; | |
| float a22; | |
| }; | |
| }; | |
| union Matrix3x3 | |
| { | |
| float values[9]; | |
| struct | |
| { | |
| float a11; | |
| float a12; | |
| float a13; | |
| float a21; | |
| float a22; | |
| float a23; | |
| float a31; | |
| float a32; | |
| float a33; | |
| }; | |
| }; | |
| union Matrix4x4 | |
| { | |
| float values[16]; | |
| struct | |
| { | |
| float a11; | |
| float a12; | |
| float a13; | |
| float a14; | |
| float a21; | |
| float a22; | |
| float a23; | |
| float a24; | |
| float a31; | |
| float a32; | |
| float a33; | |
| float a34; | |
| float a41; | |
| float a42; | |
| float a43; | |
| float a44; | |
| }; | |
| }; | |
| union Quaternion | |
| { | |
| float values[4]; | |
| struct | |
| { | |
| float x; | |
| float y; | |
| float z; | |
| float w; | |
| }; | |
| }; | |
| /************************** | |
| * Operations & Functions * | |
| **************************/ | |
| // Hashing: djb2 algorithm | |
| unsigned long long Hash(char* text) | |
| { | |
| unsigned long long hash = 5381; | |
| int c; | |
| while (c = *text++) | |
| { | |
| hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ | |
| } | |
| return hash; | |
| } | |
| // Float | |
| float Rad(float degrees) | |
| { | |
| return degrees* PI / 180; | |
| } | |
| // Vec2 | |
| inline Vec2 operator+(const Vec2& lhs, const Vec2& rhs) | |
| { | |
| const Vec2 result = { lhs.x + rhs.x, lhs.y + rhs.y }; | |
| return result; | |
| } | |
| inline Vec2 operator-(const Vec2& lhs, const Vec2& rhs) | |
| { | |
| const Vec2 result = { lhs.x - rhs.x, lhs.y - rhs.y }; | |
| return result; | |
| } | |
| inline Vec2 operator-(const Vec2& v) | |
| { | |
| const Vec2 result = { -v.x, -v.y }; | |
| return result; | |
| } | |
| inline Vec2 operator*(const Vec2& lhs, const Vec2& rhs) | |
| { | |
| const Vec2 result = | |
| { | |
| lhs.x * rhs.x, | |
| lhs.y * rhs.y, | |
| }; | |
| return result; | |
| } | |
| inline Vec2 operator*(const Matrix2x2& lhs, const Vec2& rhs) | |
| { | |
| const Vec2 result = | |
| { | |
| lhs.a11 * rhs.x + lhs.a12 * rhs.y, | |
| lhs.a21 * rhs.x + lhs.a22 * rhs.y | |
| }; | |
| return result; | |
| } | |
| // Vec3 | |
| inline Vec3 operator+(const Vec3& lhs, const Vec3& rhs) | |
| { | |
| const Vec3 result = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z }; | |
| return result; | |
| } | |
| inline Vec3 operator-(const Vec3& lhs, const Vec3& rhs) | |
| { | |
| const Vec3 result = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z }; | |
| return result; | |
| } | |
| inline Vec3 operator-(const Vec3& v) | |
| { | |
| const Vec3 result = { -v.x, -v.y, -v.z }; | |
| return result; | |
| } | |
| inline Vec3 operator*(const Vec3& lhs, const Vec3& rhs) | |
| { | |
| const Vec3 result = { lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z }; | |
| return result; | |
| } | |
| inline Vec3 operator*(const Matrix3x3& lhs, const Vec3& rhs) | |
| { | |
| const Vec3 result = | |
| { | |
| lhs.a11 * rhs.x + lhs.a12 * rhs.y + lhs.a13 * rhs.z, | |
| lhs.a21 * rhs.x + lhs.a22 * rhs.y + lhs.a23 * rhs.z, | |
| lhs.a31 * rhs.x + lhs.a32 * rhs.y + lhs.a33 * rhs.z | |
| }; | |
| return result; | |
| } | |
| inline Vec3 operator*(const Matrix4x4& lhs, const Vec3& rhs) | |
| { | |
| const Vec3 result = | |
| { | |
| lhs.a11 * rhs.x + lhs.a12 * rhs.y + lhs.a13 * rhs.z + lhs.a14, | |
| lhs.a21 * rhs.x + lhs.a22 * rhs.y + lhs.a23 * rhs.z + lhs.a24, | |
| lhs.a31 * rhs.x + lhs.a32 * rhs.y + lhs.a33 * rhs.z + lhs.a34 | |
| }; | |
| return result; | |
| } | |
| inline Vec3 operator*(const Vec3& lhs, const float rhs) | |
| { | |
| const Vec3 result = { lhs.x * rhs, lhs.y * rhs, lhs.z * rhs }; | |
| return result; | |
| } | |
| inline Vec3 operator*(const float lhs, const Vec3& rhs) | |
| { | |
| return rhs * lhs; | |
| } | |
| inline Vec3 operator/(const Vec3& lhs, const float rhs) | |
| { | |
| const Vec3 result = { lhs.x / rhs, lhs.y / rhs, lhs.z / rhs }; | |
| return result; | |
| } | |
| inline float Dot(const Vec3& lhs, const Vec3& rhs) | |
| { | |
| return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; | |
| } | |
| inline Vec3 Cross(const Vec3& lhs, const Vec3& rhs) | |
| { | |
| const Vec3 result = | |
| { | |
| (lhs.y * rhs.z) - (lhs.z * rhs.y), | |
| (lhs.z * rhs.x) - (lhs.x * rhs.z), | |
| (lhs.x * rhs.y) - (lhs.y * rhs.x) | |
| }; | |
| return result; | |
| } | |
| inline float Length(const Vec3& v) | |
| { | |
| return std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z); | |
| } | |
| inline float LengthSquared(const Vec3& v) | |
| { | |
| return v.x * v.x + v.y * v.y + v.z * v.z; | |
| } | |
| inline Vec3 Normalize(Vec3* v) | |
| { | |
| const float invLength = 1.0 / Length(*v); | |
| v->x *= invLength; | |
| v->y *= invLength; | |
| v->z *= invLength; | |
| return *v; | |
| } | |
| inline Vec3 Normalized(const Vec3& v) | |
| { | |
| const float invLength = 1.0 / Length(v); | |
| const Vec3 result = | |
| { | |
| v.x * invLength, | |
| v.y * invLength, | |
| v.z * invLength, | |
| }; | |
| return result; | |
| } | |
| inline float Distance(const Vec3& v1, const Vec3& v2) | |
| { | |
| return Length(v1 - v2); | |
| } | |
| inline float DistanceSquared(const Vec3& v1, const Vec3& v2) | |
| { | |
| return LengthSquared(v1 - v2); | |
| } | |
| inline Vec3 Lerp(const Vec3& v1, const Vec3& v2, const float amount) | |
| { | |
| const float diff = 1.0f - amount; | |
| const Vec3 result = | |
| { | |
| diff * v1.x + amount * v2.x, | |
| diff * v1.y + amount * v2.y, | |
| diff * v1.z + amount * v2.z | |
| }; | |
| return result; | |
| } | |
| // Quaternion | |
| inline Quaternion operator+(const Quaternion& lhs, const Quaternion& rhs) | |
| { | |
| const Quaternion result = | |
| { | |
| lhs.x + rhs.x, | |
| lhs.y + rhs.y, | |
| lhs.z + rhs.z, | |
| lhs.w + rhs.w | |
| }; | |
| return result; | |
| } | |
| inline Quaternion operator-(const Quaternion& lhs, const Quaternion& rhs) | |
| { | |
| const Quaternion result = | |
| { | |
| lhs.x - rhs.x, | |
| lhs.y - rhs.y, | |
| lhs.z - rhs.z, | |
| lhs.w - rhs.w | |
| }; | |
| return result; | |
| } | |
| inline Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs) | |
| { | |
| const Quaternion result = | |
| { | |
| lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y, | |
| lhs.w * rhs.y + lhs.y * rhs.w + lhs.z * rhs.x - lhs.x * rhs.z, | |
| lhs.w * rhs.z + lhs.z * rhs.w + lhs.x * rhs.y - lhs.y * rhs.x, | |
| lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z | |
| }; | |
| return result; | |
| } | |
| inline Quaternion operator*(const Quaternion& lhs, const float rhs) | |
| { | |
| const Quaternion result = | |
| { | |
| lhs.x * rhs, | |
| lhs.y * rhs, | |
| lhs.z * rhs, | |
| lhs.w * rhs | |
| }; | |
| return result; | |
| } | |
| inline Quaternion operator*(const float lhs, const Quaternion& rhs) | |
| { | |
| const Quaternion result = | |
| { | |
| rhs.x * lhs, | |
| rhs.y * lhs, | |
| rhs.z * lhs, | |
| rhs.w * lhs | |
| }; | |
| return result; | |
| } | |
| inline float Length(const Quaternion& q) | |
| { | |
| return std::sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); | |
| } | |
| inline float LengthSquared(const Quaternion& q) | |
| { | |
| return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; | |
| } | |
| inline Quaternion Normalized(const Quaternion& q) | |
| { | |
| const float invLength = 1.0 / Length(q); | |
| const Quaternion result = | |
| { | |
| q.x * invLength, | |
| q.y * invLength, | |
| q.z * invLength, | |
| q.w * invLength | |
| }; | |
| return result; | |
| } | |
| inline Quaternion QuaternionFromAxis(const float ax, const float ay, const float az, | |
| const float angleInDegrees) | |
| { | |
| const float halfRad = angleInDegrees * PI / 360; | |
| const float halfSin = std::sin(halfRad); | |
| const float halfCos = std::cos(halfRad); | |
| const Quaternion result = | |
| { | |
| -ax * halfSin, | |
| -ay * halfSin, | |
| -az * halfSin, | |
| halfCos | |
| }; | |
| return Normalized(result); | |
| } | |
| inline Quaternion QuaternionFromAxis(const Vec3& axis, const float angleInDegrees) | |
| { | |
| return QuaternionFromAxis(axis.x, axis.y, axis.z, angleInDegrees); | |
| } | |
| inline Quaternion QuaternionFromEuler(const float x, const float y, const float z) | |
| { | |
| const float rx = x * PI / 360; | |
| const float ry = y * PI / 360; | |
| const float rz = z * PI / 360; | |
| const float sinX = -std::sin(rx); | |
| const float sinY = -std::sin(ry); | |
| const float sinZ = -std::sin(rz); | |
| const float cosX = std::cos(rx); | |
| const float cosY = std::cos(ry); | |
| const float cosZ = std::cos(rz); | |
| const float sinXsinY = sinX * sinY; | |
| const float sinXcosY = sinX * cosY; | |
| const float cosXcosY = cosX * cosY; | |
| const float cosXsinY = cosX * sinY; | |
| const Quaternion result = | |
| { | |
| cosXsinY * sinZ + sinXcosY * cosZ, | |
| cosXsinY * cosZ + sinXcosY * sinZ, | |
| cosXcosY * sinZ - sinXsinY * cosZ, | |
| cosXcosY * cosZ - sinXsinY * sinZ | |
| }; | |
| return Normalized(result); | |
| } | |
| inline Quaternion QuaternionFromEuler(const Vec3& v) | |
| { | |
| return QuaternionFromEuler(v.x, v.y, v.z); | |
| } | |
| inline Quaternion Rotated(const Quaternion& q, | |
| const Vec3& axis, const float angle) | |
| { | |
| return Normalized(QuaternionFromAxis(axis, angle) * q); | |
| } | |
| inline float Dot(const Quaternion& lhs, const Quaternion& rhs) | |
| { | |
| return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w; | |
| } | |
| inline Quaternion Conjugate(const Quaternion& q) | |
| { | |
| const Quaternion result = { -q.x, -q.y, -q.z, q.w }; | |
| return result; | |
| } | |
| inline Quaternion Inverse(const Quaternion& q) | |
| { | |
| const float invLengthSquared = 1.0 / LengthSquared(q); | |
| const Quaternion result = | |
| { | |
| -q.x * invLengthSquared, | |
| -q.y * invLengthSquared, | |
| -q.z * invLengthSquared, | |
| q.w * invLengthSquared | |
| }; | |
| return result; | |
| } | |
| inline Vec3 Rotated(const Vec3& v, const Quaternion& q) | |
| { | |
| const Vec3 u = { q.x, q.y, q.z }; | |
| const float s = q.w; | |
| return 2.0f * Dot(u, v) * u | |
| + (s*s - Dot(u, u)) * v | |
| + 2.0f * s * Cross(u, v); | |
| } | |
| inline Vec3 Forward(const Quaternion& q) | |
| { | |
| return Rotated(Vec3::Forward(), q); | |
| } | |
| inline Vec3 Backward(const Quaternion& q) | |
| { | |
| return Rotated(Vec3::Backward(), q); | |
| } | |
| inline Vec3 Up(const Quaternion& q) | |
| { | |
| return Rotated(Vec3::Up(), q); | |
| } | |
| inline Vec3 Down(const Quaternion& q) | |
| { | |
| return Rotated(Vec3::Down(), q); | |
| } | |
| inline Vec3 Left(const Quaternion& q) | |
| { | |
| return Rotated(Vec3::Left(), q); | |
| } | |
| inline Vec3 Right(const Quaternion& q) | |
| { | |
| return Rotated(Vec3::Right(), q); | |
| } | |
| // Matrix2x2 | |
| inline Matrix2x2 operator*(const Matrix2x2& lhs, const Matrix2x2& rhs) | |
| { | |
| Matrix2x2 result = { 0 }; | |
| result.a11 = lhs.a11 * rhs.a11 + lhs.a12 * rhs.a21; | |
| result.a12 = lhs.a11 * rhs.a12 + lhs.a12 * rhs.a22; | |
| result.a21 = lhs.a21 * rhs.a11 + lhs.a22 * rhs.a21; | |
| result.a22 = lhs.a21 * rhs.a12 + lhs.a22 * rhs.a22; | |
| return result; | |
| } | |
| // Matrix3x3 | |
| inline Matrix3x3 operator*(const Matrix3x3& lhs, const Matrix3x3& rhs) | |
| { | |
| Matrix3x3 result = { 0 }; | |
| result.a11 = lhs.a11 * rhs.a11 + lhs.a12 * rhs.a21 + lhs.a13 * rhs.a31; | |
| result.a12 = lhs.a11 * rhs.a12 + lhs.a12 * rhs.a22 + lhs.a13 * rhs.a32; | |
| result.a13 = lhs.a11 * rhs.a13 + lhs.a12 * rhs.a23 + lhs.a13 * rhs.a33; | |
| result.a21 = lhs.a21 * rhs.a11 + lhs.a22 * rhs.a21 + lhs.a23 * rhs.a31; | |
| result.a22 = lhs.a21 * rhs.a12 + lhs.a22 * rhs.a22 + lhs.a23 * rhs.a32; | |
| result.a23 = lhs.a21 * rhs.a13 + lhs.a22 * rhs.a23 + lhs.a23 * rhs.a33; | |
| result.a31 = lhs.a31 * rhs.a11 + lhs.a32 * rhs.a21 + lhs.a33 * rhs.a31; | |
| result.a32 = lhs.a31 * rhs.a12 + lhs.a32 * rhs.a22 + lhs.a33 * rhs.a32; | |
| result.a33 = lhs.a31 * rhs.a13 + lhs.a32 * rhs.a23 + lhs.a33 * rhs.a33; | |
| return result; | |
| } | |
| // Matrix4x4 | |
| inline Matrix4x4 operator*(const Matrix4x4& lhs, const Matrix4x4& rhs) | |
| { | |
| Matrix4x4 result = { 0 }; | |
| // First row | |
| result.a11 = lhs.a11 * rhs.a11 + lhs.a12 * rhs.a21 + lhs.a13 * rhs.a31 + lhs.a14 * rhs.a41; | |
| result.a12 = lhs.a11 * rhs.a12 + lhs.a12 * rhs.a22 + lhs.a13 * rhs.a32 + lhs.a14 * rhs.a42; | |
| result.a13 = lhs.a11 * rhs.a13 + lhs.a12 * rhs.a23 + lhs.a13 * rhs.a33 + lhs.a14 * rhs.a43; | |
| result.a14 = lhs.a11 * rhs.a14 + lhs.a12 * rhs.a24 + lhs.a13 * rhs.a34 + lhs.a14 * rhs.a44; | |
| // Second row | |
| result.a21 = lhs.a21 * rhs.a11 + lhs.a22 * rhs.a21 + lhs.a23 * rhs.a31 + lhs.a24 * rhs.a41; | |
| result.a22 = lhs.a21 * rhs.a12 + lhs.a22 * rhs.a22 + lhs.a23 * rhs.a32 + lhs.a24 * rhs.a42; | |
| result.a23 = lhs.a21 * rhs.a13 + lhs.a22 * rhs.a23 + lhs.a23 * rhs.a33 + lhs.a24 * rhs.a43; | |
| result.a24 = lhs.a21 * rhs.a14 + lhs.a22 * rhs.a24 + lhs.a23 * rhs.a34 + lhs.a24 * rhs.a44; | |
| // Third row | |
| result.a31 = lhs.a31 * rhs.a11 + lhs.a32 * rhs.a21 + lhs.a33 * rhs.a31 + lhs.a34 * rhs.a41; | |
| result.a32 = lhs.a31 * rhs.a12 + lhs.a32 * rhs.a22 + lhs.a33 * rhs.a32 + lhs.a34 * rhs.a42; | |
| result.a33 = lhs.a31 * rhs.a13 + lhs.a32 * rhs.a23 + lhs.a33 * rhs.a33 + lhs.a34 * rhs.a43; | |
| result.a34 = lhs.a31 * rhs.a14 + lhs.a32 * rhs.a24 + lhs.a33 * rhs.a34 + lhs.a34 * rhs.a44; | |
| // Fourth row | |
| result.a41 = lhs.a41 * rhs.a11 + lhs.a42 * rhs.a21 + lhs.a43 * rhs.a31 + lhs.a44 * rhs.a41; | |
| result.a42 = lhs.a41 * rhs.a12 + lhs.a42 * rhs.a22 + lhs.a43 * rhs.a32 + lhs.a44 * rhs.a42; | |
| result.a43 = lhs.a41 * rhs.a13 + lhs.a42 * rhs.a23 + lhs.a43 * rhs.a33 + lhs.a44 * rhs.a43; | |
| result.a44 = lhs.a41 * rhs.a14 + lhs.a42 * rhs.a24 + lhs.a43 * rhs.a34 + lhs.a44 * rhs.a44; | |
| return result; | |
| } | |
| inline Matrix4x4 CreateMatrix4x4() | |
| { | |
| const Matrix4x4 result = | |
| { | |
| 1, 0, 0, 0, | |
| 0, 1, 0, 0, | |
| 0, 0, 1, 0, | |
| 0, 0, 0, 1 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 CreateMatrix4x4(const float d) | |
| { | |
| const Matrix4x4 result = | |
| { | |
| d, 0, 0, 0, | |
| 0, d, 0, 0, | |
| 0, 0, d, 0, | |
| 0, 0, 0, d | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 CreateMatrix4x4(const Quaternion& q) | |
| { | |
| const float xx2 = 2.0f * q.x * q.x; | |
| const float xy2 = 2.0f * q.x * q.y; | |
| const float xz2 = 2.0f * q.x * q.z; | |
| const float xw2 = 2.0f * q.x * q.w; | |
| const float yy2 = 2.0f * q.y * q.y; | |
| const float yz2 = 2.0f * q.y * q.z; | |
| const float yw2 = 2.0f * q.y * q.w; | |
| const float zz2 = 2.0f * q.z * q.z; | |
| const float zw2 = 2.0f * q.z * q.w; | |
| const Matrix4x4 result = | |
| { | |
| 1.0f - (yy2 + zz2), xy2 + zw2, xz2 - yw2, 0.0f, | |
| xy2 - zw2, 1.0f - (xx2 + zz2), yz2 + xw2, 0.0f, | |
| xz2 + yw2, yz2 - xw2, 1.0f - (xx2 + yy2), 0.0f, | |
| 0.0f, 0.0f, 0.0f, 1.0f | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 Transpose(const Matrix4x4& m) | |
| { | |
| const Matrix4x4 result = | |
| { | |
| m.a11, m.a21, m.a31, m.a41, | |
| m.a12, m.a22, m.a32, m.a42, | |
| m.a13, m.a23, m.a33, m.a43, | |
| m.a14, m.a24, m.a34, m.a44 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 Translate(const Matrix4x4& m, const Vec3& v) | |
| { | |
| const Matrix4x4 translate = | |
| { | |
| 1, 0, 0, v.x, | |
| 0, 1, 0, v.y, | |
| 0, 0, 1, v.z, | |
| 0, 0, 0, 1 | |
| }; | |
| return translate * m; | |
| } | |
| inline Matrix4x4 Translate(const Vec3& v) | |
| { | |
| const Matrix4x4 result = | |
| { | |
| 1, 0, 0, v.x, | |
| 0, 1, 0, v.y, | |
| 0, 0, 1, v.z, | |
| 0, 0, 0, 1 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 Scale(const Matrix4x4& m, const Vec3& v) | |
| { | |
| const Matrix4x4 scale = | |
| { | |
| v.x, 0, 0, 0, | |
| 0, v.y, 0, 0, | |
| 0, 0, v.z, 0, | |
| 0, 0, 0, 1 | |
| }; | |
| return scale * m; | |
| } | |
| inline Matrix4x4 Scale(const Vec3& v) | |
| { | |
| const Matrix4x4 result = | |
| { | |
| v.x, 0, 0, 0, | |
| 0, v.y, 0, 0, | |
| 0, 0, v.z, 0, | |
| 0, 0, 0, 1 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 Mirror(const Matrix4x4& m) | |
| { | |
| const Matrix4x4 scale = | |
| { | |
| -1, 0, 0, 0, | |
| 0, -1, 0, 0, | |
| 0, 0, -1, 0, | |
| 0, 0, 0, 1 | |
| }; | |
| return scale * m; | |
| } | |
| inline Matrix4x4 Mirror() | |
| { | |
| const Matrix4x4 result = | |
| { | |
| -1, 0, 0, 0, | |
| 0, -1, 0, 0, | |
| 0, 0, -1, 0, | |
| 0, 0, 0, 1 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 Ortho(const float left, const float right, | |
| const float bottom, const float top, | |
| const float zNear, const float zFar) | |
| { | |
| const float width = right - left; | |
| const float height = top - bottom; | |
| const float depth = zFar - zNear; | |
| const Matrix4x4 result = | |
| { | |
| 2.0f / width, 0, 0, -(right + left) / width, | |
| 0, 2.0f / height, 0, -(top + bottom) / height, | |
| 0, 0, -2.0f / depth, -(zFar + zNear) / depth, | |
| 0, 0, 0, 0 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 Perspective(const float fovy, const float aspect, | |
| const float zNear, const float zFar) | |
| { | |
| const float angle = (fovy / 2.0f) * PI / 180.0f; | |
| const float yScale = 1.0f / std::tan(angle); | |
| const float xScale = yScale / aspect; | |
| const float depth = zFar - zNear; | |
| const Matrix4x4 result = | |
| { | |
| xScale, 0, 0, 0, | |
| 0, yScale, 0, 0, | |
| 0, 0, (zNear + zFar) / depth, -2.0f * zNear * zFar / depth, | |
| 0, 0, 1, 0 | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 LookAt(const Vec3& eye, const Vec3& look, const Vec3& up) | |
| { | |
| const Vec3 l = Normalized(look); | |
| const Vec3 r = Cross(look, up); | |
| const Vec3 u = Normalized(Cross(r, l)); | |
| const Matrix4x4 result = | |
| { | |
| r.x, u.x, -l.x, -r.x * eye.x - u.x * eye.y + l.x * eye.z, | |
| r.y, u.y, -l.y, -r.y * eye.x - u.y * eye.y + l.y * eye.z, | |
| r.z, u.z, -l.z, -r.z * eye.x - u.z * eye.y + l.z * eye.z, | |
| 0, 0, 0, 1, | |
| }; | |
| return result; | |
| } | |
| inline Matrix4x4 ViewMatrix4x4(const Vec3& position, const Quaternion& orientation) | |
| { | |
| const Vec3 r = Right(orientation); | |
| const Vec3 u = Up(orientation); | |
| const Vec3 f = Forward(orientation); | |
| const Matrix4x4 result = | |
| { | |
| r.x, r.y, r.z, -r.x * position.x - r.y * position.y - r.z * position.z, | |
| u.x, u.y, u.z, -u.x * position.x - u.y * position.y - u.z * position.z, | |
| f.x, f.y, f.z, -f.x * position.x - f.y * position.y - f.z * position.z, | |
| 0, 0, 0, 1 | |
| }; | |
| return result; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment