Skip to content

Commit 68c5ab4

Browse files
Merge pull request vsg-dev#1546 from vsg-dev/numbers
Introduced vsg::number<> template struct for providing comon numbers in a way that works well with other templates.
2 parents 7dfa833 + 6f49076 commit 68c5ab4

13 files changed

Lines changed: 187 additions & 133 deletions

File tree

include/vsg/all.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
4848
#include <vsg/maths/mat2.h>
4949
#include <vsg/maths/mat3.h>
5050
#include <vsg/maths/mat4.h>
51+
#include <vsg/maths/numbers.h>
5152
#include <vsg/maths/plane.h>
5253
#include <vsg/maths/quat.h>
5354
#include <vsg/maths/sample.h>

include/vsg/maths/common.h

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
2323

2424
namespace vsg
2525
{
26-
constexpr float PIf = 3.14159265358979323846f;
27-
constexpr double PI = 3.14159265358979323846;
26+
27+
constexpr float PIf = numbers<float>::PI();
28+
constexpr double PI = numbers<double>::PI();
2829

2930
/// convert degrees to radians
30-
constexpr float radians(float degrees) noexcept { return degrees * (PIf / 180.0f); }
31-
constexpr double radians(double degrees) noexcept { return degrees * (PI / 180.0); }
31+
constexpr float radians(float degrees) noexcept { return degrees * numbers<float>::degrees_to_radians(); }
32+
constexpr double radians(double degrees) noexcept { return degrees * numbers<double>::degrees_to_radians(); }
3233

3334
/// convert radians to degrees
34-
constexpr float degrees(float radians) noexcept { return radians * (180.0f / PIf); }
35-
constexpr double degrees(double radians) noexcept { return radians * (180.0 / PI); }
35+
constexpr float degrees(float radians) noexcept { return radians * numbers<float>::radians_to_degrees(); }
36+
constexpr double degrees(double radians) noexcept { return radians * numbers<double>::radians_to_degrees(); }
3637

3738
/// compute value^2
3839
constexpr float square(float v) noexcept { return v * v; };
@@ -46,26 +47,26 @@ namespace vsg
4647
return edge0;
4748
else if (x >= edge1)
4849
return edge1;
49-
double r = (x - edge0) / (edge1 - edge0);
50-
return edge0 + (r * r * (3.0 - 2.0 * r)) * (edge1 - edge0);
50+
T r = (x - edge0) / (edge1 - edge0);
51+
return edge0 + (r * r * (numbers<T>::three() - numbers<T>::two() * r)) * (edge1 - edge0);
5152
}
5253

5354
/// Hermite interpolation between 0.0 and 1.0
5455
template<typename T>
5556
T smoothstep(T r)
5657
{
57-
if (r <= 0.0)
58-
return 0.0;
59-
else if (r >= 1.0)
60-
return 1.0;
61-
return r * r * (3.0 - 2.0 * r);
58+
if (r <= numbers<T>::zero())
59+
return numbers<T>::zero();
60+
else if (r >= numbers<T>::one())
61+
return numbers<T>::one();
62+
return r * r * (numbers<T>::three() - numbers<T>::two() * r);
6263
}
6364

6465
/// interpolate between two values
6566
template<typename T>
6667
T mix(T start, T end, T r)
6768
{
68-
T one_minus_r = 1.0 - r;
69+
T one_minus_r = numbers<T>::one() - r;
6970
return start * one_minus_r + end * r;
7071
}
7172

include/vsg/maths/mat2.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ namespace vsg
2828
column_type value[2];
2929

3030
constexpr t_mat2() :
31-
value{{1, 0},
32-
{0, 1}} {}
31+
value{{numbers<value_type>::one(), numbers<value_type>::zero()},
32+
{numbers<value_type>::zero(), numbers<value_type>::one()}} {}
3333

3434
constexpr explicit t_mat2(value_type v) :
35-
value{{v, 0},
36-
{0, v}} {}
35+
value{{v, numbers<value_type>::zero()},
36+
{numbers<value_type>::zero(), v}} {}
3737

3838
constexpr t_mat2(value_type v0, value_type v1, /* column 0 */
3939
value_type v2, value_type v3) /* column 1 */ :

include/vsg/maths/mat3.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ namespace vsg
2828
column_type value[3];
2929

3030
constexpr t_mat3() :
31-
value{{1, 0, 0},
32-
{0, 1, 0},
33-
{0, 0, 1}} {}
31+
value{{numbers<value_type>::one(), numbers<value_type>::zero(), numbers<value_type>::zero()},
32+
{numbers<value_type>::zero(), numbers<value_type>::one(), numbers<value_type>::zero()},
33+
{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::one()}} {}
3434

