master
ブランチ master
VulkanExample / dep / include / glm / detail / func_geometric.inl
8.1 KB、259行 生 Blame 履歴
1#include "../exponential.hpp"
2#include "../common.hpp"
3
4namespace glm{
5namespace detail
6{
7 template<length_t L, typename T, qualifier Q, bool Aligned>
8 struct compute_length
9 {
10 GLM_FUNC_QUALIFIER static T call(vec<L, T, Q> const& v)
11 {
12 return sqrt(dot(v, v));
13 }
14 };
15
16 template<length_t L, typename T, qualifier Q, bool Aligned>
17 struct compute_distance
18 {
19 GLM_FUNC_QUALIFIER static T call(vec<L, T, Q> const& p0, vec<L, T, Q> const& p1)
20 {
21 return length(p1 - p0);
22 }
23 };
24
25 template<typename V, typename T, bool Aligned>
26 struct compute_dot{};
27
28 template<typename T, qualifier Q, bool Aligned>
29 struct compute_dot<vec<1, T, Q>, T, Aligned>
30 {
31 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<1, T, Q> const& a, vec<1, T, Q> const& b)
32 {
33 return a.x * b.x;
34 }
35 };
36
37 template<typename T, qualifier Q, bool Aligned>
38 struct compute_dot<vec<2, T, Q>, T, Aligned>
39 {
40 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<2, T, Q> const& a, vec<2, T, Q> const& b)
41 {
42 vec<2, T, Q> tmp(a * b);
43 return tmp.x + tmp.y;
44 }
45 };
46
47 template<typename T, qualifier Q, bool Aligned>
48 struct compute_dot<vec<3, T, Q>, T, Aligned>
49 {
50 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<3, T, Q> const& a, vec<3, T, Q> const& b)
51 {
52 vec<3, T, Q> tmp(a * b);
53 return tmp.x + tmp.y + tmp.z;
54 }
55 };
56
57 template<typename T, qualifier Q, bool Aligned>
58 struct compute_dot<vec<4, T, Q>, T, Aligned>
59 {
60 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<4, T, Q> const& a, vec<4, T, Q> const& b)
61 {
62 // VS 17.7.4 generates longer assembly (~20 instructions vs 11 instructions)
63 #if defined(_MSC_VER)
64 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
65 #else
66 vec<4, T, Q> tmp(a * b);
67 return (tmp.x + tmp.y) + (tmp.z + tmp.w);
68 #endif
69 }
70 };
71
72 template<typename T, qualifier Q, bool Aligned>
73 struct compute_cross
74 {
75 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<3, T, Q> call(vec<3, T, Q> const& x, vec<3, T, Q> const& y)
76 {
77 static_assert(std::numeric_limits<T>::is_iec559, "'cross' accepts only floating-point inputs");
78
79 return vec<3, T, Q>(
80 x.y * y.z - y.y * x.z,
81 x.z * y.x - y.z * x.x,
82 x.x * y.y - y.x * x.y);
83 }
84
85 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& x, vec<4, T, Q> const& y)
86 {
87 static_assert(std::numeric_limits<T>::is_iec559, "'cross' accepts only floating-point inputs");
88
89 return vec<4, T, Q>(
90 x.y * y.z - y.y * x.z,
91 x.z * y.x - y.z * x.x,
92 x.x * y.y - y.x * x.y,
93 0.0f);
94 }
95 };
96
97 template<length_t L, typename T, qualifier Q, bool Aligned>
98 struct compute_normalize
99 {
100 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v)
101 {
102 static_assert(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs");
103
104 return v * inversesqrt(dot(v, v));
105 }
106 };
107
108 template<length_t L, typename T, qualifier Q, bool Aligned>
109 struct compute_faceforward
110 {
111 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& N, vec<L, T, Q> const& I, vec<L, T, Q> const& Nref)
112 {
113 static_assert(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs");
114
115 return dot(Nref, I) < static_cast<T>(0) ? N : -N;
116 }
117 };
118
119 template<length_t L, typename T, qualifier Q, bool Aligned>
120 struct compute_reflect
121 {
122 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& I, vec<L, T, Q> const& N)
123 {
124 return I - N * dot(N, I) * static_cast<T>(2);
125 }
126 };
127
128 template<length_t L, typename T, qualifier Q, bool Aligned>
129 struct compute_refract
130 {
131 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& I, vec<L, T, Q> const& N, T eta)
132 {
133 T const dotValue(dot(N, I));
134 T const k(static_cast<T>(1) - eta * eta * (static_cast<T>(1) - dotValue * dotValue));
135 vec<L, T, Q> const Result =
136 (k >= static_cast<T>(0)) ? (eta * I - (eta * dotValue + std::sqrt(k)) * N) : vec<L, T, Q>(0);
137 return Result;
138 }
139 };
140}//namespace detail
141
142 // length
143 template<typename genType>
144 GLM_FUNC_QUALIFIER genType length(genType x)
145 {
146 static_assert(std::numeric_limits<genType>::is_iec559, "'length' accepts only floating-point inputs");
147
148 return abs(x);
149 }
150
151 template<length_t L, typename T, qualifier Q>
152 GLM_FUNC_QUALIFIER T length(vec<L, T, Q> const& v)
153 {
154 static_assert(std::numeric_limits<T>::is_iec559, "'length' accepts only floating-point inputs");
155
156 return detail::compute_length<L, T, Q, detail::is_aligned<Q>::value>::call(v);
157 }
158
159 // distance
160 template<typename genType>
161 GLM_FUNC_QUALIFIER genType distance(genType const& p0, genType const& p1)
162 {
163 static_assert(std::numeric_limits<genType>::is_iec559, "'distance' accepts only floating-point inputs");
164
165 return length(p1 - p0);
166 }
167
168 template<length_t L, typename T, qualifier Q>
169 GLM_FUNC_QUALIFIER T distance(vec<L, T, Q> const& p0, vec<L, T, Q> const& p1)
170 {
171 return detail::compute_distance<L, T, Q, detail::is_aligned<Q>::value>::call(p0, p1);
172 }
173
174 // dot
175 template<typename T>
176 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T dot(T x, T y)
177 {
178 static_assert(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs");
179 return x * y;
180 }
181
182 template<length_t L, typename T, qualifier Q>
183 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T dot(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
184 {
185 static_assert(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs");
186 return detail::compute_dot<vec<L, T, Q>, T, detail::is_aligned<Q>::value>::call(x, y);
187 }
188
189 // cross
190 template<typename T, qualifier Q>
191 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> cross(vec<3, T, Q> const& x, vec<3, T, Q> const& y)
192 {
193 return detail::compute_cross<T, Q, detail::is_aligned<Q>::value>::call(x, y);
194 }
195/*
196 // normalize
197 template<typename genType>
198 GLM_FUNC_QUALIFIER genType normalize(genType const& x)
199 {
200 static_assert(std::numeric_limits<genType>::is_iec559, "'normalize' accepts only floating-point inputs");
201
202 return x < genType(0) ? genType(-1) : genType(1);
203 }
204*/
205 template<length_t L, typename T, qualifier Q>
206 GLM_FUNC_QUALIFIER vec<L, T, Q> normalize(vec<L, T, Q> const& x)
207 {
208 static_assert(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs");
209
210 return detail::compute_normalize<L, T, Q, detail::is_aligned<Q>::value>::call(x);
211 }
212
213 // faceforward
214 template<typename genType>
215 GLM_FUNC_QUALIFIER genType faceforward(genType const& N, genType const& I, genType const& Nref)
216 {
217 return dot(Nref, I) < static_cast<genType>(0) ? N : -N;
218 }
219
220 template<length_t L, typename T, qualifier Q>
221 GLM_FUNC_QUALIFIER vec<L, T, Q> faceforward(vec<L, T, Q> const& N, vec<L, T, Q> const& I, vec<L, T, Q> const& Nref)
222 {
223 return detail::compute_faceforward<L, T, Q, detail::is_aligned<Q>::value>::call(N, I, Nref);
224 }
225
226 // reflect
227 template<typename genType>
228 GLM_FUNC_QUALIFIER genType reflect(genType const& I, genType const& N)
229 {
230 return I - N * dot(N, I) * genType(2);
231 }
232
233 template<length_t L, typename T, qualifier Q>
234 GLM_FUNC_QUALIFIER vec<L, T, Q> reflect(vec<L, T, Q> const& I, vec<L, T, Q> const& N)
235 {
236 return detail::compute_reflect<L, T, Q, detail::is_aligned<Q>::value>::call(I, N);
237 }
238
239 // refract
240 template<typename genType>
241 GLM_FUNC_QUALIFIER genType refract(genType const& I, genType const& N, genType eta)
242 {
243 static_assert(std::numeric_limits<genType>::is_iec559, "'refract' accepts only floating-point inputs");
244 genType const dotValue(dot(N, I));
245 genType const k(static_cast<genType>(1) - eta * eta * (static_cast<genType>(1) - dotValue * dotValue));
246 return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast<genType>(k >= static_cast<genType>(0));
247 }
248
249 template<length_t L, typename T, qualifier Q>
250 GLM_FUNC_QUALIFIER vec<L, T, Q> refract(vec<L, T, Q> const& I, vec<L, T, Q> const& N, T eta)
251 {
252 static_assert(std::numeric_limits<T>::is_iec559, "'refract' accepts only floating-point inputs");
253 return detail::compute_refract<L, T, Q, detail::is_aligned<Q>::value>::call(I, N, eta);
254 }
255}//namespace glm
256
257#if GLM_CONFIG_SIMD == GLM_ENABLE
258# include "func_geometric_simd.inl"
259#endif