#pragma once #define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include "ps1types.h" #define WORLDSHIFT 2 #define WORLDSCALE 4 // (1 << WORLDSHIFT) typedef float scalar_t; // Scalar value, typedef struct Vec3 // Vector or Position { scalar_t x; // horizontal scalar_t y; // horizontal scalar_t z; // vertical Vec3() : x(0), y(0), z(0) { } Vec3(float x, float y, float z) : x(x), y(y), z(z) { } Vec3(double x, double y, double z) : x((float)x), y((float)y), z((float)z) { } Vec3(int x, int y, int z) : x((float)x), y((float)y), z((float)z) { } Vec3(short x, short y, short z) : x((float)x), y((float)y), z((float)z) { } Vec3 operator+(const Vec3& other) const { return Vec3(x + other.x, y + other.y, z + other.z); } Vec3 operator-(const Vec3& other) const { return Vec3(x - other.x, y - other.y, z - other.z); } Vec3 operator*(float mul) const { return Vec3(x * mul, y * mul, z * mul); } Vec3 operator*(double mul) const { return Vec3((double)x * mul, (double)y * mul, (double)z * mul); } Vec3 operator/(float div) const { return Vec3(x / div, y / div, z / div); } Vec3 operator-() const { return Vec3(-x, -y, -z); } double magnitude() const { return sqrt((double)x * x + (double)y * y + (double)z * z); } double sqrMagnitude() const { return (double)x * x + (double)y * y + (double)z * z; } double longestElement() const { double longest = fabs(x); if (fabs(y) > longest) longest = fabs(y); if (fabs(z) > longest) longest = fabs(z); return longest; } Vec3 normalized() const { double invMag = 1.0 / magnitude(); return Vec3(invMag * x, invMag * y, invMag * z); } double dotProduct(const Vec3 &other) const { return (double)x * other.x + (double)y * other.y + (double)z * other.z; } Vec3 crossProduct(const Vec3 &other) const { return Vec3( (double)y * other.z - (double)z * other.y, (double)z * other.x - (double)x * other.z, (double)x * other.y - (double)y * other.x ); } Vec3 floor() const { return Vec3(floorf(x), floorf(y), floorf(z)); } Vec3 ceil() const { return Vec3(ceilf(x), ceilf(y), ceilf(z)); } SVECTOR convertNormal() { SVECTOR outNormal; outNormal.vx = (short)(x * ONE); outNormal.vy = (short)(y * ONE); outNormal.vz = (short)(z * ONE); outNormal.pad = 0; return outNormal; } SVECTOR convertWorldPosition() { SVECTOR outPoint; outPoint.vx = (short)(x * WORLDSCALE); outPoint.vy = (short)(y * WORLDSCALE); outPoint.vz = (short)(z * WORLDSCALE); outPoint.pad = ONE; return outPoint; } } vec3_t; template<> struct std::hash { std::uint64_t operator()(const Vec3& vec) const { int x = (int)(vec.x * 100); int y = (int)(vec.y * 100); int z = (int)(vec.z * 100); return (*((uint64_t*)&x) << 40) | (*((uint64_t*)&y) << 20) | (*((uint64_t*)&z) << 0); } }; static bool operator==(const Vec3& lhs, const Vec3& rhs) { return fabs(rhs.x - lhs.x) < 0.01 && fabs(rhs.y - lhs.y) < 0.01 && fabs(rhs.z - lhs.z) < 0.01; } static bool operator<(const Vec3& lhs, const Vec3& rhs) { if (fabs(rhs.x - lhs.x) < 0.01) if (fabs(rhs.y - lhs.y) < 0.01) return lhs.z < rhs.z; else return lhs.y < rhs.y; else return lhs.x < rhs.x; } // Halton sequence, helpfully yoinked from the FSR2 code: https://github.com/GPUOpen-Effects/FidelityFX-FSR2 static float halton(int32_t index, int32_t base) { float f = 1.0f, result = 0.0f; for (int32_t currentIndex = index; currentIndex > 0;) { f /= (float)base; result = result + f * (float)(currentIndex % base); currentIndex = (uint32_t)(floorf((float)(currentIndex) / (float)(base))); } return result; } static void getJitterOffset(float* outX, float* outY, int32_t index, int32_t phaseCount) { const float x = halton((index % phaseCount) + 1, 2) - 0.5f; const float y = halton((index % phaseCount) + 1, 3) - 0.5f; *outX = x; *outY = y; }