如何检查物体是否在相机前方?

2022-09-04 21:54:27

我有一些树,它们大大滞后于游戏,所以我想检查一下这些树是否在镜头前。A swaggy picture

我从数学论坛得到了一些帮助,并且还查看了此链接,以帮助我将俯仰/偏航转换为所需的方向向量。

但是由于某种原因,每当我将相机向左移动时,树木都会变得可见,每当我将其向右移动时,它们都会变得不可见(因此,如果相机指向Z轴上的+1,它似乎正在渲染树木,但在Z轴上为-1,并且似乎没有渲染它们)。GIF of trees being dumb (请参阅 http://i.gyazo.com/cdd05dc3f5dbdc07577c6e41fab3a549 了解不那么跳跃的.mp4)

我使用以下代码来检查对象是否在相机前面:

Ship you = shipsID.get(UID);
int dis = 300;
Vector3f X = new Vector3f(camera.x(), camera.y(), camera.z());
float x = (float) (Math.cos(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float y = (float) (Math.sin(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float z = (float) Math.sin(Math.toRadians(camera.pitch()));
Vector3f V = new Vector3f(x, y, z);

for (Tree tree : trees){
    Vector3f Y = new Vector3f(tree.location.x, tree.location.y, tree.location.z);
    Vector3f YMinusX = Y.negate(X);//new Vector3f(Y.x - X.x, Y.y - X.y, Y.z - X.z);
    float dot = Vector3f.dot(YMinusX, V);
    if (dot > 0){
        tree.render();
    }
}

有谁能告诉我我在这里做错了什么吗?我无法确定这是否是数学。或代码..还是什么?

相机翻译代码:

 public void applyTranslations() {
    glPushAttrib(GL_TRANSFORM_BIT);
    glMatrixMode(GL_MODELVIEW);
    glRotatef(pitch, 1, 0, 0);
    glRotatef(yaw, 0, 1, 0);
    lastYaw = yaw;
    glRotatef(roll, 0, 0, 1);
    glTranslatef(-x, -y, -z);
    glPopAttrib();
}

更新:

它似乎是相机正在看的地方。例如,如果我看-Z,什么也没发生,但是如果我看+Z,它们都会渲染。看起来是+Z而不是+TheCameraRotation。if (dot > 0) code


答案 1

您的相机围绕 Y 偏航旋转,这意味着 Y 是您的向上矢量。但是,放弃你的向上向量。存在不一致。我会从交换开始,然后在这里打印出每一帧的所有内容,这样你就可以看到旋转相机时会发生什么。同时只渲染一棵树并打印。例如,只有当您查看树的左侧90度时,您才可能很快注意到数字接近1.0,从而缩小了问题的范围。正如@DWilches所指出的,交换cos/sin会改变旋转的相位,这将产生这样的效果。float z = (float) Math.sin(Math.toRadians(camera.pitch()));Zyzdot

您可以考虑将点积限制在相机的视场内。仍然存在一些问题,因为树不仅仅是点。更好的方法是根据相机视锥体测试树边界框,如@glampert所示。

尽管如此,树几何图形看起来并不那么复杂。在优化方面,我会开始尝试更快地绘制它们。您是否在使用维京群岛?也许可以看看减少绘制调用的方法,例如实例化。甚至可以为LOD或广告牌使用一些模型。更进一步,广告牌上有多棵树。遮挡剔除方法可用于忽略山脉后面的树木。

[编辑]
由于您的树木大致都在飞机上,因此您可以将问题限制在相机的偏航上:

float angleToTree = Math.atan2(tree.location.z - camera.z(), tree.location.x - camera.x());
float angleDiff = angleToTree - camera.yaw();
if (angleDiff > Math.PI)
    angleDiff -= 2.0f * Math.PI;
if (angleDiff < -Math.PI)
    angleDiff += 2.0f * Math.PI;
if (abs(angleDiff) < cameraFOV + 0.1f) //bias as trees are not points
    tree.render();

答案 2

你能这样写吗?

    Ship you = shipsID.get(UID);
    int dis = 300;
    Vector3f X = new Vector3f(camera.x(), camera.y(), camera.z());
    float x = (float) (Math.cos(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
    float y = (float) (Math.sin(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
    float z = (float) Math.sin(Math.toRadians(camera.pitch()));
    Vector3f V = new Vector3f(x, y, z);

    for (Tree tree : trees){
        Vector3f Y = new Vector3f(tree.location.x, tree.location.y, tree.location.z);
        Vector3f YMinusX = Y.negate(X);//new Vector3f(Y.x - X.x, Y.y - X.y, Y.z - X.z);
        float dot = Vector3f.dot(YMinusX, V);
        if (dot > 0){
            tree.render();
        }
    }

如您所见,对每棵树执行的计算要少得多。