台球游戏物理速度计算问题
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 设置为零,您应该会得到您想要的结果。
您好,我正在制作 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 设置为零,您应该会得到您想要的结果。