Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 球体到球体碰撞(C+;+;)_C++_Collision Detection_Game Engine_Physics - Fatal编程技术网

C++ 球体到球体碰撞(C+;+;)

C++ 球体到球体碰撞(C+;+;),c++,collision-detection,game-engine,physics,C++,Collision Detection,Game Engine,Physics,我正在实现一些基本的3D物理引擎。对于球体到球体的碰撞,我遵循这一点。我有两个移动球体的问题。我想我找到“缩短速度”的方法可能有问题 在我的测试场景中,速度向量是(-2,-4,-2)和(1,2,1)。因此,“短波”实际上大于原始速度 vec3 shortVel = sphere.velocity.substract(velocity); vec3 fromAtoBCenter = position.substract(sphere.position); float dis

我正在实现一些基本的3D物理引擎。对于球体到球体的碰撞,我遵循这一点。我有两个移动球体的问题。我想我找到“缩短速度”的方法可能有问题

在我的测试场景中,速度向量是(-2,-4,-2)和(1,2,1)。因此,“短波”实际上大于原始速度

    vec3 shortVel = sphere.velocity.substract(velocity);
    vec3 fromAtoBCenter = position.substract(sphere.position);
    float distSquare = fromAtoBCenter.getLengthSquare();
    float sumRadii = (radius + sphere.radius);
    distSquare -= sumRadii*sumRadii;
    if (shortVel.getLengthSquare() < distSquare){
        return false;
    }

    // Normalize the movevec
    vec3 N = shortVel.normalize();

    // Find C, the vector from the center of the moving 
    // circle A to the center of B
    vec3 C = sphere.position.substract(position);

    // D = N . C = ||C|| * cos(angle between N and C)
    float D = N.dot(C);

    // Another early escape: Make sure that A is moving 
    // towards B! If the dot product between the movevec and 
    // B.center - A.center is less that or equal to 0, 
    // A isn't isn't moving towards B
    if (D <= 0){
        return false;
    }
    // Find the length of the vector C
    float lengthCSquare = C.getLengthSquare();

    float F = (lengthCSquare)-(D * D);

    // Escape test: if the closest that A will get to B 
    // is more than the sum of their radii, there's no 
    // way they are going collide
    float sumRadiiSquared = sumRadii * sumRadii;
    if (F >= sumRadiiSquared){
        return false;
    }

    // We now have F and sumRadii, two sides of a right triangle. 
    // Use these to find the third side, sqrt(T)
    double T = sumRadiiSquared - F;

    // If there is no such right triangle with sides length of 
    // sumRadii and sqrt(f), T will probably be less than 0. 
    // Better to check now than perform a square root of a 
    // negative number. 
    if (T < 0){
        return false;
    }

    // Therefore the distance the circle has to travel along 
    // movevec is D - sqrt(T)
    float distance = D - sqrt(T);

    // Get the magnitude of the movement vector
    float mag = velocity.getLength();

    // Finally, make sure that the distance A has to move 
    // to touch B is not greater than the magnitude of the 
    // movement vector. 
    if (mag < distance){
        return false;
    }
我的vec3课程如下:

class vec3 {
public:
    float x; float y; float z;
    vec3() : x(0), y(0), z(0) { }
    vec3 substract(vec3 v){
        vec3 sub;
        sub.x = x - v.x;
        sub.y = y - v.y;
        sub.z = z - v.z;
        return sub;
    }
float getLength() {
        return sqrt(x*x + y*y + z*z);
    }
float getLengthSquare() {
        return x*x + y*y + z*z;
    }
vec3 normalize(){
        vec3 n;
        n.x = x / getLength();
        n.y = y / getLength();
        n.z = z / getLength();
        return n;
    }
float dot(vec3 v) {
        return x*v.x + y*v.y + z*v.z;
    }
}
你能解释一下我做错了什么吗

这是我的更新功能。其中deltaT是两帧之间的时间间隔

