LCOV - code coverage report
Current view: top level - source/maths - Frustum.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 10 65 15.4 %
Date: 2023-01-19 00:18:29 Functions: 5 12 41.7 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : /*
      19             : Usually associated with the camera, there are 6 planes which define the
      20             : view pyramid. But we allow more planes per frustum which may be used for
      21             : portal rendering, where a portal may have 3 or more edges.
      22             : */
      23             : 
      24             : #include "precompiled.h"
      25             : 
      26             : #include "Frustum.h"
      27             : 
      28             : #include "maths/BoundingBoxAligned.h"
      29             : #include "maths/MathUtil.h"
      30             : #include "maths/Matrix3D.h"
      31             : 
      32          37 : CFrustum::CFrustum()
      33             : {
      34          37 :     m_NumPlanes = 0;
      35          37 : }
      36             : 
      37          38 : CFrustum::~CFrustum()
      38             : {
      39          38 : }
      40             : 
      41           4 : void CFrustum::SetNumPlanes(size_t num)
      42             : {
      43           4 :     m_NumPlanes = num;
      44             : 
      45           4 :     if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
      46             :     {
      47           0 :         debug_warn(L"CFrustum::SetNumPlanes: Too many planes");
      48           0 :         m_NumPlanes = MAX_NUM_FRUSTUM_PLANES - 1;
      49             :     }
      50           4 : }
      51             : 
      52           0 : void CFrustum::AddPlane(const CPlane& plane)
      53             : {
      54           0 :     if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
      55             :     {
      56           0 :         debug_warn(L"CFrustum::AddPlane: Too many planes");
      57           0 :         return;
      58             :     }
      59             : 
      60           0 :     m_Planes[m_NumPlanes++] = plane;
      61             : }
      62             : 
      63           0 : void CFrustum::Transform(const CMatrix3D& m)
      64             : {
      65           0 :     for (size_t i = 0; i < m_NumPlanes; ++i)
      66             :     {
      67           0 :         CVector3D n = m.Rotate(m_Planes[i].m_Norm);
      68           0 :         CVector3D p = m.Transform(m_Planes[i].m_Norm * -m_Planes[i].m_Dist);
      69           0 :         m_Planes[i].Set(n, p);
      70           0 :         m_Planes[i].Normalize();
      71             :     }
      72           0 : }
      73             : 
      74           0 : bool CFrustum::IsPointVisible(const CVector3D& point) const
      75             : {
      76           0 :     for (size_t i = 0; i < m_NumPlanes; ++i)
      77             :     {
      78           0 :         if (m_Planes[i].IsPointOnBackSide(point))
      79           0 :             return false;
      80             :     }
      81             : 
      82           0 :     return true;
      83             : }
      84             : 
      85           0 : bool CFrustum::DoesSegmentIntersect(const CVector3D& startRef, const CVector3D& endRef) const
      86             : {
      87           0 :     CVector3D start = startRef;
      88           0 :     CVector3D end = endRef;
      89             : 
      90           0 :     if (IsPointVisible(start) || IsPointVisible(end))
      91           0 :         return true;
      92             : 
      93           0 :     CVector3D intersect;
      94           0 :     for (size_t i = 0; i < m_NumPlanes; ++i)
      95             :     {
      96           0 :         if (m_Planes[i].FindLineSegIntersection(start, end, &intersect))
      97             :         {
      98           0 :             if (IsPointVisible(intersect))
      99           0 :                 return true;
     100             :         }
     101             :     }
     102           0 :     return false;
     103             : }
     104             : 
     105           0 : bool CFrustum::IsSphereVisible(const CVector3D& center, float radius) const
     106             : {
     107           0 :     for (size_t i = 0; i < m_NumPlanes; ++i)
     108             :     {
     109             :         // If none of the sphere is in front of the plane, then
     110             :         // it is outside the frustum.
     111           0 :         if (-m_Planes[i].DistanceToPlane(center) > radius)
     112           0 :             return false;
     113             :     }
     114             : 
     115           0 :     return true;
     116             : }
     117             : 
     118           0 : bool CFrustum::IsBoxVisible(const CVector3D& position, const CBoundingBoxAligned& bounds) const
     119             : {
     120             :     // Basically for every plane we calculate the furthest point
     121             :     // in the box to that plane. If that point is beyond the plane
     122             :     // then the box is not visible.
     123           0 :     CVector3D farPoint;
     124           0 :     CVector3D minPoint = position + bounds[0];
     125           0 :     CVector3D maxPoint = position + bounds[1];
     126             : 
     127           0 :     for (size_t i = 0; i < m_NumPlanes; ++i)
     128             :     {
     129           0 :         farPoint.X = m_Planes[i].m_Norm.X > 0.0f ? maxPoint.X : minPoint.X;
     130           0 :         farPoint.Y = m_Planes[i].m_Norm.Y > 0.0f ? maxPoint.Y : minPoint.Y;
     131           0 :         farPoint.Z = m_Planes[i].m_Norm.Z > 0.0f ? maxPoint.Z : minPoint.Z;
     132             : 
     133           0 :         if (m_Planes[i].IsPointOnBackSide(farPoint))
     134           0 :             return false;
     135             :     }
     136             : 
     137           0 :     return true;
     138             : }
     139             : 
     140           0 : bool CFrustum::IsBoxVisible(const CBoundingBoxAligned& bounds) const
     141             : {
     142             :     // Same as the previous one, but with the position = (0, 0, 0).
     143           0 :     CVector3D farPoint;
     144             : 
     145           0 :     for (size_t i = 0; i < m_NumPlanes; ++i)
     146             :     {
     147           0 :         farPoint.X = m_Planes[i].m_Norm.X > 0.0f ? bounds[1].X : bounds[0].X;
     148           0 :         farPoint.Y = m_Planes[i].m_Norm.Y > 0.0f ? bounds[1].Y : bounds[0].Y;
     149           0 :         farPoint.Z = m_Planes[i].m_Norm.Z > 0.0f ? bounds[1].Z : bounds[0].Z;
     150             : 
     151           0 :         if (m_Planes[i].IsPointOnBackSide(farPoint))
     152           0 :             return false;
     153             :     }
     154             : 
     155           0 :     return true;
     156           3 : }

Generated by: LCOV version 1.13