台球游戏物理速度计算问题

Pool Game physics velocity calculation issue

您好,我正在制作 3d 台球游戏,目前处于应用碰撞的状态,我正在使用 openGL 和 C++。我已经写了碰撞并且它工作正常。我遇到的问题仅与球的速度 class 和碰撞时传递给其他球的力有关。

我有一个球 class 用于包括母球在内的所有球。我有一个 drawBall() 函数:

void drawBall(Shader ourShader) {
    extern GLfloat deltaTime;
    a = F / radius;
    v = v + (a * deltaTime);
    ballPos = ballPos + (v*deltaTime) + (0.5f*a*deltaTime*deltaTime);
    collision();

    //F = glm::vec3(0.0f, 0.0f, 0.0f);
//ACTUAL DRAWING
    glBindVertexArray(VAO);
        glm::mat4 model;

        model = glm::translate(model, ballPos);
        model = glm::rotate(model, glm::radians(40.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

还有一个碰撞函数:

void collision()  {
    extern vector <Ball> ballCollection;
    for (int i = 0; i < ballCollection.size(); i++) {
        if (glm::distance(ballCollection.at(i).ballPos, ballPos) <= (2 * radius)) {
            if (!glm::distance(ballCollection.at(i).ballPos, ballPos) == 0) {
                extern GLfloat forceAmount;
                if (isColliding == 0) {
                    glm::vec3 collPoint = glm::vec3((ballPos.x + ballCollection.at(i).ballPos.x) / 2, 0.0f, (ballPos.z + ballCollection.at(i).ballPos.z) / 2);
                    glm::vec3 collPointPerp = collPoint - ballPos;

                    glm::vec3 otherNew = collPointPerp;
                    glm::vec3 thisNew = glm::cross(collPointPerp, glm::vec3(0.0, 1.0, 0.0));

                    F = thisNew;
                    ballCollection.at(i).F = otherNew;

                    glm::vec3 newV;
                    glm::vec3 otherNewV;

                    newV.x = (v.x * (2 * ballCollection.at(i).radius * ballCollection.at(i).v.x)) / (radius + ballCollection.at(i).radius);
                    newV.z = (v.z * (2 * ballCollection.at(i).radius * ballCollection.at(i).v.z)) / (radius + ballCollection.at(i).radius);
                    newV.y = 0.0f;

                    otherNewV.x = (ballCollection.at(i).v.x * (2 * radius * v.x)) / (radius + ballCollection.at(i).radius);
                    otherNewV.z = (ballCollection.at(i).v.z * (2 * radius * v.z)) / (radius + ballCollection.at(i).radius);
                    otherNewV.y = 0.0f;



                    v.x = newV.x;
                    v.z = newV.z;

                    ballCollection.at(i).v.x = otherNewV.x;
                    ballCollection.at(i).v.z = otherNewV.z;



                }
                isColliding = 1;
                ballCollection.at(i).isColliding = 1;
            }
        }
    }
    isColliding = 0;

这个 calss 在一个单独的文件中,在我的主 cpp 中。这有一个 key_kallback 功能:

void do_movement()
{
glm::vec3  cameraRight = glm::normalize(glm::cross(cameraFront, cameraUp));
GLfloat cameraSpeed = 50.0f;

glm::vec3 aboveBall = glm::vec3(ballCollection.at(15).ballPos.x, ballCollection.at(15).ballPos.y + 20.0f, ballCollection.at(15).ballPos.z);
glm::vec3 cameraFwd = aboveBall - cameraPos;

//cout << cameraFwd.x << "," << cameraFwd.y << "," << cameraFwd.z << endl;
if (keys[GLFW_KEY_W])
    ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(0.0f, 0.0f, -0.1f);
if (keys[GLFW_KEY_S])
    ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(0.0f, 0.0f, 0.1f);
if (keys[GLFW_KEY_A])
    ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(-0.1f, 0.0f, 0.0f);
if (keys[GLFW_KEY_D])
    ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(0.1f, 0.0f, 0.0f);
if (keys[GLFW_KEY_SPACE]) {
    ballCollection.at(15).F = 10.0f*glm::normalize(cameraFwd);
}
if (keys[GLFW_KEY_E]) {
    ballCollection.at(15).F = -10.0f * glm::normalize(cameraFwd);
}

}

然后在游戏循环中:

        for (int i = 0; i < 16; i++) {

            ballCollection.at(i).drawBall(ourShader);
        }
        cameraPos = ballCollection.at(15).ballPos + glm::vec3(0.0f, 20.0f, 20.0f);
        do_movement();

我的问题是,当我用 space 向母球施加力时,由于 F 值不断增加到 v,我的母球速度每帧都会增加。如果我施力后把F调回0,我就不能给其他球传力,所以它们的v为0,碰撞后就不动了。

任何帮助将不胜感激,如果我需要额外的信息,请发表评论。

编辑

我发现我碰撞计算有误,应该是:

newV.x = (v.x + (2 * ballCollection.at(i).radius * ballCollection.at(i).v.x)) / (radius + ballCollection.at(i).radius);
newV.z = (v.z + (2 * ballCollection.at(i).radius * ballCollection.at(i).v.z)) / (radius + ballCollection.at(i).radius);
newV.y = 0.0f;

otherNewV.x = (ballCollection.at(i).v.x + (2 * radius * v.x)) / (radius + ballCollection.at(i).radius);
otherNewV.z = (ballCollection.at(i).v.z + (2 * radius * v.z)) / (radius + ballCollection.at(i).radius);
otherNewV.y = 0.0f;

现在,如果我在计算后 class 中使 F 回到零,球将以恒定速度移动,这暂时没问题。我现在的问题是,有时碰撞有效,有时球飞走了,有时击中第一个球没问题,但如果第二个球击中另一个球,那么它又错了。我认为发生这种情况是因为他们不断碰撞并且计算速度错误,但我不知道如何设置一个布尔值只碰撞一次,有人知道吗?

编辑 我现在设法正确设置了布尔值。

碰撞时,应该施加在另一个球上的力是速度矢量的大小。因此,如果您传入 sqrt(v.x*v.x+v.y*v.y+v.z*v.z) 作为碰撞的初始力,并在按照您说明的方式施加力后将 F 设置为零,您应该会得到您想要的结果。