1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Math/BsMath.h"
4#include "Math/BsVector2.h"
5#include "Math/BsVector3.h"
6#include "Math/BsVector4.h"
7#include "Math/BsQuaternion.h"
8
9namespace bs
10{
11 const float Math::LOG2 = std::log(2.0f);
12
13 Radian Math::acos(float val)
14 {
15 if (-1.0f < val)
16 {
17 if (val < 1.0f)
18 return Radian(std::acos(val));
19 else
20 return Radian(0.0f);
21 }
22 else
23 {
24 return Radian(PI);
25 }
26 }
27
28 Radian Math::asin(float val)
29 {
30 if (-1.0f < val)
31 {
32 if (val < 1.0f)
33 return Radian(std::asin(val));
34 else
35 return Radian(HALF_PI);
36 }
37 else
38 {
39 return Radian(-HALF_PI);
40 }
41 }
42
43 float Math::sign(float val)
44 {
45 if (val > 0.0f)
46 return 1.0f;
47
48 if (val < 0.0f)
49 return -1.0f;
50
51 return 0.0f;
52 }
53
54 float Math::invSqrt(float val)
55 {
56 return 1.0f/sqrt(val);
57 }
58
59 float Math::fastSin0(float val)
60 {
61 float angleSqr = val*val;
62 float result = 7.61e-03f;
63 result *= angleSqr;
64 result -= 1.6605e-01f;
65 result *= angleSqr;
66 result += 1.0f;
67 result *= val;
68 return result;
69 }
70
71 float Math::fastSin1(float val)
72 {
73 float angleSqr = val*val;
74 float result = -2.39e-08f;
75 result *= angleSqr;
76 result += 2.7526e-06f;
77 result *= angleSqr;
78 result -= 1.98409e-04f;
79 result *= angleSqr;
80 result += 8.3333315e-03f;
81 result *= angleSqr;
82 result -= 1.666666664e-01f;
83 result *= angleSqr;
84 result += 1.0f;
85 result *= val;
86
87 return result;
88 }
89
90 float Math::fastCos0(float val)
91 {
92 float angleSqr = val*val;
93 float result = 3.705e-02f;
94 result *= angleSqr;
95 result -= 4.967e-01f;
96 result *= angleSqr;
97 result += 1.0f;
98
99 return result;
100 }
101
102 float Math::fastCos1(float val)
103 {
104 float angleSqr = val*val;
105 float result = -2.605e-07f;
106 result *= angleSqr;
107 result += 2.47609e-05f;
108 result *= angleSqr;
109 result -= 1.3888397e-03f;
110 result *= angleSqr;
111 result += 4.16666418e-02f;
112 result *= angleSqr;
113 result -= 4.999999963e-01f;
114 result *= angleSqr;
115 result += 1.0f;
116
117 return result;
118 }
119
120 float Math::fastTan0(float val)
121 {
122 float angleSqr = val*val;
123 float result = 2.033e-01f;
124 result *= angleSqr;
125 result += 3.1755e-01f;
126 result *= angleSqr;
127 result += 1.0f;
128 result *= val;
129 return result;
130 }
131
132 float Math::fastTan1(float val)
133 {
134 float angleSqr = val*val;
135 float result = 9.5168091e-03f;
136 result *= angleSqr;
137 result += 2.900525e-03f;
138 result *= angleSqr;
139 result += 2.45650893e-02f;
140 result *= angleSqr;
141 result += 5.33740603e-02f;
142 result *= angleSqr;
143 result += 1.333923995e-01f;
144 result *= angleSqr;
145 result += 3.333314036e-01f;
146 result *= angleSqr;
147 result += 1.0f;
148 result *= val;
149 return result;
150 }
151
152 float Math::fastASin0(float val)
153 {
154 float root = sqrt(abs(1.0f - val));
155 float result = -0.0187293f;
156 result *= val;
157 result += 0.0742610f;
158 result *= val;
159 result -= 0.2121144f;
160 result *= val;
161 result += 1.5707288f;
162 result = HALF_PI - root*result;
163 return result;
164 }
165
166 float Math::fastASin1(float val)
167 {
168 float root = sqrt(abs(1.0f - val));
169 float result = -0.0012624911f;
170 result *= val;
171 result += 0.0066700901f;
172 result *= val;
173 result -= 0.0170881256f;
174 result *= val;
175 result += 0.0308918810f;
176 result *= val;
177 result -= 0.0501743046f;
178 result *= val;
179 result += 0.0889789874f;
180 result *= val;
181 result -= 0.2145988016f;
182 result *= val;
183 result += 1.5707963050f;
184 result = HALF_PI - root*result;
185 return result;
186 }
187
188 float Math::fastACos0(float val)
189 {
190 float root = sqrt(abs(1.0f - val));
191 float result = -0.0187293f;
192 result *= val;
193 result += 0.0742610f;
194 result *= val;
195 result -= 0.2121144f;
196 result *= val;
197 result += 1.5707288f;
198 result *= root;
199 return result;
200 }
201
202 float Math::fastACos1(float val)
203 {
204 float root = sqrt(abs(1.0f - val));
205 float result = -0.0012624911f;
206 result *= val;
207 result += 0.0066700901f;
208 result *= val;
209 result -= 0.0170881256f;
210 result *= val;
211 result += 0.0308918810f;
212 result *= val;
213 result -= 0.0501743046f;
214 result *= val;
215 result += 0.0889789874f;
216 result *= val;
217 result -= 0.2145988016f;
218 result *= val;
219 result += 1.5707963050f;
220 result *= root;
221 return result;
222 }
223
224 float Math::fastATan0(float val)
225 {
226 float valueSqr = val*val;
227 float result = 0.0208351f;
228 result *= valueSqr;
229 result -= 0.085133f;
230 result *= valueSqr;
231 result += 0.180141f;
232 result *= valueSqr;
233 result -= 0.3302995f;
234 result *= valueSqr;
235 result += 0.999866f;
236 result *= val;
237 return result;
238 }
239
240 float Math::fastATan1(float val)
241 {
242 float valueSqr = val*val;
243 float result = 0.0028662257f;
244 result *= valueSqr;
245 result -= 0.0161657367f;
246 result *= valueSqr;
247 result += 0.0429096138f;
248 result *= valueSqr;
249 result -= 0.0752896400f;
250 result *= valueSqr;
251 result += 0.1065626393f;
252 result *= valueSqr;
253 result -= 0.1420889944f;
254 result *= valueSqr;
255 result += 0.1999355085f;
256 result *= valueSqr;
257 result -= 0.3333314528f;
258 result *= valueSqr;
259 result += 1.0f;
260 result *= val;
261 return result;
262 }
263
264 bool Math::approxEquals(const Vector2& a, const Vector2& b, float tolerance)
265 {
266 return fabs(b.x - a.x) <= tolerance && fabs(b.y - a.y) <= tolerance;
267 }
268
269 bool Math::approxEquals(const Vector3& a, const Vector3& b, float tolerance)
270 {
271 return fabs(b.x - a.x) <= tolerance && fabs(b.y - a.y) <= tolerance && fabs(b.z - a.z) <= tolerance;
272 }
273
274 bool Math::approxEquals(const Vector4& a, const Vector4& b, float tolerance)
275 {
276 return fabs(b.x - a.x) <= tolerance && fabs(b.y - a.y) <= tolerance && fabs(b.z - a.z) <= tolerance &&
277 fabs(b.w - a.w) <= tolerance;
278 }
279
280 bool Math::approxEquals(const Quaternion& a, const Quaternion& b, float tolerance)
281 {
282 return fabs(b.x - a.x) <= tolerance && fabs(b.y - a.y) <= tolerance && fabs(b.z - a.z) <= tolerance &&
283 fabs(b.w - a.w) <= tolerance;
284 }
285
286 Vector3 Math::calculateTriTangent(const Vector3& position1, const Vector3& position2,
287 const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3)
288 {
289 Vector3 side0 = position1 - position2;
290 Vector3 side1 = position3 - position1;
291
292 // Calculate face normal
293 Vector3 normal = side1.cross(side0);
294 normal.normalize();
295
296 // Now we use a formula to calculate the tangent.
297 float deltaV0 = v1 - v2;
298 float deltaV1 = v3 - v1;
299 Vector3 tangent = deltaV1 * side0 - deltaV0 * side1;
300 tangent.normalize();
301
302 // Calculate binormal
303 float deltaU0 = u1 - u2;
304 float deltaU1 = u3 - u1;
305 Vector3 binormal = deltaU1 * side0 - deltaU0 * side1;
306 binormal.normalize();
307
308 // Now, we take the cross product of the tangents to get a vector which
309 // should point in the same direction as our normal calculated above.
310 // If it points in the opposite direction (the dot product between the normals is less than zero),
311 // then we need to reverse the s and t tangents.
312 // This is because the triangle has been mirrored when going from tangent space to object space.
313 // reverse tangents if necessary.
314 Vector3 tangentCross = tangent.cross(binormal);
315 if (tangentCross.dot(normal) < 0.0f)
316 {
317 tangent = -tangent;
318 binormal = -binormal;
319 }
320
321 return tangent;
322 }
323}
324