3535
constexpr explicit t_mat3(value_type v) :
36-
value{{v, 0, 0},
37-
{0, v, 0},
38-
{0, 0, v}} {}
36+
value{{v, numbers<value_type>::zero(), numbers<value_type>::zero()},
37+
{numbers<value_type>::zero(), v, numbers<value_type>::zero()},
38+
{numbers<value_type>::zero(), numbers<value_type>::zero(), v}} {}
3939

4040
constexpr t_mat3(value_type v0, value_type v1, value_type v2, /* column 0 */
4141
value_type v3, value_type v4, value_type v5, /* column 1 */

include/vsg/maths/mat4.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ namespace vsg
3030
column_type value[4];
3131

3232
constexpr t_mat4() :
33-
value{{1, 0, 0, 0},
34-
{0, 1, 0, 0},
35-
{0, 0, 1, 0},
36-
{0, 0, 0, 1}} {}
33+
value{{numbers<value_type>::one(), numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero()},
34+
{numbers<value_type>::zero(), numbers<value_type>::one(), numbers<value_type>::zero(), numbers<value_type>::zero()},
35+
{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::one(), numbers<value_type>::zero()},
36+
{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::one()}} {}
3737

3838
constexpr explicit t_mat4(value_type v) :
39-
value{{v, 0, 0, 0},
40-
{0, v, 0, 0},
41-
{0, 0, v, 0},
42-
{0, 0, 0, v}} {}
39+
value{{v, numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero()},
40+
{numbers<value_type>::zero(), v, numbers<value_type>::zero(), numbers<value_type>::zero()},
41+
{numbers<value_type>::zero(), numbers<value_type>::zero(), v, numbers<value_type>::zero()},
42+
{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero(), v}} {}
4343

4444
constexpr t_mat4(value_type v0, value_type v1, value_type v2, value_type v3, /* column 0 */
4545
value_type v4, value_type v5, value_type v6, value_type v7, /* column 1 */
@@ -219,14 +219,14 @@ namespace vsg
219219
lhs[0] * rhs[1][0] + lhs[1] * rhs[1][1] + lhs[2] * rhs[1][2] + lhs[3] * rhs[1][3],
220220
lhs[0] * rhs[2][0] + lhs[1] * rhs[2][1] + lhs[2] * rhs[2][2] + lhs[3] * rhs[2][3],
221221
lhs[0] * rhs[3][0] + lhs[1] * rhs[3][1] + lhs[2] * rhs[3][2] + lhs[3] * rhs[3][3]);
222-
T inv = static_cast<T>(1.0) / length(transformed.n);
222+
T inv = numbers<T>::one() / length(transformed.n);
223223
return t_plane<T>(transformed[0] * inv, transformed[1] * inv, transformed[2] * inv, transformed[3] * inv);
224224
}
225225

226226
template<typename T>
227227
t_vec3<T> operator*(const t_mat4<T>& lhs, const t_vec3<T>& rhs)
228228
{
229-
T inv = static_cast<T>(1.0) / (lhs[0][3] * rhs[0] + lhs[1][3] * rhs[1] + lhs[2][3] * rhs[2] + lhs[3][3]);
229+
T inv = numbers<T>::one() / (lhs[0][3] * rhs[0] + lhs[1][3] * rhs[1] + lhs[2][3] * rhs[2] + lhs[3][3]);
230230
return t_vec3<T>((lhs[0][0] * rhs[0] + lhs[1][0] * rhs[1] + lhs[2][0] * rhs[2] + lhs[3][0]) * inv,
231231
(lhs[0][1] * rhs[0] + lhs[1][1] * rhs[1] + lhs[2][1] * rhs[2] + lhs[3][1]) * inv,
232232
(lhs[0][2] * rhs[0] + lhs[1][2] * rhs[1] + lhs[2][2] * rhs[2] + lhs[3][2]) * inv);
@@ -235,7 +235,7 @@ namespace vsg
235235
template<typename T>
236236
t_vec3<T> operator*(const t_vec3<T>& lhs, const t_mat4<T>& rhs)
237237
{
238-
T inv = static_cast<T>(1.0) / (lhs[0] * rhs[3][0] + lhs[1] * rhs[3][1] + lhs[2] * rhs[3][2] + rhs[3][3]);
238+
T inv = numbers<T>::one() / (lhs[0] * rhs[3][0] + lhs[1] * rhs[3][1] + lhs[2] * rhs[3][2] + rhs[3][3]);
239239
return t_vec3<T>(lhs[0] * rhs[0][0] + lhs[1] * rhs[0][1] + lhs[2] * rhs[0][2] + rhs[0][3] * inv,
240240
lhs[0] * rhs[1][0] + lhs[1] * rhs[1][1] + lhs[2] * rhs[1][2] + rhs[1][3] * inv,
241241
lhs[0] * rhs[2][0] + lhs[1] * rhs[2][1] + lhs[2] * rhs[2][2] + rhs[2][3] * inv);

include/vsg/maths/numbers.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
3+
/* <editor-fold desc="MIT License">
4+
5+
Copyright(c) 2018 Robert Osfield
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
9+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10+
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12+
13+
</editor-fold> */
14+
15+
#include <limits>
16+
17+
namespace vsg
18+
{
19+
template<typename T>
20+
struct numbers
21+
{
22+
static constexpr T zero() { return static_cast<T>(0.0); }
23+
static constexpr T half() { return static_cast<T>(0.5); }
24+
static constexpr T one() { return static_cast<T>(1.0); }
25+
static constexpr T two() { return static_cast<T>(2.0); }
26+
static constexpr T three() { return static_cast<T>(3.0); }
27+
28+
static constexpr T minus_one() { return static_cast<T>(-1.0); }
29+
30+
static constexpr T epsilon() { return std::numeric_limits<T>::epsilon(); }
31+
32+
static constexpr T PI() { return static_cast<T>(3.14159265358979323846); }
33+
static constexpr T degrees_to_radians() { return PI() / static_cast<T>(180.0); }
34+
static constexpr T radians_to_degrees() { return static_cast<T>(180.0) / PI(); }
35+
};
36+
37+
} // namespace vsg

include/vsg/maths/plane.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace vsg
5050
};
5151

5252
constexpr t_plane() :
53-
value{0.0, 0.0, 0.0, 0.0} {}
53+
value{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero()} {}
5454

5555
constexpr t_plane(const t_plane& pl) :
5656
value{pl[0], pl[1], pl[2], pl[3]} {}
@@ -100,7 +100,7 @@ namespace vsg
100100
value[3] = in_d;
101101
}
102102

