diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index a7bebfe..765444f 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -65,19 +65,33 @@ std::vector SC_SACD_Get_Box_Normals( std::vector normals; normals.emplace_back(SC_SACD_Vec3{1.0F, 0.0F, 0.0F}); - normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, - box->y_radians, box->z_radians); + normals.back() = box->transform * normals.back(); normals.emplace_back(SC_SACD_Vec3{0.0F, 1.0F, 0.0F}); - normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, - box->y_radians, box->z_radians); + normals.back() = box->transform * normals.back(); normals.emplace_back(SC_SACD_Vec3{0.0F, 0.0F, 1.0F}); - normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, - box->y_radians, box->z_radians); + normals.back() = box->transform * normals.back(); + + return normals; +} + +std::vector SC_SACD_Get_Box_Normals_Normalized( + const SC_SACD_Generic_Box *box) { + std::vector normals; + + normals.emplace_back(SC_SACD_Vec3{1.0F, 0.0F, 0.0F}); + normals.back() = box->transform * normals.back(); + normals.back() = normals.back() / SC_SACD_Vec3_Length(normals.back()); + + normals.emplace_back(SC_SACD_Vec3{0.0F, 1.0F, 0.0F}); + normals.back() = box->transform * normals.back(); + normals.back() = normals.back() / SC_SACD_Vec3_Length(normals.back()); + + normals.emplace_back(SC_SACD_Vec3{0.0F, 0.0F, 1.0F}); + normals.back() = box->transform * normals.back(); + normals.back() = normals.back() / SC_SACD_Vec3_Length(normals.back()); - // Not normalizing the normals on purpose for optimization. It should already - // be normalized as each normal is a rotated unit vector. return normals; } @@ -85,55 +99,61 @@ std::vector SC_SACD_Get_Box_Corners( const SC_SACD_Generic_Box *box) { std::vector corners; - SC_SACD_Vec3 pos{box->x, box->y, box->z}; + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + -box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, -box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + -box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, -box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + -box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, -box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + -box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, -box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); - - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; return corners; } @@ -226,9 +246,7 @@ int SC_SACD_AABB_Generic_Box_Collision(const SC_SACD_AABB_Box *a, a_conv.width = a->width; a_conv.height = a->height; a_conv.depth = a->depth; - a_conv.x_radians = 0.0F; - a_conv.y_radians = 0.0F; - a_conv.z_radians = 0.0F; + a_conv.transform = SC_SACD_Mat4_Identity(); return SC_SACD_Generic_Box_Collision(&a_conv, b); } @@ -478,3 +496,7 @@ SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, SC_SACD_Dot_Product(*dir, *dir); return *pos + *dir * alpha; } + +float SC_SACD_Vec3_Length(const SC_SACD_Vec3 vec) { + return std::sqrt(SC_SACD_Dot_Product(vec, vec)); +} diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 3ad66b9..7ba1c7e 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -55,10 +55,8 @@ typedef struct SC_SACD_EXPORT SC_SACD_Generic_Box { float height; /// z-axis depth. float depth; - /// Rotation about center of box about axis. - float x_radians; - float y_radians; - float z_radians; + /// Local transform; expects center of box as origin. + SC_SACD_Mat4 transform; } SC_SACD_Generic_Box; typedef struct SC_SACD_EXPORT SC_SACD_Sphere { @@ -106,6 +104,7 @@ SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Mat4_Mult(const SC_SACD_Mat4 *a, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat4_Vec3_Mult(const SC_SACD_Mat4 *mat, const SC_SACD_Vec3 vec); +/// Rotates by x-axis first, then y-axis, then finally z-axis. SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, float y_axis, float z_axis); @@ -124,6 +123,8 @@ SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point); +SC_SACD_EXPORT float SC_SACD_Vec3_Length(const SC_SACD_Vec3 vec); + #ifdef __cplusplus } #endif diff --git a/src/test.cpp b/src/test.cpp index 58e9c2d..b9b32c0 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -96,8 +96,10 @@ int main() { // Test Separating_Axis_Collision check. { - SC_SACD_Generic_Box a{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F}; - SC_SACD_Generic_Box b{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F}; + SC_SACD_Generic_Box a{ + 0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, SC_SACD_Mat4_Identity()}; + SC_SACD_Generic_Box b{ + 0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, SC_SACD_Mat4_Identity()}; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); @@ -106,37 +108,37 @@ int main() { b.x = -1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); - a.z_radians = std::numbers::pi_v / 4.0F; - b.z_radians = a.z_radians; + a.transform = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); + b.transform = a.transform; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.x = 1.1F; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.x = 0.0F; b.y = 1.1F; - a.z_radians = 0.0F; - b.z_radians = 0.0F; + a.transform = SC_SACD_Mat4_Identity(); + b.transform = a.transform; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); b.y = -1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); - a.z_radians = std::numbers::pi_v / 4.0F; - b.z_radians = a.z_radians; + a.transform = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); + b.transform = a.transform; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.y = 1.1F; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.y = 0.0F; - a.z_radians = 0.0F; - b.z_radians = 0.0F; + a.transform = SC_SACD_Mat4_Identity(); + b.transform = a.transform; b.z = 1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); b.z = -1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); - a.y_radians = std::numbers::pi_v / 4.0F; - b.y_radians = a.y_radians; + a.transform = SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v / 4.0F); + b.transform = a.transform; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.z = 1.1F; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); @@ -236,9 +238,14 @@ int main() { // Test Sphere/Generic_Box collision check. { SC_SACD_Sphere sphere{0.0F, 0.0F, 0.0F, 1.0F}; - SC_SACD_Generic_Box box{0.0F, 0.0F, 0.0F, - 2.0F, 2.0F, 2.0F, - 0.0F, 0.0F, std::numbers::pi_v / 4.0F}; + SC_SACD_Generic_Box box{ + 0.0F, + 0.0F, + 0.0F, + 2.0F, + 2.0F, + 2.0F, + SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F)}; CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box));