GteCuller.cpp
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #include <GTEnginePCH.h>
9 #include <Graphics/GteCamera.h>
10 #include <Graphics/GteSpatial.h>
11 using namespace gte;
12 
13 
15 {
16 }
17 
19  :
21 {
22  // The data members mFrustum, mPlane, and mPlaneState are
23  // uninitialized. They are initialized in the GetVisibleSet call.
25 }
26 
27 bool Culler::PushPlane(CullingPlane const& plane)
28 {
30  {
31  // The number of user-defined planes is limited.
32  mPlane[mPlaneQuantity] = plane;
34  return true;
35  }
36  return false;
37 }
38 
40 {
42  {
43  // Only non-view-frustum planes may be removed from the stack.
45  return true;
46  }
47  return false;
48 }
49 
50 void Culler::ComputeVisibleSet(std::shared_ptr<Camera> const& camera,
51  std::shared_ptr<Spatial> const& scene)
52 {
53  if (scene)
54  {
55  PushViewFrustumPlanes(camera);
56  mVisibleSet.clear();
57  scene->OnGetVisibleSet(*this, camera, false);
58  }
59  else
60  {
61  LogError("A scene is required for culling.");
62  }
63 }
64 
65 bool Culler::IsVisible(BoundingSphere const& sphere)
66 {
67  if (sphere.GetRadius() == 0.0f)
68  {
69  // The node is a dummy node and cannot be visible.
70  return false;
71  }
72 
73  // Start with the last pushed plane, which is potentially the most
74  // restrictive plane.
75  int index = mPlaneQuantity - 1;
76  unsigned int mask = (1u << index);
77 
78  for (int i = 0; i < mPlaneQuantity; ++i, --index, mask >>= 1)
79  {
80  if (mPlaneState & mask)
81  {
82  int side = sphere.WhichSide(mPlane[index]);
83 
84  if (side < 0)
85  {
86  // The object is on the negative side of the plane, so
87  // cull it.
88  return false;
89  }
90 
91  if (side > 0)
92  {
93  // The object is on the positive side of plane. There is
94  // no need to compare subobjects against this plane, so
95  // mark it as inactive.
96  mPlaneState &= ~mask;
97  }
98  }
99  }
100 
101  return true;
102 }
103 
104 void Culler::Insert(Visual* visible)
105 {
106  mVisibleSet.push_back(visible);
107 }
108 
109 void Culler::PushViewFrustumPlanes(std::shared_ptr<Camera> const& camera)
110 {
111  // Get the frustum values.
112  float dMax = camera->GetDMax();
113  float dMin = camera->GetDMin(), dMin2 = dMin * dMin;
114  float rMax = camera->GetRMax(), rMax2 = rMax * rMax;
115  float rMin = camera->GetRMin(), rMin2 = rMin * rMin;
116  float uMax = camera->GetUMax(), uMax2 = uMax * uMax;
117  float uMin = camera->GetUMin(), uMin2 = uMin * uMin;
118 
119  // Get the camera coordinate frame.
120  Vector4<float> P = camera->GetPosition();
121  Vector4<float> D = camera->GetDVector();
122  Vector4<float> U = camera->GetUVector();
123  Vector4<float> R = camera->GetRVector();
124  float dirDotEye = Dot(D, P);
125 
126  // Compute the frustum planes in world coordinates.
127  Vector4<float> N;
128  float invLength, a0, a1, c;
129 
130  // Compute the near plane, N = D.
131  c = -(dirDotEye + dMin);
132  mPlane[Camera::VF_DMIN].Set(D, c);
133 
134  // Compute the far plane, N = -D.
135  c = dirDotEye + dMax;
136  mPlane[Camera::VF_DMAX].Set(-D, c);
137 
138  // Compute the bottom plane
139  invLength = 1.0f / sqrt(dMin2 + uMin2);
140  a0 = -uMin*invLength; // D component
141  a1 = +dMin*invLength; // U component
142  N = a0*D + a1*U;
143  c = -Dot(N, P);
144  mPlane[Camera::VF_UMIN].Set(N, c);
145 
146  // Compute the top plane.
147  invLength = 1.0f / sqrt(dMin2 + uMax2);
148  a0 = +uMax*invLength; // D component
149  a1 = -dMin*invLength; // U component
150  N = a0*D + a1*U;
151  c = -Dot(N, P);
152  mPlane[Camera::VF_UMAX].Set(N, c);
153 
154  // Compute the left plane.
155  invLength = 1.0f / sqrt(dMin2 + rMin2);
156  a0 = -rMin*invLength; // D component
157  a1 = +dMin*invLength; // R component
158  N = a0*D + a1*R;
159  c = -Dot(N, P);
160  mPlane[Camera::VF_RMIN].Set(N, c);
161 
162  // Compute the right plane.
163  invLength = 1.0f / sqrt(dMin2 + rMax2);
164  a0 = +rMax*invLength; // D component
165  a1 = -dMin*invLength; // R component
166  N = a0*D + a1*R;
167  c = -Dot(N, P);
168  mPlane[Camera::VF_RMAX].Set(N, c);
169 
170  // All planes are active initially.
171  mPlaneState = 0xFFFFFFFFu;
172 }
173 
int WhichSide(CullingPlane const &plane) const
VisibleSet mVisibleSet
Definition: GteCuller.h:119
float GetRadius() const
int mPlaneQuantity
Definition: GteCuller.h:114
GLint GLuint mask
Definition: glcorearb.h:119
void Set(Vector4< float > const &N, float c)
virtual void Insert(Visual *visible)
Definition: GteCuller.cpp:104
const GLubyte * c
Definition: glext.h:11671
#define LogError(message)
Definition: GteLogger.h:92
bool PushPlane(CullingPlane const &plane)
Definition: GteCuller.cpp:27
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
unsigned int mPlaneState
Definition: GteCuller.h:116
GLuint index
Definition: glcorearb.h:781
virtual ~Culler()
Definition: GteCuller.cpp:14
CullingPlane mPlane[MAX_PLANE_QUANTITY]
Definition: GteCuller.h:115
bool IsVisible(BoundingSphere const &sphere)
Definition: GteCuller.cpp:65
void PushViewFrustumPlanes(std::shared_ptr< Camera > const &camera)
Definition: GteCuller.cpp:109
void ComputeVisibleSet(std::shared_ptr< Camera > const &camera, std::shared_ptr< Spatial > const &scene)
Definition: GteCuller.cpp:50
bool PopPlane()
Definition: GteCuller.cpp:39


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:59