我试图通过旋转点并检查它们是否在摄像机前面(具有球形物体的半径)来执行视锥体剔除 . 远近顶部和底部平面工作正常,但是当摄像机角度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);