我正在使用 Java 和 OpenGL 为 Android 编写游戏。我可以将所有内容完美地渲染到屏幕上,但是当我尝试检查两个对象是否发生碰撞时,我的算法会在碰撞发生在屏幕上之前检测到碰撞。
这是我测试碰撞的方法:
for(int i=0; i<enemies.size(); i++) {
float enemyRadius = enemies.elementAt(i).worldSpaceBoundingSphereRadius();
float[] enemyPosition = enemies.elementAt(i).getWorldSpaceCoordinates();
for(int j=0; j<qubieBullets.size(); j++) {
float bulletRadius = bullets.elementAt(j).worldSpaceBoundingSphereRadius();
float[] bulletPosition = bullets.elementAt(j).getWorldSpaceCoordinates();
float[] distanceVector = Vector3f.subtract(enemyPosition, bulletPosition);
float distance = Vector3f.length(distanceVector);
if(distance < (enemyRadius + bulletRadius)) {
enemies.remove(i);
qubieBullets.remove(j);
i--;
j--;
// Reset enemy position
}
}
}
当敌人的立方体(由用于碰撞检测的球体表示)接近玩家时,玩家向敌人发射一颗子弹(也是由球体表示的立方体)。我的期望是,当子弹击中屏幕上的敌人时,敌人会被重置,但它发生的时间比这早得多。
世界空间位置和半径的计算方法:
public float[] getWorldSpaceCoordinates() {
float[] modelSpaceCenter = {0.0f, 0.0f, 0.0f, 1.0f};
float[] worldSpaceCenter = new float[4];
Matrix.multiplyMV(worldSpaceCenter, 0, getModelMatrix(), 0, modelSpaceCenter, 0);
return new float[] {worldSpaceCenter[0]/worldSpaceCenter[3], worldSpaceCenter[1]/worldSpaceCenter[3], worldSpaceCenter[2]/worldSpaceCenter[3]};
}
public float worldSpaceBoundingSphereRadius() {
float[] arbitraryVertex = new float[] {1.0f, 1.0f, 1.0f, 1.0f};
float[] worldSpaceVector = new float[4];
Matrix.multiplyMV(worldSpaceVector, 0, getModelMatrix(), 0, arbitraryVertex, 0);
float[] xyz = new float[] {worldSpaceVector[0]/worldSpaceVector[3], worldSpaceVector[1]/worldSpaceVector[3], worldSpaceVector[2]/worldSpaceVector[3]};
return Vector3f.length(xyz);
}
是我的代码或数学有问题吗?我想不出还有什么可以尝试的,如果有人能指出我正确的方向,将会很有帮助。
最佳答案
您的 worldSpaceBoundingSphereRadius()
很可能是罪魁祸首。 任意顶点
是 (1,1,1) 的 vector ,因此只有当立方体模型的边长度为 2 * sqrt(1/3)
时,您的数学运算才有效。您想要做的是找到立方体模型边缘的确切长度,使用我的评论中的公式 (rad = sqrt( 3 * (x/2) * (x/2) )
) 并使用该半径作为您的 任意顶点
(rad,rad,rad,1
)。
此外,将乘法结果除以齐次坐标 (worldSpaceVector[0]/worldSpaceVector[3]
)。通过适当的旋转、平移或缩放,齐次坐标应始终恰好为 1
(如果它以 1 开始)。如果不是,则可能有一个投影矩阵或其他不是基本变换的东西。
编辑:
由于您使用 worldSpaceBoundingSphereRadius()
仅获取半径,因此您只需要 getModelMatrix()
的缩放组件。如果返回缩放和平移,则该平移将应用于您的半径并使其比实际大得多。
关于java - 球体碰撞测试 react 太快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34319226/