diff --git a/SA2LevelEditor/SA2LevelEditor.vcxproj b/SA2LevelEditor/SA2LevelEditor.vcxproj index 77b7a63..cfb3354 100644 --- a/SA2LevelEditor/SA2LevelEditor.vcxproj +++ b/SA2LevelEditor/SA2LevelEditor.vcxproj @@ -94,6 +94,7 @@ true true ../Libraries/Include;%(AdditionalIncludeDirectories) + stdcpp20 opengl32.lib;glfw3.lib;SOIL.lib;%(AdditionalDependencies) @@ -106,6 +107,7 @@ true true ../Libraries/Include;%(AdditionalIncludeDirectories) + stdcpp20 opengl32.lib;glfw3.lib;SOIL.lib;%(AdditionalDependencies) @@ -124,6 +126,7 @@ Speed true true + stdcpp20 true @@ -144,6 +147,7 @@ Speed true true + stdcpp20 true diff --git a/SA2LevelEditor/src/collision/Triangle3D.cpp b/SA2LevelEditor/src/collision/Triangle3D.cpp index 3f26013..f95aa71 100644 --- a/SA2LevelEditor/src/collision/Triangle3D.cpp +++ b/SA2LevelEditor/src/collision/Triangle3D.cpp @@ -2,7 +2,6 @@ #include "triangle3d.h" #include "../toolbox/vector.h" - Triangle3D::Triangle3D(Vector3f* newP1, Vector3f* newP2, Vector3f* newP3) { this->p1X = newP1->x; @@ -22,12 +21,12 @@ Triangle3D::Triangle3D(Vector3f* newP1, Vector3f* newP2, Vector3f* newP3) void Triangle3D::generateValues() { - Vector3f vec1(p1X - p3X, p1Y - p3Y, p1Z - p3Z); - Vector3f vec2(p2X - p3X, p2Y - p3Y, p2Z - p3Z); + Vector3f vec1(p2X - p1X, p2Y - p1Y, p2Z - p1Z); + Vector3f vec2(p3X - p1X, p3Y - p1Y, p3Z - p1Z); Vector3f cross = vec1.cross(&vec2); - float newD = cross.x*p3X + cross.y*p3Y + cross.z*p3Z; + float newD = cross.x*p1X + cross.y*p1Y + cross.z*p1Z; A = cross.x; B = cross.y; diff --git a/SA2LevelEditor/src/entities/StageCollision.cpp b/SA2LevelEditor/src/entities/StageCollision.cpp index fb32bb0..30bd732 100644 --- a/SA2LevelEditor/src/entities/StageCollision.cpp +++ b/SA2LevelEditor/src/entities/StageCollision.cpp @@ -8,8 +8,10 @@ #include "../main/main.h" #include "../collision/collisionmodel.h" #include "../collision/collisionchecker.h" +#include "../collision/triangle3d.h" #include +#include std::list StageCollision::models; CollisionModel* StageCollision::collisionModel; @@ -27,10 +29,11 @@ StageCollision::StageCollision() scaleZ = 1; visible = true; baseColour.set(0.70f, 0.70f, 0.70f); - updateTransformationMatrixYXZ(); + } + void StageCollision::step() { visible = Global::displayStageCollision; @@ -57,6 +60,7 @@ void StageCollision::loadModels(const char* objFolder, const char* objFilename) } StageCollision::collisionModel = loadCollisionModel(objFolder, objFilename); + StageCollision::collisionModel->parent = Global::gameStageCollision; CollisionChecker::addCollideModel(StageCollision::collisionModel); } @@ -68,3 +72,228 @@ void StageCollision::deleteStaticModels() Entity::deleteModels(&StageCollision::models); } + +// yoinked from dolphin MathUtil.cpp +const int frsqrte_expected_base[] = +{ + 0x3ffa000, 0x3c29000, 0x38aa000, 0x3572000, + 0x3279000, 0x2fb7000, 0x2d26000, 0x2ac0000, + 0x2881000, 0x2665000, 0x2468000, 0x2287000, + 0x20c1000, 0x1f12000, 0x1d79000, 0x1bf4000, + 0x1a7e800, 0x17cb800, 0x1552800, 0x130c000, + 0x10f2000, 0x0eff000, 0x0d2e000, 0x0b7c000, + 0x09e5000, 0x0867000, 0x06ff000, 0x05ab800, + 0x046a000, 0x0339800, 0x0218800, 0x0105800, +}; +const int frsqrte_expected_dec[] = +{ + 0x7a4, 0x700, 0x670, 0x5f2, + 0x584, 0x524, 0x4cc, 0x47e, + 0x43a, 0x3fa, 0x3c2, 0x38e, + 0x35e, 0x332, 0x30a, 0x2e6, + 0x568, 0x4f3, 0x48d, 0x435, + 0x3e7, 0x3a2, 0x365, 0x32e, + 0x2fc, 0x2d0, 0x2a8, 0x283, + 0x261, 0x243, 0x226, 0x20b, +}; + +double gcApproxInvSqrt(double val) { + union + { + double valf; + int64_t vali; + }; + valf = val; + int64_t mantissa = vali & ((1LL << 52) - 1); + int64_t sign = vali & (1ULL << 63); + int64_t exponent = vali & (0x7FFLL << 52); + + // Special case 0 + if (mantissa == 0 && exponent == 0) + return sign ? -std::numeric_limits::infinity() : + std::numeric_limits::infinity(); + // Special case NaN-ish numbers + if (exponent == (0x7FFLL << 52)) + { + if (mantissa == 0) + { + if (sign) + return std::numeric_limits::quiet_NaN(); + + return 0.0; + } + + return 0.0 + valf; + } + + // Negative numbers return NaN + if (sign) + return std::numeric_limits::quiet_NaN(); + + if (!exponent) + { + // "Normalize" denormal values + do + { + exponent -= 1LL << 52; + mantissa <<= 1; + } while (!(mantissa & (1LL << 52))); + mantissa &= (1LL << 52) - 1; + exponent += 1LL << 52; + } + + bool odd_exponent = !(exponent & (1LL << 52)); + exponent = ((0x3FFLL << 52) - ((exponent - (0x3FELL << 52)) / 2)) & (0x7FFLL << 52); + + int i = (int)(mantissa >> 37); + vali = sign | exponent; + int index = i / 2048 + (odd_exponent ? 16 : 0); + vali |= (int64_t)(frsqrte_expected_base[index] - frsqrte_expected_dec[index] * (i % 2048)) << 26; + return valf; +} + +const int fres_expected_base[] = +{ + 0x7ff800, 0x783800, 0x70ea00, 0x6a0800, + 0x638800, 0x5d6200, 0x579000, 0x520800, + 0x4cc800, 0x47ca00, 0x430800, 0x3e8000, + 0x3a2c00, 0x360800, 0x321400, 0x2e4a00, + 0x2aa800, 0x272c00, 0x23d600, 0x209e00, + 0x1d8800, 0x1a9000, 0x17ae00, 0x14f800, + 0x124400, 0x0fbe00, 0x0d3800, 0x0ade00, + 0x088400, 0x065000, 0x041c00, 0x020c00, +}; +const int fres_expected_dec[] = +{ + 0x3e1, 0x3a7, 0x371, 0x340, + 0x313, 0x2ea, 0x2c4, 0x2a0, + 0x27f, 0x261, 0x245, 0x22a, + 0x212, 0x1fb, 0x1e5, 0x1d1, + 0x1be, 0x1ac, 0x19b, 0x18b, + 0x17c, 0x16e, 0x15b, 0x15b, + 0x143, 0x143, 0x12d, 0x12d, + 0x11a, 0x11a, 0x108, 0x106, +}; + +float gcApproxInv(float val) { + union + { + double valf; + int64_t vali; + }; + + valf = val; + int64_t mantissa = vali & ((1LL << 52) - 1); + int64_t sign = vali & (1ULL << 63); + int64_t exponent = vali & (0x7FFLL << 52); + + // Special case 0 + if (mantissa == 0 && exponent == 0) + return sign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); + + // Special case NaN-ish numbers + if (exponent == (0x7FFLL << 52)) + { + if (mantissa == 0) + return sign ? -0.0 : 0.0; + return 0.0 + valf; + } + + // Special case small inputs + if (exponent < (895LL << 52)) + return sign ? -std::numeric_limits::max() : std::numeric_limits::max(); + + // Special case large inputs + if (exponent >= (1149LL << 52)) + return sign ? -0.0f : 0.0f; + + exponent = (0x7FDLL << 52) - exponent; + + int i = (int)(mantissa >> 37); + vali = sign | exponent; + vali |= (int64_t)(fres_expected_base[i / 1024] - (fres_expected_dec[i / 1024] * (i % 1024) + 1) / 2) << 29; + return valf; +} + +Vector3f generateGamecubeNormals(Triangle3D* tri) { + Vector3f retVec; + + // Matching what njUnitVector does + float sum = tri->A * tri->A; + sum = std::fmaf(tri->B, tri->B, sum); + sum = std::fmaf(tri->C, tri->C, sum); + + float invSqrt = gcApproxInvSqrt(sum); + + float mag = gcApproxInv(invSqrt); + + if (mag != 0) { + retVec.x = tri->A * invSqrt; + retVec.y = tri->B * invSqrt; + retVec.z = tri->C * invSqrt; + } + else { + retVec.x = 0; + retVec.y = 1; + retVec.z = 0; + } + return retVec; +} + +void StageCollision::updateEditorWindows() +{ + SetWindowTextA(Global::windowLabels[0], "Triangle Collision Info"); + SetWindowTextA(Global::windowLabels[1], ""); + SetWindowTextA(Global::windowLabels[2], "PC Norm.X"); + SetWindowTextA(Global::windowLabels[3], "PC Norm.Y"); + SetWindowTextA(Global::windowLabels[4], "PC Norm.Z"); + SetWindowTextA(Global::windowLabels[5], "GC Norm.X"); + SetWindowTextA(Global::windowLabels[6], "GC Norm.Y"); + SetWindowTextA(Global::windowLabels[7], "GC Norm.Z"); + SetWindowTextA(Global::windowLabels[8], ""); + SetWindowTextA(Global::windowLabels[9], ""); + SetWindowTextA(Global::windowLabels[10], ""); + + SetWindowTextA(Global::windowValues[0], ""); + SetWindowTextA(Global::windowValues[1], ""); + + Triangle3D *collided = CollisionChecker::getCollideTriangle(); + SetWindowTextA(Global::windowValues[2], std::format("{:.12f}", collided->normal.getX()).c_str()); + SetWindowTextA(Global::windowValues[3], std::format("{:.12f}", collided->normal.getY()).c_str()); + SetWindowTextA(Global::windowValues[4], std::format("{:.12f}", collided->normal.getZ()).c_str()); + + Vector3f gcNorm = generateGamecubeNormals(collided); + SetWindowTextA(Global::windowValues[5], std::format("{:.12f}", gcNorm.getX()).c_str()); + SetWindowTextA(Global::windowValues[6], std::format("{:.12f}", gcNorm.getY()).c_str()); + SetWindowTextA(Global::windowValues[7], std::format("{:.12f}", gcNorm.getZ()).c_str()); + + SetWindowTextA(Global::windowValues[8], ""); + SetWindowTextA(Global::windowValues[9], ""); + SetWindowTextA(Global::windowValues[10], ""); + + SendMessageA(Global::windowValues[0], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[1], EM_SETREADONLY, 1, 0); + SendMessageA(Global::windowValues[2], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[3], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[4], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[5], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[6], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[7], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[8], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[9], EM_SETREADONLY, 0, 0); + SendMessageA(Global::windowValues[10], EM_SETREADONLY, 1, 0); + + SetWindowTextA(Global::windowDescriptions[0], ""); + SetWindowTextA(Global::windowDescriptions[1], ""); + SetWindowTextA(Global::windowDescriptions[2], ""); + SetWindowTextA(Global::windowDescriptions[3], ""); + SetWindowTextA(Global::windowDescriptions[4], ""); + SetWindowTextA(Global::windowDescriptions[5], ""); + SetWindowTextA(Global::windowDescriptions[6], ""); + SetWindowTextA(Global::windowDescriptions[7], ""); + SetWindowTextA(Global::windowDescriptions[8], ""); + SetWindowTextA(Global::windowDescriptions[9], ""); + SetWindowTextA(Global::windowDescriptions[10], ""); + + updateTransformationMatrixYXZ(); +} diff --git a/SA2LevelEditor/src/entities/stagecollision.h b/SA2LevelEditor/src/entities/stagecollision.h index 2f1f515..8fcadb8 100644 --- a/SA2LevelEditor/src/entities/stagecollision.h +++ b/SA2LevelEditor/src/entities/stagecollision.h @@ -6,8 +6,9 @@ class CollisionModel; #include #include "entity.h" +#include "sa2object.h" -class StageCollision : public Entity +class StageCollision : public SA2Object { private: static std::list models; @@ -22,6 +23,8 @@ class StageCollision : public Entity static void loadModels(const char* objFolder, const char* objFilename); + void updateEditorWindows(); + static void deleteStaticModels(); }; #endif