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 | |
9 | namespace 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 | |