Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Frustum.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2009 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  * CFrustum is a collection of planes which define a viewing space.
20  */
21 
22 /*
23 Usually associated with the camera, there are 6 planes which define the
24 view pyramid. But we allow more planes per frustum which may be used for
25 portal rendering, where a portal may have 3 or more edges.
26 */
27 
28 #include "precompiled.h"
29 
30 #include "Frustum.h"
32 #include "maths/MathUtil.h"
33 
35 {
36  m_NumPlanes = 0;
37 }
38 
40 {
41 }
42 
43 void CFrustum::SetNumPlanes (size_t num)
44 {
45  m_NumPlanes = num;
46 
47  //clip it
50 }
51 
52 void CFrustum::AddPlane (const CPlane& plane)
53 {
55  {
56  debug_warn(L"CFrustum::AddPlane: Too many planes");
57  return;
58  }
59 
60  m_aPlanes[m_NumPlanes++] = plane;
61 }
62 
63 bool CFrustum::IsPointVisible (const CVector3D &point) const
64 {
65  PLANESIDE Side;
66 
67  for (size_t i=0; i<m_NumPlanes; i++)
68  {
69  Side = m_aPlanes[i].ClassifyPoint (point);
70 
71  if (Side == PS_BACK)
72  return false;
73  }
74 
75  return true;
76 }
77 bool CFrustum::DoesSegmentIntersect(const CVector3D& startRef, const CVector3D &endRef)
78 {
79  CVector3D start = startRef;
80  CVector3D end = endRef;
81 
82  if(IsPointVisible(start) || IsPointVisible(end))
83  return true;
84 
85  CVector3D intersect;
86  for ( size_t i = 0; i<m_NumPlanes; ++i )
87  {
88  if ( m_aPlanes[i].FindLineSegIntersection(start, end, &intersect) )
89  {
90  if ( IsPointVisible( intersect ) )
91  return true;
92  }
93  }
94  return false;
95 }
96 bool CFrustum::IsSphereVisible (const CVector3D &center, float radius) const
97 {
98  for (size_t i=0; i<m_NumPlanes; i++)
99  {
100  float Dist = m_aPlanes[i].DistanceToPlane (center);
101 
102  //is it behind the plane
103  if (Dist < 0)
104  {
105  //if non of it falls in front its outside the
106  //frustum
107  if (-Dist > radius)
108  return false;
109  }
110  }
111 
112  return true;
113 }
114 
115 
116 bool CFrustum::IsBoxVisible (const CVector3D &position,const CBoundingBoxAligned &bounds) const
117 {
118  //basically for every plane we calculate the furthest point
119  //in the box to that plane. If that point is beyond the plane
120  //then the box is not visible
121  CVector3D FarPoint;
122  PLANESIDE Side;
123  CVector3D Min = position+bounds[0];
124  CVector3D Max = position+bounds[1];
125 
126  for (size_t i=0; i<m_NumPlanes; i++)
127  {
128  if (m_aPlanes[i].m_Norm.X > 0.0f)
129  {
130  if (m_aPlanes[i].m_Norm.Y > 0.0f)
131  {
132  if (m_aPlanes[i].m_Norm.Z > 0.0f)
133  {
134  FarPoint.X = Max.X; FarPoint.Y = Max.Y; FarPoint.Z = Max.Z;
135  }
136  else
137  {
138  FarPoint.X = Max.X; FarPoint.Y = Max.Y; FarPoint.Z = Min.Z;
139  }
140  }
141  else
142  {
143  if (m_aPlanes[i].m_Norm.Z > 0.0f)
144  {
145  FarPoint.X = Max.X; FarPoint.Y = Min.Y; FarPoint.Z = Max.Z;
146  }
147  else
148  {
149  FarPoint.X = Max.X; FarPoint.Y = Min.Y; FarPoint.Z = Min.Z;
150  }
151  }
152  }
153  else
154  {
155  if (m_aPlanes[i].m_Norm.Y > 0.0f)
156  {
157  if (m_aPlanes[i].m_Norm.Z > 0.0f)
158  {
159  FarPoint.X = Min.X; FarPoint.Y = Max.Y; FarPoint.Z = Max.Z;
160  }
161  else
162  {
163  FarPoint.X = Min.X; FarPoint.Y = Max.Y; FarPoint.Z = Min.Z;
164  }
165  }
166  else
167  {
168  if (m_aPlanes[i].m_Norm.Z > 0.0f)
169  {
170  FarPoint.X = Min.X; FarPoint.Y = Min.Y; FarPoint.Z = Max.Z;
171  }
172  else
173  {
174  FarPoint.X = Min.X; FarPoint.Y = Min.Y; FarPoint.Z = Min.Z;
175  }
176  }
177  }
178 
179  Side = m_aPlanes[i].ClassifyPoint (FarPoint);
180 
181  if (Side == PS_BACK)
182  return false;
183  }
184 
185  return true;
186 }
187 
188 
bool IsSphereVisible(const CVector3D &center, float radius) const
Definition: Frustum.cpp:96
PLANESIDE
Definition: Plane.h:31
CFrustum()
Definition: Frustum.cpp:34
bool IsBoxVisible(const CVector3D &position, const CBoundingBoxAligned &bounds) const
Definition: Frustum.cpp:116
bool IsPointVisible(const CVector3D &point) const
Definition: Frustum.cpp:63
size_t m_NumPlanes
Definition: Frustum.h:68
float X
Definition: Vector3D.h:31
float DistanceToPlane(const CVector3D &point) const
Definition: Plane.cpp:99
float Y
Definition: Vector3D.h:31
PLANESIDE ClassifyPoint(const CVector3D &point) const
Definition: Plane.cpp:79
#define MAX_NUM_FRUSTUM_PLANES
Definition: Frustum.h:34
void AddPlane(const CPlane &plane)
Definition: Frustum.cpp:52
~CFrustum()
Definition: Frustum.cpp:39
CPlane m_aPlanes[MAX_NUM_FRUSTUM_PLANES]
Definition: Frustum.h:65
bool DoesSegmentIntersect(const CVector3D &start, const CVector3D &end)
Definition: Frustum.cpp:77
void SetNumPlanes(size_t num)
Definition: Frustum.cpp:43
float Z
Definition: Vector3D.h:31
Definition: Plane.h:38
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:324
Definition: Plane.h:34