480 lines
9.9 KiB
C++
480 lines
9.9 KiB
C++
#include "../engine/Shared.h"
|
|
#include "Global.h"
|
|
#include "Instance.h"
|
|
#include "bx/bx.h"
|
|
#include "bx/math.h"
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
|
|
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<uint8_t*>(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<void*>(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;
|
|
}
|