Nebula
Loading...
Searching...
No Matches
frustum.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
11#include "math/plane.h"
12#include "math/mat4.h"
13#include "math/bbox.h"
14#include "math/clipstatus.h"
15
16//------------------------------------------------------------------------------
17namespace Math
18{
20{
21public:
34
36 frustum();
38 frustum(const mat4& invViewProj);
40 void set(const mat4& invViewProj);
42 void set(const bbox& box, const mat4& boxTransform);
44 bool inside(const point& p) const;
46 uint clipmask(const point& p) const;
48 ClipStatus::Type clip(const line& l, line& clippedLine) const;
50 ClipStatus::Type clipstatus(const bbox& box) const;
52 ClipStatus::Type clipstatus(const bbox& box, const mat4& boxTransform) const;
54 template<typename T> T as() const;
55
56 static const int TopLeftFar = 0;
57 static const int TopRightFar = 1;
58 static const int BottomLeftFar = 2;
59 static const int BottomRightFar = 3;
60 static const int TopLeftNear = 4;
61 static const int TopRightNear = 5;
62 static const int BottomLeftNear = 6;
63 static const int BottomRightNear = 7;
64
66};
67
68//------------------------------------------------------------------------------
71inline
73{
74 // empty
75}
76
77//------------------------------------------------------------------------------
80inline
81frustum::frustum(const mat4& invViewProj)
82{
83 this->set(invViewProj);
84}
85
86//------------------------------------------------------------------------------
91inline void
92frustum::set(const mat4& invViewProj)
93{
94 // frustum corners in projection space
95 vec4 projPoints[8];
96 projPoints[TopLeftFar].set(-1.0f, 1.0f, 1.0f, 1);
97 projPoints[TopRightFar].set(1.0f, 1.0f, 1.0f, 1);
98 projPoints[BottomLeftFar].set(-1.0f, -1.0f, 1.0f, 1);
99 projPoints[BottomRightFar].set(1.0f, -1.0f, 1.0f, 1);
100 projPoints[TopLeftNear].set(-1.0f, 1.0f, 0.0f, 1);
101 projPoints[TopRightNear].set(1.0f, 1.0f, 0.0f, 1);
102 projPoints[BottomLeftNear].set(-1.0f, -1.0f, 0.0f, 1);
103 projPoints[BottomRightNear].set(1.0f, -1.0f, 0.0f, 1);
104
105 // compute frustum corners in world space
106 vec3 worldPoints[8];
107 IndexT i;
108 for (i = 0; i < 8; i++)
109 {
110 vec4 p = invViewProj * projPoints[i];
111 p *= 1.0f / p.w;
112 worldPoints[i] = xyz(p);
113 }
114
115 // setup planes
116 this->planes[Near] = plane(worldPoints[TopRightNear], worldPoints[TopLeftNear], worldPoints[BottomLeftNear]);
117 this->planes[Far] = plane(worldPoints[TopLeftFar], worldPoints[TopRightFar], worldPoints[BottomRightFar]);
118 this->planes[Left] = plane(worldPoints[BottomLeftFar], worldPoints[BottomLeftNear], worldPoints[TopLeftNear]);
119 this->planes[Right] = plane(worldPoints[TopRightFar], worldPoints[TopRightNear], worldPoints[BottomRightNear]);
120 this->planes[Top] = plane(worldPoints[TopLeftNear], worldPoints[TopRightNear], worldPoints[TopRightFar]);
121 this->planes[Bottom] = plane(worldPoints[BottomLeftFar], worldPoints[BottomRightFar], worldPoints[BottomRightNear]);
122}
123
124//------------------------------------------------------------------------------
128inline void
129frustum::set(const bbox& box, const mat4& boxTransform)
130{
131 // compute frustum corners in world space
132 vec4 localPoint;
133 vec3 worldPoints[8];
134 IndexT i;
135 for (i = 0; i < 8; i++)
136 {
137 // Top: pmax.y, Bottom: pmin.y, Left: pmin.x, Right: pmax.x, Far: pmax.z, Near: pmin.z
138 switch (i)
139 {
140 // FIXME: replace with permute!
141 case TopLeftFar: localPoint.set(box.pmin.x, box.pmax.y, box.pmax.z, 1); break;
142 case TopRightFar: localPoint.set(box.pmax.x, box.pmax.y, box.pmax.z, 1); break;
143 case BottomLeftFar: localPoint.set(box.pmin.x, box.pmin.y, box.pmax.z, 1); break;
144 case BottomRightFar: localPoint.set(box.pmax.x, box.pmin.y, box.pmax.z, 1); break;
145 case TopLeftNear: localPoint.set(box.pmin.x, box.pmax.y, box.pmin.z, 1); break;
146 case TopRightNear: localPoint.set(box.pmax.x, box.pmax.y, box.pmin.z, 1); break;
147 case BottomLeftNear: localPoint.set(box.pmin.x, box.pmin.y, box.pmin.z, 1); break;
148 case BottomRightNear: localPoint.set(box.pmax.x, box.pmin.y, box.pmin.z, 1); break;
149 }
150 worldPoints[i] = xyz(boxTransform * localPoint);
151 }
152
153 // setup planes from transformed world space coordinates
154 this->planes[Near] = plane(worldPoints[TopLeftNear], worldPoints[TopRightNear], worldPoints[BottomLeftNear]);
155 this->planes[Far] = plane(worldPoints[TopRightFar], worldPoints[TopLeftFar], worldPoints[BottomRightFar]);
156 this->planes[Left] = plane(worldPoints[BottomLeftNear], worldPoints[BottomLeftFar], worldPoints[TopLeftNear]);
157 this->planes[Right] = plane(worldPoints[BottomRightNear], worldPoints[TopRightNear], worldPoints[TopRightFar]);
158 this->planes[Top] = plane(worldPoints[TopRightNear], worldPoints[TopLeftNear], worldPoints[TopRightFar]);
159 this->planes[Bottom] = plane(worldPoints[BottomRightFar], worldPoints[BottomLeftFar], worldPoints[BottomRightNear]);
160}
161
162//------------------------------------------------------------------------------
166inline bool
167frustum::inside(const point& p) const
168{
169 IndexT i;
170 for (i = 0; i < NumPlanes; i++)
171 {
172 if (dot(this->planes[i], p) > 0.0f)
173 {
174 return false;
175 }
176 }
177 return true;
178}
179
180//------------------------------------------------------------------------------
184inline uint
186{
187 uint clipMask = 0;
188 IndexT i;
189 for (i = 0; i < NumPlanes; i++)
190 {
191 if (dot(this->planes[i], p) > 0.0f)
192 {
193 clipMask |= 1<<i;
194 }
195 }
196 return clipMask;
197}
198
199//------------------------------------------------------------------------------
202inline ClipStatus::Type
203frustum::clip(const line& l, line& clippedLine) const
204{
206 line l0(l);
207 line l1;
208 IndexT i;
209 for (i = 0; i < NumPlanes; i++)
210 {
211 ClipStatus::Type planeClipStatus = Math::clip(this->planes[i], l0, l1);
212 if (ClipStatus::Outside == planeClipStatus)
213 {
214 return ClipStatus::Outside;
215 }
216 else if (ClipStatus::Clipped == planeClipStatus)
217 {
218 clipStatus = ClipStatus::Clipped;
219 }
220 l0 = l1;
221 }
222 clippedLine = l0;
223 return clipStatus;
224}
225
226//------------------------------------------------------------------------------
229inline ClipStatus::Type
230frustum::clipstatus(const bbox& box) const
231{
232 uint andFlags = 0xffff;
233 uint orFlags = 0;
234 point p;
235 IndexT i;
236 for (i = 0; i < 8; i++)
237 {
238 // get corner point of bounding box
239 switch (i)
240 {
241 // FIXME: REPLACE WITH PERMUTE!
242 case 0: p = box.pmin; break;
243 case 1: p.set(box.pmin.x, box.pmax.y, box.pmin.z); break;
244 case 2: p.set(box.pmax.x, box.pmax.y, box.pmin.z); break;
245 case 3: p.set(box.pmax.x, box.pmin.y, box.pmin.z); break;
246 case 4: p = box.pmax; break;
247 case 5: p.set(box.pmin.x, box.pmax.y, box.pmax.z); break;
248 case 6: p.set(box.pmin.x, box.pmin.y, box.pmax.z); break;
249 case 7: p.set(box.pmax.x, box.pmin.y, box.pmax.z); break;
250 }
251
252 // get clip mask of current box corner against frustum
253 uint clipMask = this->clipmask(p);
254 andFlags &= clipMask;
255 orFlags |= clipMask;
256 }
257 if (0 == orFlags) return ClipStatus::Inside;
258 else if (0 != andFlags) return ClipStatus::Outside;
259 else return ClipStatus::Clipped;
260}
261
262//------------------------------------------------------------------------------
266inline ClipStatus::Type
267frustum::clipstatus(const bbox& box, const mat4& boxTransform) const
268{
269 uint andFlags = 0xffff;
270 uint orFlags = 0;
271 vec4 localPoint, transformedPoint;
272 IndexT i;
273 for (i = 0; i < 8; i++)
274 {
275 // get corner point of bounding box
276 switch (i)
277 {
278 // FIXME: REPLACE WITH PERMUTE!
279 case 0: localPoint = box.pmin; break;
280 case 1: localPoint.set(box.pmin.x, box.pmax.y, box.pmin.z, 1); break;
281 case 2: localPoint.set(box.pmax.x, box.pmax.y, box.pmin.z, 1); break;
282 case 3: localPoint.set(box.pmax.x, box.pmin.y, box.pmin.z, 1); break;
283 case 4: localPoint = box.pmax; break;
284 case 5: localPoint.set(box.pmin.x, box.pmax.y, box.pmax.z, 1); break;
285 case 6: localPoint.set(box.pmin.x, box.pmin.y, box.pmax.z, 1); break;
286 case 7: localPoint.set(box.pmax.x, box.pmin.y, box.pmax.z, 1); break;
287 }
288
289 // transform bounding box point
290 transformedPoint = boxTransform * localPoint;
291
292 // get clip mask of current box corner against frustum
293 uint clipMask = this->clipmask(xyz(transformedPoint));
294 andFlags &= clipMask;
295 orFlags |= clipMask;
296 }
297 if (0 == orFlags) return ClipStatus::Inside;
298 else if (0 != andFlags) return ClipStatus::Outside;
299 else return ClipStatus::Clipped;
300}
301
302} // namespace Math
303//------------------------------------------------------------------------------
304
Type
Definition clipstatus.h:22
@ Outside
Definition clipstatus.h:24
@ Inside
Definition clipstatus.h:23
@ Clipped
Definition clipstatus.h:25
Nebula's bounding box class.
Definition bbox.h:24
point pmax
Definition bbox.h:93
point pmin
Definition bbox.h:92
Defines a clipping frustum made of 6 planes.
Definition frustum.h:20
static const int BottomLeftFar
Definition frustum.h:58
ClipStatus::Type clip(const line &l, line &clippedLine) const
clip line against view frustum
Definition frustum.h:203
bool inside(const point &p) const
test if point is inside frustum
Definition frustum.h:167
static const int BottomRightFar
Definition frustum.h:59
static const int TopLeftFar
Definition frustum.h:56
ClipStatus::Type clipstatus(const bbox &box) const
get clip status of a local bounding box
Definition frustum.h:230
static const int BottomLeftNear
Definition frustum.h:62
static const int TopRightNear
Definition frustum.h:61
void set(const mat4 &invViewProj)
setup from view and proj matrix
Definition frustum.h:92
static const int TopLeftNear
Definition frustum.h:60
T as() const
convert to any type
PlaneIndex
plane indices
Definition frustum.h:24
@ Right
Definition frustum.h:28
@ Top
Definition frustum.h:29
@ Left
Definition frustum.h:27
@ NumPlanes
Definition frustum.h:32
@ Bottom
Definition frustum.h:30
@ Far
Definition frustum.h:26
@ Near
Definition frustum.h:25
static const int BottomRightNear
Definition frustum.h:63
plane planes[NumPlanes]
Definition frustum.h:65
frustum()
default constructor
Definition frustum.h:72
uint clipmask(const point &p) const
get clip bitmask of point (0 if inside, (1<<PlaneIndex) if outside)
Definition frustum.h:185
static const int TopRightFar
Definition frustum.h:57
A line in 3d space.
Definition line.h:22
Half precision (16 bit) float implementation.
Definition angularpfeedbackloop.h:17
__forceinline scalar dot(const plane &p, const vec4 &v1)
Definition plane.h:246
ClipStatus::Type clip(const plane &plane, const line &l, line &outClippedLine)
Definition plane.h:208
__forceinline vec3 xyz(const point &v)
Definition point.h:528
A 4x4 single point precision float matrix.
Definition mat4.h:47
A mathematical plane represented by a normal and a distance from origin.
Definition plane.h:22
Represents a 3D point in space.
Definition point.h:22
void set(scalar x, scalar y, scalar z)
set content
Definition point.h:332
float z
Definition point.h:78
float x
Definition point.h:78
float y
Definition point.h:78
A 3D vector.
Definition vec3.h:39
A 4D vector.
Definition vec4.h:24
float w
Definition vec4.h:93
void set(scalar x, scalar y, scalar z, scalar w)
set content
Definition vec4.h:301
unsigned int uint
Definition types.h:31
int IndexT
Definition types.h:48