103-
bool valid() const { return n.x != 0.0 && n.y != 0.0 && n.z != 0.0; }
103+
bool valid() const { return n.x != numbers<value_type>::zero() && n.y != numbers<value_type>::zero() && n.z != numbers<value_type>::zero(); }
104104

105105
explicit operator bool() const noexcept { return valid(); }
106106

include/vsg/maths/quat.h

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ namespace vsg
4545
};
4646

4747
constexpr t_quat() :
48-
value{0.0, 0.0, 0.0, 1.0} {}
48+
value{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::one()} {}
4949
constexpr t_quat(const t_quat& v) :
5050
value{v.x, v.y, v.z, v.w} {}
5151
constexpr t_quat(value_type in_x, value_type in_y, value_type in_z, value_type in_w) :
@@ -93,18 +93,17 @@ namespace vsg
9393

9494
void set(value_type angle_radians, const t_vec3<value_type>& axis)
9595
{
96-
const value_type epsilon = 1e-7;
9796
value_type len = length(axis);
98-
if (len < epsilon)
97+
if (len < numbers<value_type>::epsilon())
9998
{
10099
// ~zero length axis, so reset rotation to zero.
101100
*this = {};
102101
return;
103102
}
104103

105-
value_type inversenorm = 1.0 / len;
106-
value_type coshalfangle = cos(0.5 * angle_radians);
107-
value_type sinhalfangle = sin(0.5 * angle_radians);
104+
value_type inversenorm = numbers<value_type>::one() / len;
105+
value_type coshalfangle = cos(numbers<value_type>::half() * angle_radians);
106+
value_type sinhalfangle = sin(numbers<value_type>::half() * angle_radians);
108107

109108
x = axis.x * sinhalfangle * inversenorm;
110109
y = axis.y * sinhalfangle * inversenorm;
@@ -114,12 +113,10 @@ namespace vsg
114113

115114
void set(const t_vec3<value_type>& from, const t_vec3<value_type>& to)
116115
{
117-
const value_type epsilon = 1e-7;
118-
119116
value_type dot_pd = vsg::dot(from, to);
120117
value_type div = std::sqrt(length2(from) * length2(to));
121118
vsg::dvec3 axis;
122-
if (div - std::abs(dot_pd) < epsilon)
119+
if (div - std::abs(dot_pd) < numbers<value_type>::epsilon())
123120
{
124121
axis = orthogonal(from);
125122
}
@@ -132,17 +129,17 @@ namespace vsg
132129

133130
double angle_radians = acos(dot_pd / div);
134131

135-
value_type inversenorm = 1.0 / len;
136-
value_type coshalfangle = cos(0.5 * angle_radians);
137-
value_type sinhalfangle = sin(0.5 * angle_radians);
132+
value_type inversenorm = numbers<value_type>::one() / len;
133+
value_type coshalfangle = cos(numbers<value_type>::half() * angle_radians);
134+
value_type sinhalfangle = sin(numbers<value_type>::half() * angle_radians);
138135

139136
x = axis.x * sinhalfangle * inversenorm;
140137
y = axis.y * sinhalfangle * inversenorm;
141138
z = axis.z * sinhalfangle * inversenorm;
142139
w = coshalfangle;
143140
}
144141

145-
explicit operator bool() const noexcept { return value[0] != 0.0 || value[1] != 0.0 || value[2] != 0.0 || value[3] != 0.0; }
142+
explicit operator bool() const noexcept { return value[0] != numbers<value_type>::zero() || value[1] != numbers<value_type>::zero() || value[2] != numbers<value_type>::zero() || value[3] != numbers<value_type>::zero(); }
146143
};
147144

