Reputation: 11
I am implementing a sphere to sphere collision resolution and I am a little confused on where to start. First question, is there a standard way that games/engines do sphere to sphere collision resolution? Is there only like a couple standard ways to do it? Or does the resolution vary very heavily based on whats needed?
I want to implement this in my engine and I wrote a basic one that pushes a sphere and another sphere (so basically the one interacting can push the other) but this was just a super simple concept. How exactly can I improve this to make it more accurate? (Mind you the code isn't optimized since I am still testing)
It seems like there is a lack of solid documentation on collision resolution in general as it's a more niche topic. Most resources I found only concern the detection part.
bool isSphereInsideSphere(glm::vec3 sphere, float sphereRadius, glm::vec3 otherSphere, float otherSphereRadius, Entity* e1, Entity* e2)
{
float dist = glm::sqrt((sphere.x - otherSphere.x) * (sphere.x - otherSphere.x) + (sphere.y - otherSphere.y) * (sphere.y - otherSphere.y) + (sphere.z - otherSphere.z) * (sphere.z - otherSphere.z));
if (dist <= (sphereRadius + otherSphereRadius))
{
//Push code
e1->move(-e1->xVelocity / 2, 0, -e1->zVelocity / 2);
e2->move(e1->xVelocity / 2, 0, e1->zVelocity / 2);
}
return dist <= (sphereRadius + otherSphereRadius);
}
Upvotes: 0
Views: 366
Reputation: 10591
Here is a simpler example (without involving new classes).
bool isSphereInsideSphere(glm::vec3 sphere, float sphereRadius, glm::vec3 otherSphere, float otherSphereRadius, Entity* e1, Entity* e2)
{
auto delta = otherSphere - sphere;
auto r2 = (sphereRadius + otherSphereRadius)*(sphereRadius + otherSphereRadius);
if (glm::dot(delta,delta) <= r2)
{
//Push code
return true;
}
return false;
}
Upvotes: 0
Reputation: 117288
Using std::sqrt
is unnecessary and it's probably a lot quicker to compare the squared length against (sphereRadius + otherSphereRadius)
2
.
Example:
#include <glm/glm.hpp>
#include <iostream>
#include <cstdlib>
auto squared_length(const glm::vec3& v) {
return std::abs(v.x * v.x + v.y * v.y + v.z * v.z);
}
class Sphere {
public:
Sphere(const glm::vec3& Position, float Radius) :
position{Position}, radius(Radius) {}
bool isSphereInsideSphere(const Sphere& other) const {
auto dist = squared_length(position - other.position);
// compare the squared values
if(dist <= (radius + other.radius) * (radius + other.radius)) {
// Push code ...
return true;
}
return false;
}
private:
glm::vec3 position;
float radius;
};
int main() {
Sphere a({2, 3, 0}, 2.5);
Sphere b({5, 7, 0}, 2.5);
std::cout << std::boolalpha << a.isSphereInsideSphere(b) << '\n'; // prints true
}
Upvotes: 2