Compare commits

...

4 commits

4 changed files with 110 additions and 73 deletions

View file

@ -6,6 +6,10 @@ Add collision detection with Spheres.
Add some more vector/matrix math stuff. Add some more vector/matrix math stuff.
Replace Mat3 with Mat4.
Replace xyz-axis rotation floats in GenericBox with Mat4.
## Version 1.0.0 ## Version 1.0.0
First version of this library. First version of this library.

View file

@ -65,19 +65,33 @@ std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Normals(
std::vector<SC_SACD_Vec3> normals; std::vector<SC_SACD_Vec3> normals;
normals.emplace_back(SC_SACD_Vec3{1.0F, 0.0F, 0.0F}); normals.emplace_back(SC_SACD_Vec3{1.0F, 0.0F, 0.0F});
normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, normals.back() = box->transform * normals.back();
box->y_radians, box->z_radians);
normals.emplace_back(SC_SACD_Vec3{0.0F, 1.0F, 0.0F}); normals.emplace_back(SC_SACD_Vec3{0.0F, 1.0F, 0.0F});
normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, normals.back() = box->transform * normals.back();
box->y_radians, box->z_radians);
normals.emplace_back(SC_SACD_Vec3{0.0F, 0.0F, 1.0F}); normals.emplace_back(SC_SACD_Vec3{0.0F, 0.0F, 1.0F});
normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, normals.back() = box->transform * normals.back();
box->y_radians, box->z_radians);
return normals;
}
std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Normals_Normalized(
const SC_SACD_Generic_Box *box) {
std::vector<SC_SACD_Vec3> 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; return normals;
} }
@ -85,55 +99,61 @@ std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Corners(
const SC_SACD_Generic_Box *box) { const SC_SACD_Generic_Box *box) {
std::vector<SC_SACD_Vec3> corners; std::vector<SC_SACD_Vec3> 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( corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, -box->height / 2.0F, -box->height / 2.0F,
-box->depth / 2.0F}, -box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); corners.back().y += box->y;
corners.back().z += box->z;
corners.push_back( corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, -box->height / 2.0F, box->height / 2.0F,
-box->depth / 2.0F}, -box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); corners.back().y += box->y;
corners.back().z += box->z;
corners.push_back( corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, box->height / 2.0F, box->height / 2.0F,
-box->depth / 2.0F}, -box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); corners.back().y += box->y;
corners.back().z += box->z;
corners.push_back( corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, box->height / 2.0F, -box->height / 2.0F,
-box->depth / 2.0F}, box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); corners.back().y += box->y;
corners.back().z += box->z;
corners.push_back( corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, -box->height / 2.0F, -box->height / 2.0F,
box->depth / 2.0F}, box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); corners.back().y += box->y;
corners.back().z += box->z;
corners.push_back( corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, -box->height / 2.0F, box->height / 2.0F,
box->depth / 2.0F}, box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); corners.back().y += box->y;
corners.back().z += box->z;
corners.push_back( corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F,
SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, box->height / 2.0F, box->height / 2.0F,
box->depth / 2.0F}, box->depth / 2.0F});
box->x_radians, box->y_radians, box->z_radians) + corners.back().x += box->x;
pos); 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);
return corners; 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.width = a->width;
a_conv.height = a->height; a_conv.height = a->height;
a_conv.depth = a->depth; a_conv.depth = a->depth;
a_conv.x_radians = 0.0F; a_conv.transform = SC_SACD_Mat4_Identity();
a_conv.y_radians = 0.0F;
a_conv.z_radians = 0.0F;
return SC_SACD_Generic_Box_Collision(&a_conv, b); 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); SC_SACD_Dot_Product(*dir, *dir);
return *pos + *dir * alpha; return *pos + *dir * alpha;
} }
float SC_SACD_Vec3_Length(const SC_SACD_Vec3 vec) {
return std::sqrt(SC_SACD_Dot_Product(vec, vec));
}

View file

