Allolib  1.0
C++ Components For Interactive Multimedia
al_Frustum.hpp
1 #ifndef INCLUDE_AL_FRUSTUM_HPP
2 #define INCLUDE_AL_FRUSTUM_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  This is a rectangular frustum useful for computer graphics
40 
41  File author(s):
42  Lance Putnam, 2011, putnam.lance@gmail.com
43 */
44 
45 #include "al/math/al_Plane.hpp"
46 #include "al/math/al_Vec.hpp"
47 
48 namespace al {
49 
50 template <class T>
51 class Frustum;
53 
55 
64 template <class T>
65 class Frustum {
66  public:
67  enum { TOP = 0, BOTTOM, LEFT, RIGHT, NEARP, FARP };
68  enum { OUTSIDE = 0, INTERSECT, INSIDE };
69 
70  Vec<3, T> ntl, ntr, nbl, nbr, ftl, ftr, fbl, fbr;
71  Plane<T> pl[6];
72 
73  const Vec<3, T>& corner(int i) const { return (&ntl)[i]; }
74 
75  const Vec<3, T>& corner(int i0, int i1, int i2) const {
76  return corner(i2 << 2 | i1 << 1 | i0);
77  }
78 
80  template <class U>
81  Vec<3, T> getPoint(const Vec<3, U>& frac) const {
82  return lerp(frac[2],
83  lerp(frac[1], lerp(frac[0], corner(0, 0, 0), corner(1, 0, 0)),
84  lerp(frac[0], corner(0, 1, 0), corner(1, 1, 0))),
85  lerp(frac[1], lerp(frac[0], corner(0, 0, 1), corner(1, 0, 1)),
86  lerp(frac[0], corner(0, 1, 1), corner(1, 1, 1))));
87  }
88 
90  template <class U>
91  Vec<3, T> getPoint(const U& fracx, const U& fracy, const U& fracz) const {
92  return getPoint(Vec<3, U>(fracx, fracy, fracz));
93  }
94 
96  int testPoint(const Vec<3, T>& p) const;
97 
99  int testSphere(const Vec<3, T>& center, float radius) const;
100 
102 
106  int testBox(const Vec<3, T>& xyz, const Vec<3, T>& dim) const;
107 
109  template <class V>
110  void boundingBox(Vec<3, V>& xyz, Vec<3, V>& dim) const;
111 
113  Vec<3, T> center() const {
114  return (ntl + ntr + nbl + nbr + ftl + ftr + fbl + fbr) * 0.125;
115  }
116 
118 
121  void computePlanes();
122 
123  private:
124  template <class Tf, class Tv>
125  static Tv lerp(Tf f, const Tv& x, const Tv& y) {
126  return (y - x) * f + x;
127  }
128 };
129 
130 template <class T>
131 template <class V>
133  Vec<3, T> vmin = corner(0);
134  Vec<3, T> vmax = vmin;
135 
136  for (int i = 1; i < 8; ++i) {
137  Vec<3, T> v = corner(i);
138  vmin = min(vmin, v);
139  vmax = max(vmax, v);
140  }
141 
142  xyz = vmin;
143  dim = vmax - vmin;
144 }
145 
146 template <class T>
148  pl[TOP].from3Points(ntr, ntl, ftl);
149  pl[BOTTOM].from3Points(nbl, nbr, fbr);
150  pl[LEFT].from3Points(ntl, nbl, fbl);
151  pl[RIGHT].from3Points(nbr, ntr, fbr);
152  pl[NEARP].from3Points(ntl, ntr, nbr);
153  pl[FARP].from3Points(ftr, ftl, fbl);
154 }
155 
156 template <class T>
157 int Frustum<T>::testPoint(const Vec<3, T>& p) const {
158  for (int i = 0; i < 6; ++i) {
159  if (pl[i].inNegativeSpace(p)) return OUTSIDE;
160  }
161  return INSIDE;
162 }
163 
164 template <class T>
165 int Frustum<T>::testSphere(const Vec<3, T>& c, float r) const {
166  int result = INSIDE;
167  for (int i = 0; i < 6; ++i) {
168  float distance = pl[i].distance(c);
169  if (distance < -r)
170  return OUTSIDE;
171  else if (distance < r)
172  result = INTERSECT;
173  }
174  return result;
175 }
176 
177 template <class T>
178 int Frustum<T>::testBox(const Vec<3, T>& xyz, const Vec<3, T>& dim) const {
179  int result = INSIDE;
180  for (int i = 0; i < 6; ++i) {
181  const Vec3d& plNrm = pl[i].normal();
182 
183  /*
184  The positive vertex is the vertex from the box that is further along
185  the normal's direction. The negative vertex is the opposite vertex.
186 
187  If the p-vertex is on the wrong side of the plane, the box can be
188  immediately rejected, as it falls completely outside the frustum. On the
189  other hand, if the p-vertex is on the right side of the plane, then
190  testing the whereabouts of the n-vertex tells if the box is totally on
191  the right side of the plane, or if the box intersects the plane.
192  */
193  // Is positive vertex outside?
194  Vec<3, T> vp = xyz;
195  if (plNrm[0] > 0) vp[0] += dim[0];
196  if (plNrm[1] > 0) vp[1] += dim[1];
197  if (plNrm[2] > 0) vp[2] += dim[2];
198  if (pl[i].inNegativeSpace(vp)) return OUTSIDE;
199 
200  // Is negative vertex outside?
201  Vec<3, T> vn = xyz;
202  if (plNrm[0] < 0) vn[0] += dim[0];
203  if (plNrm[1] < 0) vn[1] += dim[1];
204  if (plNrm[2] < 0) vn[2] += dim[2];
205  if (pl[i].inNegativeSpace(vn)) result = INTERSECT;
206  }
207  return result;
208 }
209 
210 } // namespace al
211 
212 #endif
Rectangular frustum.
Definition: al_Frustum.hpp:65
int testBox(const Vec< 3, T > &xyz, const Vec< 3, T > &dim) const
Test whether axis-aligned box is in frustum.
Definition: al_Frustum.hpp:178
int testPoint(const Vec< 3, T > &p) const
Test whether point is in frustum.
Definition: al_Frustum.hpp:157
int testSphere(const Vec< 3, T > &center, float radius) const
Test whether sphere is in frustum.
Definition: al_Frustum.hpp:165
Vec< 3, T > getPoint(const Vec< 3, U > &frac) const
Get point in frustum corresponding to fraction along edges.
Definition: al_Frustum.hpp:81
Vec< 3, T > getPoint(const U &fracx, const U &fracy, const U &fracz) const
Get point in frustum corresponding to fraction along edges.
Definition: al_Frustum.hpp:91
void boundingBox(Vec< 3, V > &xyz, Vec< 3, V > &dim) const
Get axis-aligned bounding box.
Definition: al_Frustum.hpp:132
Vec< 3, T > fbr
Corners.
Definition: al_Frustum.hpp:70
Plane< T > pl[6]
Faces.
Definition: al_Frustum.hpp:71
Vec< 3, T > center() const
Returns center of frustum.
Definition: al_Frustum.hpp:113
void computePlanes()
Compute planes based on frustum corners (planes face to inside)
Definition: al_Frustum.hpp:147
T distance(const Vec3 &p) const
Returns distance from plane to point (measured relative to plane normal)
Definition: al_Plane.hpp:67
const Vec3 & normal() const
Get normal perpendicular to plane (a, b, and c components)
Definition: al_Plane.hpp:61
Plane & from3Points(const Vec3 &v1, const Vec3 &v2, const Vec3 &v3)
Set from three points lying on the plane.
Definition: al_Plane.hpp:98
T min(const T &v1, const T &v2, const T &v3)
T max(const T &v1, const T &v2, const T &v3)
Definition: al_App.hpp:23
Frustum< double > Frustumd
Double precision frustrum.
Definition: al_Frustum.hpp:51