从相机旋转查看视锥体平面

时间:2014-03-11 18:50:16

标签: 3d camera rotation culling

我正在尝试通过旋转点并检查它们是否在相机前面(具有球形物体的半径)来执行视锥体剔除。远近顶部和底部平面工作正常,但是当摄像机角度camRot.y不接近0时,左右不会剔除。

当我旋转平面以匹配视锥体时出现问题,旋转的平面最终围绕错误的轴旋转。 (当我向下看时,左右平面的法线向量与近平面的方向相同)。

    (objectOffsetFromCamera.z*-cos(camRot.x)*cos(camRot.y) +
    objectOffsetFromCamera.x * sin(camRot.x)*cos(camRot.y) +
    objectOffsetFromCamera.y *-sin(camRot.y) - (DRAW_DISTANCE + radius) < 0 && //FARPLANE DISTANCE

    objectOffsetFromCamera.z*-cos(camRot.x)*cos(camRot.y) +
    objectOffsetFromCamera.x* sin(camRot.x)*cos(camRot.y) +
    objectOffsetFromCamera.y*-sin(camRot.y) + radius >= 0 && //NEAR PLANE

    objectOffsetFromCamera.z*-cos(camRot.x + (FOV_X / 2)) *cos(camRot.y) + 
    objectOffsetFromCamera.x* sin(camRot.x + (FOV_X / 2)) *cos(camRot.y) +
    objectOffsetFromCamera.y*-sin(camRot.y) + radius >= 0 && //RIGHT PLANE, bugged for none zero camRot.y values.

    objectOffsetFromCamera.z*-cos(camRot.x - (FOV_X / 2)) * cos(camRot.y) +
    objectOffsetFromCamera.x* sin(camRot.x - (FOV_X / 2)) * cos(camRot.y) +
    objectOffsetFromCamera.y*-sin(camRot.y) + radius >= 0 && //LEFT PLANE, bugged for none zero camRot.y values.

    objectOffsetFromCamera.z*-cos(camRot.x)*cos(camRot.y + (FOV_Y / 2)) +
    objectOffsetFromCamera.x* sin(camRot.x)*cos(camRot.y + (FOV_Y / 2)) +
    objectOffsetFromCamera.y*-sin(camRot.y + (FOV_Y / 2)) + radius >= 0 && //TOP PLANE

    objectOffsetFromCamera.z*-cos(camRot.x)*cos(camRot.y - (FOV_Y / 2)) +
    objectOffsetFromCamera.x* sin(camRot.x)*cos(camRot.y - (FOV_Y  / 2)) +
    objectOffsetFromCamera.y*-sin(camRot.y - (FOV_Y  / 2)) + radius >= 0) //BOTTOM PLANE

我不确定这个问题是否有一个简单的解决方案,但由于它接近工作,我希望我不必像我发现的一些教程那样重做。

需要做的是确保在向上或向下查看时额外的(FOV_X / 2)旋转与相机正确旋转,但我无法围绕如何旋转。

此外,所有cos和sin计算都是每帧完成的,只需将它们移动到代码中即可显示已完成的内容。

如果我的帖子/代码难以理解,我很抱歉。

我现在正在使用它,至少它看起来像是有效的。 我目前的代码(差不多)。 FOV_X和FOV_Y是常数,取决于fov和纵横比。

    void Camera::calcFrustumPlanes()
    {
frustumPlanes.pfar.x = sin(rot.x)*cos(rot.y);
frustumPlanes.pfar.y = -sin(rot.y);
frustumPlanes.pfar.z = -cos(rot.x)*cos(rot.y);

frustumPlanes.pnear.x = sin(rot.x)*cos(rot.y);
frustumPlanes.pnear.y = -sin(rot.y);
frustumPlanes.pnear.z = -cos(rot.x)*cos(rot.y);

frustumPlanes.pleft.x = sin(rot.x + cos(rot.y)*FOV_X*cos(rot.y) + cos(rot.x)*sin(sin(rot.y)*FOV_X)*sin(rot.y);
frustumPlanes.pleft.y = -sin(rot.y)*cos(sin(rot.y)*FOV_X);
frustumPlanes.pleft.z = -cos(rot.x + cos(rot.y)*FOV_X)*cos(rot.y) + sin(rot.x)*sin(sin(rot.y)*FOV_X)*sin(rot.y);

frustumPlanes.pright.x = sin(rot.x - cos(rot.y)*FOV_X)*cos(rot.y) + cos(rot.x)*sin(-sin(rot.y)*FOV_X)*sin(rot.y);
frustumPlanes.pright.y = -sin(rot.y)*cos(-sin(rot.y)*FOV_X);
frustumPlanes.pright.z = -cos(rot.x - cos(rot.y)*FOV_X)*cos(rot.y) +  sin(rot.x)*sin(-sin(rot.y)*FOV_X)*sin(rot.y);

frustumPlanes.ptop.x = sin(rot.x)*cos(rot.y + FOV_Y);
frustumPlanes.ptop.y = -sin(rot.y + FOV_Y);
frustumPlanes.ptop.z = -cos(rot.x)*cos(rot.y + FOV_Y);

frustumPlanes.pbottom.x = sin(rot.x)*cos(rot.y - FOV_Y);
frustumPlanes.pbottom.y = -sin(rot.y - FOV_Y);
frustumPlanes.pbottom.z = -cos(rot.x)*cos(rot.y - FOV_Y);
    }

    bool Camera::isWithinFrustum(glm::ivec3 objectPos, float radius)
glm::vec3 camOffset = objectPos - pos;
return (glm::dot(camOffset, frustumPlanes.pfar) < (DRAW_DISTANCE + radius ) &&
        glm::dot(camOffset, frustumPlanes.pnear)   >= -radius &&
        glm::dot(camOffset, frustumPlanes.pleft)   >= -radius &&
        glm::dot(camOffset, frustumPlanes.pright)  >= -radius  &&
        glm::dot(camOffset, frustumPlanes.ptop)    >= -radius  &&
        glm::dot(camOffset, frustumPlanes.pbottom) >= -radius);

0 个答案:

没有答案