Allolib  1.0
C++ Components For Interactive Multimedia
al_Ray.hpp
1 #ifndef INCLUDE_AL_RAY_HPP
2 #define INCLUDE_AL_RAY_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 simple Ray class with some intersection tests
40 
41  File author(s):
42  Tim Wood, 2014, fishuyo@gmail.com
43 */
44 
45 #include "al/math/al_Vec.hpp"
46 
47 namespace al {
48 
49 template <class T>
50 class Ray;
51 typedef Ray<float> Rayf;
52 typedef Ray<double> Rayd;
53 
57 template <class T>
58 class Ray {
59  public:
60  Vec<3, T> o, d; // origin and direction of ray
61 
62  Ray(){};
63  Ray(Vec<3, T> origin, Vec<3, T> direction) { set(origin, direction); }
64 
65  void set(Vec<3, T> origin, Vec<3, T> direction) {
66  o.set(origin);
67  d.set(direction.normalized());
68  }
69 
70  // return point on ray
71  Vec<3, T> operator()(T t) { return o + d * t; }
72 
73  Vec<3, T>& origin() { return o; }
74  Vec<3, T>& direction() { return d; }
75 
76  T intersectPlane(Vec<3, T> p0, Vec<3, T> n) {
77  T den = n.dot(d);
78  if (den == 0) return -1;
79  return n.dot(p0 - o) / den;
80  }
81 
82  T intersectCircle(Vec<3, T> p0, Vec<3, T> n, T rmax, T rmin = 0.0) {
83  T den = n.dot(d);
84  if (den == 0) return -1;
85  T t = n.dot(p0 - o) / den;
86  T r = ((*this)(t)-p0).mag();
87  if (r <= rmax && r >= rmin)
88  return t;
89  else
90  return -1;
91  }
92 
93  // intersect sphere
94  T intersectSphere(Vec<3, T> cen, T radius) {
95  Vec<3, T> o_c = o - cen;
96  T A = d.dot(d);
97  T B = 2. * (d.dot(o_c));
98  T C = (o_c.dot(o_c)) - radius * radius;
99  T det = B * B - 4 * A * C;
100 
101  if (det > 0.) {
102  T t1 = (-B - sqrt(det)) / (2. * A);
103  if (t1 > 0.) return t1;
104  T t2 = (-B + sqrt(det)) / (2. * A);
105  if (t2 > 0.) return t2;
106 
107  } else if (det == 0.) {
108  T t = -B / (2. * A);
109  if (t > 0.) return t;
110  }
111  return -1.; // will be ignoring negative intersections -1 qualifies a miss
112  }
113 
114  bool intersectsSphere(Vec<3, T> cen, T radius) {
115  return intersectSphere(cen, radius) > 0.;
116  }
117 
118  T intersectBox(Vec<3, T> cen, Vec<3, T> scl) {
119  // courtesy of http://www.cs.utah.edu/~awilliam/box/
120  float tmin, tmax, tymin, tymax, tzmin, tzmax;
121 
122  Vec<3, T> parameters[2];
123  Vec<3, T> min = cen - scl / 2;
124  Vec<3, T> max = cen + scl / 2;
125  parameters[0] = min;
126  parameters[1] = max;
127 
128  Vec<3, T> inv_direction = 1.0 / d;
129  int sign[3];
130  sign[0] = (inv_direction.x < 0);
131  sign[1] = (inv_direction.y < 0);
132  sign[2] = (inv_direction.z < 0);
133 
134  tmin = (parameters[sign[0]].x - o.x) * inv_direction.x;
135  tmax = (parameters[1 - sign[0]].x - o.x) * inv_direction.x;
136  tymin = (parameters[sign[1]].y - o.y) * inv_direction.y;
137  tymax = (parameters[1 - sign[1]].y - o.y) * inv_direction.y;
138  if ((tmin > tymax) || (tymin > tmax)) return -1.0;
139  if (tymin > tmin) tmin = tymin;
140  if (tymax < tmax) tmax = tymax;
141  tzmin = (parameters[sign[2]].z - o.z) * inv_direction.z;
142  tzmax = (parameters[1 - sign[2]].z - o.z) * inv_direction.z;
143  if ((tmin > tzmax) || (tzmin > tmax)) return -1.0;
144  if (tzmin > tmin) tmin = tzmin;
145  if (tzmax < tmax) tmax = tzmax;
146 
147  if (tmin < 0.0)
148  if (tmax < 0.0)
149  return -1.0;
150  else
151  return tmax;
152  else
153  return tmin;
154  }
155 
156  bool intersectsBox(Vec<3, T> cen, Vec<3, T> scl) {
157  return intersectBox(cen, scl) > 0.0;
158  }
159 
160  // intersect cylinder positioned at origin oriented with Z axis
161  T intersectCylinderXY(T radius) {
162  T A = d.x * d.x + d.y * d.y;
163  T B = 2. * (d.x * o.x + d.y * o.y);
164  T C = (o.x * o.x + o.y * o.y) - radius * radius;
165  T det = B * B - 4 * A * C;
166 
167  if (det > 0.) {
168  T t1 = (-B - sqrt(det)) / (2. * A);
169  if (t1 > 0.) return t1;
170  T t2 = (-B + sqrt(det)) / (2. * A);
171  if (t2 > 0.) return t2;
172 
173  } else if (det == 0.) {
174  T t = -B / (2. * A);
175  if (t > 0.) return t;
176  }
177  return -1.; // will be ignoring negative intersections so this is ok for
178  // now
179  }
180 
181  // intersect cylinder positioned at origin oriented with Y axis
182  T intersectCylinderXZ(T radius) {
183  T A = d.x * d.x + d.z * d.z;
184  T B = 2. * (d.x * o.x + d.z * o.z);
185  T C = (o.x * o.x + o.z * o.z) - radius * radius;
186  T det = B * B - 4 * A * C;
187 
188  if (det > 0.) {
189  T t1 = (-B - sqrt(det)) / (2. * A);
190  if (t1 > 0.) return t1;
191  T t2 = (-B + sqrt(det)) / (2. * A);
192  if (t2 > 0.) return t2;
193 
194  } else if (det == 0.) {
195  T t = -B / (2. * A);
196  if (t > 0.) return t;
197  }
198  return -1.; // will be ignoring negative intersections so this is ok for
199  // now
200  }
201 
202  // intersect with the capsule shape of the AlloSphere
203  // assumes the ray is originating near the center of the sphere
204  // check this..
205  T intersectAllosphere() {
206  T radius = 4.842f;
207  T bridgeWidth2 = 2.09f / 2.;
208 
209  // intersect with bridge cylinder
210  T t = intersectCylinderXY(radius);
211 
212  // if no intersection intersect with appropriate hemisphere
213  if (t == -1.) {
214  if (d.z < 0.)
215  return intersectSphere(Vec<3, T>(0, 0, -bridgeWidth2), radius);
216  else
217  return intersectSphere(Vec<3, T>(0, 0, bridgeWidth2), radius);
218  }
219 
220  Vec<3, T> p = (*this)(t);
221  if (p.z < -bridgeWidth2) {
222  return intersectSphere(Vec<3, T>(0, 0, -bridgeWidth2), radius);
223  } else if (p.z > bridgeWidth2) {
224  return intersectSphere(Vec<3, T>(0, 0, bridgeWidth2), radius);
225  } else
226  return t;
227  }
228 };
229 
230 } // namespace al
231 
232 #endif
Vec & set(const Vec< N, T2 > &v)
Set elements from another vector.
Definition: al_Vec.hpp:301
Vec normalized(T scale=T(1)) const
Return closest vector lying on unit sphere.
Definition: al_Vec.hpp:489
T dot(const Vec< N, U > &v) const
Returns dot (inner) product between vectors.
Definition: al_Vec.hpp:406
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