void updateVelocity(double deltaT){
        velocity.x = velocity.x + acceleration.x*deltaT;
        velocity.y = velocity.y + acceleration.y*deltaT;
        velocity.z = velocity.z + acceleration.z*deltaT;
    }
    void updatePosition(double deltaT){
        position.x = position.x + velocity.x * deltaT + 0.5 * acceleration.x * deltaT * deltaT;
        position.y = position.y + velocity.y * deltaT + 0.5 * acceleration.y * deltaT * deltaT;
        position.z = position.z + velocity.z * deltaT + 0.5 * acceleration.z * deltaT * deltaT;
    }
    void update(double deltaT){
        updateVelocity(deltaT);
        updatePosition(deltaT);

    }

首先,在vec3中创建add和times函数

如果球体s1和球体s2的位置为p(vec3)、速度v(vec3)、半径r(float)和质量m(float)发生碰撞,则可以执行以下操作:

// from s1 to s2
vec3 pDiff = s2.p.subtract(s1.p);
// collision detection
if (pDiff.getLength() >= s1.r + s2.r) {
    return;
}
// find direction from s1 to s2
vec3 dir = pDiff.normalize();
vec3 vDiff = s2.v.subtract(s1.v);
float fellingSpeed = vDiff.dot(dir);
// don't collide in this case
if (fellingSpeed >= 0) {
    return;
}
// perfect spheric collision
float speed1 = (2 * s2.m * fellingSpeed) / (s1.m + s2.m);
float speed2 = (fellingSpeed * (s2.m - s1.m)) / (s1.m + s2.m);
s1.v = s1.v.add(dir.times(speed1));
s2.v = s2.v.add(dir.times(speed2 - fellingSpeed));

我希望它有帮助。

它没有回答您的问题,但不应该
shortVel.normalize().getLength()
be
1
?我的意思是,归一化向量的长度总是
1
,对吗?没错。为了修复代码,我添加了这个normalize()步骤。本教程的作者并没有提到规范化步骤。引用:如果它们发生冲突,将缩短向量的长度除以最初传递到函数中的向量的长度。结果应该是一个介于0和1之间的浮点数。这表示圆在运动过程中发生碰撞。用这个数字乘以原始的运动矢量。你做的一件事就是忽略对这个规模的项目进行适当的维护。您应该知道,
vec3
要么有错,要么根本跳过它。特别是,您没有为完整的模块编写单元测试。还有,你为什么不拿一支铅笔和一个信封,一步一步地检查你的算法,看看是否一切都正常?不幸的是,这个问题也不属于主题,因为你问代码有什么问题,没有一个最小的示例,也没有任何预期的输入和输出。你有什么问题?如果我理解正确,文章中的“运动向量”是对象在此帧中的运动,即速度乘以时间步长,不是速度(除非你用每帧的距离来测量速度,在这种情况下,你应该立即停止这样做。)
void updateVelocity(double deltaT){
        velocity.x = velocity.x + acceleration.x*deltaT;
        velocity.y = velocity.y + acceleration.y*deltaT;
        velocity.z = velocity.z + acceleration.z*deltaT;
    }
    void updatePosition(double deltaT){
        position.x = position.x + velocity.x * deltaT + 0.5 * acceleration.x * deltaT * deltaT;
        position.y = position.y + velocity.y * deltaT + 0.5 * acceleration.y * deltaT * deltaT;
        position.z = position.z + velocity.z * deltaT + 0.5 * acceleration.z * deltaT * deltaT;
    }
    void update(double deltaT){
        updateVelocity(deltaT);
        updatePosition(deltaT);

    }
// from s1 to s2
vec3 pDiff = s2.p.subtract(s1.p);
// collision detection
if (pDiff.getLength() >= s1.r + s2.r) {
    return;
}
// find direction from s1 to s2
vec3 dir = pDiff.normalize();
vec3 vDiff = s2.v.subtract(s1.v);
float fellingSpeed = vDiff.dot(dir);
// don't collide in this case
if (fellingSpeed >= 0) {
    return;
}
// perfect spheric collision
float speed1 = (2 * s2.m * fellingSpeed) / (s1.m + s2.m);
float speed2 = (fellingSpeed * (s2.m - s1.m)) / (s1.m + s2.m);
s1.v = s1.v.add(dir.times(speed1));
s2.v = s2.v.add(dir.times(speed2 - fellingSpeed));