]>
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>
22 /** Sign of input value as double. */
23 template < typename T
>
24 double sign(T value
) {
25 return value
< T(0) ? -1.0 : (value
> T(0) ? 1.0 : 0.0);
28 /** Clamp input value to the range [min, max]. */
29 template < typename T
>
30 T
clamp(T value
, T min
, T max
) {
31 return std::max(std::min(value
, max
), min
);
34 /** Test input value for inclusion in [min, max]. */
35 template < typename T
>
36 bool in_range(T value
, T min
, T max
) {
37 return value
>= min
&& value
<= max
;
40 /** Map input value from [min1, max1] to [min2, max2]. */
41 template < typename T
>
42 T
map_range(T value
, T min1
, T max1
, T min2
, T max2
) {
43 return min2
+ ((value
- min1
) / (max1
- min1
)) * (max2
- min2
);
47 /** Wrap std::acos() and clamp argument to [-1, 1]. */
48 template < typename T
>
49 T
acos_safe(T theta
) {
50 return T(std::acos(clamp(theta
, T(-1.0), T(1.0))));
53 /** Wrap std::asin() and clamp argument to [-1, 1]. */
54 template < typename T
>
55 T
asin_safe(T theta
) {
56 return T(std::asin(clamp(theta
, T(-1.0), T(1.0))));
59 /** Wrap std::sqrt() and clamp argument to [0, inf). */
60 template < typename T
>
61 T
sqrt_safe(T value
) {
62 return T(std::sqrt(std::max(value
, T(0.0))));
66 /** For convenient squaring of expressions. */
67 template < typename T
>
72 /** Inverse square root. */
73 template < typename T
>
75 return T(1.0 / std::sqrt(value
));
79 /* The next few functions deal with indexing. next() and prev() are useful
80 * for operations involving the vertices of a polygon or other cyclic set,
81 * and cyclic_permutation() is used by various functions that deal with
82 * axes or basis vectors in a generic way. As these functions are only
83 * relevant for unsigned integer types, I've just used size_t, but there
84 * may be reasons I haven't thought of that they should be templated.
87 /** Return next, with cycling, in a series of N non-negative integers. */
88 inline size_t next(size_t i
, size_t N
) {
92 /** Return previous, with cycling, in a series of N non-negative integers. */
93 inline size_t prev(size_t i
, size_t N
) {
94 return i
? (i
- 1) : (N
- 1);
97 /** Cyclic permutation of the set { 0, 1 }, starting with 'first'. */
98 inline void cyclic_permutation(size_t first
, size_t& i
, size_t& j
) {
103 /** Cyclic permutation of the set { 0, 1, 2 }, starting with 'first'. */
104 inline void cyclic_permutation(size_t first
, size_t& i
, size_t& j
, size_t& k
)
111 /** Cyclic permutation of the set { 0, 1, 2, 3 }, starting with 'first'. */
112 inline void cyclic_permutation(
113 size_t first
, size_t& i
, size_t& j
, size_t& k
, size_t& l
)
122 /** Convert radians to degrees. */
123 template < typename T
>
125 return theta
* constants
<T
>::deg_per_rad();
128 /** Convert degrees to radians. */
129 template < typename T
>
131 return theta
* constants
<T
>::rad_per_deg();
134 /* Note: Moving interpolation functions to interpolation.h */
137 /** Linear interpolation of 2 values.
139 * @note The data points are assumed to be sampled at u = 0 and u = 1, so
140 * for interpolation u must lie between 0 and 1.
142 template <typename T
, typename Scalar
>
143 T
lerp(const T
& f0
, const T
& f1
, Scalar u
) {
144 return (Scalar(1.0) - u
) * f0
+ u
* f1
;
149 /** Bilinear interpolation of 4 values.
151 * @note The data points are assumed to be sampled at the corners of a unit
152 * square, so for interpolation u and v must lie between 0 and 1,
154 template <typename T
, typename Scalar
>
155 T
bilerp(const T
& f00
, const T
& f10
,
156 const T
& f01
, const T
& f11
,
161 (Scalar(1.0) - u
- v
+ uv
) * f00
+
170 /** Trilinear interpolation of 8 values.
172 * @note The data values are assumed to be sampled at the corners of a unit
173 * cube, so for interpolation, u, v, and w must lie between 0 and 1.
175 template <typename T
, typename Scalar
>
176 T
trilerp(const T
& f000
, const T
& f100
,
177 const T
& f010
, const T
& f110
,
178 const T
& f001
, const T
& f101
,
179 const T
& f011
, const T
& f111
,
180 Scalar u
, Scalar v
, Scalar w
)
188 (Scalar(1.0) - u
- v
- w
+ uv
+ vw
+ wu
- uvw
) * f000
+
189 (u
- uv
- wu
+ uvw
) * f100
+
190 (v
- uv
- vw
+ uvw
) * f010
+
192 (w
- vw
- wu
+ uvw
) * f001
+
200 /** Random binary (0,1) value. */
201 inline size_t random_binary() {
202 return std::rand() % 2;
205 /** Random polar (-1,1) value. */
206 inline int random_polar() {
207 return random_binary() ? 1 : -1;
210 /** Random real in [0,1]. */
211 inline double random_unit() {
212 return double(std::rand()) / double(RAND_MAX
);
215 /* Random integer in the range [min, max] */
216 inline long random_integer(long min
, long max
) {
217 return min
+ std::rand() % (max
- min
+ 1);
220 /* Random real number in the range [min, max] */
221 template < typename T
>
222 T
random_real(T min
, T max
) {
223 return min
+ random_unit() * (max
- min
);
226 /** Squared length in R2. */
227 template < typename T
>
228 T
length_squared(T x
, T y
) {
229 return x
* x
+ y
* y
;
232 /** Squared length in R3. */
233 template < typename T
>
234 T
length_squared(T x
, T y
, T z
) {
235 return x
* x
+ y
* y
+ z
* z
;
239 template < typename T
>
241 return std::sqrt(length_squared(x
,y
));
245 template < typename T
>
246 T
length(T x
, T y
, T z
) {
247 return std::sqrt(length_squared(x
,y
,z
));
250 /** Index of maximum of 3 values. */
251 template < typename T
>
252 size_t index_of_max(T a
, T b
, T c
) {
253 return a
> b
? (c
> a
? 2 : 0) : (b
> c
? 1 : 2);
256 /** Index of maximum of 3 values by magnitude. */
257 template < typename T
>
258 size_t index_of_max_abs(T a
, T b
, T c
) {
259 return index_of_max(std::fabs(a
),std::fabs(b
),std::fabs(c
));
262 /** Index of minimum of 3 values. */
263 template < typename T
>
264 size_t index_of_min(T a
, T b
, T c
) {
265 return a
< b
? (c
< a
? 2 : 0) : (b
< c
? 1 : 2);
268 /** Index of minimum of 3 values by magnitude. */
269 template < typename T
>
270 size_t index_of_min_abs(T a
, T b
, T c
) {
271 return index_of_min(std::fabs(a
),std::fabs(b
),std::fabs(c
));
274 /** Wrap input value to the range [min,max]. */
275 template < typename T
>
276 T
wrap(T value
, T min
, T max
) {
278 value
= std::fmod(value
- min
, max
);
285 /** Convert horizontal field of view to vertical field of view. */
286 template < typename T
>
287 T
xfov_to_yfov(T xfov
, T aspect
) {
288 return T(2.0 * std::atan(std::tan(xfov
* T(.5)) / double(aspect
)));
291 /** Convert vertical field of view to horizontal field of view. */
292 template < typename T
>
293 T
yfov_to_xfov(T yfov
, T aspect
) {
294 return T(2.0 * std::atan(std::tan(yfov
* T(.5)) * double(aspect
)));
297 /** Convert horizontal zoom to vertical zoom. */
298 template < typename T
>
299 T
xzoom_to_yzoom(T xzoom
, T aspect
) {
300 return xzoom
* aspect
;
303 /** Convert vertical zoom to horizontal zoom. */
304 template < typename T
>
305 T
yzoom_to_xzoom(T yzoom
, T aspect
) {
306 return yzoom
/ aspect
;
309 /** Convert zoom factor to field of view. */
310 template < typename T
>
311 T
zoom_to_fov(T zoom
) {
312 return T(2) * T(std::atan(T(1) / zoom
));
315 /** Convert field of view to zoom factor. */
316 template < typename T
>
317 T
fov_to_zoom(T fov
) {
318 return T(1) / T(std::tan(fov
* T(.5)));
325 // -------------------------------------------------------------------------
This page took 0.050206 seconds and 4 git commands to generate.