1 | /**************************************************************************/ |
2 | /* vector3.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef VECTOR3_H |
32 | #define VECTOR3_H |
33 | |
34 | #include "core/error/error_macros.h" |
35 | #include "core/math/math_funcs.h" |
36 | |
37 | class String; |
38 | struct Basis; |
39 | struct Vector2; |
40 | struct Vector3i; |
41 | |
42 | struct _NO_DISCARD_ Vector3 { |
43 | static const int AXIS_COUNT = 3; |
44 | |
45 | enum Axis { |
46 | AXIS_X, |
47 | AXIS_Y, |
48 | AXIS_Z, |
49 | }; |
50 | |
51 | union { |
52 | struct { |
53 | real_t x; |
54 | real_t y; |
55 | real_t z; |
56 | }; |
57 | |
58 | real_t coord[3] = { 0 }; |
59 | }; |
60 | |
61 | _FORCE_INLINE_ const real_t &operator[](const int p_axis) const { |
62 | DEV_ASSERT((unsigned int)p_axis < 3); |
63 | return coord[p_axis]; |
64 | } |
65 | |
66 | _FORCE_INLINE_ real_t &operator[](const int p_axis) { |
67 | DEV_ASSERT((unsigned int)p_axis < 3); |
68 | return coord[p_axis]; |
69 | } |
70 | |
71 | _FORCE_INLINE_ Vector3::Axis min_axis_index() const { |
72 | return x < y ? (x < z ? Vector3::AXIS_X : Vector3::AXIS_Z) : (y < z ? Vector3::AXIS_Y : Vector3::AXIS_Z); |
73 | } |
74 | |
75 | _FORCE_INLINE_ Vector3::Axis max_axis_index() const { |
76 | return x < y ? (y < z ? Vector3::AXIS_Z : Vector3::AXIS_Y) : (x < z ? Vector3::AXIS_Z : Vector3::AXIS_X); |
77 | } |
78 | |
79 | Vector3 min(const Vector3 &p_vector3) const { |
80 | return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z)); |
81 | } |
82 | |
83 | Vector3 max(const Vector3 &p_vector3) const { |
84 | return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z)); |
85 | } |
86 | |
87 | _FORCE_INLINE_ real_t length() const; |
88 | _FORCE_INLINE_ real_t length_squared() const; |
89 | |
90 | _FORCE_INLINE_ void normalize(); |
91 | _FORCE_INLINE_ Vector3 normalized() const; |
92 | _FORCE_INLINE_ bool is_normalized() const; |
93 | _FORCE_INLINE_ Vector3 inverse() const; |
94 | Vector3 limit_length(const real_t p_len = 1.0) const; |
95 | |
96 | _FORCE_INLINE_ void zero(); |
97 | |
98 | void snap(const Vector3 p_val); |
99 | Vector3 snapped(const Vector3 p_val) const; |
100 | |
101 | void rotate(const Vector3 &p_axis, const real_t p_angle); |
102 | Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const; |
103 | |
104 | /* Static Methods between 2 vector3s */ |
105 | |
106 | _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, const real_t p_weight) const; |
107 | _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, const real_t p_weight) const; |
108 | _FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const; |
109 | _FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; |
110 | _FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; |
111 | _FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; |
112 | |
113 | Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const; |
114 | |
115 | Vector2 octahedron_encode() const; |
116 | static Vector3 octahedron_decode(const Vector2 &p_oct); |
117 | Vector2 octahedron_tangent_encode(const float sign) const; |
118 | static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *sign); |
119 | |
120 | _FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const; |
121 | _FORCE_INLINE_ real_t dot(const Vector3 &p_with) const; |
122 | Basis outer(const Vector3 &p_with) const; |
123 | |
124 | _FORCE_INLINE_ Vector3 abs() const; |
125 | _FORCE_INLINE_ Vector3 floor() const; |
126 | _FORCE_INLINE_ Vector3 sign() const; |
127 | _FORCE_INLINE_ Vector3 ceil() const; |
128 | _FORCE_INLINE_ Vector3 round() const; |
129 | Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const; |
130 | |
131 | _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const; |
132 | _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const; |
133 | |
134 | _FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const; |
135 | _FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const; |
136 | _FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const; |
137 | |
138 | _FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const; |
139 | _FORCE_INLINE_ real_t signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const; |
140 | _FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const; |
141 | |
142 | _FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const; |
143 | _FORCE_INLINE_ Vector3 bounce(const Vector3 &p_normal) const; |
144 | _FORCE_INLINE_ Vector3 reflect(const Vector3 &p_normal) const; |
145 | |
146 | bool is_equal_approx(const Vector3 &p_v) const; |
147 | bool is_zero_approx() const; |
148 | bool is_finite() const; |
149 | |
150 | /* Operators */ |
151 | |
152 | _FORCE_INLINE_ Vector3 &operator+=(const Vector3 &p_v); |
153 | _FORCE_INLINE_ Vector3 operator+(const Vector3 &p_v) const; |
154 | _FORCE_INLINE_ Vector3 &operator-=(const Vector3 &p_v); |
155 | _FORCE_INLINE_ Vector3 operator-(const Vector3 &p_v) const; |
156 | _FORCE_INLINE_ Vector3 &operator*=(const Vector3 &p_v); |
157 | _FORCE_INLINE_ Vector3 operator*(const Vector3 &p_v) const; |
158 | _FORCE_INLINE_ Vector3 &operator/=(const Vector3 &p_v); |
159 | _FORCE_INLINE_ Vector3 operator/(const Vector3 &p_v) const; |
160 | |
161 | _FORCE_INLINE_ Vector3 &operator*=(const real_t p_scalar); |
162 | _FORCE_INLINE_ Vector3 operator*(const real_t p_scalar) const; |
163 | _FORCE_INLINE_ Vector3 &operator/=(const real_t p_scalar); |
164 | _FORCE_INLINE_ Vector3 operator/(const real_t p_scalar) const; |
165 | |
166 | _FORCE_INLINE_ Vector3 operator-() const; |
167 | |
168 | _FORCE_INLINE_ bool operator==(const Vector3 &p_v) const; |
169 | _FORCE_INLINE_ bool operator!=(const Vector3 &p_v) const; |
170 | _FORCE_INLINE_ bool operator<(const Vector3 &p_v) const; |
171 | _FORCE_INLINE_ bool operator<=(const Vector3 &p_v) const; |
172 | _FORCE_INLINE_ bool operator>(const Vector3 &p_v) const; |
173 | _FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const; |
174 | |
175 | operator String() const; |
176 | operator Vector3i() const; |
177 | |
178 | _FORCE_INLINE_ Vector3() {} |
179 | _FORCE_INLINE_ Vector3(const real_t p_x, const real_t p_y, const real_t p_z) { |
180 | x = p_x; |
181 | y = p_y; |
182 | z = p_z; |
183 | } |
184 | }; |
185 | |
186 | Vector3 Vector3::cross(const Vector3 &p_with) const { |
187 | Vector3 ret( |
188 | (y * p_with.z) - (z * p_with.y), |
189 | (z * p_with.x) - (x * p_with.z), |
190 | (x * p_with.y) - (y * p_with.x)); |
191 | |
192 | return ret; |
193 | } |
194 | |
195 | real_t Vector3::dot(const Vector3 &p_with) const { |
196 | return x * p_with.x + y * p_with.y + z * p_with.z; |
197 | } |
198 | |
199 | Vector3 Vector3::abs() const { |
200 | return Vector3(Math::abs(x), Math::abs(y), Math::abs(z)); |
201 | } |
202 | |
203 | Vector3 Vector3::sign() const { |
204 | return Vector3(SIGN(x), SIGN(y), SIGN(z)); |
205 | } |
206 | |
207 | Vector3 Vector3::floor() const { |
208 | return Vector3(Math::floor(x), Math::floor(y), Math::floor(z)); |
209 | } |
210 | |
211 | Vector3 Vector3::ceil() const { |
212 | return Vector3(Math::ceil(x), Math::ceil(y), Math::ceil(z)); |
213 | } |
214 | |
215 | Vector3 Vector3::round() const { |
216 | return Vector3(Math::round(x), Math::round(y), Math::round(z)); |
217 | } |
218 | |
219 | Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const { |
220 | Vector3 res = *this; |
221 | res.x = Math::lerp(res.x, p_to.x, p_weight); |
222 | res.y = Math::lerp(res.y, p_to.y, p_weight); |
223 | res.z = Math::lerp(res.z, p_to.z, p_weight); |
224 | return res; |
225 | } |
226 | |
227 | Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { |
228 | // This method seems more complicated than it really is, since we write out |
229 | // the internals of some methods for efficiency (mainly, checking length). |
230 | real_t start_length_sq = length_squared(); |
231 | real_t end_length_sq = p_to.length_squared(); |
232 | if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) { |
233 | // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. |
234 | return lerp(p_to, p_weight); |
235 | } |
236 | Vector3 axis = cross(p_to); |
237 | real_t axis_length_sq = axis.length_squared(); |
238 | if (unlikely(axis_length_sq == 0.0f)) { |
239 | // Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp. |
240 | return lerp(p_to, p_weight); |
241 | } |
242 | axis /= Math::sqrt(axis_length_sq); |
243 | real_t start_length = Math::sqrt(start_length_sq); |
244 | real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight); |
245 | real_t angle = angle_to(p_to); |
246 | return rotated(axis, angle * p_weight) * (result_length / start_length); |
247 | } |
248 | |
249 | Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const { |
250 | Vector3 res = *this; |
251 | res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight); |
252 | res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight); |
253 | res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight); |
254 | return res; |
255 | } |
256 | |
257 | Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const { |
258 | Vector3 res = *this; |
259 | res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t); |
260 | res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t); |
261 | res.z = Math::cubic_interpolate_in_time(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t); |
262 | return res; |
263 | } |
264 | |
265 | Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const { |
266 | Vector3 res = *this; |
267 | res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); |
268 | res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); |
269 | res.z = Math::bezier_interpolate(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); |
270 | return res; |
271 | } |
272 | |
273 | Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const { |
274 | Vector3 res = *this; |
275 | res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); |
276 | res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); |
277 | res.z = Math::bezier_derivative(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); |
278 | return res; |
279 | } |
280 | |
281 | real_t Vector3::distance_to(const Vector3 &p_to) const { |
282 | return (p_to - *this).length(); |
283 | } |
284 | |
285 | real_t Vector3::distance_squared_to(const Vector3 &p_to) const { |
286 | return (p_to - *this).length_squared(); |
287 | } |
288 | |
289 | Vector3 Vector3::posmod(const real_t p_mod) const { |
290 | return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod)); |
291 | } |
292 | |
293 | Vector3 Vector3::posmodv(const Vector3 &p_modv) const { |
294 | return Vector3(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z)); |
295 | } |
296 | |
297 | Vector3 Vector3::project(const Vector3 &p_to) const { |
298 | return p_to * (dot(p_to) / p_to.length_squared()); |
299 | } |
300 | |
301 | real_t Vector3::angle_to(const Vector3 &p_to) const { |
302 | return Math::atan2(cross(p_to).length(), dot(p_to)); |
303 | } |
304 | |
305 | real_t Vector3::signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const { |
306 | Vector3 cross_to = cross(p_to); |
307 | real_t unsigned_angle = Math::atan2(cross_to.length(), dot(p_to)); |
308 | real_t sign = cross_to.dot(p_axis); |
309 | return (sign < 0) ? -unsigned_angle : unsigned_angle; |
310 | } |
311 | |
312 | Vector3 Vector3::direction_to(const Vector3 &p_to) const { |
313 | Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z); |
314 | ret.normalize(); |
315 | return ret; |
316 | } |
317 | |
318 | /* Operators */ |
319 | |
320 | Vector3 &Vector3::operator+=(const Vector3 &p_v) { |
321 | x += p_v.x; |
322 | y += p_v.y; |
323 | z += p_v.z; |
324 | return *this; |
325 | } |
326 | |
327 | Vector3 Vector3::operator+(const Vector3 &p_v) const { |
328 | return Vector3(x + p_v.x, y + p_v.y, z + p_v.z); |
329 | } |
330 | |
331 | Vector3 &Vector3::operator-=(const Vector3 &p_v) { |
332 | x -= p_v.x; |
333 | y -= p_v.y; |
334 | z -= p_v.z; |
335 | return *this; |
336 | } |
337 | |
338 | Vector3 Vector3::operator-(const Vector3 &p_v) const { |
339 | return Vector3(x - p_v.x, y - p_v.y, z - p_v.z); |
340 | } |
341 | |
342 | Vector3 &Vector3::operator*=(const Vector3 &p_v) { |
343 | x *= p_v.x; |
344 | y *= p_v.y; |
345 | z *= p_v.z; |
346 | return *this; |
347 | } |
348 | |
349 | Vector3 Vector3::operator*(const Vector3 &p_v) const { |
350 | return Vector3(x * p_v.x, y * p_v.y, z * p_v.z); |
351 | } |
352 | |
353 | Vector3 &Vector3::operator/=(const Vector3 &p_v) { |
354 | x /= p_v.x; |
355 | y /= p_v.y; |
356 | z /= p_v.z; |
357 | return *this; |
358 | } |
359 | |
360 | Vector3 Vector3::operator/(const Vector3 &p_v) const { |
361 | return Vector3(x / p_v.x, y / p_v.y, z / p_v.z); |
362 | } |
363 | |
364 | Vector3 &Vector3::operator*=(const real_t p_scalar) { |
365 | x *= p_scalar; |
366 | y *= p_scalar; |
367 | z *= p_scalar; |
368 | return *this; |
369 | } |
370 | |
371 | // Multiplication operators required to workaround issues with LLVM using implicit conversion |
372 | // to Vector3i instead for integers where it should not. |
373 | |
374 | _FORCE_INLINE_ Vector3 operator*(const float p_scalar, const Vector3 &p_vec) { |
375 | return p_vec * p_scalar; |
376 | } |
377 | |
378 | _FORCE_INLINE_ Vector3 operator*(const double p_scalar, const Vector3 &p_vec) { |
379 | return p_vec * p_scalar; |
380 | } |
381 | |
382 | _FORCE_INLINE_ Vector3 operator*(const int32_t p_scalar, const Vector3 &p_vec) { |
383 | return p_vec * p_scalar; |
384 | } |
385 | |
386 | _FORCE_INLINE_ Vector3 operator*(const int64_t p_scalar, const Vector3 &p_vec) { |
387 | return p_vec * p_scalar; |
388 | } |
389 | |
390 | Vector3 Vector3::operator*(const real_t p_scalar) const { |
391 | return Vector3(x * p_scalar, y * p_scalar, z * p_scalar); |
392 | } |
393 | |
394 | Vector3 &Vector3::operator/=(const real_t p_scalar) { |
395 | x /= p_scalar; |
396 | y /= p_scalar; |
397 | z /= p_scalar; |
398 | return *this; |
399 | } |
400 | |
401 | Vector3 Vector3::operator/(const real_t p_scalar) const { |
402 | return Vector3(x / p_scalar, y / p_scalar, z / p_scalar); |
403 | } |
404 | |
405 | Vector3 Vector3::operator-() const { |
406 | return Vector3(-x, -y, -z); |
407 | } |
408 | |
409 | bool Vector3::operator==(const Vector3 &p_v) const { |
410 | return x == p_v.x && y == p_v.y && z == p_v.z; |
411 | } |
412 | |
413 | bool Vector3::operator!=(const Vector3 &p_v) const { |
414 | return x != p_v.x || y != p_v.y || z != p_v.z; |
415 | } |
416 | |
417 | bool Vector3::operator<(const Vector3 &p_v) const { |
418 | if (x == p_v.x) { |
419 | if (y == p_v.y) { |
420 | return z < p_v.z; |
421 | } |
422 | return y < p_v.y; |
423 | } |
424 | return x < p_v.x; |
425 | } |
426 | |
427 | bool Vector3::operator>(const Vector3 &p_v) const { |
428 | if (x == p_v.x) { |
429 | if (y == p_v.y) { |
430 | return z > p_v.z; |
431 | } |
432 | return y > p_v.y; |
433 | } |
434 | return x > p_v.x; |
435 | } |
436 | |
437 | bool Vector3::operator<=(const Vector3 &p_v) const { |
438 | if (x == p_v.x) { |
439 | if (y == p_v.y) { |
440 | return z <= p_v.z; |
441 | } |
442 | return y < p_v.y; |
443 | } |
444 | return x < p_v.x; |
445 | } |
446 | |
447 | bool Vector3::operator>=(const Vector3 &p_v) const { |
448 | if (x == p_v.x) { |
449 | if (y == p_v.y) { |
450 | return z >= p_v.z; |
451 | } |
452 | return y > p_v.y; |
453 | } |
454 | return x > p_v.x; |
455 | } |
456 | |
457 | _FORCE_INLINE_ Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) { |
458 | return p_a.cross(p_b); |
459 | } |
460 | |
461 | _FORCE_INLINE_ real_t vec3_dot(const Vector3 &p_a, const Vector3 &p_b) { |
462 | return p_a.dot(p_b); |
463 | } |
464 | |
465 | real_t Vector3::length() const { |
466 | real_t x2 = x * x; |
467 | real_t y2 = y * y; |
468 | real_t z2 = z * z; |
469 | |
470 | return Math::sqrt(x2 + y2 + z2); |
471 | } |
472 | |
473 | real_t Vector3::length_squared() const { |
474 | real_t x2 = x * x; |
475 | real_t y2 = y * y; |
476 | real_t z2 = z * z; |
477 | |
478 | return x2 + y2 + z2; |
479 | } |
480 | |
481 | void Vector3::normalize() { |
482 | real_t lengthsq = length_squared(); |
483 | if (lengthsq == 0) { |
484 | x = y = z = 0; |
485 | } else { |
486 | real_t length = Math::sqrt(lengthsq); |
487 | x /= length; |
488 | y /= length; |
489 | z /= length; |
490 | } |
491 | } |
492 | |
493 | Vector3 Vector3::normalized() const { |
494 | Vector3 v = *this; |
495 | v.normalize(); |
496 | return v; |
497 | } |
498 | |
499 | bool Vector3::is_normalized() const { |
500 | // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. |
501 | return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); |
502 | } |
503 | |
504 | Vector3 Vector3::inverse() const { |
505 | return Vector3(1.0f / x, 1.0f / y, 1.0f / z); |
506 | } |
507 | |
508 | void Vector3::zero() { |
509 | x = y = z = 0; |
510 | } |
511 | |
512 | // slide returns the component of the vector along the given plane, specified by its normal vector. |
513 | Vector3 Vector3::slide(const Vector3 &p_normal) const { |
514 | #ifdef MATH_CHECKS |
515 | ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized." ); |
516 | #endif |
517 | return *this - p_normal * this->dot(p_normal); |
518 | } |
519 | |
520 | Vector3 Vector3::bounce(const Vector3 &p_normal) const { |
521 | return -reflect(p_normal); |
522 | } |
523 | |
524 | Vector3 Vector3::reflect(const Vector3 &p_normal) const { |
525 | #ifdef MATH_CHECKS |
526 | ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized." ); |
527 | #endif |
528 | return 2.0f * p_normal * this->dot(p_normal) - *this; |
529 | } |
530 | |
531 | #endif // VECTOR3_H |
532 | |