148145
using quat = t_quat<float>; /// float quaternion
@@ -222,9 +219,8 @@ namespace vsg
222219
t_vec3<T> qvec(q[0], q[1], q[2]);
223220
uv = cross(qvec, v);
224221
uuv = cross(qvec, uv);
225-
T two(2.0);
226-
uv *= (two * q[3]);
227-
uuv *= two;
222+
uv *= (numbers<T>::two() * q[3]);
223+
uuv *= numbers<T>::two();
228224
return v + uv + uuv;
229225
}
230226

@@ -237,7 +233,7 @@ namespace vsg
237233
template<typename T>
238234
constexpr t_quat<T> operator/(const t_quat<T>& lhs, T rhs)
239235
{
240-
T inv = static_cast<T>(1.0) / rhs;
236+
T inv = numbers<T>::one() / rhs;
241237
return t_quat<T>(lhs[0] * inv, lhs[1] * inv, lhs[2] * inv, lhs[3] * inv);
242238
}
243239

@@ -250,7 +246,7 @@ namespace vsg
250246
template<typename T>
251247
constexpr t_quat<T> normalize(const t_quat<T>& v)
252248
{
253-
T inverse_len = static_cast<T>(1.0) / length(v);
249+
T inverse_len = numbers<T>::one() / length(v);
254250
return t_quat<T>(v[0] * inverse_len, v[1] * inverse_len, v[2] * inverse_len, v[3] * inverse_len);
255251
}
256252

@@ -264,18 +260,15 @@ namespace vsg
264260
constexpr t_quat<T> inverse(const t_quat<T>& v)
265261
{
266262
t_quat<T> c = conjugate(v);
267-
T inverse_len = static_cast<T>(1.0) / length(v);
263+
T inverse_len = numbers<T>::one() / length(v);
268264
return t_quat<T>(c[0] * inverse_len, c[1] * inverse_len, c[2] * inverse_len, c[3] * inverse_len);
269265
}
270266

271267
template<typename T>
272268
constexpr t_quat<T> mix(const t_quat<T>& from, t_quat<T> to, T r)
273269
{
274-
T epsilon = std::numeric_limits<T>::epsilon();
275-
T one(1.0);
276-
277270
T cosomega = dot(from, to);
278-
if (cosomega < 0.0)
271+
if (cosomega < numbers<T>::zero())
279272
{
280273
cosomega = -cosomega;
281274
to.x = -to.x;
@@ -284,18 +277,18 @@ namespace vsg
284277
to.w = -to.w;
285278
}
286279

287-
if ((one - cosomega) > epsilon)
280+
if ((numbers<T>::one() - cosomega) > numbers<T>::epsilon())
288281
{
289282
T omega = acos(cosomega);
290283
T sinomega = sin(omega);
291-
T scale_from = sin((one - r) * omega) / sinomega;
284+
T scale_from = sin((numbers<T>::one() - r) * omega) / sinomega;
292285
T scale_to = sin(r * omega) / sinomega;
293286
return (from * scale_from) + (to * scale_to);
294287
}
295288
else
296289
{
297290
// quaternions are very close so just linearly interpolate
298-
return (from * (one - r)) + (to * r);
291+
return (from * (numbers<T>::one() - r)) + (to * r);
299292
}
300293
}
301294

include/vsg/maths/sphere.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ namespace vsg
5555
};
5656

5757
constexpr t_sphere() :
58-
value{0.0, 0.0, 0.0, -1.0} {}
58+
value{numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::minus_one()} {}
5959

6060
constexpr t_sphere(const t_sphere& s) :
6161
value{s[0], s[1], s[2], s[3]} {}
@@ -106,7 +106,7 @@ namespace vsg
106106
r = rad;
107107
}
108108

109-
bool valid() const { return radius >= 0.0; }
109+
bool valid() const { return radius >= numbers<value_type>::zero(); }
110110

111111
explicit operator bool() const noexcept { return valid(); }
112112

@@ -115,8 +115,8 @@ namespace vsg
115115

116116
void reset()
117117
{
118-
center.set(0.0, 0.0, 0.0);
119-
radius = -1.0;
118+
center.set(numbers<value_type>::zero(), numbers<value_type>::zero(), numbers<value_type>::zero());
119+
radius = numbers<value_type>::minus_one();
120120
}
121121
};
122122

0 commit comments

Comments
 (0)