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