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