diff --git a/rehlds/msvc/ReHLDS.vcxproj b/rehlds/msvc/ReHLDS.vcxproj
index 834c912..0dd2b0c 100644
--- a/rehlds/msvc/ReHLDS.vcxproj
+++ b/rehlds/msvc/ReHLDS.vcxproj
@@ -185,6 +185,7 @@
+
@@ -269,6 +270,14 @@
true
true
+
+ true
+ true
+ true
+ true
+ true
+ true
+
true
@@ -538,6 +547,7 @@
+
@@ -833,7 +843,7 @@
Level3
Disabled
true
- REHLDS_FIXES;REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)
+ REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)
Precise
/arch:IA32 %(AdditionalOptions)
MultiThreadedDebug
diff --git a/rehlds/msvc/ReHLDS.vcxproj.filters b/rehlds/msvc/ReHLDS.vcxproj.filters
index 29382ae..0559a24 100644
--- a/rehlds/msvc/ReHLDS.vcxproj.filters
+++ b/rehlds/msvc/ReHLDS.vcxproj.filters
@@ -346,6 +346,12 @@
rehlds
+
+ rehlds
+
+
+ unittests
+
@@ -1065,6 +1071,9 @@
rehlds
+
+ rehlds
+
diff --git a/rehlds/public/rehlds/rehlds_api.h b/rehlds/public/rehlds/rehlds_api.h
index b25364b..3bb74c7 100644
--- a/rehlds/public/rehlds/rehlds_api.h
+++ b/rehlds/public/rehlds/rehlds_api.h
@@ -35,7 +35,7 @@
#include "model.h"
#define REHLDS_API_VERSION_MAJOR 1
-#define REHLDS_API_VERSION_MINOR 2
+#define REHLDS_API_VERSION_MINOR 3
//Steam_NotifyClientConnect hook
typedef IHookChain IRehldsHook_Steam_NotifyClientConnect;
@@ -199,6 +199,7 @@ struct RehldsFuncs_t {
void(*MSG_WriteBitVec3Coord)(const float *fa);
void(*MSG_EndBitWriting)(sizebuf_t *buf);
void*(*SZ_GetSpace)(sizebuf_t *buf, int length);
+ bool(*GetHitboxCorners)(int hitboxId, float* /* [8*3] */ corners);
};
class IRehldsApi {
diff --git a/rehlds/rehlds/math_utils.cpp b/rehlds/rehlds/math_utils.cpp
new file mode 100644
index 0000000..df93fe3
--- /dev/null
+++ b/rehlds/rehlds/math_utils.cpp
@@ -0,0 +1,81 @@
+#include "precompiled.h"
+
+double CalculateDeterminant(matrix33_t &matrix) {
+ return
+ matrix[0][0] * matrix[1][1] * matrix[2][2]
+ - matrix[0][0] * matrix[1][2] * matrix[2][1]
+ + matrix[1][0] * matrix[2][1] * matrix[0][2]
+ - matrix[1][0] * matrix[2][2] * matrix[0][1]
+ + matrix[2][0] * matrix[0][1] * matrix[1][2]
+ - matrix[2][0] * matrix[0][2] * matrix[1][1];
+}
+
+equation_sys_resolve_res ResolveEq3Sys(equation3_t* eqs, double* res) {
+ matrix33_t mainDtMtx = {
+ { eqs[0].a, eqs[0].b, eqs[0].c },
+ { eqs[1].a, eqs[1].b, eqs[1].c },
+ { eqs[2].a, eqs[2].b, eqs[2].c }
+ };
+
+ matrix33_t dtxMtx = {
+ { eqs[0].h, eqs[0].b, eqs[0].c },
+ { eqs[1].h, eqs[1].b, eqs[1].c },
+ { eqs[2].h, eqs[2].b, eqs[2].c }
+ };
+
+ matrix33_t dtyMtx = {
+ { eqs[0].a, eqs[0].h, eqs[0].c },
+ { eqs[1].a, eqs[1].h, eqs[1].c },
+ { eqs[2].a, eqs[2].h, eqs[2].c }
+ };
+
+ matrix33_t dtzMtx = {
+ { eqs[0].a, eqs[0].b, eqs[0].h },
+ { eqs[1].a, eqs[1].b, eqs[1].h },
+ { eqs[2].a, eqs[2].b, eqs[2].h }
+ };
+
+ double mainDt = CalculateDeterminant(mainDtMtx);
+ double dtx = CalculateDeterminant(dtxMtx);
+ double dty = CalculateDeterminant(dtyMtx);
+ double dtz = CalculateDeterminant(dtzMtx);
+
+ if (abs(mainDt) > 0.000001) {
+ res[0] = dtx / mainDt;
+ res[1] = dty / mainDt;
+ res[2] = dtz / mainDt;
+
+ return EQSR_1;
+ }
+
+ return (abs(dtx) > 0.000001) ? EQSR_NONE : EQSR_INF;
+}
+
+plane_itx_res CalcPlanesIntersection(mplane_t* p1, mplane_t* p2, mplane_t* p3, float* res) {
+ equation3_t eqs[] = {
+ { p1->normal[0], p1->normal[1], p1->normal[2], p1->dist },
+ { p2->normal[0], p2->normal[1], p2->normal[2], p2->dist },
+ { p3->normal[0], p3->normal[1], p3->normal[2], p3->dist },
+ };
+
+ double dblRes[3];
+
+ auto resKind = ResolveEq3Sys(eqs, dblRes);
+ switch (resKind) {
+ case EQSR_1:
+ res[0] = dblRes[0];
+ res[1] = dblRes[1];
+ res[2] = dblRes[2];
+ return PIR_1;
+
+ case EQSR_INF:
+ return PIR_INF;
+
+ case EQSR_NONE:
+ return PIR_NONE;
+
+ default:
+ rehlds_syserror(__FUNCTION__": invalid resKind %d", resKind);
+ return PIR_NONE;
+ }
+}
diff --git a/rehlds/rehlds/math_utils.h b/rehlds/rehlds/math_utils.h
new file mode 100644
index 0000000..0fcf3bb
--- /dev/null
+++ b/rehlds/rehlds/math_utils.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "engine.h"
+
+typedef float matrix33_t[3][3];
+
+//ax + by + cz = h
+struct equation3_t {
+ double a, b, c, h;
+};
+
+enum equation_sys_resolve_res {
+ EQSR_1,
+ EQSR_NONE,
+ EQSR_INF,
+};
+
+enum plane_itx_res {
+ PIR_1,
+ PIR_NONE,
+ PIR_INF,
+};
+
+extern double CalculateDeterminant(matrix33_t &matrix);
+extern equation_sys_resolve_res ResolveEq3Sys(equation3_t* eqs, double* res);
+extern plane_itx_res CalcPlanesIntersection(mplane_t* p1, mplane_t* p2, mplane_t* p3, float* res);
+
+
diff --git a/rehlds/rehlds/precompiled.h b/rehlds/rehlds/precompiled.h
index 401c661..1393cca 100644
--- a/rehlds/rehlds/precompiled.h
+++ b/rehlds/rehlds/precompiled.h
@@ -19,6 +19,8 @@
#include "RehldsRuntimeConfig.h"
#include "rehlds_debug.h"
+#include "math_utils.h"
+
#ifdef HOOK_ENGINE
#include "hooker.h"
#endif
@@ -35,6 +37,7 @@
#include "iosutil.h"
+
//testsuite
#include "testsuite.h"
#include "funccalls.h"
diff --git a/rehlds/rehlds/rehlds_api_impl.cpp b/rehlds/rehlds/rehlds_api_impl.cpp
index 5a6b070..3c34ea4 100644
--- a/rehlds/rehlds/rehlds_api_impl.cpp
+++ b/rehlds/rehlds/rehlds_api_impl.cpp
@@ -65,6 +65,52 @@ DLL_FUNCTIONS* EXT_FUNC GetEntityInterface_api() {
return &gEntityInterface;
}
+bool EXT_FUNC GetHitboxCorners(int hitboxId, float* /* [8*3] */ corners) {
+ mplane_t* right = &studio_planes[hitboxId * 6 + 0 * 2 + 0];
+ mplane_t* left = &studio_planes[hitboxId * 6 + 0 * 2 + 1];
+ mplane_t* rear = &studio_planes[hitboxId * 6 + 1 * 2 + 0];
+ mplane_t* front = &studio_planes[hitboxId * 6 + 1 * 2 + 1];
+ mplane_t* top = &studio_planes[hitboxId * 6 + 2 * 2 + 0];
+ mplane_t* bottom = &studio_planes[hitboxId * 6 + 2 * 2 + 1];
+
+ float p[3];
+
+ if (PIR_1 != CalcPlanesIntersection(left, front, bottom, p))
+ return false;
+ corners[0 * 3 + 0] = p[0]; corners[0 * 3 + 1] = p[1]; corners[0 * 3 + 1] = p[2];
+
+ if (PIR_1 != CalcPlanesIntersection(left, front, top, p))
+ return false;
+ corners[1 * 3 + 0] = p[0]; corners[1 * 3 + 1] = p[1]; corners[1 * 3 + 1] = p[2];
+
+ if (PIR_1 != CalcPlanesIntersection(right, front, top, p))
+ return false;
+ corners[2 * 3 + 0] = p[0]; corners[2 * 3 + 1] = p[1]; corners[2 * 3 + 1] = p[2];
+
+ if (PIR_1 != CalcPlanesIntersection(right, front, bottom, p))
+ return false;
+ corners[3 * 3 + 0] = p[0]; corners[3 * 3 + 1] = p[1]; corners[3 * 3 + 1] = p[2];
+
+
+ if (PIR_1 != CalcPlanesIntersection(left, rear, bottom, p))
+ return false;
+ corners[4 * 3 + 0] = p[0]; corners[4 * 3 + 1] = p[1]; corners[4 * 3 + 1] = p[2];
+
+ if (PIR_1 != CalcPlanesIntersection(left, rear, top, p))
+ return false;
+ corners[5 * 3 + 0] = p[0]; corners[5 * 3 + 1] = p[1]; corners[5 * 3 + 1] = p[2];
+
+ if (PIR_1 != CalcPlanesIntersection(right, rear, top, p))
+ return false;
+ corners[6 * 3 + 0] = p[0]; corners[6 * 3 + 1] = p[1]; corners[6 * 3 + 1] = p[2];
+
+ if (PIR_1 != CalcPlanesIntersection(right, rear, bottom, p))
+ return false;
+ corners[7 * 3 + 0] = p[0]; corners[7 * 3 + 1] = p[1]; corners[7 * 3 + 1] = p[2];
+
+ return true;
+}
+
CRehldsServerStatic g_RehldsServerStatic;
CRehldsServerData g_RehldsServerData;
CRehldsHookchains g_RehldsHookchains;
@@ -99,7 +145,8 @@ RehldsFuncs_t g_RehldsApiFuncs =
&MSG_WriteBits,
&MSG_WriteBitVec3Coord,
&MSG_EndBitWriting,
- &SZ_GetSpace
+ &SZ_GetSpace,
+ &GetHitboxCorners
};
sizebuf_t* EXT_FUNC GetNetMessage_api()
diff --git a/rehlds/rehlds/rehlds_api_impl.h b/rehlds/rehlds/rehlds_api_impl.h
index fdfdc9b..5362878 100644
--- a/rehlds/rehlds/rehlds_api_impl.h
+++ b/rehlds/rehlds/rehlds_api_impl.h
@@ -31,6 +31,8 @@
#include "rehlds_api.h"
#include "rehlds_interfaces_impl.h"
+extern bool GetHitboxCorners(int hitboxId, float* /* [8*3] */ corners);
+
//Steam_NotifyClientConnect
typedef IHookChainImpl CRehldsHook_Steam_NotifyClientConnect;
typedef IHookChainRegistryImpl CRehldsHookRegistry_Steam_NotifyClientConnect;
diff --git a/rehlds/unittests/math_util_tests.cpp b/rehlds/unittests/math_util_tests.cpp
new file mode 100644
index 0000000..f2f2e1e
--- /dev/null
+++ b/rehlds/unittests/math_util_tests.cpp
@@ -0,0 +1,91 @@
+#include "precompiled.h"
+#include "rehlds_tests_shared.h"
+#include "cppunitlite/TestHarness.h"
+
+TEST(CalculateDeterminant, MathUtils, 1000) {
+
+ struct testdata_t {
+ matrix33_t mtx;
+ double d;
+ };
+
+ testdata_t testdata[] = {
+ {
+ {
+ { 2.0, 5.0, -2.0 },
+ { 3.0, 8.0, 0.0 },
+ { 1.0, 3.0, 5.0 },
+ },
+ 3.0
+ },
+ {
+ {
+ { 4.0, -3.0, 2.0 },
+ { 6.0, 11.0, 1.0 },
+ { 0.0, 3.0, 0.0 },
+ },
+ 24.0
+ }
+ };
+
+ for (int i = 0; i < ARRAYSIZE(testdata); i++) {
+ testdata_t* t = &testdata[i];
+
+ double dt = CalculateDeterminant(t->mtx);
+ DOUBLES_EQUAL("Determinant mismatch", t->d, dt, 0.001);
+ }
+}
+
+TEST(ResolveEq3Sys, MathUtils, 1000) {
+
+ struct testdata_t {
+ equation3_t eqs[3];
+ equation_sys_resolve_res resKind;
+ double res[3];
+ };
+
+ testdata_t testdata[] = {
+ {
+ {
+ { 3.0, 4.0, 2.0, 5.0 },
+ { 5.0, -6.0, -4.0, -3.0 },
+ { -4.0, 5.0, 3.0, 1.0 }
+ },
+ EQSR_1,
+ { 1.0, -2.0, 5.0 }
+ },
+ {
+ {
+ { 1.0, 1.0, 1.0, 5.0 },
+ { 1.0, -1.0, 1.0, 1.0 },
+ { 1.0, 0.0, 1.0, 2.0 }
+ },
+ EQSR_NONE,
+ { 0.0, 0.0, 0.0 }
+ },
+ {
+ {
+ { 1.0, 1.0, 1.0, 5.0 },
+ { 1.0, -1.0, 1.0, 1.0 },
+ { 1.0, 0.0, 1.0, 3.0 }
+ },
+ EQSR_INF,
+ { 0.0, 0.0, 0.0 }
+ }
+ };
+
+ for (int i = 0; i < ARRAYSIZE(testdata); i++) {
+ testdata_t* t = &testdata[i];
+
+ double res[3];
+ equation_sys_resolve_res resKind = ResolveEq3Sys(t->eqs, res);
+ UINT32_EQUALS("resKind mismatch", (uint32)t->resKind, (uint32)resKind);
+
+ if (resKind == EQSR_1) {
+ DOUBLES_EQUAL("res[0] mismatch", t->res[0], res[0], 0.00001);
+ DOUBLES_EQUAL("res[1] mismatch", t->res[1], res[1], 0.00001);
+ DOUBLES_EQUAL("res[2] mismatch", t->res[2], res[2], 0.00001);
+ }
+ }
+
+}
\ No newline at end of file