]>
Dogcows Code - chaz/yoink/blob - src/Moof/cml/util.h
1 /* -*- C++ -*- ------------------------------------------------------------
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
8 *-----------------------------------------------------------------------*/
16 #include <algorithm> // For std::min and std::max.
17 #include <cstdlib> // For std::rand.
18 #include <cml/constants.h>
21 #pragma push_macro("min")
22 #pragma push_macro("max")
29 /** Sign of input value as double. */
30 template < typename T
>
31 double sign(T value
) {
32 return value
< T(0) ? -1.0 : (value
> T(0) ? 1.0 : 0.0);
35 /** Clamp input value to the range [min, max]. */
36 template < typename T
>
37 T
clamp(T value
, T min
, T max
) {
38 return std::max(std::min(value
, max
), min
);
41 /** Test input value for inclusion in [min, max]. */
42 template < typename T
>
43 bool in_range(T value
, T min
, T max
) {
44 return !(value
< min
) && !(value
> max
);
47 /** Map input value from [min1, max1] to [min2, max2]. */
48 template < typename T
>
49 T
map_range(T value
, T min1
, T max1
, T min2
, T max2
) {
50 return min2
+ ((value
- min1
) / (max1
- min1
)) * (max2
- min2
);
54 /** Wrap std::acos() and clamp argument to [-1, 1]. */
55 template < typename T
>
56 T
acos_safe(T theta
) {
57 return T(std::acos(clamp(theta
, T(-1.0), T(1.0))));
60 /** Wrap std::asin() and clamp argument to [-1, 1]. */
61 template < typename T
>
62 T
asin_safe(T theta
) {
63 return T(std::asin(clamp(theta
, T(-1.0), T(1.0))));
66 /** Wrap std::sqrt() and clamp argument to [0, inf). */
67 template < typename T
>
68 T
sqrt_safe(T value
) {
69 return T(std::sqrt(std::max(value
, T(0.0))));
73 /** Square a value. */
74 template < typename T
>
80 template < typename T
>
82 return value
* value
* value
;
85 /** Inverse square root. */
86 template < typename T
>
88 return T(1.0 / std::sqrt(value
));
92 /* The next few functions deal with indexing. next() and prev() are useful
93 * for operations involving the vertices of a polygon or other cyclic set,
94 * and cyclic_permutation() is used by various functions that deal with
95 * axes or basis vectors in a generic way. As these functions are only
96 * relevant for unsigned integer types, I've just used size_t, but there
97 * may be reasons I haven't thought of that they should be templated.
100 /** Return next, with cycling, in a series of N non-negative integers. */
101 inline size_t next(size_t i
, size_t N
) {
105 /** Return previous, with cycling, in a series of N non-negative integers. */
106 inline size_t prev(size_t i
, size_t N
) {
107 return i
? (i
- 1) : (N
- 1);
110 /** Cyclic permutation of the set { 0, 1 }, starting with 'first'. */
111 inline void cyclic_permutation(size_t first
, size_t& i
, size_t& j
) {
116 /** Cyclic permutation of the set { 0, 1, 2 }, starting with 'first'. */
117 inline void cyclic_permutation(size_t first
, size_t& i
, size_t& j
, size_t& k
)
124 /** Cyclic permutation of the set { 0, 1, 2, 3 }, starting with 'first'. */
125 inline void cyclic_permutation(
126 size_t first
, size_t& i
, size_t& j
, size_t& k
, size_t& l
)
135 /** Convert radians to degrees. */
136 template < typename T
>
138 return theta
* constants
<T
>::deg_per_rad();
141 /** Convert degrees to radians. */
142 template < typename T
>
144 return theta
* constants
<T
>::rad_per_deg();
147 /* Note: Moving interpolation functions to interpolation.h */
150 /** Linear interpolation of 2 values.
152 * @note The data points are assumed to be sampled at u = 0 and u = 1, so
153 * for interpolation u must lie between 0 and 1.
155 template <typename T
, typename Scalar
>
156 T
lerp(const T
& f0
, const T
& f1
, Scalar u
) {
157 return (Scalar(1.0) - u
) * f0
+ u
* f1
;
162 /** Bilinear interpolation of 4 values.
164 * @note The data points are assumed to be sampled at the corners of a unit
165 * square, so for interpolation u and v must lie between 0 and 1,
167 template <typename T
, typename Scalar
>
168 T
bilerp(const T
& f00
, const T
& f10
,
169 const T
& f01
, const T
& f11
,
174 (Scalar(1.0) - u
- v
+ uv
) * f00
+
183 /** Trilinear interpolation of 8 values.
185 * @note The data values are assumed to be sampled at the corners of a unit
186 * cube, so for interpolation, u, v, and w must lie between 0 and 1.
188 template <typename T
, typename Scalar
>
189 T
trilerp(const T
& f000
, const T
& f100
,
190 const T
& f010
, const T
& f110
,
191 const T
& f001
, const T
& f101
,
192 const T
& f011
, const T
& f111
,
193 Scalar u
, Scalar v
, Scalar w
)
201 (Scalar(1.0) - u
- v
- w
+ uv
+ vw
+ wu
- uvw
) * f000
+
202 (u
- uv
- wu
+ uvw
) * f100
+
203 (v
- uv
- vw
+ uvw
) * f010
+
205 (w
- vw
- wu
+ uvw
) * f001
+
213 /** Random binary (0,1) value. */
214 inline size_t random_binary() {
215 return std::rand() % 2;
218 /** Random polar (-1,1) value. */
219 inline int random_polar() {
220 return random_binary() ? 1 : -1;
223 /** Random real in [0,1]. */
224 inline double random_unit() {
225 return double(std::rand()) / double(RAND_MAX
);
228 /* Random integer in the range [min, max] */
229 inline long random_integer(long min
, long max
) {
230 return min
+ std::rand() % (max
- min
+ 1);
233 /* Random real number in the range [min, max] */
234 template < typename T
>
235 T
random_real(T min
, T max
) {
236 return min
+ random_unit() * (max
- min
);
239 /** Squared length in R2. */
240 template < typename T
>
241 T
length_squared(T x
, T y
) {
242 return x
* x
+ y
* y
;
245 /** Squared length in R3. */
246 template < typename T
>
247 T
length_squared(T x
, T y
, T z
) {
248 return x
* x
+ y
* y
+ z
* z
;
252 template < typename T
>
254 return std::sqrt(length_squared(x
,y
));
258 template < typename T
>
259 T
length(T x
, T y
, T z
) {
260 return std::sqrt(length_squared(x
,y
,z
));
263 /** Index of maximum of 2 values. */
264 template < typename T
>
265 size_t index_of_max(T a
, T b
) {
266 return a
> b
? 0 : 1;
269 /** Index of maximum of 2 values by magnitude. */
270 template < typename T
>
271 size_t index_of_max_abs(T a
, T b
) {
272 return index_of_max(std::fabs(a
),std::fabs(b
));
275 /** Index of minimum of 2 values. */
276 template < typename T
>
277 size_t index_of_min(T a
, T b
) {
278 return a
< b
? 0 : 1;
281 /** Index of minimum of 2 values by magnitude. */
282 template < typename T
>
283 size_t index_of_min_abs(T a
, T b
) {
284 return index_of_min(std::fabs(a
),std::fabs(b
));
287 /** Index of maximum of 3 values. */
288 template < typename T
>
289 size_t index_of_max(T a
, T b
, T c
) {
290 return a
> b
? (c
> a
? 2 : 0) : (b
> c
? 1 : 2);
293 /** Index of maximum of 3 values by magnitude. */
294 template < typename T
>
295 size_t index_of_max_abs(T a
, T b
, T c
) {
296 return index_of_max(std::fabs(a
),std::fabs(b
),std::fabs(c
));
299 /** Index of minimum of 3 values. */
300 template < typename T
>
301 size_t index_of_min(T a
, T b
, T c
) {
302 return a
< b
? (c
< a
? 2 : 0) : (b
< c
? 1 : 2);
305 /** Index of minimum of 3 values by magnitude. */
306 template < typename T
>
307 size_t index_of_min_abs(T a
, T b
, T c
) {
308 return index_of_min(std::fabs(a
),std::fabs(b
),std::fabs(c
));
311 /** Wrap input value to the range [min,max]. */
312 template < typename T
>
313 T
wrap(T value
, T min
, T max
) {
315 value
= std::fmod(value
- min
, max
);
322 /** Convert horizontal field of view to vertical field of view. */
323 template < typename T
>
324 T
xfov_to_yfov(T xfov
, T aspect
) {
325 return T(2.0 * std::atan(std::tan(xfov
* T(.5)) / double(aspect
)));
328 /** Convert vertical field of view to horizontal field of view. */
329 template < typename T
>
330 T
yfov_to_xfov(T yfov
, T aspect
) {
331 return T(2.0 * std::atan(std::tan(yfov
* T(.5)) * double(aspect
)));
334 /** Convert horizontal zoom to vertical zoom. */
335 template < typename T
>
336 T
xzoom_to_yzoom(T xzoom
, T aspect
) {
337 return xzoom
* aspect
;
340 /** Convert vertical zoom to horizontal zoom. */
341 template < typename T
>
342 T
yzoom_to_xzoom(T yzoom
, T aspect
) {
343 return yzoom
/ aspect
;
346 /** Convert zoom factor to field of view. */
347 template < typename T
>
348 T
zoom_to_fov(T zoom
) {
349 return T(2) * T(std::atan(T(1) / zoom
));
352 /** Convert field of view to zoom factor. */
353 template < typename T
>
354 T
fov_to_zoom(T fov
) {
355 return T(1) / T(std::tan(fov
* T(.5)));
360 #if defined(_MSC_VER)
361 #pragma pop_macro("min")
362 #pragma pop_macro("max")
367 // -------------------------------------------------------------------------
This page took 0.050146 seconds and 4 git commands to generate.