Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
MathVectors.inl
Go to the documentation of this file.
1/* Copyright (c) 2018 DIVIDE-Studio
2 Copyright (c) 2009 Ionut Cava
3
4 This file is part of DIVIDE Framework.
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software
8 and associated documentation files (the "Software"), to deal in the Software
9 without restriction,
10 including without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense,
12 and/or sell copies of the Software, and to permit persons to whom the
13 Software is furnished to do so,
14 subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED,
21 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22 PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
24 DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
26 IN CONNECTION WITH THE SOFTWARE
27 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 */
30
31#ifndef DVD_CORE_MATH_MATH_VECTORS_INL_
32#define DVD_CORE_MATH_MATH_VECTORS_INL_
33
34namespace Divide
35{
36
37 namespace AVX
38 {
39 //ref: http://stackoverflow.com/questions/6042399/how-to-compare-m128-types
40 FORCE_INLINE bool Fneq128( __m128 const& a, __m128 const& b ) noexcept
41 {
42 // returns true if at least one element in a is not equal to
43 // the corresponding element in b
44 return _mm_movemask_ps( _mm_cmpeq_ps( a, b ) ) != 0xF;
45 }
46
47 FORCE_INLINE bool Fneq128( __m128 const& a, __m128 const& b, const F32 epsilon ) noexcept
48 {
49 // epsilon vector
50 const auto eps = _mm_set1_ps( epsilon );
51 // absolute of difference of a and b
52 const auto abd = _mm_andnot_ps( _mm_set1_ps( -0.0f ), _mm_sub_ps( a, b ) );
53 // compare abd to eps
54 // returns true if one of the elements in abd is not less than epsilon
55 return _mm_movemask_ps( _mm_cmplt_ps( abd, eps ) ) != 0xF;
56 }
57
58 //ref: https://www.opengl.org/discussion_boards/showthread.php/159586-my-SSE-code-is-slower-than-normal-why
59 FORCE_INLINE __m128 DotSimd( const __m128& a, const __m128& b ) noexcept
60 {
61 __m128 r = _mm_mul_ps( a, b );
62 r = _mm_add_ps( _mm_movehl_ps( r, r ), r );
63 r = _mm_add_ss( _mm_shuffle_ps( r, r, 1 ), r );
64
65 return r;
66 }
67
68 FORCE_INLINE __m128 SimpleDot( __m128 a, __m128 b ) noexcept
69 {
70 a = _mm_mul_ps( a, b );
71 b = _mm_hadd_ps( a, a );
72 return _mm_hadd_ps( b, b );
73 }
74 }
75 /*
76 * useful vector functions
77 */
79 template <typename T>
80 FORCE_INLINE vec2<T> Cross( const vec2<T> v1, const vec2<T> v2 ) noexcept
81 {
82 return v1.x * v2.y - v1.y * v2.x;
83 }
84
85 template <typename T>
86 FORCE_INLINE vec2<T> Inverse( const vec2<T> v ) noexcept
87 {
88 return vec2<T>( v.y, v.x );
89 }
90
91 template <typename T>
93 {
94 return vector.normalize();
95 }
96
97 template <typename T>
99 {
100 return vec2<T>( vector ).normalize();
101 }
102
104 template <typename T>
105 FORCE_INLINE vec2<T> operator*( T fl, const vec2<T> v ) noexcept
106 {
107 return v * fl;
108 }
109
111 template <typename T>
112 FORCE_INLINE T Dot( const vec2<T> a, const vec2<T> b ) noexcept
113 {
114 return a.x * b.x + a.y * b.y;
115 }
116
117 template <typename T>
119 {
120 n.normalize();
121 u.set( Cross( Normalized( Cross( n, u ) ), n ) );
122 }
123
124 template <typename T>
125 [[nodiscard]]
126 FORCE_INLINE vec2<T> Clamped( const vec2<T> v, const vec2<T> min, const vec2<T> max ) noexcept
127 {
128 return vec2<T>{
129 CLAMPED( v.x, min.x, max.x ),
130 CLAMPED( v.y, min.y, max.y )
131 };
132 }
133
134 template <typename T>
136 {
137 return vector.normalize();
138 }
139
140 template <typename T>
142 {
143 return vec3<T>( vector ).normalize();
144 }
145
147 template <typename T>
148 FORCE_INLINE vec3<T> operator*( T fl, const vec3<T>& v ) noexcept
149 {
150 return v * fl;
151 }
152
154 template <typename T>
155 FORCE_INLINE T Dot( const vec3<T>& a, const vec3<T>& b ) noexcept
156 {
157 return a.x * b.x + a.y * b.y + a.z * b.z;
158 }
159
161 template <typename T>
162 FORCE_INLINE vec3<T> Cross( const vec3<T>& v1, const vec3<T>& v2 ) noexcept
163 {
164 return vec3<T>( v1.y * v2.z - v1.z * v2.y,
165 v1.z * v2.x - v1.x * v2.z,
166 v1.x * v2.y - v1.y * v2.x );
167 }
168
169 template <typename T>
170 FORCE_INLINE vec3<T> AreOrthogonal( const vec3<T>& v1, const vec3<T>& v2 ) noexcept
171 {
172 constexpr F32 tolerance = 1e-6f;
173 return SQUARED( Dot( v1, v2 ) ) < Dot( v1, v1 ) * Dot( v2, v2 ) * tolerance;
174 }
175
176 template <typename T>
177 FORCE_INLINE vec3<T> Inverse( const vec3<T>& v ) noexcept
178 {
179 return vec3<T>( v.z, v.y, v.x );
180 }
181
182 template <typename T>
184 {
185 T min = std::abs( v.x );
186 vec3<T> cardinalAxis = WORLD_X_AXIS;
187
188 if ( std::abs( v.y ) < min )
189 {
190 min = std::abs( v.y );
191 cardinalAxis = WORLD_Y_AXIS;
192 }
193
194 if ( std::abs( v.z ) < min )
195 {
196 cardinalAxis = WORLD_Z_AXIS;
197 }
198
199 return Cross( v, cardinalAxis );
200 }
201
202 template<typename T>
203 FORCE_INLINE vec3<T> ProjectToNorm( const vec3<T>& in, const vec3<T>& direction )
204 {
205 return direction * Dot( in, direction );
206 }
207
208 template <typename T>
210 {
211 n.normalize();
212 u.set( Cross( Normalized( Cross( n, u ) ), n ) );
213 }
214
215 template <typename T>
216 FORCE_INLINE void OrthoNormalize( vec3<T>& v1, vec3<T>& v2, vec3<T>& v3 ) noexcept
217 {
218 v1.normalize();
219 v2 -= v2.projectToNorm( v1 );
220 v2.normalize();
221 v3 -= v3.projectToNorm( v1 );
222 v3 -= v3.projectToNorm( v2 );
223 v3.normalize();
224 }
225
226 template <typename T>
227 [[nodiscard]]
228 FORCE_INLINE vec3<T> Clamped( const vec3<T>& v, const vec3<T>& min, const vec3<T>& max ) noexcept
229 {
230 return vec3<T>{
231 CLAMPED( v.x, min.x, max.x ),
232 CLAMPED( v.y, min.y, max.y ),
233 CLAMPED( v.z, min.z, max.z )
234 };
235 }
236
237 template <typename T>
239 {
240 return { std::abs( vector.x ), std::abs( vector.y ), std::abs( vector.z ), std::abs( vector.z ) };
241 }
242
244 template <typename T>
245 FORCE_INLINE vec4<T> Min( const vec4<T>& v1, const vec4<T>& v2 ) noexcept
246 {
247 return vec4<T>( std::min( v1.x, v2.x ), std::min( v1.y, v2.y ),
248 std::min( v1.z, v2.z ), std::min( v1.w, v2.w ) );
249 }
250
251 template <typename T>
252 FORCE_INLINE vec4<T> Max( const vec4<T>& v1, const vec4<T>& v2 ) noexcept
253 {
254 return vec4<T>( std::max( v1.x, v2.x ), std::max( v1.y, v2.y ),
255 std::max( v1.z, v2.z ), std::max( v1.w, v2.w ) );
256 }
257
258 template <typename T>
260 {
261 return vector.normalize();
262 }
263
264 template <typename T>
266 {
267 return vec4<T>( vector ).normalize();
268 }
269
270 template <typename T>
272 {
273 n.normalize();
274 u.set( Cross( Normalized( Cross( n, u ) ), n ) );
275 }
276
277 template <typename T>
279 {
280 v1.normalize();
281 v2 -= v2.projectToNorm( v1 );
282 v2.normalize();
283 v3 -= v3.projectToNorm( v1 );
284 v3 -= v3.projectToNorm( v2 );
285 v3.normalize();
286 }
287
288 template <typename T>
289 FORCE_INLINE vec4<T> Perpendicular( const vec4<T>& vec, const vec4<T>& hint1, const vec4<T>& hint2 ) noexcept
290 {
291 const vec4 perp = Normalized( Cross( vec, hint1 ) );
292 if ( IS_ZERO( perp.length() ) )
293 {
294 return hint2;
295 }
296
297 return perp;
298 }
299
300 template <typename T>
301 [[nodiscard]]
302 FORCE_INLINE vec4<T> Clamped( const vec4<T>& v, const vec4<T>& min, const vec4<T>& max ) noexcept
303 {
304 return vec4<T>{
305 CLAMPED( v.x, min.x, max.x ),
306 CLAMPED( v.y, min.y, max.y ),
307 CLAMPED( v.z, min.z, max.z ),
308 CLAMPED( v.w, min.w, max.w )
309 };
310 }
311
313 template <typename T>
314 FORCE_INLINE vec4<T> operator*( T fl, const vec4<T>& v ) noexcept
315 {
316 return v * fl;
317 }
318
319 /*
320 * vec2 inline definitions
321 */
323 template <typename T>
325 {
326 return Divide::Dot( *this, *this );
327 }
328
330 template <typename T>
332 {
333 return Divide::Sqrt( distanceSquared( v ) );
334 }
335
337 template <typename T>
338 FORCE_INLINE T vec2<T>::distanceSquared( const vec2& v ) const noexcept
339 {
340 const vec2 d = v - *this;
341 return Divide::Dot( d, d );
342 }
343
345 template <typename T>
347 {
348 const T l = this->length();
349
350 if ( l >= EPSILON_F32 )
351 {
352 *this *= 1.f / l;
353 }
354
355 return *this;
356 }
357
359 template <typename T>
361 {
362 return std::min( x, y );
363 }
365 template <typename T>
367 {
368 return std::max( x, y );
369 }
370
372 template <typename T>
373 template <typename U> requires std::is_pod_v<U>
374 FORCE_INLINE bool vec2<T>::compare( const vec2<U> v ) const noexcept
375 {
376 return COMPARE( this->x, v.x ) &&
377 COMPARE( this->y, v.y );
378 }
381 template <typename T>
382 template <typename U> requires std::is_pod_v<U>
383 FORCE_INLINE bool vec2<T>::compare( const vec2<U> v, U epsi ) const noexcept
384 {
385 return COMPARE_TOLERANCE( this->x, v.x, epsi ) &&
386 COMPARE_TOLERANCE( this->y, v.y, epsi );
387 }
388
391 template <typename T>
392 FORCE_INLINE T vec2<T>::projectionOnLine( const vec2& vA, const vec2& vB ) const
394 const vec2 v( vB - vA );
395 return v.dot( *this - vA ) / v.dot( v );
396 }
399 template <typename T>
400 FORCE_INLINE T vec2<T>::dot( const vec2& v ) const noexcept
402 return this->x * v.x + this->y * v.y;
404
406 template <typename T>
408 {
409 set( static_cast<T>(std::roundf( this->x )), static_cast<T>(std::roundf( this->y )) );
410 }
414 template <typename T>
415 FORCE_INLINE void vec2<T>::get( T* v ) const
416 {
417 v[0] = static_cast<T>(this->_v[0]);
418 v[1] = static_cast<T>(this->_v[1]);
419 }
420
423 template <typename T>
425 {
426 return (vB - vA) * this->projectionOnLine( vA, vB ) + vA;
427 }
428
431 template <typename T>
433 {
434 const T factor = this->projectionOnLine( vA, vB );
435
436 if ( factor <= 0 ) return vA;
437 if ( factor >= 1 ) return vB;
438
439 return (vB - vA) * factor + vA;
440 }
441
443 template <typename T>
444 FORCE_INLINE void vec2<T>::lerp( const vec2& v, T factor ) noexcept
445 {
446 set( Lerp( *this, v, factor ) );
447 }
448
450 template <typename T>
451 FORCE_INLINE void vec2<T>::lerp( const vec2& v, const vec2& factor ) noexcept
452 {
453 set( Lerp( *this, v, factor ) );
454 }
455
457 template <typename T, typename U> requires std::is_pod_v<U>
458 FORCE_INLINE vec2<T> Lerp( const vec2<T> u, const vec2<T> v, U factor ) noexcept
459 {
460 return { Lerp( u.x, v.x, factor ), Lerp( u.y, v.y, factor ) };
461 }
462
464 template <typename T>
465 FORCE_INLINE vec2<T> Lerp( const vec2<T> u, const vec2<T> v, const vec2<T> factor ) noexcept
466 {
467 return { Lerp( u.x, v.x, factor.x ), Lerp( u.y, v.y, factor.y ) };
468 }
469
470 /*
471 * vec3 inline definitions
472 */
473
475 template <typename T>
476 template <typename U> requires std::is_pod_v<U>
477 FORCE_INLINE bool vec3<T>::compare( const vec3<U>& v ) const noexcept
478 {
479 return COMPARE( this->x, v.x ) &&
480 COMPARE( this->y, v.y ) &&
481 COMPARE( this->z, v.z );
482 }
483
485 template <typename T>
486 template <typename U> requires std::is_pod_v<U>
487 FORCE_INLINE bool vec3<T>::compare( const vec3<U>& v, U epsi ) const noexcept
488 {
489 return COMPARE_TOLERANCE( this->x, v.x, epsi ) &&
490 COMPARE_TOLERANCE( this->y, v.y, epsi ) &&
491 COMPARE_TOLERANCE( this->z, v.z, epsi );
492 }
493
495 template <typename T>
496 FORCE_INLINE bool vec3<T>::isUniform( const F32 tolerance ) const noexcept
497 {
498 return COMPARE_TOLERANCE( this->x, this->y, tolerance ) && COMPARE_TOLERANCE( this->y, this->z, tolerance );
499 }
500
501 template <typename T>
502 template <typename U> requires std::is_pod_v<U>
503 FORCE_INLINE bool vec3<T>::isPerpendicular( const vec3<U>& other, const F32 epsilon ) const noexcept
504 {
505 return SQUARED( dot( other ) ) <= SQUARED( epsilon ) * lengthSquared() * other.lengthSquared();
506 }
508 template <typename T>
510 {
511 return Divide::Dot( *this, *this );
512 }
513
515 template <typename T>
517 {
518 const T l = this->length();
519
520 if ( l >= EPSILON_F32 )
521 {
522 // multiply by the inverse length
523 *this *= 1.f / l;
524 }
525
526 return *this;
527 }
528
530 template <typename T>
532 {
533 return std::min( x, std::min( y, z ) );
534 }
535
537 template <typename T>
539 {
540 return std::max( x, std::max( y, z ) );
541 }
542
544 template <typename T>
545 FORCE_INLINE void vec3<T>::cross( const vec3& v1, const vec3& v2 ) noexcept
546 {
547 this->x = v1.y * v2.z - v1.z * v2.y;
548 this->y = v1.z * v2.x - v1.x * v2.z;
549 this->z = v1.x * v2.y - v1.y * v2.x;
550 }
551
553 template <typename T>
554 FORCE_INLINE void vec3<T>::cross( const vec3& v2 ) noexcept
555 {
556 this->cross( *this, v2 );
557 }
558
560 template <typename T>
561 FORCE_INLINE T vec3<T>::dot( const vec3& v ) const noexcept
562 {
563 return Divide::Dot( *this, v );
564 }
565
567 template <typename T>
568 FORCE_INLINE T vec3<T>::distance( const vec3& v ) const noexcept
569 {
570 return Divide::Sqrt( distanceSquared( v ) );
571 }
572
574 template <typename T>
575 FORCE_INLINE T vec3<T>::distanceSquared( const vec3& v ) const noexcept
576 {
577 const vec3 d{ v.x - this->x, v.y - this->y, v.z - this->z };
578 return Divide::Dot( d, d );
579 }
580
582 template <typename T>
584 {
585 const T angle = static_cast<T>(std::abs( std::acos( this->dot( v ) / (this->length() * v.length()) ) ));
586 return std::max( angle, EPSILON_F32 );
587 }
588
590 template <typename T>
591 FORCE_INLINE vec3<T> vec3<T>::direction( const vec3& u ) const noexcept
592 {
593 return Normalized( vec3( u.x - this->x, u.y - this->y, u.z - this->z ) );
594 }
595
596 template <typename T>
597 FORCE_INLINE vec3<T> vec3<T>::projectToNorm( const vec3& direction ) noexcept
598 {
599 return direction * dot( direction );
600 }
601
603 template <typename T>
604 FORCE_INLINE T vec3<T>::projectionOnLine( const vec3& vA, const vec3& vB ) const
605 {
606 const vec3 vector( vB - vA );
607 return vector.dot( *this - vA ) / vector.dot( vector );
608 }
609
611 template <typename T>
612 FORCE_INLINE void vec3<T>::lerp( const vec3& v, T factor ) noexcept
613 {
614 set( Lerp( *this, v, factor ) );
615 }
616
619 template <typename T>
620 FORCE_INLINE void vec3<T>::lerp( const vec3& v, const vec3& factor ) noexcept
621 {
622 set( Lerp( *this, v, factor ) );
623 }
624
626 template <typename T>
627 FORCE_INLINE void vec3<T>::rotateX( const D64 radians )
628 {
629 this->y = static_cast<T>(std::cos( radians ) * this->y +
630 std::sin( radians ) * this->z);
631 this->z = static_cast<T>(-std::sin( radians ) * this->y +
632 std::cos( radians ) * this->z);
633 }
634
636 template <typename T>
637 FORCE_INLINE void vec3<T>::rotateY( const D64 radians )
638 {
639 this->x = static_cast<T>(std::cos( radians ) * this->x -
640 std::sin( radians ) * this->z);
641 this->z = static_cast<T>(std::sin( radians ) * this->x +
642 std::cos( radians ) * this->z);
643 }
644
646 template <typename T>
647 FORCE_INLINE void vec3<T>::rotateZ( const D64 radians )
648 {
649 this->x = static_cast<T>(std::cos( radians ) * this->x +
650 std::sin( radians ) * this->y);
651 this->y = static_cast<T>(-std::sin( radians ) * this->x +
652 std::cos( radians ) * this->y);
653 }
654
656 template <typename T>
658 {
659 set( static_cast<T>(std::roundf( this->x )),
660 static_cast<T>(std::roundf( this->y )),
661 static_cast<T>(std::roundf( this->z )) );
662 }
663
665 template <typename T>
666 FORCE_INLINE void vec3<T>::swap( vec3& iv ) noexcept
667 {
668 std::swap( this->x, iv.x );
669 std::swap( this->y, iv.y );
670 std::swap( this->z, iv.z );
671 }
672
674 template <typename T>
675 FORCE_INLINE void vec3<T>::swap( vec3* iv ) noexcept
676 {
677 std::swap( this->x, iv->x );
678 std::swap( this->y, iv->y );
679 std::swap( this->z, iv->z );
680 }
681
684 template <typename T>
685 FORCE_INLINE void vec3<T>::get( T* v ) const noexcept
686 {
687 v[0] = static_cast<T>(this->_v[0]);
688 v[1] = static_cast<T>(this->_v[1]);
689 v[2] = static_cast<T>(this->_v[2]);
690 }
691
694 template <typename T>
695 FORCE_INLINE vec3<T> vec3<T>::vector( const vec3& vp1, const vec3& vp2 ) const noexcept
696 {
697 return vec3( vp1.x - vp2.x, vp1.y - vp2.y, vp1.z - vp2.z );
698 }
699
702 template <typename T>
704 {
705 return (vB - vA) * this->projectionOnLine( vA, vB ) + vA;
706 }
707
710 template <typename T>
712 {
713 const T factor = this->projectionOnLine( vA, vB );
714
715 if ( factor <= 0.0f ) return vA;
716
717 if ( factor >= 1.0f ) return vB;
718
719 return (vB - vA) * factor + vA;
720 }
721
723 template <typename T, typename U> requires std::is_pod_v<U>
724 FORCE_INLINE vec3<T> Lerp( const vec3<T>& u, const vec3<T>& v, U factor ) noexcept
725 {
726 return { Lerp( u.x, v.x, factor ), Lerp( u.y, v.y, factor ), Lerp( u.z, v.z, factor ) };
727 }
728
730 template <typename T>
731 FORCE_INLINE vec3<T> Lerp( const vec3<T>& u, const vec3<T>& v, const vec3<T>& factor ) noexcept
732 {
733 return { Lerp( u.x, v.x, factor.x ), Lerp( u.y, v.y, factor.y ), Lerp( u.z, v.z, factor.z ) };
734 }
735
736 template <typename T>
738 {
739 return { std::abs( vector.x ), std::abs( vector.y ), std::abs( vector.z ) };
740 }
741
742 template <typename T>
743 FORCE_INLINE vec3<T> Min( const vec3<T>& v1, const vec3<T>& v2 ) noexcept
744 {
745 return vec3<T>( std::min( v1.x, v2.x ), std::min( v1.y, v2.y ), std::min( v1.z, v2.z ) );
746 }
747
748 template <typename T>
749 FORCE_INLINE vec3<T> Max( const vec3<T>& v1, const vec3<T>& v2 ) noexcept
750 {
751 return vec3<T>( std::max( v1.x, v2.x ), std::max( v1.y, v2.y ), std::max( v1.z, v2.z ) );
752 }
753 /*
754 * vec4 inline definitions
755 */
756
757 template<>
758 template<>
760 {
761 return vec4<F32>( _mm_sub_ps( _reg._reg, _mm_set1_ps( _f ) ) );
762 }
764 template<>
765 template<>
767 {
768 _reg._reg = _mm_sub_ps( _reg._reg, _mm_set1_ps( _f ) );
769 return *this;
771
772 template<>
773 template<>
775 {
776 return vec4<F32>( _mm_add_ps( _reg._reg, _mm_set1_ps( _f ) ) );
777 }
779 template<>
780 template<>
783 _reg._reg = _mm_add_ps( _reg._reg, _mm_set1_ps( _f ) );
784 return *this;
785 }
787 template<>
788 template<>
790 {
791 return vec4<F32>( _mm_mul_ps( _reg._reg, _mm_set1_ps( _f ) ) );
793
794 template<>
795 template<>
797 {
798 _reg._reg = _mm_mul_ps( _reg._reg, _mm_set1_ps( _f ) );
799 return *this;
800 }
802 template<>
803 template<>
805 {
806 return vec4<F32>( _mm_div_ps( _reg._reg, _mm_set1_ps( _f ) ) );
807 }
808
809 template<>
810 template<>
812 {
813 _reg._reg = _mm_div_ps( _reg._reg, _mm_set1_ps( _f ) );
814 return *this;
816
817 template<>
818 template<>
820 {
821 return vec4<F32>( _mm_add_ps( _reg._reg, v._reg._reg ) );
823
824 template<>
825 template<>
827 {
828 _reg._reg = _mm_add_ps( _reg._reg, v._reg._reg );
829 return *this;
830 }
831
832 template<>
833 template<>
835 {
836 return vec4<F32>( _mm_sub_ps( _reg._reg, v._reg._reg ) );
837 }
838
839 template<>
840 template<>
842 {
843 _reg._reg = _mm_sub_ps( _reg._reg, v._reg._reg );
844 return *this;
845 }
846
847 template<>
848 template<>
850 {
851 return vec4<F32>( _mm_div_ps( _reg._reg, v._reg._reg ) );
852 }
853
854 template<>
855 template<>
857 {
858 _reg._reg = _mm_div_ps( _reg._reg, v._reg._reg );
859 return *this;
860 }
861
862 template<>
863 template<>
865 {
866 return vec4<F32>( _mm_mul_ps( _reg._reg, v._reg._reg ) );
867 }
868
869 template<>
870 template<>
872 {
873 _reg._reg = _mm_mul_ps( _reg._reg, v._reg._reg );
874 return *this;
875 }
876
878 template <typename T>
879 template <typename U> requires std::is_pod_v<U>
880 FORCE_INLINE bool vec4<T>::compare( const vec4<U>& v ) const noexcept
881 {
882 return COMPARE( this->x, v.x ) &&
883 COMPARE( this->y, v.y ) &&
884 COMPARE( this->z, v.z ) &&
885 COMPARE( this->w, v.w );
886 }
887
888 template <>
889 template <>
890 FORCE_INLINE bool vec4<F32>::compare( const vec4<F32>& v ) const noexcept
891 {
892 // returns true if at least one element in a is not equal to
893 // the corresponding element in b
894 return compare( v, EPSILON_F32 );
895 }
896
898 template <typename T>
899 template <typename U> requires std::is_pod_v<U>
900 FORCE_INLINE bool vec4<T>::compare( const vec4<U>& v, const U epsi ) const noexcept
901 {
902 if constexpr ( std::is_same<T, U>::value && std::is_same<U, F32>::value )
903 {
904 return !AVX::Fneq128( _reg._reg, v._reg._reg, epsi );
905 }
906 else
907 {
908 return COMPARE_TOLERANCE( this->x, v.x, epsi ) &&
909 COMPARE_TOLERANCE( this->y, v.y, epsi ) &&
910 COMPARE_TOLERANCE( this->z, v.z, epsi ) &&
911 COMPARE_TOLERANCE( this->w, v.w, epsi );
912 }
913 }
914
916 template <typename T>
918 {
919 set( static_cast<T>(std::roundf( this->x )), static_cast<T>(std::roundf( this->y )),
920 static_cast<T>(std::roundf( this->z )), static_cast<T>(std::roundf( this->w )) );
921 }
922
924 template <typename T>
925 FORCE_INLINE void vec4<T>::swap( vec4* iv ) noexcept
926 {
927 std::swap( this->x, iv->x );
928 std::swap( this->y, iv->y );
929 std::swap( this->z, iv->z );
930 std::swap( this->w, iv->w );
931 }
932
933 template <>
935 {
936 std::swap( _reg._reg, iv->_reg._reg );
937 }
938
940 template <typename T>
941 FORCE_INLINE void vec4<T>::swap( vec4& iv ) noexcept
942 {
943 swap( &iv );
944 }
945
947 template <typename T>
948 FORCE_INLINE T Dot( const vec4<T>& a, const vec4<T>& b ) noexcept
949 {
950 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
951 }
952
953 template <>
954 FORCE_INLINE F32 Dot( const vec4<F32>& a, const vec4<F32>& b ) noexcept
955 {
956 return _mm_cvtss_f32( AVX::DotSimd( a._reg._reg, b._reg._reg ) );
957 }
958
960 template <typename T>
961 FORCE_INLINE T vec4<T>::dot( const vec4& v ) const noexcept
962 {
963 return Divide::Dot( *this, v );
964 }
965
966 template<>
968 {
969 return Divide::Sqrt<F32>( AVX::DotSimd( _reg._reg, _reg._reg ) );
970 }
971
973 template <typename T>
975 {
976 return Dot( *this, *this );
977 }
978
980 template <typename T>
982 {
983 return direction * dot( direction );
984 }
985
987 template <typename T>
989 {
990 const T l = this->length();
991
992 if ( l >= EPSILON_F32 )
993 {
994 // multiply by the inverse length
995 *this *= 1.f / l;
996 }
997
998 return *this;
999 }
1000
1001 template <>
1003 {
1004 _reg._reg = _mm_mul_ps( _reg._reg, _mm_rsqrt_ps( AVX::SimpleDot( _reg._reg, _reg._reg ) ) );
1005 return *this;
1006 }
1007
1009 template <typename T>
1010 template <typename U> requires std::is_pod_v<U>
1011 FORCE_INLINE bool vec4<T>::isPerpendicular( const vec4<U>& other, const F32 epsilon ) const noexcept
1012 {
1013 return SQUARED( dot( other ) ) <= SQUARED( epsilon ) * lengthSquared() * other.lengthSquared();
1014 }
1015
1017 template <typename T>
1019 {
1020 return std::min( x, std::min( y, std::min( z, w ) ) );
1021 }
1022
1024 template <typename T>
1026 {
1027 return std::max( x, std::max( y, std::min( z, w ) ) );
1028 }
1029
1031 template <typename T>
1032 FORCE_INLINE void vec4<T>::lerp( const vec4& v, T factor ) noexcept
1033 {
1034 set( Lerp( *this, v, factor ) );
1035 }
1036
1039 template <typename T>
1040 FORCE_INLINE void vec4<T>::lerp( const vec4& v, const vec4& factor ) noexcept
1041 {
1042 set( Lerp( *this, v, factor ) );
1043 }
1045 template <typename T>
1046 FORCE_INLINE vec4<T> Lerp( const vec4<T>& u, const vec4<T>& v, T factor ) noexcept
1047 {
1048 return { Lerp( u.x, v.x, factor ), Lerp( u.y, v.y, factor ), Lerp( u.z, v.z, factor ), Lerp( u.w, v.w, factor ) };
1049 }
1050
1052 template <typename T>
1053 FORCE_INLINE vec4<T> Lerp( const vec4<T>& u, const vec4<T>& v, const vec4<T>& factor ) noexcept
1054 {
1055 return { Lerp( u.x, v.x, factor.x ), Lerp( u.y, v.y, factor.y ), Lerp( u.z, v.z, factor.z ), Lerp( u.w, v.w, factor.w ) };
1056 }
1057
1058 template <typename Type>
1060 {
1061 return vec2<Type>( Random( min.x, max.x ), Random( min.y, max.y ) );
1062 }
1063
1064 template <typename Type>
1066 {
1067 return vec3<Type>( Random( min.x, max.x ), Random( min.y, max.y ),
1068 Random( min.z, max.z ) );
1069 }
1070
1071 template <typename Type>
1073 {
1074 return vec4<Type>( Random( min.x, max.x ), Random( min.y, max.y ),
1075 Random( min.z, max.z ), Random( min.w, max.w ) );
1076 }
1077} // namespace Divide
1078
1079#endif //DVD_CORE_MATH_MATH_VECTORS_INL_
#define FORCE_INLINE
bool compare(vec2< U > v) const noexcept
compare 2 vectors
void lerp(const vec2 &v, T factor) noexcept
lerp between this and the specified vector by the specified amount
T minComponent() const noexcept
get the smallest value of X or Y
vec2 closestPointOnSegment(const vec2 &vA, const vec2 &vB)
return the closest point on the line segment defined between the 2 points (A, B) and this vector
vec2 & normalize() noexcept
convert the vector to unit length
T distance(const vec2 &v) const
compute the vector's distance to another specified vector
T maxComponent() const noexcept
get the largest value of X or Y
T distanceSquared(const vec2 &v) const noexcept
compute the vector's squared distance to another specified vector
vec2 closestPointOnLine(const vec2 &vA, const vec2 &vB)
return the closest point on the line defined by the 2 points (A, B) and this vector
T lengthSquared() const noexcept
return the squared distance of the vector
void round()
round both values
void get(T *v) const
export the vector's components in the first 2 positions of the specified array
T projectionOnLine(const vec2 &vA, const vec2 &vB) const
project this vector on the line defined by the 2 points(A, B)
T dot(const vec2 &v) const noexcept
calculate the dot product between this vector and the specified one
T angle(vec3 &v) const
returns the angle in radians between '*this' and 'v'
T dot(const vec3 &v) const noexcept
calculate the dot product between this vector and the specified one
vec3 & normalize() noexcept
transform the vector to unit length
void lerp(const vec3 &v, T factor) noexcept
lerp between this and the specified vector by the specified amount
T length() const noexcept
return the vector's length
Definition: MathVectors.h:747
T maxComponent() const noexcept
get the largest value of X,Y or Z
T projectionOnLine(const vec3 &vA, const vec3 &vB) const
project this vector on the line defined by the 2 points(A, B)
vec3 closestPointOnLine(const vec3 &vA, const vec3 &vB)
void swap(vec3 &iv) noexcept
swap the components of this vector with that of the specified one
T minComponent() const noexcept
get the smallest value of X,Y or Z
void rotateX(D64 radians)
rotate this vector on the X axis
T lengthSquared() const noexcept
return the squared distance of the vector
vec3 direction(const vec3 &u) const noexcept
get the direction vector to the specified point
void cross(const vec3 &v1, const vec3 &v2) noexcept
set this vector to be equal to the cross of the 2 specified vectors
vec3 closestPointOnSegment(const vec3 &vA, const vec3 &vB)
void rotateZ(D64 radians)
rotate this vector on the Z axis
void get(T *v) const noexcept
bool isUniform(F32 tolerance=0.0001f) const noexcept
uniform vector: x = y = z
void rotateY(D64 radians)
rotate this vector on the Y axis
T distanceSquared(const vec3 &v) const noexcept
compute the vector's squared distance to another specified vector
vec3 projectToNorm(const vec3< T > &direction) noexcept
project this vector onto the given direction
bool compare(const vec3< U > &v) const noexcept
compare 2 vectors
vec3 vector(const vec3 &vp1, const vec3 &vp2) const noexcept
bool isPerpendicular(const vec3< U > &other, F32 epsilon=EPSILON_F32) const noexcept
The current vector is perpendicular to the specified one within epsilon.
T distance(const vec3 &v) const noexcept
compute the vector's distance to another specified vector
void round()
round all three values
vec4 & operator+=(U _f) noexcept
Definition: MathVectors.h:1073
void set(const T *v) noexcept
set the 4 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:1241
vec4 operator-() const noexcept
Definition: MathVectors.h:1043
vec4 projectToNorm(const vec4< T > &direction)
project this vector onto the given direction
vec4 operator+(U _f) const noexcept
Definition: MathVectors.h:1020
T maxComponent() const noexcept
get the largest value of X,Y,Z or W
vec4 & operator-=(U _f) noexcept
Definition: MathVectors.h:1078
vec4 operator*(U _f) const noexcept
Definition: MathVectors.h:1025
vec4 & operator*=(U _f) noexcept
Definition: MathVectors.h:1083
T lengthSquared() const noexcept
return the squared distance of the vector
void round() noexcept
round all four values
void swap(vec4 *iv) noexcept
swap the components of this vector with that of the specified one
vec4 & operator/=(U _f) noexcept
Definition: MathVectors.h:1088
T minComponent() const noexcept
get the smallest value of X,Y,Z or W
SimdVector< T > _reg
Definition: MathVectors.h:1398
void lerp(const vec4 &v, T factor) noexcept
lerp between this and the specified vector by the specified amount
bool compare(const vec4< U > &v) const noexcept
compare 2 vectors
T length() const noexcept
return the vector's length
Definition: MathVectors.h:1312
vec4 & normalize() noexcept
transform the vector to unit length
bool isPerpendicular(const vec4< U > &other, F32 epsilon=EPSILON_F32) const noexcept
The current vector is perpendicular to the specified one within epsilon.
T dot(const vec4 &v) const noexcept
calculate the dot product between this vector and the specified one
vec4 operator/(U _f) const noexcept
Definition: MathVectors.h:1030
__m128 SimpleDot(__m128 a, __m128 b) noexcept
Definition: MathVectors.inl:68
__m128 DotSimd(const __m128 &a, const __m128 &b) noexcept
Definition: MathVectors.inl:59
bool Fneq128(__m128 const &a, __m128 const &b) noexcept
Definition: MathVectors.inl:40
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
vec2< T > Normalized(vec2< T > vector) noexcept
Definition: MathVectors.inl:98
vec3< T > Abs(const vec3< T > &vector) noexcept
bool IS_ZERO(const T X) noexcept
T Lerp(T v1, T v2, U t) noexcept
Definition: MathHelper.inl:240
vec2< T > operator*(T fl, vec2< T > v) noexcept
multiply a vector by a value
constexpr T SQUARED(T input) noexcept
Definition: MathHelper.inl:156
T Sqrt(T input) noexcept
Definition: MathHelper.inl:252
static const vec3< F32 > WORLD_X_AXIS
Definition: MathVectors.h:1439
vec3< T > Min(const vec3< T > &v1, const vec3< T > &v2) noexcept
static const vec3< F32 > WORLD_Z_AXIS
Definition: MathVectors.h:1441
vec2< T > Inverse(vec2< T > v) noexcept
Definition: MathVectors.inl:86
vec3< T > Perpendicular(const vec3< T > &v) noexcept
T Random()
Definition: MathHelper.inl:95
T Dot(vec2< T > a, vec2< T > b) noexcept
general vec2 dot product
constexpr F32 EPSILON_F32
eastl::vector< Type > vector
Definition: Vector.h:42
vec3< T > AreOrthogonal(const vec3< T > &v1, const vec3< T > &v2) noexcept
vec3< T > Max(const vec3< T > &v1, const vec3< T > &v2) noexcept
vec2< T > Normalize(vec2< T > &vector) noexcept
void OrthoNormalize(vec2< T > &n, vec2< T > &u) noexcept
bool COMPARE_TOLERANCE(const T X, const U Y, const T TOLERANCE) noexcept
::value constexpr T CLAMPED(T n, T min, T max) noexcept
Definition: MathHelper.inl:126
vec2< T > Cross(vec2< T > v1, vec2< T > v2) noexcept
general vec2 cross function
Definition: MathVectors.inl:80
double D64
bool COMPARE(T X, U Y) noexcept
vec3< T > ProjectToNorm(const vec3< T > &in, const vec3< T > &direction)
vec2< T > Clamped(vec2< T > v, vec2< T > min, vec2< T > max) noexcept
static const vec3< F32 > WORLD_Y_AXIS
Definition: MathVectors.h:1440