@ -55,10 +55,8 @@ typedef struct SC_SACD_EXPORT SC_SACD_Generic_Box {
float height; float height;
/// z-axis depth. /// z-axis depth.
float depth; float depth;
/// Rotation about center of box about axis. /// Local transform; expects center of box as origin.
float x_radians; SC_SACD_Mat4 transform;
float y_radians;
float z_radians;
} SC_SACD_Generic_Box; } SC_SACD_Generic_Box;
typedef struct SC_SACD_EXPORT SC_SACD_Sphere { typedef struct SC_SACD_EXPORT SC_SACD_Sphere {
@ -80,12 +78,15 @@ SC_SACD_EXPORT int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a,
SC_SACD_EXPORT int SC_SACD_AABB_Generic_Box_Collision( SC_SACD_EXPORT int SC_SACD_AABB_Generic_Box_Collision(
const SC_SACD_AABB_Box *a, const SC_SACD_Generic_Box *b); const SC_SACD_AABB_Box *a, const SC_SACD_Generic_Box *b);
/// Returns non-zero if there is collision.
SC_SACD_EXPORT int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a, SC_SACD_EXPORT int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a,
const SC_SACD_Sphere *b); const SC_SACD_Sphere *b);
/// Returns non-zero if there is collision.
SC_SACD_EXPORT int SC_SACD_Sphere_AABB_Box_Collision( SC_SACD_EXPORT int SC_SACD_Sphere_AABB_Box_Collision(
const SC_SACD_Sphere *sphere, const SC_SACD_AABB_Box *box); const SC_SACD_Sphere *sphere, const SC_SACD_AABB_Box *box);
/// Returns non-zero if there is collision.
SC_SACD_EXPORT int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, SC_SACD_EXPORT int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere,
const SC_SACD_Generic_Box *box); const SC_SACD_Generic_Box *box);
@ -103,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, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat4_Vec3_Mult(const SC_SACD_Mat4 *mat,
const SC_SACD_Vec3 vec); 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, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec,
float x_axis, float y_axis, float x_axis, float y_axis,
float z_axis); float z_axis);
@ -121,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 *dir,
const SC_SACD_Vec3 *point); const SC_SACD_Vec3 *point);
SC_SACD_EXPORT float SC_SACD_Vec3_Length(const SC_SACD_Vec3 vec);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -96,8 +96,10 @@ int main() {
// Test Separating_Axis_Collision check. // 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 a{
SC_SACD_Generic_Box b{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F}; 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)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
@ -106,37 +108,37 @@ int main() {
b.x = -1.1F; b.x = -1.1F;
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
a.z_radians = std::numbers::pi_v<float> / 4.0F; a.transform = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v<float> / 4.0F);
b.z_radians = a.z_radians; b.transform = a.transform;
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
b.x = 1.1F; b.x = 1.1F;
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
b.x = 0.0F; b.x = 0.0F;
b.y = 1.1F; b.y = 1.1F;
a.z_radians = 0.0F; a.transform = SC_SACD_Mat4_Identity();
b.z_radians = 0.0F; b.transform = a.transform;
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
b.y = -1.1F; b.y = -1.1F;
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
a.z_radians = std::numbers::pi_v<float> / 4.0F; a.transform = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v<float> / 4.0F);
b.z_radians = a.z_radians; b.transform = a.transform;
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
b.y = 1.1F; b.y = 1.1F;
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
b.y = 0.0F; b.y = 0.0F;
a.z_radians = 0.0F; a.transform = SC_SACD_Mat4_Identity();
b.z_radians = 0.0F; b.transform = a.transform;
b.z = 1.1F; b.z = 1.1F;
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
b.z = -1.1F; b.z = -1.1F;
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
a.y_radians = std::numbers::pi_v<float> / 4.0F; a.transform = SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v<float> / 4.0F);
b.y_radians = a.y_radians; b.transform = a.transform;
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
b.z = 1.1F; b.z = 1.1F;
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
@ -236,9 +238,14 @@ int main() {
// Test Sphere/Generic_Box collision check. // Test Sphere/Generic_Box collision check.
{ {
SC_SACD_Sphere sphere{0.0F, 0.0F, 0.0F, 1.0F}; SC_SACD_Sphere sphere{0.0F, 0.0F, 0.0F, 1.0F};
SC_SACD_Generic_Box box{0.0F, 0.0F, 0.0F, SC_SACD_Generic_Box box{
2.0F, 2.0F, 2.0F, 0.0F,
0.0F, 0.0F, std::numbers::pi_v<float> / 4.0F}; 0.0F,
0.0F,
2.0F,
2.0F,
2.0F,
SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v<float> / 4.0F)};
CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box));
@ -564,5 +571,5 @@ int main() {
std::cout << "Checks checked: " << checks_checked << '\n' std::cout << "Checks checked: " << checks_checked << '\n'
<< "Checks passed: " << checks_passed << '\n'; << "Checks passed: " << checks_passed << '\n';
return 0; return checks_checked == checks_passed ? 0 : 1;
} }