#include "../engine/Shared.h" #include "Global.h" #include "Instance.h" #include "bx/bx.h" #include "bx/math.h" #include #include using namespace Gen; namespace { SharedData* SharedInstance = nullptr; Game::GameInstance* GameInst = nullptr; } // namespace namespace Game { SharedData& GetShared() { assert(SharedInstance != nullptr); return *SharedInstance; } void SetShared(SharedData& instance) { SharedInstance = &instance; } GameInstance& GetInstance() { assert(GameInst != nullptr); return *GameInst; } void SetInstance(Game::GameInstance& instance) { GameInst = &instance; } void* AllocateScratch(size_t byteCount, size_t align) { size_t offset = GetInstance().UsedScratchAmount; uint8_t* base = static_cast(GetShared().Game.TransientStorage); uint8_t* current = base + offset; size_t offsetAligned = ((offset + align - 1) / align) * align; uint8_t* ptrAligned = base + offsetAligned; size_t newOffset = offsetAligned + byteCount; if (newOffset > GetShared().Game.TransientStorageSize) return nullptr; GetInstance().UsedScratchAmount = newOffset; return reinterpret_cast(ptrAligned); } } // namespace Game void Transform::CreateTransform(float* out, bx::Vec3 pos, bx::Quaternion rot, bx::Vec3 scale) { if (out == nullptr) return; float rMat[16]{0}; float tMat[16]{0}; float sMat[16]{0}; bx::mtxFromQuaternion(rMat, bx::Quaternion{rot.x, rot.y, rot.z, rot.w}); bx::mtxTranslate(tMat, pos.x, pos.y, pos.z); bx::mtxScale(sMat, scale.x, scale.y, scale.z); float buf[16]{0}; bx::mtxMul(buf, rMat, sMat); bx::mtxMul(out, buf, tMat); } void Transform::Translate(Vec3 offset) { Position = bx::add(Position, {offset.x, offset.y, offset.z}); } void Transform::TranslateLocal(Vec3 offset) { Vec3 localOffset = GlobalToLocalDirection(offset); Position = bx::add(Position, {localOffset.x, localOffset.y, localOffset.z}); } void Transform::Rotate(Vec3 rotation) { float rot[16]{0}; bx::mtxRotateXYZ(rot, rotation.x, rotation.y, rotation.z); float temp[16]{0}; bx::mtxMul(temp, rot, Rotation.M); bx::memCopy(Rotation.M, temp, sizeof(temp)); } void Transform::RotateLocal(Vec3 rotation) { float rot[16]{0}; bx::mtxRotateXYZ(rot, rotation.x, rotation.y, rotation.z); float temp[16]{0}; bx::mtxMul(temp, Rotation.M, rot); bx::memCopy(Rotation.M, temp, sizeof(temp)); } Vec3 Transform::Right() const { return {M.M[0], M.M[1], M.M[2]}; } Vec3 Transform::Up() const { return {M.M[4], M.M[5], M.M[6]}; } Vec3 Transform::Forward() const { return {M.M[8], M.M[9], M.M[10]}; } void Transform::UpdateMatrix() { Mat4 pos; Mat4 scale; bx::mtxTranslate(pos.M, Position.x, Position.y, Position.z); bx::mtxScale(scale.M, Scale.x, Scale.y, Scale.z); Mat4 temp; bx::mtxMul(temp.M, scale.M, Rotation.M); bx::mtxMul(M.M, temp.M, pos.M); bx::mtxInverse(MI.M, M.M); } Vec3 Transform::GlobalToLocalDirection(Vec3 global) { UpdateMatrix(); float in[4]{global.x, global.y, global.z, 0.0f}; float out[4]{0.0f}; bx::vec4MulMtx(out, in, Transpose(MI).M); return {out[0], out[1], out[2]}; } Vec3 Transform::GlobalToLocalPoint(Vec3 global) { UpdateMatrix(); float in[4]{global.x, global.y, global.z, 1.0f}; float out[4]{0.0f}; bx::vec4MulMtx(out, in, MI.M); return {out[0], out[1], out[2]}; } Vec3 Transform::LocalToGlobalDirection(Vec3 local) { UpdateMatrix(); float in[4]{local.x, local.y, local.z, 0.0f}; float out[4]{0.0f}; bx::vec4MulMtx(out, in, Transpose(M).M); return {out[0], out[1], out[2]}; } Vec3 Transform::LocalToGlobalPoint(Vec3 local) { UpdateMatrix(); float in[4]{local.x, local.y, local.z, 1.0f}; float out[4]{0.0f}; bx::vec4MulMtx(out, in, M.M); return {out[0], out[1], out[2]}; } void Transform::SetPosition(Vec3 pos) { Position = {pos.x, pos.y, pos.z}; } Vec3 Transform::GetPosition() { return {Position.x, Position.y, Position.z}; } // Vec4 Vec4& operator+=(Vec4& lhs, const Vec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; } Vec4 operator+(const Vec4& lhs, const Vec4& rhs) { Vec4 out = lhs; return out += rhs; } Vec4& operator+=(Vec4& lhs, float rhs) { lhs.x += rhs; lhs.y += rhs; lhs.z += rhs; lhs.w += rhs; return lhs; } Vec4 operator+(Vec4& lhs, float rhs) { Vec4 out = lhs; return out += rhs; } Vec4& operator-=(Vec4& lhs, const Vec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; } Vec4 operator-(const Vec4& lhs, const Vec4& rhs) { Vec4 out = lhs; return out -= rhs; } Vec4& operator-=(Vec4& lhs, float rhs) { lhs.x -= rhs; lhs.y -= rhs; lhs.z -= rhs; lhs.w -= rhs; return lhs; } Vec4 operator-(const Vec4& lhs, float rhs) { Vec4 out = lhs; return out -= rhs; } Vec4& operator*=(Vec4& lhs, float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; } Vec4 operator*(const Vec4& lhs, float rhs) { Vec4 out = lhs; return out *= rhs; } Vec4& operator/=(Vec4& lhs, float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; } Vec4 operator/(const Vec4& lhs, float rhs) { Vec4 out = lhs; return out /= rhs; } // Vec3 Vec3& operator+=(Vec3& lhs, const Vec3& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; return lhs; } Vec3 operator+(const Vec3& lhs, const Vec3& rhs) { Vec3 out = lhs; return out += rhs; } Vec3& operator+=(Vec3& lhs, float rhs) { lhs.x += rhs; lhs.y += rhs; lhs.z += rhs; return lhs; } Vec3 operator+(Vec3& lhs, float rhs) { Vec3 out = lhs; return out += rhs; } Vec3& operator-=(Vec3& lhs, const Vec3& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; return lhs; } Vec3 operator-(const Vec3& lhs, const Vec3& rhs) { Vec3 out = lhs; return out -= rhs; } Vec3& operator-=(Vec3& lhs, float rhs) { lhs.x -= rhs; lhs.y -= rhs; lhs.z -= rhs; return lhs; } Vec3 operator-(const Vec3& lhs, float rhs) { Vec3 out = lhs; return out -= rhs; } Vec3& operator*=(Vec3& lhs, float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; return lhs; } Vec3 operator*(const Vec3& lhs, float rhs) { Vec3 out = lhs; return out *= rhs; } Vec3& operator/=(Vec3& lhs, float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; return lhs; } Vec3 operator/(const Vec3& lhs, float rhs) { Vec3 out = lhs; return out /= rhs; } // Vec2 Vec2& operator+=(Vec2& lhs, const Vec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } Vec2 operator+(const Vec2& lhs, const Vec2& rhs) { Vec2 out = lhs; return out += rhs; } Vec2& operator+=(Vec2& lhs, float rhs) { lhs.x += rhs; lhs.y += rhs; return lhs; } Vec2 operator+(Vec2& lhs, float rhs) { Vec2 out = lhs; return out += rhs; } Vec2& operator-=(Vec2& lhs, const Vec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } Vec2 operator-(const Vec2& lhs, const Vec2& rhs) { Vec2 out = lhs; return out -= rhs; } Vec2& operator-=(Vec2& lhs, float rhs) { lhs.x -= rhs; lhs.y -= rhs; return lhs; } Vec2 operator-(const Vec2& lhs, float rhs) { Vec2 out = lhs; return out -= rhs; } Vec2& operator*=(Vec2& lhs, float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } Vec2 operator*(const Vec2& lhs, float rhs) { Vec2 out = lhs; return out *= rhs; } Vec2& operator/=(Vec2& lhs, float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } Vec2 operator/(const Vec2& lhs, float rhs) { Vec2 out = lhs; return out /= rhs; } Mat4 Inverse(const Mat4& mat) { Mat4 result; bx::mtxInverse(result.M, &mat.M[0]); return result; } Mat4 Transpose(const Mat4& mat) { Mat4 result; bx::mtxTranspose(result.M, &mat.M[0]); return result; } Vec4 Mul(const Mat4& mat, const Vec4& vec) { Vec4 out; bx::vec4MulMtx(&out.x, &vec.x, &mat.M[0]); return out; } float Magnitude(const Vec4& vec) { return bx::sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z + vec.w * vec.w); } float Magnitude(const Vec3& vec) { return bx::sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z); } float Magnitude(const Vec2& vec) { return bx::sqrt(vec.x * vec.x + vec.y * vec.y); } Vec4 Normalized(const Vec4& vec) { Vec4 res = vec; return res /= Magnitude(vec); } Vec3 Normalized(const Vec3& vec) { Vec3 res = vec; return res /= Magnitude(vec); } Vec2 Normalized(const Vec2& vec) { Vec2 res = vec; return res /= Magnitude(vec); } float DotProduct(Vec3 a, Vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } Vec3 CrossProduct(Vec3 a, Vec3 b) { float x = a.y * b.z - a.z * b.y; float y = a.z * b.x - a.x * b.z; float z = a.x * b.y - a.y * b.x; return {x, y, z}; } Vec3 CrossProductFromPlane(Vec3 a, Vec3 b, Vec3 c) { // TODO: normalize might not be necessary Vec3 lineA = Normalized(b - a); Vec3 lineB = Normalized(c - a); return CrossProduct(lineA, lineB); } bool RayPlaneIntersect(Vec3 l1, Vec3 l2, Vec3 p1, Vec3 p2, Vec3 p3, Vec3& out) { // thanks to Paul Bourke and Bryan Hanson // l1,l2 constitute the line. P1,P2,P3 constitute the plane out = {}; Vec3 N = CrossProductFromPlane(p1, p2, p3); // N is the normal of the plane float n = DotProduct(N, Vec3{p3.x - l1.x, p3.y - l1.y, p3.z - l1.z}); Vec3 LbMinusLa = Vec3{l2.x - l1.x, l2.y - l1.y, l2.z - l1.z}; float d = DotProduct(N, LbMinusLa); if (d == 0) return false; // Line is parallel to or in the plane float u = n / d; if ((u >= 0.0) && (u <= 1.0)) { // Plane is between the two points } // can be used for checking but does not influence the outcome out = Vec3{l1.x + u * LbMinusLa.x, l1.y + u * LbMinusLa.y, l1.z + u * LbMinusLa.z}; return true; }