问题描述
我正在实现一个球到球的碰撞解决方案,我对从哪里开始感到有些困惑。第一个问题,游戏/引擎是否有标准方法来解决球到球的碰撞?只有几种标准方法可以做到吗?还是根据需要的分辨率差异很大?
我想在我的引擎中实现这一点,我写了一个基本的推球体和另一个球体(因此基本上一个交互的球体可以推另一个球体),但这只是一个超级简单的概念。我到底该如何改善它以使其更加准确? (请注意,由于我仍在测试中,因此代码未经过优化)
由于它是一个比较小众的话题,因此似乎总体上缺乏关于冲突解决的可靠文档。我发现的大多数资源仅涉及检测部分。
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,-e1->zVeLocity / 2);
e2->move(e1->xVeLocity / 2,e1->zVeLocity / 2);
}
return dist <= (sphereRadius + otherSphereRadius);
}
解决方法
不需要使用std::sqrt
,并且将平方长度与(sphereRadius + otherSphereRadius)
2
进行比较可能要快得多。
示例:
#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,2.5);
std::cout << std::boolalpha << a.isSphereInsideSphere(b) << '\n'; // prints true
}
,
这是一个更简单的示例(不涉及新类)。
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;
}