const Frustum& Camera::GetFrustum() const { // Use projection_ instead of GetProjection() so that Y-flip has no effect. Update first if necessary if (projectionDirty_) UpdateProjection(); if (frustumDirty_) { if (customProjection_) frustum_.Define(projection_ * GetView()); else { // If not using a custom projection, prefer calculating frustum from projection parameters instead of matrix // for better accuracy if (!orthographic_) frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), GetFarClip(), GetEffectiveWorldTransform()); else frustum_.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), GetFarClip(), GetEffectiveWorldTransform()); } frustumDirty_ = false; } return frustum_; }
bool Camera::ObjectFrustumCulling( const RenderObject& obj ) { const AABB& aabb = obj.m_worldAABB; //物体坐标转换到相机空间进行裁减 VEC4 pos(aabb.GetCenter(), 1.0f); Common::Transform_Vec4_By_Mat44(pos, pos, GetViewMatrix()); float n = GetNearClip(); float f = GetFarClip(); float fov = GetFov(); float half_w = n * std::tan(fov/2); float half_h = half_w / GetAspectRatio(); //检测前后面 if(-pos.z+aabb.m_boundingRadius <= n || -pos.z-aabb.m_boundingRadius >= f) return true; //检测左右面 float planeX = half_w * pos.z / -n; if(pos.x - planeX >= aabb.m_boundingRadius || pos.x + aabb.m_boundingRadius <= -planeX) return true; //检测上下面 float planeY = half_h * pos.z / -n; if(pos.y - planeY >= aabb.m_boundingRadius || pos.y + aabb.m_boundingRadius <= -planeY) return true; return false; }
Frustum Camera::GetViewSpaceFrustum() const { if (projectionDirty_) UpdateProjection(); Frustum ret; if (customProjection_) ret.Define(projection_); else { if (!orthographic_) ret.Define(fov_, aspectRatio_, zoom_, GetNearClip(), GetFarClip()); else ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), GetFarClip()); } return ret; }
bool Camera::IsProjectionValid() const { return GetFarClip() > GetNearClip(); }