Version

menu_open
Wwise SDK 2024.1.1
AkVectors.h
Go to the documentation of this file.
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 // AkVectors.h
28 //
29 
30 #pragma once
31 
36 #include <AK/Tools/Common/AkArray.h>
37 
38 #include <math.h>
39 #include <stdio.h>
40 #include <float.h>
41 
42 //#define AKVBAP_DEBUG 1
43 //#define AKPORTALS_DEBUG
44 
45 #define AKVECTORS_PI (3.1415926535897932384626433832795f)
46 #define AKVECTORS_TWOPI (6.283185307179586476925286766559f)
47 #define AKVECTORS_PIOVERTWO (1.5707963267948966192313216916398f)
48 #define AKVECTORS_EPSILON (1.0e-38f) // epsilon value for fast log(0)
49 
50 class Ak4DVector
51 {
52 public:
53  //-----------------------------------------------------------
54  // Constructor/Destructor functions
56  {
57  v[0] = 0.0f;
58  v[1] = 0.0f;
59  v[2] = 0.0f;
60  v[3] = 0.0f;
61  }
62 
63  Ak4DVector(const AkVector& b)
64  {
65  v[0] = b.X;
66  v[1] = b.Y;
67  v[2] = b.Z;
68  v[3] = 1;
69  }
70 
71  //-----------------------------------------------------------
72  // Basic vector operators
74  {
75  v[0] = b.v[0];
76  v[1] = b.v[1];
77  v[2] = b.v[2];
78  v[3] = b.v[3];
79 
80  return *this;
81  }
82 
84  {
85  v[0] = v[0] / f;
86  v[1] = v[1] / f;
87  v[2] = v[2] / f;
88  v[3] = v[3] / f;
89 
90  return *this;
91  }
92 
93  Ak4DVector operator-(const Ak4DVector& b) const
94  {
95  Ak4DVector p;
96 
97  p.v[0] = v[0] - b.v[0];
98  p.v[1] = v[1] - b.v[1];
99  p.v[2] = v[2] - b.v[2];
100  p.v[3] = v[3] - b.v[3];
101 
102  return p;
103  }
104 
105  AkReal32 v[4];
106 };
107 
109 {
110 public:
111  Ak3DIntVector() = default;
112 
114  X(x),
115  Y(y),
116  Z(z)
117  {
118  }
119 
120  AkInt32 X; ///< X Position
121  AkInt32 Y; ///< Y Position
122  AkInt32 Z; ///< Z Position
123 };
124 
125 ///
126 /// Specialization must provide these methods. Could enforce that through static_assert...
127 /// static TDataType Cos(TDataType in_value) const;
128 /// static TDataType Sin(TDataType in_value) const;
129 /// static TDataType Sqrt(TDataType in_value) const;
130 /// static constexpr TDataType POSITIVE_EPSILON;
131 /// static constexpr TDataType VECTOR_EPSILON;
132 ///
133 template<typename TDataType> class RealPrecision;
134 
135 template<>
137 {
138 public:
139  static AkReal32 Cos(AkReal32 in_value) { return cosf(in_value); }
140  static AkReal32 Sin(AkReal32 in_value) { return sinf(in_value); }
141  static AkReal32 Sqrt(AkReal32 in_value) { return sqrtf(in_value); }
142  static AkReal32 ACos(AkReal32 in_value) { return acosf(in_value); }
143  static bool IsFinite(AkReal32 in_val)
144  {
145  // Purposely not using std::isnan() or isfinite because fastmath on clang & gcc may optimize them to be false always.
146  return !(((*(AkUInt32*)&in_val) & 0x7fffffff) >= 0x7f800000);
147  }
148 
149  static constexpr AkReal32 POSITIVE_EPSILON = 0.00001f;
150  static constexpr AkReal32 VECTOR_EPSILON = AKVECTORS_EPSILON;
151 
152  static constexpr AkReal32 MAX_VALUE = FLT_MAX;
153 };
154 
155 template<>
157 {
158 public:
159  static AkReal64 Cos(AkReal64 in_value) { return cos(in_value); }
160  static AkReal64 Sin(AkReal64 in_value) { return sin(in_value); }
161  static AkReal64 Sqrt(AkReal64 in_value) { return sqrt(in_value); }
162  static AkReal64 ACos(AkReal64 in_value) { return acos(in_value); }
163  static bool IsFinite(AkReal64 in_val)
164  {
165  // Purposely not using std::isnan() or isfinite because fastmath on clang & gcc may optimize them to be false always.
166  return !(((*(AkUInt64*)&in_val) & 0x7fffffffffffffff) >= 0x7ff0000000000000);
167  }
168 
169  static constexpr AkReal64 POSITIVE_EPSILON = 0.000000000001f;
170  static constexpr AkReal64 VECTOR_EPSILON = AKVECTORS_EPSILON;
171 
172  static constexpr AkReal64 MAX_VALUE = DBL_MAX;
173 };
174 
175 // AkImplicitConversion
176 // Permits automatic conversion from any real type to any other real type.
177 // May result in loss of precision.
179 {
180 public:
181  template<typename TFromReal, typename TToReal>
182  AkForceInline void Convert(TToReal& out_to, TFromReal in_from)
183  {
184  out_to = static_cast<TToReal>(in_from);
185  }
186 };
187 
188 // AkSafeConversion
189 // Permits automatic conversion only from 32-bit to 64-bit types.
190 // Conversion from 64-bit to 32-bit is not permitted and will generate and error.
192 {
193 public:
194  AkForceInline void Convert(AkReal64& out_to, AkReal32 in_from)
195  {
196  out_to = in_from;
197  }
198  template<typename TReal>
199  AkForceInline void Convert(TReal& out_to, TReal in_from)
200  {
201  out_to = in_from;
202  }
203 };
204 
205 // T3DVector<>
206 // Template 3D vector class, to support both 32 and 64-bit vector types.
207 // Ak3DVector32 and Ak3DVector64 typedefs are provided below for convenience.
208 template<typename TDataType>
209 class T3DVector
210 {
211 public:
212  /// Expose the data type
213  ///
214  typedef TDataType data_type;
215 
216  // Conversion policy for conversions between 32 and 64 bit types.
218 
219 public:
220 
221  //-----------------------------------------------------------
222  // Constructor/Destructor functions
223 
224  T3DVector() :
225  X(static_cast<TDataType>(0.0)),
226  Y(static_cast<TDataType>(0.0)),
227  Z(static_cast<TDataType>(0.0))
228  {}
229 
230  T3DVector(TDataType in_x, TDataType in_y, TDataType in_z) :
231  X(in_x),
232  Y(in_y),
233  Z(in_z)
234  {}
235 
236  // Construct from another T3DVector<> type.
237  // Conversion is (only) permitted in accordance to the conversion policy.
238  template<typename TFromDataType>
240  {
241  TTypeConverter converter;
242  converter.Convert(X, in_vector.X);
243  converter.Convert(Y, in_vector.Y);
244  converter.Convert(Z, in_vector.Z);
245  }
246 
247  // Construct from an AkVector type.
248  // Conversion is (only) permitted in accordance to the conversion policy.
249  T3DVector(const AkVector& in_vector)
250  {
251  TTypeConverter converter;
252  converter.Convert(X, in_vector.X);
253  converter.Convert(Y, in_vector.Y);
254  converter.Convert(Z, in_vector.Z);
255  }
256 
257  // Construct from an AkVector64 type.
258  // Conversion is (only) permitted in accordance to the conversion policy.
259  T3DVector(const AkVector64& in_vector)
260  {
261  TTypeConverter converter;
262  converter.Convert(X, in_vector.X);
263  converter.Convert(Y, in_vector.Y);
264  converter.Convert(Z, in_vector.Z);
265  }
266 
267  // Implicit conversion to AkVector type, it the conversion policy permits it.
268  operator AkVector() const
269  {
270  AkVector v;
271  TTypeConverter converter;
272  converter.Convert(v.X, X);
273  converter.Convert(v.Y, Y);
274  converter.Convert(v.Z, Z);
275  return v;
276  }
277 
278  // Implicit conversion to AkVector64 type, it the conversion policy permits it.
279  operator AkVector64() const
280  {
281  AkVector64 v;
282  TTypeConverter converter;
283  converter.Convert(v.X, X);
284  converter.Convert(v.Y, Y);
285  converter.Convert(v.Z, Z);
286  return v;
287  }
288 
289  // Casting method for explicit conversion to another vector type.s
290  template<typename TVectorType>
291  TVectorType Cast() const;
292 
293  // Construct a vector from a scalar.
294  explicit T3DVector(TDataType in_scalar)
295  : X(in_scalar)
296  , Y(in_scalar)
297  , Z(in_scalar)
298  {}
299 
300  // Convert from a vector from a AKSIMD_V4F32.
301  explicit T3DVector(const AKSIMD_V4F32& in_v4f32)
302  {
303  X = static_cast<TDataType>(AKSIMD_GETELEMENT_V4F32(in_v4f32, 0));
304  Y = static_cast<TDataType>(AKSIMD_GETELEMENT_V4F32(in_v4f32, 1));
305  Z = static_cast<TDataType>(AKSIMD_GETELEMENT_V4F32(in_v4f32, 2));
306  }
307 
309  {
310  AKSIMD_V4F32 v4f32;
311  AKSIMD_GETELEMENT_V4F32(v4f32, 0) = static_cast<AkReal32>(X);
312  AKSIMD_GETELEMENT_V4F32(v4f32, 1) = static_cast<AkReal32>(Y);
313  AKSIMD_GETELEMENT_V4F32(v4f32, 2) = static_cast<AkReal32>(Z);
314  AKSIMD_GETELEMENT_V4F32(v4f32, 3) = 1.f;
315  return v4f32;
316  }
317 
319  {
320  AKSIMD_V4F32 v4f32;
321  AKSIMD_GETELEMENT_V4F32(v4f32, 0) = static_cast<TDataType>(X);
322  AKSIMD_GETELEMENT_V4F32(v4f32, 1) = static_cast<TDataType>(Y);
323  AKSIMD_GETELEMENT_V4F32(v4f32, 2) = static_cast<TDataType>(Z);
324  AKSIMD_GETELEMENT_V4F32(v4f32, 3) = static_cast<TDataType>(0.0);
325  return v4f32;
326  }
327 
328  void Zero()
329  {
330  X = static_cast<TDataType>(0.0);
331  Y = static_cast<TDataType>(0.0);
332  Z = static_cast<TDataType>(0.0);
333  }
334 
335  //-----------------------------------------------------------
336  // Basic vector operators
337  AkForceInline bool operator==(const T3DVector& b) const
338  {
339  return X == b.X && Y == b.Y && Z == b.Z;
340  }
341 
342  AkForceInline bool operator!=(const T3DVector& b) const
343  {
344  return X != b.X || Y != b.Y || Z != b.Z;
345  }
346 
347  AkForceInline bool operator<(const T3DVector& b) const
348  {
349  return X < b.X && Y < b.Y && Z < b.Z;
350  }
351 
352  AkForceInline bool operator<=(const T3DVector& b) const
353  {
354  return X <= b.X && Y <= b.Y && Z <= b.Z;
355  }
356 
357  AkForceInline bool operator>(const T3DVector b) const
358  {
359  return X > b.X && Y > b.Y && Z > b.Z;
360  }
361 
362  AkForceInline bool operator>=(const T3DVector& b) const
363  {
364  return X >= b.X && Y >= b.Y && Z >= b.Z;
365  }
366 
367  AkForceInline T3DVector& operator*=(const TDataType f)
368  {
369  X = X * f;
370  Y = Y * f;
371  Z = Z * f;
372 
373  return *this;
374  }
375 
376  AkForceInline T3DVector& operator/=(const TDataType f)
377  {
378  TDataType oneoverf = static_cast<TDataType>(1.0) / f;
379  X = X * oneoverf;
380  Y = Y * oneoverf;
381  Z = Z * oneoverf;
382 
383  return *this;
384  }
385 
387  {
388  T3DVector v;
389 
390  v.X = X * v2.X;
391  v.Y = Y * v2.Y;
392  v.Z = Z * v2.Z;
393 
394  return v;
395  }
396 
397  AkForceInline T3DVector operator*(const TDataType f) const
398  {
399  T3DVector v;
400 
401  v.X = X * f;
402  v.Y = Y * f;
403  v.Z = Z * f;
404 
405  return v;
406  }
407 
409  {
410  T3DVector v;
411 
412  v.X = X / in_rhs.X;
413  v.Y = Y / in_rhs.Y;
414  v.Z = Z / in_rhs.Z;
415 
416  return v;
417  }
418 
419  AkForceInline T3DVector operator/(const TDataType f) const
420  {
421  T3DVector v;
422 
423  TDataType oneoverf = static_cast<TDataType>(1.0) / f;
424 
425  v.X = X * oneoverf;
426  v.Y = Y * oneoverf;
427  v.Z = Z * oneoverf;
428 
429  return v;
430  }
431 
432  AkForceInline T3DVector operator+(const TDataType f) const
433  {
434  T3DVector v;
435 
436  v.X = X + f;
437  v.Y = Y + f;
438  v.Z = Z + f;
439 
440  return v;
441  }
442 
443  AkForceInline T3DVector operator-(const TDataType f) const
444  {
445  T3DVector v;
446 
447  v.X = X - f;
448  v.Y = Y - f;
449  v.Z = Z - f;
450 
451  return v;
452  }
453 
455  {
456  T3DVector v;
457 
458  v.X = X + b.X;
459  v.Y = Y + b.Y;
460  v.Z = Z + b.Z;
461 
462  return v;
463  }
464 
466  {
467  T3DVector v;
468 
469  v.X = X - b.X;
470  v.Y = Y - b.Y;
471  v.Z = Z - b.Z;
472 
473  return v;
474  }
475 
476  AkForceInline TDataType HorizontalMin() const
477  {
478  return AkMin(X, AkMin(Y, Z));
479  }
480 
481  AkForceInline TDataType HorizontalMax() const
482  {
483  return AkMax(X, AkMax(Y, Z));
484  }
485 
486  AkForceInline static T3DVector Min(const T3DVector& A, const T3DVector& B)
487  {
488  T3DVector min;
489 
490  min.X = AkMin(A.X, B.X);
491  min.Y = AkMin(A.Y, B.Y);
492  min.Z = AkMin(A.Z, B.Z);
493 
494  return min;
495  }
496 
497  AkForceInline static T3DVector Max(const T3DVector& A, const T3DVector& B)
498  {
499  T3DVector max;
500 
501  max.X = AkMax(A.X, B.X);
502  max.Y = AkMax(A.Y, B.Y);
503  max.Z = AkMax(A.Z, B.Z);
504 
505  return max;
506  }
507 
508  AkForceInline bool Equals(const T3DVector& b, const TDataType tolerance = static_cast<TDataType>(0.0)) const
509  {
510  return fabs(X - b.X) <= tolerance && fabs(Y - b.Y) <= tolerance && fabs(Z - b.Z) <= tolerance;
511  }
512 
513  //-----------------------------------------------------------
514  // Conversion functions
516  {
517  T3DVector v;
518 
519  v.X = -X;
520  v.Y = Z;
521  v.Z = -Y;
522 
523  return v;
524  }
525 
527  const TDataType azimuth,
528  const TDataType elevation)
529  {
530  TDataType cosElevation = RealPrecision<TDataType>::Cos(elevation);
531  X = RealPrecision<TDataType>::Cos(azimuth) * cosElevation;
532  Y = RealPrecision<TDataType>::Sin(azimuth) * cosElevation;
533  Z = RealPrecision<TDataType>::Sin(elevation);
534 
535  return *this;
536  }
537 
538  // Determinant of 3 column vectors.
539  static AkForceInline TDataType Determinant(
540  const T3DVector& a,
541  const T3DVector& b,
542  const T3DVector& c)
543  {
544  return (a.X*b.Y*c.Z + a.Y*b.Z*c.X + a.Z*b.X*c.Y) -
545  (a.Z*b.Y*c.X + a.Y*b.X*c.Z + a.X*b.Z*c.Y);
546  }
547 
548  // Convert a vector to a different base
550  const T3DVector& A,
551  const T3DVector& B,
552  const T3DVector& C) const
553  {
554  T3DVector v;
555 
556  TDataType d = Determinant(A, B, C);
557 
559  {
560  v.X = static_cast<TDataType>(0.0); v.Y = static_cast<TDataType>(0.0); v.Z = static_cast<TDataType>(0.0);
561  return v;
562  }
563 
564  // http://mathworld.wolfram.com/MatrixInverse.html
565  T3DVector invA = T3DVector(B.Y*C.Z - B.Z*C.Y, A.Z*C.Y - A.Y*C.Z, A.Y*B.Z - A.Z*B.Y);
566  T3DVector invB = T3DVector(B.Z*C.X - B.X*C.Z, A.X*C.Z - A.Z*C.X, A.Z*B.X - A.X*B.Z);
567  T3DVector invC = T3DVector(B.X*C.Y - B.Y*C.X, A.Y*C.X - A.X*C.Y, A.X*B.Y - A.Y*B.X);
568 
569  TDataType oneover_d = static_cast<TDataType>(1.0) / d;
570  invA *= oneover_d;
571  invB *= oneover_d;
572  invC *= oneover_d;
573 
574  // Project coordinates using a vector to matrix multiplication
575  v.X = X * invA.X + Y * invB.X + Z * invC.X;
576  v.Y = X * invA.Y + Y * invB.Y + Z * invC.Y;
577  v.Z = X * invA.Z + Y * invB.Z + Z * invC.Z;
578 
579  // v /= v.Length();
580 
581  return v;
582  }
583 
585  {
586  TDataType l = Length();
587  if (l != static_cast<TDataType>(0.0))
588  {
589  X /= l;
590  Y /= l;
591  Z /= l;
592  }
593  else
594  {
595  X = static_cast<TDataType>(0.0);
596  Y = static_cast<TDataType>(0.0);
597  Z = static_cast<TDataType>(0.0);
598  }
599  return *this;
600  }
601 
602  AkForceInline TDataType L2_Norm() const
603  {
604  return RealPrecision<TDataType>::Sqrt(X*X + Y*Y + Z*Z);
605  }
606 
607  AkForceInline TDataType DotProduct(const T3DVector& v2) const
608  {
609  return X*v2.X + Y*v2.Y + Z*v2.Z;
610  }
611 
612  AkForceInline TDataType Dot(const T3DVector& v2) const
613  {
614  return DotProduct(v2);
615  }
616 
618  {
619  T3DVector uxv;
620 
621  const T3DVector& u = *this;
622 
623  uxv.X = u.Y*v.Z - u.Z*v.Y;
624  uxv.Y = u.Z*v.X - u.X*v.Z;
625  uxv.Z = u.X*v.Y - u.Y*v.X;
626 
627  return uxv;
628  }
629 
630  AkForceInline TDataType Length() const
631  {
632  return RealPrecision<TDataType>::Sqrt(X*X + Y*Y + Z*Z);
633  }
634 
635  AkForceInline TDataType LengthSquared() const
636  {
637  return X*X + Y*Y + Z*Z;
638  }
639 
640  // Usefull in VBAP algorithm, only points that are a positive linear composition matters.
642  {
646  }
647 
649  {
650  T3DVector abs = *this;
651  abs.X = (TDataType)fabs(abs.X);
652  abs.Y = (TDataType)fabs(abs.Y);
653  abs.Z = (TDataType)fabs(abs.Z);
654  return abs;
655  }
656 
657  AkForceInline bool IsFinite() const
658  {
659  return
663  }
664 
665  TDataType X;
666  TDataType Y;
667  TDataType Z;
668 };
669 
670 template<typename TDataType>
672 {
673  return v * f;
674 }
675 
676 template<typename TDataType>
678 {
679  T3DVector<TDataType> res;
680  res.X = f / v.X;
681  res.Y = f / v.Y;
682  res.Z = f / v.Z;
683  return res;
684 }
685 
686 
687 // Ak3DVector typedefs
688 
689 // Ak3DVector32 - Can be implicitly converted to 64 but not the other way around.
692 
693 // Ak3DVector64 - It is necessary to call vec.Cast<Ak3DVector64>() to convert to 32 bit vector type.
695 
696 // Casting methods.
697 
698 // Generic cast between two T3DVector<> types.
699 template<typename TDataType>
700 template<typename TVectorType>
701 TVectorType T3DVector<TDataType>::Cast() const
702 {
703  TVectorType v;
704  v.X = static_cast<typename TVectorType::data_type>(X);
705  v.Y = static_cast<typename TVectorType::data_type>(Y);
706  v.Z = static_cast<typename TVectorType::data_type>(Z);
707  return v;
708 }
709 
710 
711 class Ak2DVector
712 {
713 public:
714  //-----------------------------------------------------------
715  // Constructor/Destructor functions
716  Ak2DVector() = default;
717 
719  X(x),
720  Y(y)
721  {
722  }
723 
724  //-----------------------------------------------------------
725  // Basic vector operators
727  {
728  X = b.X;
729  Y = b.Y;
730 
731  return *this;
732  }
733 
735  {
736  X = b.theta;
737  Y = b.phi;
738 
739  return *this;
740  }
741 
742  Ak2DVector operator-(const Ak2DVector& b) const
743  {
744  Ak2DVector v;
745 
746  v.X = X - b.X;
747  v.Y = Y - b.Y;
748 
749  return v;
750  }
751 
753  {
754  X = X * f;
755  Y = Y * f;
756 
757  return *this;
758  }
759 
761  {
762  AkReal32 oneoverf = 1.f / f;
763  X = X * oneoverf;
764  Y = Y * oneoverf;
765 
766  return *this;
767  }
768 
769  AkForceInline bool operator==(const Ak2DVector& b) const
770  {
771  return b.X == X && b.Y == Y;
772  }
773 
774  AkForceInline bool operator!=(const Ak2DVector& b) const
775  {
776  return b.X != X && b.Y != Y;
777  }
778 
780  {
781  return sqrtf(X*X+Y*Y);
782  }
783 
784  //-----------------------------------------------------------
785  // Conversion functions
787  {
788  // (radial, azimuth, elevation)
789  AkReal32 r = sqrtf( in_Cartesian.X*in_Cartesian.X + in_Cartesian.Y*in_Cartesian.Y + in_Cartesian.Z*in_Cartesian.Z);
790  AKASSERT( r != 0);
791 
792  X = atan2f(in_Cartesian.Y, in_Cartesian.X);
793  Y = asinf(in_Cartesian.Z / r);
794 
795  NormalizeSpherical();
796 
797  return *this;
798  }
799 
801  const Ak2DVector& A,
802  const Ak2DVector& B) const
803  {
804  Ak2DVector v;
805 
806  // Project coordinates using a vector to matrix multiplication
807  AkReal32 d = (A.X*B.Y - A.Y*B.X);
808 
809  if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
810  {
811  v.X = 0.0f; v.Y = 0.0f;
812  return v;
813  }
814 
815  Ak2DVector invA = Ak2DVector( B.Y, -A.Y );
816  Ak2DVector invB = Ak2DVector( -B.X, A.X );
817 
818  AkReal32 oneover_d = 1.f / d;
819  invA *= oneover_d;
820  invB *= oneover_d;
821 
822  v.X = X * invA.X + Y * invB.X;
823  v.Y = X * invA.Y + Y * invB.Y;
824  // v /= v.Length();
825 
826  return v;
827  }
828 
830  {
831  /*
832  Normalise spherical coordinates.
833  X (azimuthal) -> [-PI, PI], circle lies on xy plan, 0 is on X axix
834  Y (elevation) -> [-PI/2, PI/2], half circle on Z axis, 0 on XY plan, PI/2 straigt up on Z axis.
835  */
836 
837  Ak2DVector v;
838 
839  v.X = X;
840  v.Y = Y;
841 
842  if (X > AKVECTORS_PI)
843  v.X = X - AKVECTORS_TWOPI;
844  else if (X < -AKVECTORS_PI)
845  v.X = X + AKVECTORS_TWOPI;
846 
847  if (Y > AKVECTORS_PIOVERTWO)
848  v.Y = Y - AKVECTORS_PI;
849  else if (Y < -AKVECTORS_PIOVERTWO)
850  v.Y = Y + AKVECTORS_PI;
851 
854 
855  return v;
856  }
857 
859  {
860  /*
861  Normalise spherical coordinates.
862  X (azimuthal) -> [-PI, PI], circle lies on xy plan, 0 is on X axix
863  Y (elevation) -> [-PI/2, PI/2], half circle on Z axis, 0 on XY plan, PI/2 straigt up on Z axis.
864  */
865 
866  if (X > AKVECTORS_PI)
867  X = X - AKVECTORS_TWOPI;
868  else if (X < -AKVECTORS_PI)
869  X = X + AKVECTORS_TWOPI;
870 
871  if (Y > AKVECTORS_PIOVERTWO)
872  Y = Y - AKVECTORS_PI;
873  else if (Y < -AKVECTORS_PIOVERTWO)
874  Y = Y + AKVECTORS_PI;
875  }
876 
877  // Useful in VBAP algorithm, only points that are a positive linear composition matters.
879  {
880  const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f; //0.005f;
881  return X >= -POSITIVE_TEST_EPSILON &&
882  Y >= -POSITIVE_TEST_EPSILON;
883  }
884 
887 };
888 
889 
890 
891 class AkMatrix4x4
892 {
893  static const int MAX_SIZE = 16;
894 
895 public:
896  //-----------------------------------------------------------
897  // Constructor/Destructor functions
898  AkMatrix4x4() = default;
899 
900  //-----------------------------------------------------------
901  // Basic vector operators
903  {
904  for (int i = 0; i < MAX_SIZE; i++)
905  m_Data[i] /= f;
906 
907  return *this;
908  }
909 
911  {
912  for (int i = 0; i < MAX_SIZE; i++)
913  {
914  m_Data[i] = in_Data[i];
915  }
916 
917  return *this;
918  }
919 
920  AkReal32 m_Data[MAX_SIZE];
921 };
922 
923 class AkMatrix3x3
924 {
925 
926 public:
927  //-----------------------------------------------------------
928  // Constructor/Destructor functions
929  AkMatrix3x3() = default;
930 
931  static AkMatrix3x3 FromColumnVectors(const Ak3DVector& in_col0, const Ak3DVector& in_col1, const Ak3DVector& in_col2)
932  {
933  AkMatrix3x3 m;
934 
935  m(0, 0) = in_col0.X;
936  m(1, 0) = in_col0.Y;
937  m(2, 0) = in_col0.Z;
938 
939  m(0, 1) = in_col1.X;
940  m(1, 1) = in_col1.Y;
941  m(2, 1) = in_col1.Z;
942 
943  m(0, 2) = in_col2.X;
944  m(1, 2) = in_col2.Y;
945  m(2, 2) = in_col2.Z;
946 
947  return m;
948  }
949 
950  //-----------------------------------------------------------
951  // Basic vector operators
953  {
954  for (int i = 0; i < 3; i++)
955  {
956  for (int j = 0; j < 3; j++)
957  {
958  m_Data[i][j] /= f;
959  }
960  }
961  return *this;
962  }
963 
964  AkForceInline AkReal32& operator()(const AkUInt32 row, const AkUInt32 column)
965  {
966  return m_Data[column][row];
967  }
968 
969  AkForceInline const AkReal32& operator()(const AkUInt32 row, const AkUInt32 column) const
970  {
971  return m_Data[column][row];
972  }
973 
975  {
976  Ak3DVector res;
977  res.X = in_rhs.X * m_Data[0][0] + in_rhs.Y * m_Data[1][0] + in_rhs.Z * m_Data[2][0];
978  res.Y = in_rhs.X * m_Data[0][1] + in_rhs.Y * m_Data[1][1] + in_rhs.Z * m_Data[2][1];
979  res.Z = in_rhs.X * m_Data[0][2] + in_rhs.Y * m_Data[1][2] + in_rhs.Z * m_Data[2][2];
980  return res;
981  }
982 
984  {
985  Add(*this, *this, in_rhs);
986  return *this;
987  }
988 
989  static AkForceInline void Add(AkMatrix3x3& out_res, const AkMatrix3x3& in_m0, const AkMatrix3x3& in_m1)
990  {
991 #define ADD(i,j) out_res(i,j) = in_m0(i,j) + in_m1(i,j)
992  ADD(0, 0); ADD(0, 1); ADD(0, 2);
993  ADD(1, 0); ADD(1, 1); ADD(1, 2);
994  ADD(2, 0); ADD(2, 1); ADD(2, 2);
995 #undef ADD
996  }
997 
999  {
1000  m_Data[0][0] *= in_f; m_Data[0][1] *= in_f; m_Data[0][2] *= in_f;
1001  m_Data[1][0] *= in_f; m_Data[1][1] *= in_f; m_Data[1][2] *= in_f;
1002  m_Data[2][0] *= in_f; m_Data[2][1] *= in_f; m_Data[2][2] *= in_f;
1003  return *this;
1004  }
1005 
1006  static AkForceInline void Diagonal(AkMatrix3x3& out_mat, AkReal32 in_f)
1007  {
1008  out_mat(0, 0) = in_f; out_mat(0, 1) = 0.f; out_mat(0, 2) = 0.f;
1009  out_mat(1, 0) = 0.f; out_mat(1, 1) = in_f; out_mat(1, 2) = 0.f;
1010  out_mat(2, 0) = 0.f; out_mat(2, 1) = 0.f; out_mat(2, 2) = in_f;
1011  }
1012 
1013  // Creates the matrix Mu such that Mu*v = u X v
1014  static AkForceInline void CrossProductMatrix(AkMatrix3x3& out_mat, const Ak3DVector& in_u)
1015  {
1016  out_mat(0, 0) = 0.f; out_mat(0, 1) = -in_u.Z; out_mat(0, 2) = in_u.Y;
1017  out_mat(1, 0) = in_u.Z; out_mat(1, 1) = 0.f; out_mat(1, 2) = -in_u.X;
1018  out_mat(2, 0) = -in_u.Y; out_mat(2, 1) = in_u.X; out_mat(2, 2) = 0.f;
1019  }
1020 
1021  static AkForceInline void OuterProduct(AkMatrix3x3& out_mat, const Ak3DVector& in_v0, const Ak3DVector& in_v1)
1022  {
1023  out_mat(0, 0) = in_v0.X*in_v1.X; out_mat(0, 1) = in_v0.X*in_v1.Y; out_mat(0, 2) = in_v0.X*in_v1.Z;
1024  out_mat(1, 0) = in_v0.Y*in_v1.X; out_mat(1, 1) = in_v0.Y*in_v1.Y; out_mat(1, 2) = in_v0.Y*in_v1.Z;
1025  out_mat(2, 0) = in_v0.Z*in_v1.X; out_mat(2, 1) = in_v0.Z*in_v1.Y; out_mat(2, 2) = in_v0.Z*in_v1.Z;
1026  }
1027 
1028  static AkForceInline void Rotation(AkMatrix3x3& out_mat, AkReal32 in_angle, const Ak3DVector& in_axis)
1029  {
1030  Rotation(out_mat, sinf(in_angle), cosf(in_angle), in_axis);
1031  }
1032 
1033  static void Rotation(AkMatrix3x3& out_mat, AkReal32 in_sin, AkReal32 in_cos, const Ak3DVector& in_axis)
1034  {
1035  Diagonal(out_mat, in_cos);
1036 
1037  AkMatrix3x3 outer;
1038  OuterProduct(outer, in_axis, in_axis);
1039  outer *= (1.f - in_cos);
1040  out_mat += outer;
1041 
1042  AkMatrix3x3 cross;
1043  CrossProductMatrix(cross, in_axis*in_sin);
1044  out_mat += cross;
1045  }
1046 
1047  // [column][row]
1048  AkReal32 m_Data[3][3];
1049 };
1050 
1052 {
1053 public:
1054  // Identity quaternion
1055  AkQuaternion(): W(1.f), X(0.f), Y(0.f), Z(0.f) {}
1056 
1057  AkQuaternion(AkReal32 in_W, AkReal32 in_X, AkReal32 in_Y, AkReal32 in_Z) :
1058  W(in_W),
1059  X(in_X),
1060  Y(in_Y),
1061  Z(in_Z)
1062  {}
1063 
1064  // Create a quaternion from a 3x3 rotation matrix
1066  {
1067  AkQuaternion q;
1068 
1069  AkReal32 trace = in_mat(0,0) + in_mat(1, 1) + in_mat(2, 2);
1070  if (trace > 0.0f)
1071  {
1072  AkReal32 srt = sqrtf(trace + 1.f);
1073  AkReal32 s = 0.5f / srt;
1074 
1075  q.W = 0.5f * srt;
1076  q.X = (in_mat(2, 1) - in_mat(1, 2)) * s;
1077  q.Y = (in_mat(0, 2) - in_mat(2, 0)) * s;
1078  q.Z = (in_mat(1, 0) - in_mat(0, 1)) * s;
1079 
1080  }
1081  else
1082  {
1083  // diagonal is negative
1084  AkUInt32 i = 0;
1085  if (in_mat(1, 1) > in_mat(0, 0))
1086  i = 1;
1087  if (in_mat(2, 2) > in_mat(i, i))
1088  i = 2;
1089 
1090  AkUInt32 j = (i + 1) % 3;
1091  AkUInt32 k = (i + 2) % 3;
1092 
1093  AkReal32 s = sqrtf( in_mat(i, i) - in_mat(j, j) - in_mat(k, k) + 1.0f );
1094  AkReal32 t = (s == 0.f) ? 0.f : (0.5f / s);
1095 
1096  AkReal32 qt[4];
1097 
1098  qt[i] = 0.5f * s;
1099  qt[j] = (in_mat(j, i) + in_mat(i, j)) * t;
1100  qt[k] = (in_mat(k, i) + in_mat(i, k)) * t;
1101  qt[3] = (in_mat(k, j) - in_mat(j, k)) * t;
1102 
1103  q.X = qt[0];
1104  q.Y = qt[1];
1105  q.Z = qt[2];
1106  q.W = qt[3];
1107  }
1108 
1109  return q;
1110  }
1111 
1112  // Create a rotation quaternion from euler angles.
1114  AkReal32 in_x, // Rotation around the X axis, in radians.
1115  AkReal32 in_y, // Rotation around the Y axis, in radians.
1116  AkReal32 in_z // Rotation around the Z axis, in radians.
1117  )
1118  {
1119  AkReal32 sy = sinf(in_z / 2.f);
1120  AkReal32 cy = cosf(in_z / 2.f);
1121  AkReal32 sp = sinf(in_y / 2.f);
1122  AkReal32 cp = cosf(in_y / 2.f);
1123  AkReal32 sr = sinf(in_x / 2.f);
1124  AkReal32 cr = cosf(in_x / 2.f);
1125 
1126  AkQuaternion q;
1127  q.W = cr * cp * cy + sr * sp * sy;
1128  q.X = sr * cp * cy - cr * sp * sy;
1129  q.Y = cr * sp * cy + sr * cp * sy;
1130  q.Z = cr * cp * sy - sr * sp * cy;
1131 
1132  return q;
1133  }
1134 
1135  static AkQuaternion FromAngleAndAxis(AkReal32 in_angle, const Ak3DVector& in_axis)
1136  {
1137  AkQuaternion q;
1138 
1139  AkReal32 sa = sinf(in_angle / 2.f);
1140  q.W = cosf(in_angle / 2.f);
1141  q.X = in_axis.X * sa;
1142  q.Y = in_axis.Y * sa;
1143  q.Z = in_axis.Z * sa;
1144 
1145  return q;
1146  }
1147 
1149  {
1150  return sqrtf( W*W + X*X + Y*Y + Z*Z );
1151  }
1152 
1154  {
1155  AkReal32 f = 1.0f / Length();
1156  W *= f;
1157  X *= f;
1158  Y *= f;
1159  Z *= f;
1160  return *this;
1161  }
1162 
1164  {
1165  AkReal32 norm = W*W + X*X + Y*Y + Z*Z;
1166  if (norm > 0.0)
1167  {
1168  AkReal32 invNorm = 1.0f / norm;
1169  return AkQuaternion(W*invNorm, -X*invNorm, -Y*invNorm, -Z*invNorm);
1170  }
1171  else
1172  {
1173  return AkQuaternion();
1174  }
1175  }
1176 
1177  // Create a quaternion representing the shortest arc rotation between (normalized) vectors v0, v1
1178  AkQuaternion(const Ak3DVector& in_v0, const Ak3DVector& in_v1)
1179  {
1180  AkReal32 dot = in_v0.Dot(in_v1);
1181  if (dot >= 1.0f - AKVECTORS_EPSILON)
1182  {
1183  // No rotation - return unity quaternion.
1184  AkQuaternion();
1185  }
1186  if (dot <= -1.f - AKVECTORS_EPSILON)
1187  {
1188  // 180 degree rotation - can use any non-zero length axis.
1189  Ak3DVector axis = Ak3DVector(0.f, 0.f, 1.f).Cross(in_v0);
1190  AkReal32 len = axis.Length();
1191  if (len < AKVECTORS_EPSILON)
1192  {
1193  axis = Ak3DVector(0.f, 1.f, 0.f).Cross(in_v0);
1194  len = axis.Length();
1195  }
1196  axis.Normalize();
1197  AkQuaternion(AKVECTORS_PI, axis);
1198  }
1199  else
1200  {
1201  AkReal32 sqrt = sqrtf((1.f + dot) * 2.f);
1202  AkReal32 invs = 1.f / sqrt;
1203 
1204  Ak3DVector cross = in_v0.Cross(in_v1);
1205 
1206  X = cross.X * invs;
1207  Y = cross.Y * invs;
1208  Z = cross.Z * invs;
1209  W = sqrt * 0.5f;
1210  Normalize();
1211  }
1212  }
1213 
1214  // Build quaternion from an axis and angle representation.
1215  AkQuaternion(AkReal32 in_angle, const Ak3DVector& in_axis)
1216  {
1217  AkReal32 cosHalfAngle = cosf(in_angle / 2.f);
1218  W = cosHalfAngle;
1219  X = cosHalfAngle*in_axis.X;
1220  Y = cosHalfAngle*in_axis.Y;
1221  Z = cosHalfAngle*in_axis.Z;
1222  }
1223 
1224  /// Quaternion multiplication.
1226  {
1227  return AkQuaternion(
1228  W*Q.W - X*Q.X - Y*Q.Y - Z*Q.Z,
1229  W*Q.X + X*Q.W + Y*Q.Z - Z*Q.Y,
1230  W*Q.Y - X*Q.Z + Y*Q.W + Z*Q.X,
1231  W*Q.Z + X*Q.Y - Y*Q.X + Z*Q.W);
1232  }
1233 
1235  {
1236  return RotateVector(in_v);
1237  }
1238 
1240  {
1241  /*
1242  // impl 1
1243  Ak3DVector uv, uuv;
1244  Ak3DVector qvec(X, Y, Z);
1245  uv = qvec.Cross(in_v);
1246  uuv = qvec.Cross(uv);
1247  uv *= (2.0f * W);
1248  uuv *= 2.0f;
1249  return in_v + uv + uuv;
1250  */
1251 
1252  // impl 2
1253  Ak3DVector32 u(X, Y, Z);
1254  Ak3DVector32 res =
1255  u * u.Dot(in_v) * 2.f
1256  + in_v * (W * W - u.Dot(u))
1257  + u.Cross(in_v) * W * 2.0f;
1258 
1259  return res;
1260  }
1261 
1263  {
1264  Ak3DVector32 u(-X, -Y, -Z);
1265  Ak3DVector32 t = 2.f * u.Cross(in_v);
1266  Ak3DVector32 res = in_v + (W * t) + u.Cross(t);
1267  return res;
1268  }
1269 
1274 };
1275 
1277 {
1280 };
1281 
1282 class AkLine
1283 {
1284 public:
1285  AkLine() :
1286  mint(1.175494351e-38F),
1287  maxt(3.402823466e+38F)
1288  {
1289  }
1290 
1291  AkLine(Ak3DVector in_L, Ak3DVector in_P) :
1292  L(in_L),
1293  P(in_P),
1294  mint(1.175494351e-38F),
1295  maxt(3.402823466e+38F)
1296  {
1297  }
1298 
1300  {
1301  return P + L*t;
1302  }
1303 
1305  {
1306  /*
1307  a (V1 X V2) = (P2 - P1) X V2
1308  If the lines intersect at a single point, then the resultant vectors
1309  on each side of this equation must be parallel, and the left side must
1310  not be the zero vector. We should check to make sure that this is
1311  true. Once we have checked this, we can solve for 'a' by taking the
1312  magnitude of each side and dividing. If the resultant vectors are
1313  parallel, but in opposite directions, then 'a' is the negative of the
1314  ratio of magnitudes. Once we have 'a' we can go back to the equation
1315  for L1 to find the intersection point.
1316  */
1317  Ak3DVector V1 = L;
1318  Ak3DVector V2 = B - A;
1319  Ak3DVector P1 = P;
1320  Ak3DVector P2 = A;
1321 
1322  // k(V1 X V2) = (A - P) X V2
1323 
1324  Ak3DVector v1CrossV2 = V1.Cross(V2);
1326  P2 - P1,
1327  V2,
1328  v1CrossV2
1329  );
1330  AkReal32 t = det / v1CrossV2.LengthSquared();
1331 
1332  det = Ak3DVector::Determinant(
1333  P2 - P1,
1334  V1,
1335  v1CrossV2
1336  );
1337  AkReal32 s = det / v1CrossV2.LengthSquared();
1338 
1339  AkReal32 distsqrd = ((P2 + V2*s) - (P1 + V1*t)).LengthSquared();
1340 
1341  if ((AkReal32)fabs(v1CrossV2.L2_Norm()) >= AKVECTORS_EPSILON
1342  && distsqrd < 0.001
1343  && s <= 1.0f )
1344  {
1345 #ifdef AKPORTALS_DEBUG
1346  Ak3DVector minPoint = PointAt(t);
1347 
1348  char msg[256];
1349  sprintf(msg, "L1a=[%0.2f,%0.2f,%0.2f];\n", P.X, P.Y, P.Z); AKPLATFORM::OutputDebugMsg(msg);
1350  sprintf(msg, "L1b=[%0.2f,%0.2f,%0.2f];\n", V1.X + P.X, V1.Y + P.Y, V1.Z + P.Z); AKPLATFORM::OutputDebugMsg(msg);
1351  sprintf(msg, "L2a=[%0.2f,%0.2f,%0.2f];\n", A.X, A.Y, A.Z); AKPLATFORM::OutputDebugMsg(msg);
1352  sprintf(msg, "L2b=[%0.2f,%0.2f,%0.2f];\n", B.X, B.Y, B.Z); AKPLATFORM::OutputDebugMsg(msg);
1353  sprintf(msg, "%% t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
1354  sprintf(msg, "intrPoint=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
1355  sprintf(msg, "\n"); AKPLATFORM::OutputDebugMsg(msg);
1356 #endif
1357 
1358  mint = AkMin(mint, t);
1359  maxt = AkMax(maxt, t);
1360 
1361  return true;
1362  }
1363 
1364 #ifdef AKPORTALS_DEBUG
1365  // char msg[256];
1366  // sprintf(msg, "%% DISCARTED t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
1367 #endif
1368  return false;
1369  }
1370 
1373 
1376 };
1377 
1378 class AkPlane
1379 {
1380 public:
1381  AkPlane() = default;
1382 
1384  Ak3DVector in_p1,
1385  Ak3DVector in_p2,
1386  Ak3DVector in_p4)
1387  {
1388  SetPlane(
1389  in_p1,
1390  in_p2,
1391  in_p4);
1392  }
1393 
1394  void SetPlane(
1395  Ak3DVector in_p1,
1396  Ak3DVector in_p2,
1397  Ak3DVector in_p4)
1398  {
1399  // Reorder A-B-C to clockwwise if necessary
1400  AKASSERT(in_p1.X < 100000 && in_p1.X > -100000);
1401  AKASSERT(in_p1.Y < 100000 && in_p1.Y > -100000);
1402  AKASSERT(in_p1.Z < 100000 && in_p1.Z > -100000);
1403 
1404  AKASSERT(in_p2.X < 100000 && in_p2.X > -100000);
1405  AKASSERT(in_p2.Y < 100000 && in_p2.Y > -100000);
1406  AKASSERT(in_p2.Z < 100000 && in_p2.Z > -100000);
1407 
1408  AKASSERT(in_p4.X < 100000 && in_p4.X > -100000);
1409  AKASSERT(in_p4.Y < 100000 && in_p4.Y > -100000);
1410  AKASSERT(in_p4.Z < 100000 && in_p4.Z > -100000);
1411 
1412  p1 = in_p1;
1413  p2 = in_p2;
1414  p4 = in_p4;
1415 
1416  SetNormal();
1417 
1418  // Ax + By + Cz + D = 0
1419  // Find D using the normal and a point
1420  D = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
1421  }
1422 
1423 #define EPSILON 0.01f
1425  const Ak3DVector& in_Origin,
1426  const Ak3DVector& in_Destination,
1427  Ak3DVector& out_Intersection
1428  ) const
1429  {
1430  AkReal32 A = N.X;
1431  AkReal32 B = N.Y;
1432  AkReal32 C = N.Z;
1433 
1434  Ak3DVector ray = in_Destination - in_Origin;
1435  AkReal32 rayLength = ray.Length();
1436 
1437  Ak3DVector intersect;
1438 
1439  // If ray is < EPSILON, use on of the point directly for the test and skip the linear projection
1440  if (rayLength <= EPSILON)
1441  {
1442  Ak3DVector temp = in_Origin - p1;
1443  AkReal32 dot = temp.DotProduct(N);
1444  if (dot < EPSILON && dot > -EPSILON)
1445  {
1446  intersect = in_Origin;
1447  }
1448  else
1449  {
1450  // For debug only, to remove
1451  out_Intersection = p1;
1452  return false;
1453  }
1454 
1455  }
1456  else
1457  {
1458  // Normalize ray
1459  ray.Normalize();
1460 
1461  // 1) if ray len ~= 0, only check if one of the point is on target, ie: assign the intersect point
1462 
1463  // Is ray parallel to the plane?
1464  if ((A*ray.X + B*ray.Y + C*ray.Z) == 0.0f)
1465  {
1466  // For debug only, to remove
1467  AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
1468  intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
1469  out_Intersection = intersect; // For debugging
1470  return false;
1471  }
1472 
1473 
1474  // Distance along the ray where reflector is hit
1475  AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
1476 
1477  // Is the ray going towards the plane? Is it long enough?
1478  if (t < -EPSILON || t >(rayLength + EPSILON))
1479  {
1480  // For debug only, to remove
1481  intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
1482  out_Intersection = intersect; // For debugging
1483  return false; // The ray doesn't intersect
1484  }
1485 
1486  // Find the coordinate of intersection on the plane
1487  intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
1488  }
1489  ///////////////////////////////////////
1490  //
1491  // p2____v3____p3
1492  // | . |
1493  // ^ inter v4
1494  // v1 v
1495  // | |
1496  // p1__ v2>___p4
1497 
1498  Ak3DVector v1 = p2 - p1;
1499  Ak3DVector v2 = p4 - p1;
1500  Ak3DVector vInter1 = intersect - p1;
1501 
1502  Ak3DVector p3 = p4 + v1;
1503  Ak3DVector v3 = p2 - p3;
1504  Ak3DVector v4 = p4 - p3;
1505  Ak3DVector vInter2 = intersect - p3;
1506 
1507  v1.Normalize(); v2.Normalize(); v3.Normalize(); v4.Normalize(); vInter1.Normalize(); vInter2.Normalize();
1508 
1509  // Since it's a square, the angle between the point of intersection and any segment of the pannel should be < 90 degree,
1510  // therefore the dot product of the two normalized vectors should be > 0
1511  AkReal32 dot1 = v1.DotProduct(vInter1);
1512  AkReal32 dot2 = v2.DotProduct(vInter1);
1513  AkReal32 dot3 = v3.DotProduct(vInter2);
1514  AkReal32 dot4 = v4.DotProduct(vInter2);
1515 
1516  out_Intersection = intersect;
1517 
1518  return dot1 >= -EPSILON && dot2 >= -EPSILON && dot3 >= -EPSILON && dot4 >= -EPSILON;
1519  }
1520 
1522  Ak3DVector in_P,
1523  Ak3DVector& out_B) const
1524  {
1525  AkReal32 distance = (AkReal32)(AkReal32)fabs(N.X * in_P.X + N.Y * in_P.Y + N.Z * in_P.Z + D);
1526 
1527  Ak3DVector pointToPlane = N;
1528  pointToPlane *= distance;
1529 
1530  out_B = in_P + pointToPlane;
1531 
1532  return (AkReal32)fabs(distance);
1533  }
1534 
1536  AkReal32* out_mat) const
1537  {
1538  // http://ami.ektf.hu/uploads/papers/finalpdf/AMI_40_from175to186.pd
1539  /* m_pReflectionMatrix
1540  reflection on z axis
1541 
1542  P0 (x0, y0, z0), P1 (x1, y1, z1) and P2 (x2, y2, z2),
1543  normal = (cx, cy, cz)
1544  d = -CxX0 - CyY0 - CzZ0
1545 
1546  Reflect = 1-2Cx^2 -2CxCy -2CxCz -2Cxd
1547  -2CxCy 1-2Cy^2 -2CyCz -2Cyd
1548  -2CxCz -2CyCz 1-2Cz^2 -2Czd
1549  0 0 0 1
1550  */
1551 
1552  AkReal32 d = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
1553 
1554  out_mat[0] = 1 - 2 * N.X*N.X; out_mat[1] = -2 * N.X*N.Y; out_mat[2] = -2 * N.X*N.Z; out_mat[3] = -2 * N.X*d;
1555  out_mat[0 + 4] = -2 * N.X*N.Y; out_mat[1 + 4] = 1 - 2 * N.Y*N.Y; out_mat[2 + 4] = -2 * N.Y*N.Z; out_mat[3 + 4] = -2 * N.Y*d;
1556  out_mat[0 + 8] = -2 * N.X*N.Z; out_mat[1 + 8] = -2 * N.Y*N.Z; out_mat[2 + 8] = 1 - 2 * N.Z*N.Z; out_mat[3 + 8] = -2 * N.Z*d;
1557  out_mat[0 + 12] = 0; out_mat[1 + 12] = 0; out_mat[2 + 12] = 0; out_mat[3 + 12] = 1;
1558  }
1559 
1560  Ak3DVector GetN() const { return N; }
1561  AkReal32 GetD() const { return D; }
1562 
1564  const AkPlane& in_PlaneB,
1565  AkIntersectionPoints& out_Intrs) const
1566  {
1567  out_Intrs.count = 0;
1568 
1569  // Use vector to solve A
1570 
1571  Ak3DVector point;
1572 
1573  Ak3DVector N1 = N;
1574  Ak3DVector N2 = in_PlaneB.GetN();
1575  AkReal32 D1 = D;
1576  AkReal32 D2 = in_PlaneB.GetD();
1577 
1578  Ak3DVector L = N1.Cross(N2);
1579  if (L.Length() < 0.001f)
1580  {
1581  return false; // The two planes are parallel
1582  }
1583 
1584  AkUInt8 pivotAxis = 0;
1585 
1586  if ((AkReal32)fabs(L.Y) > (AkReal32)fabs(L.X))
1587  {
1588  pivotAxis = 1;
1589  if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.Y))
1590  {
1591  pivotAxis = 2;
1592  }
1593  }
1594  else if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.X))
1595  {
1596  pivotAxis = 2;
1597  }
1598 
1599  /*
1600  Pu = ( N1v*D2 - N2v*D1 ) / Lw
1601  Pv = ( N2u*D1 - N1u*D2 ) / Lw
1602  Pz = 0
1603  */
1604 
1605  switch (pivotAxis)
1606  {
1607  case 0:
1608  AKASSERT((AkReal32)fabs(L.X) > AKVECTORS_EPSILON);
1609  point.X = 0.f;
1610  point.Y = (N1.Z*D2 - N2.Z*D1) / L.X;
1611  point.Z = (N2.Y*D1 - N1.Y*D2) / L.X;
1612  break;
1613  case 1:
1614  AKASSERT((AkReal32)fabs(L.Y) > AKVECTORS_EPSILON);
1615  point.X = (N1.Z*D2 - N2.Z*D1) / L.Y;
1616  point.Y = 0.f;
1617  point.Z = (N2.X*D1 - N1.X*D2) / L.Y;
1618  break;
1619  case 2:
1620  AKASSERT((AkReal32)fabs(L.Z) > AKVECTORS_EPSILON);
1621  point.X = (N1.Y*D2 - N2.Y*D1) / L.Z;
1622  point.Y = (N2.X*D1 - N1.X*D2) / L.Z;
1623  point.Z = 0.f;
1624  break;
1625  };
1626 
1627 
1628 
1629  L.Normalize();
1630 
1631  AkLine intrLine = AkLine(L, point);
1632  AkLine intrLine2 = AkLine(L, point);
1633 
1634  //in_PlaneB.GetP1()
1635 
1636  // find min max
1637  AkUInt32 cpt = 0;
1638  AkUInt32 cpt2 = 0;
1639  Ak3DVector p3 = GetP2() + (GetP4() - GetP1());
1640 
1641 #ifdef AKPORTALS_DEBUG
1642  char msg[256];
1643  sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
1644  sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
1645  sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
1646 
1647  sprintf(msg, "P1b=[%0.2f,%0.2f,%0.2f];\n", in_PlaneB.GetP1().X, in_PlaneB.GetP1().Y, in_PlaneB.GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
1648  sprintf(msg, "P2b=[%0.2f,%0.2f,%0.2f];\n", in_PlaneB.GetP2().X, in_PlaneB.GetP2().Y, in_PlaneB.GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
1649  sprintf(msg, "P4b=[%0.2f,%0.2f,%0.2f];\n", in_PlaneB.GetP4().X, in_PlaneB.GetP4().Y, in_PlaneB.GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
1650 
1651  sprintf(msg, "line1=[%0.2f,%0.2f,%0.2f];\n", point.X + L.X*1000.f, point.Y + L.Y*1000.f, point.Z + L.Z*1000.f); AKPLATFORM::OutputDebugMsg(msg);
1652  sprintf(msg, "line2=[%0.2f,%0.2f,%0.2f];\n", point.X - L.X*1000.f, point.Y - L.Y*500.f, point.Z - L.Z*500.f); AKPLATFORM::OutputDebugMsg(msg);
1653 
1654 
1655  sprintf(msg, "%% Plane intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
1656 #endif
1657  // for the four lines in rectangle
1658  // Find where the line is crossing with plane A
1659  if (intrLine.Intersect(GetP1(), GetP2())) cpt++;
1660  if (intrLine.Intersect(GetP1(), GetP4())) cpt++;
1661  if (intrLine.Intersect(GetP2(), p3)) cpt++;
1662  if (intrLine.Intersect(p3, GetP4())) cpt++;
1663  //AKASSERT(cpt == 2);
1664 
1665 #ifdef AKPORTALS_DEBUG
1666  sprintf(msg, "%% Portal intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
1667 #endif
1668 
1669  // Find where the line is crossing with plane B
1670  p3 = in_PlaneB.GetP2() + (in_PlaneB.GetP4() - in_PlaneB.GetP1());
1671  if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP2())) cpt2++;
1672  if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP4())) cpt2++;
1673  if (intrLine2.Intersect(in_PlaneB.GetP2(), p3)) cpt2++;
1674  if (intrLine2.Intersect(p3, in_PlaneB.GetP4())) cpt2++;
1675  // **AKASSERT(cpt2 == 2 || cpt == 2);
1676 
1677  if (cpt < 2 || cpt2 < 2)
1678  {
1679 #ifdef AKPORTALS_DEBUG
1680  sprintf(msg, "%% NON \n"); AKPLATFORM::OutputDebugMsg(msg);
1681  sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
1682 #endif
1683  return false;
1684  }
1685 
1686  AkReal32 start = AkMax(intrLine.mint, intrLine2.mint);
1687  AkReal32 end = AkMin(intrLine.maxt, intrLine2.maxt);
1688 
1689  Ak3DVector minPoint = intrLine.PointAt(start);
1690  Ak3DVector maxPoint = intrLine.PointAt(end);
1691 #ifdef AKPORTALS_DEBUG
1692  sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
1693  sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
1694  sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
1695 
1696  sprintf(msg, "P1b=[%0.2f,%0.2f,%0.2f];\n", in_PlaneB.GetP1().X, in_PlaneB.GetP1().Y, in_PlaneB.GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
1697  sprintf(msg, "P2b=[%0.2f,%0.2f,%0.2f];\n", in_PlaneB.GetP2().X, in_PlaneB.GetP2().Y, in_PlaneB.GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
1698  sprintf(msg, "P4b=[%0.2f,%0.2f,%0.2f];\n", in_PlaneB.GetP4().X, in_PlaneB.GetP4().Y, in_PlaneB.GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
1699 
1700  sprintf(msg, "line1=[%0.2f,%0.2f,%0.2f];\n", point.X + L.X*1000.f, point.Y + L.Y*1000.f, point.Z + L.Z*1000.f); AKPLATFORM::OutputDebugMsg(msg);
1701  sprintf(msg, "line2=[%0.2f,%0.2f,%0.2f];\n", point.X - L.X*1000.f, point.Y - L.Y*500.f, point.Z - L.Z*500.f); AKPLATFORM::OutputDebugMsg(msg);
1702 
1703  sprintf(msg, "intr1=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
1704  sprintf(msg, "intr2=[%0.2f,%0.2f,%0.2f];\n", maxPoint.X, maxPoint.Y, maxPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
1705 
1706  sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
1707 #endif
1708  out_Intrs.points[0] = minPoint;
1709  out_Intrs.points[1] = maxPoint;
1710  out_Intrs.count = 2;
1711 
1712  return true;
1713  }
1714 
1715  Ak3DVector GetP1() const { return p1; }
1716  Ak3DVector GetP2() const { return p2; }
1717  Ak3DVector GetP4() const { return p4; }
1718 
1719 private:
1720  bool SetNormal()
1721  {
1722  //m_pNormal = (B-A) cross (C-A); normalize
1723  Ak3DVector a = p2 - p1;
1724  Ak3DVector b = p4 - p1;
1725 
1726  N = Ak3DVector(a.Y*b.Z - a.Z*b.Y, -(a.X*b.Z - a.Z*b.X), a.X*b.Y - a.Y*b.X);
1727 
1728  AkReal32 len = N.Length();
1729  AKASSERT(len > 0.f);
1730 
1731  if (len > 0)
1732  {
1733  N /= len;
1734  }
1735  else
1736  {
1737  return false;
1738  }
1739 
1740  return true;
1741  };
1742 
1743  /*
1744  p2__________p3
1745  | . |
1746  ^ inter v3
1747  v1 v
1748  | |
1749  p1__ v2>___p4
1750  */
1751 
1752  Ak3DVector p1; // Bottom left
1753  Ak3DVector p2; // Top left
1754  Ak3DVector p4; // Tottom right
1755  Ak3DVector N; // Normal vector
1756  AkReal32 D; // Plane equation: Ax + By + Cz = D => N.Xx + N.Yy + N.Zz = D
1757 };
1758 
1759 template<typename TReal>
1761 {
1763 
1764  TBoundingBox(const TVectorType& in_min, const TVectorType& in_max) :
1765  m_Min(in_min),
1766  m_Max(in_max)
1767  {}
1768 
1770  m_Min(TVectorType(RealPrecision<TReal>::MAX_VALUE, RealPrecision<TReal>::MAX_VALUE, RealPrecision<TReal>::MAX_VALUE)),
1771  m_Max(TVectorType(-RealPrecision<TReal>::MAX_VALUE, -RealPrecision<TReal>::MAX_VALUE, -RealPrecision<TReal>::MAX_VALUE))
1772  {}
1773 
1774  void Update(const TVectorType& in_point)
1775  {
1776  if (m_Min.X > in_point.X)
1777  m_Min.X = in_point.X;
1778 
1779  if (m_Min.Y > in_point.Y)
1780  m_Min.Y = in_point.Y;
1781 
1782  if (m_Min.Z > in_point.Z)
1783  m_Min.Z = in_point.Z;
1784 
1785  if (m_Max.X < in_point.X)
1786  m_Max.X = in_point.X;
1787 
1788  if (m_Max.Y < in_point.Y)
1789  m_Max.Y = in_point.Y;
1790 
1791  if (m_Max.Z < in_point.Z)
1792  m_Max.Z = in_point.Z;
1793  }
1794 
1795  AkForceInline bool IsWithin(const TVectorType& in_Point) const
1796  {
1797  return in_Point >= m_Min && in_Point <= m_Max;
1798  }
1799 
1800  AkForceInline bool IsWithin(const TBoundingBox& in_BB) const
1801  {
1802  return (m_Min.X <= in_BB.m_Max.X && m_Max.X >= in_BB.m_Min.X) &&
1803  (m_Min.Y <= in_BB.m_Max.Y && m_Max.Y >= in_BB.m_Min.Y) &&
1804  (m_Min.Z <= in_BB.m_Max.Z && m_Max.Z >= in_BB.m_Min.Z);
1805  }
1806 
1807  TBoundingBox Intersect(const TBoundingBox& in_BB) const
1808  {
1809  TBoundingBox result;
1810 
1811  result.m_Max.X = AkMin(m_Max.X, in_BB.m_Max.X);
1812  result.m_Max.Y = AkMin(m_Max.Y, in_BB.m_Max.Y);
1813  result.m_Max.Z = AkMin(m_Max.Z, in_BB.m_Max.Z);
1814 
1815  result.m_Min.X = AkMax(m_Min.X, in_BB.m_Min.X);
1816  result.m_Min.Y = AkMax(m_Min.Y, in_BB.m_Min.Y);
1817  result.m_Min.Z = AkMax(m_Min.Z, in_BB.m_Min.Z);
1818 
1819  return result;
1820  }
1821 
1822  AkForceInline bool IsEmpty() const
1823  {
1824  return (m_Min.X >= m_Max.X) || (m_Min.Y >= m_Max.Y) || (m_Min.Z >= m_Max.Z);
1825  }
1826 
1827  AkForceInline bool IsValid() const
1828  {
1829  return (m_Min.X <= m_Max.X) && (m_Min.Y <= m_Max.Y) && (m_Min.Z <= m_Max.Z);
1830  }
1831 
1834 };
1835 
1838 
1839 class AkBox
1840 {
1841 public:
1842  AkBox() = default;
1843 
1844  void Init(
1845  const Ak3DVector& in_center,
1846  const Ak3DVector& in_extent,
1847  const Ak3DVector& in_Front,
1848  const Ak3DVector& in_Up)
1849  {
1850  AKASSERT(fabs(in_Front.Length() - 1.f) < 0.001 && fabs(in_Up.Length() - 1.f) < 0.001);//Must be unit vectors.
1851  AKASSERT(fabs(in_Front.Dot(in_Up) - 0.f) < 0.001); //Must be orthogonal.
1852 
1853  m_Center = in_center;
1854  m_Extent = in_extent;
1855 
1856  m_Z = in_Front;
1857  m_Y = in_Up;
1858  m_X = m_Z.Cross(m_Y);
1859  }
1860 
1861  bool IsPointInBox(const Ak3DVector& in_Point) const
1862  {
1863  Ak3DVector pt = in_Point - m_Center;
1864  return fabs(pt.Dot(m_X)) <= m_Extent.X && fabs(pt.Dot(m_Y)) <= m_Extent.Y && fabs(pt.Dot(m_Z)) <= m_Extent.Z;
1865  }
1866 
1867  Ak3DVector GetSize() const { return m_Extent*2.f; }
1868  Ak3DVector GetCenter() const { return m_Center; }
1869 
1870  Ak3DVector GetUx() const { return m_X; }
1871  Ak3DVector GetUy() const { return m_Y; }
1872  Ak3DVector GetUz() const { return m_Z; }
1873 
1874  Ak3DVector GetFront() const { return m_Z; }
1875  Ak3DVector GetUp() const { return m_Y; }
1876  Ak3DVector GetSide() const { return m_X; }
1877 
1879  {
1880  Ak3DVector size = GetSize();
1881  return size.X * size.Y * size.Z;
1882  }
1883 
1885  const Ak3DVector& L,
1886  const AkBox& B) const
1887  {
1888  // Separating Axis Theorem for Oriented Bounding Boxes by Johnny Huynh
1889  const AkBox& A = *this;
1890  Ak3DVector T = B.GetCenter() - A.GetCenter();
1891 
1892  AkReal32 WA = A.m_Extent.X;
1893  AkReal32 HA = A.m_Extent.Y;
1894  AkReal32 DA = A.m_Extent.Z;
1895 
1896  AkReal32 WB = B.m_Extent.X;
1897  AkReal32 HB = B.m_Extent.Y;
1898  AkReal32 DB = B.m_Extent.Z;
1899 
1900  Ak3DVector Ax = A.GetUx();
1901  Ak3DVector Ay = A.GetUy();
1902  Ak3DVector Az = A.GetUz();
1903 
1904  Ak3DVector Bx = B.GetUx();
1905  Ak3DVector By = B.GetUy();
1906  Ak3DVector Bz = B.GetUz();
1907 
1908  /*
1909  | T • L | > | (WA*Ax) • L | + | (HA*Ay) • L | + |(DA*Az) • L | +
1910  | (WB*Bx) • L | +| (HB*By) • L | +| (DB*Bz) • L |*/
1911 
1912  AkReal32 left = (AkReal32)fabs(T.DotProduct(L));
1913  AkReal32 dpax = (AkReal32)fabs((Ax*WA).DotProduct(L));
1914  AkReal32 dpay = (AkReal32)fabs((Ay*HA).DotProduct(L));
1915  AkReal32 dpaz = (AkReal32)fabs((Az*DA).DotProduct(L));
1916  AkReal32 dpbx = (AkReal32)fabs((Bx*WB).DotProduct(L));
1917  AkReal32 dpby = (AkReal32)fabs((By*HB).DotProduct(L));
1918  AkReal32 dpbz = (AkReal32)fabs((Bz*DB).DotProduct(L));
1919 
1920  AkReal32 right = dpax + dpay + dpaz + dpbx + dpby + dpbz;
1921 
1922  return left > right;
1923  }
1924 
1925  void UpdateBoundingBox(AkBoundingBox& out_aabb) const
1926  {
1927  Ak3DVector x = m_X * m_Extent.X;
1928  out_aabb.Update(m_Center + x);
1929  out_aabb.Update(m_Center - x);
1930  Ak3DVector y = m_Y * m_Extent.Y;
1931  out_aabb.Update(m_Center + y);
1932  out_aabb.Update(m_Center - y);
1933  Ak3DVector Z = m_Z * m_Extent.Z;
1934  out_aabb.Update(m_Center + Z);
1935  out_aabb.Update(m_Center - Z);
1936  }
1937 
1938 private:
1939 
1940  Ak3DVector m_Center;
1941  Ak3DVector m_Extent;
1942 
1943  //Orthonormal Axes
1944  Ak3DVector m_X;
1945  Ak3DVector m_Y;
1946  Ak3DVector m_Z;
1947 };
AkMatrix3x3 & operator/=(const AkReal32 f)
Definition: AkVectors.h:952
AkForceInline T3DVector & operator*=(const TDataType f)
Definition: AkVectors.h:367
AkForceInline AkQuaternion & Normalize()
Definition: AkVectors.h:1153
#define AkMin(x1, x2)
T3DVector< AkReal32 > Ak3DVector
Definition: AkVectors.h:690
TDataType X
Definition: AkVectors.h:665
bool FindIntersectionPoints(const AkPlane &in_PlaneB, AkIntersectionPoints &out_Intrs) const
Definition: AkVectors.h:1563
T3DVector(const AkVector &in_vector)
Definition: AkVectors.h:249
AkReal32 DistPoint_to_Plane(Ak3DVector in_P, Ak3DVector &out_B) const
Definition: AkVectors.h:1521
#define AKVECTORS_TWOPI
Definition: AkVectors.h:46
Ak3DVector GetUz() const
Definition: AkVectors.h:1872
T3DVector(TDataType in_x, TDataType in_y, TDataType in_z)
Definition: AkVectors.h:230
AkForceInline T3DVector Abs() const
Definition: AkVectors.h:648
AkInt32 Y
Y Position.
Definition: AkVectors.h:121
static AkReal64 ACos(AkReal64 in_value)
Definition: AkVectors.h:162
Ak3DVector points[2]
Definition: AkVectors.h:1278
AkForceInline bool operator==(const T3DVector &b) const
Definition: AkVectors.h:337
AkForceInline bool IsWithin(const TBoundingBox &in_BB) const
Definition: AkVectors.h:1800
AkPlane()=default
AkForceInline Ak2DVector operator=(const Ak2DVector &b)
Definition: AkVectors.h:726
TBoundingBox< AkReal32 > AkBoundingBox
Definition: AkVectors.h:1836
T3DVector< AkReal64 > Ak3DVector64
Definition: AkVectors.h:694
#define AKVECTORS_PI
Definition: AkVectors.h:45
#define AkMax(x1, x2)
Ak3DVector GetN() const
Definition: AkVectors.h:1560
Ak3DVector PointAt(AkReal32 t) const
Definition: AkVectors.h:1299
bool Intersect(Ak3DVector A, Ak3DVector B)
Definition: AkVectors.h:1304
AkReal32 phi
Elevation.
Definition: AkTypes.h:747
AkReal32 X
Definition: AkVectors.h:1271
Ak4DVector operator-(const Ak4DVector &b) const
Definition: AkVectors.h:93
bool SeparatingAxisExists(const Ak3DVector &L, const AkBox &B) const
Definition: AkVectors.h:1884
AkSafeConversion TTypeConverter
Definition: AkVectors.h:217
bool IsPointInBox(const Ak3DVector &in_Point) const
Definition: AkVectors.h:1861
TDataType Y
Definition: AkVectors.h:666
static AkReal64 Cos(AkReal64 in_value)
Definition: AkVectors.h:159
static bool IsFinite(AkReal64 in_val)
Definition: AkVectors.h:163
AkForceInline AkQuaternion Inverse() const
Definition: AkVectors.h:1163
AkForceInline AkQuaternion operator*(const AkQuaternion &Q) const
Quaternion multiplication.
Definition: AkVectors.h:1225
Ak4DVector & operator/=(const AkReal32 f)
Definition: AkVectors.h:83
Ak3DIntVector(AkInt32 x, AkInt32 y, AkInt32 z)
Definition: AkVectors.h:113
static AkQuaternion FromRotationMatrix(const AkMatrix3x3 &in_mat)
Definition: AkVectors.h:1065
void SetPlane(Ak3DVector in_p1, Ak3DVector in_p2, Ak3DVector in_p4)
Definition: AkVectors.h:1394
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
AkMatrix4x4()=default
static AkForceInline void Diagonal(AkMatrix3x3 &out_mat, AkReal32 in_f)
Definition: AkVectors.h:1006
T3DVector(TDataType in_scalar)
Definition: AkVectors.h:294
AkForceInline bool IsEmpty() const
Definition: AkVectors.h:1822
T3DVector< AkReal32 > Ak3DVector32
Definition: AkVectors.h:691
static void Rotation(AkMatrix3x3 &out_mat, AkReal32 in_sin, AkReal32 in_cos, const Ak3DVector &in_axis)
Definition: AkVectors.h:1033
float32x4_t AKSIMD_V4F32
Vector of 4 32-bit floats.
Definition: AkSimdTypes.h:62
AkForceInline bool operator==(const Ak2DVector &b) const
Definition: AkVectors.h:769
Ak3DVector GetUx() const
Definition: AkVectors.h:1870
uint8_t AkUInt8
Unsigned 8-bit integer.
void UpdateBoundingBox(AkBoundingBox &out_aabb) const
Definition: AkVectors.h:1925
static AkReal64 Sqrt(AkReal64 in_value)
Definition: AkVectors.h:161
Ak3DVector GetCenter() const
Definition: AkVectors.h:1868
static AkForceInline TDataType Determinant(const T3DVector &a, const T3DVector &b, const T3DVector &c)
Definition: AkVectors.h:539
float AkReal32
32-bit floating point
Ak2DVector & operator/=(const AkReal32 f)
Definition: AkVectors.h:760
AkForceInline T3DVector LinearCombination(const T3DVector &A, const T3DVector &B, const T3DVector &C) const
Definition: AkVectors.h:549
static AkReal32 Sqrt(AkReal32 in_value)
Definition: AkVectors.h:141
AkReal32 X
Definition: AkVectors.h:885
int32_t AkInt32
Signed 32-bit integer.
AkReal32 maxt
Definition: AkVectors.h:1375
static AkMatrix3x3 FromColumnVectors(const Ak3DVector &in_col0, const Ak3DVector &in_col1, const Ak3DVector &in_col2)
Definition: AkVectors.h:931
TBoundingBox Intersect(const TBoundingBox &in_BB) const
Definition: AkVectors.h:1807
Ak2DVector()=default
AkForceInline TDataType DotProduct(const T3DVector &v2) const
Definition: AkVectors.h:607
AkForceInline T3DVector operator-(const T3DVector &b) const
Definition: AkVectors.h:465
AkForceInline T3DVector & operator/=(const TDataType f)
Definition: AkVectors.h:376
AkForceInline T3DVector operator*(const T3DVector v2) const
Definition: AkVectors.h:386
#define AKVECTORS_PIOVERTWO
Definition: AkVectors.h:47
AkForceInline bool IsFinite() const
Definition: AkVectors.h:657
Ak4DVector & operator=(const Ak4DVector &b)
Definition: AkVectors.h:73
AkForceInline bool operator!=(const Ak2DVector &b) const
Definition: AkVectors.h:774
AkForceInline void Convert(AkReal64 &out_to, AkReal32 in_from)
Definition: AkVectors.h:194
AkForceInline bool IsAllPositive() const
Definition: AkVectors.h:878
AkForceInline AkReal32 Length() const
Definition: AkVectors.h:779
Ak4DVector()
Definition: AkVectors.h:55
Ak3DVector GetSide() const
Definition: AkVectors.h:1876
AkLine()
Definition: AkVectors.h:1285
AkReal32 Y
Y Position.
Definition: AkTypes.h:423
Ak2DVector(AkReal32 x, AkReal32 y)
Definition: AkVectors.h:718
static AkReal64 Sin(AkReal64 in_value)
Definition: AkVectors.h:160
AkForceInline AkMatrix3x3 & operator*=(const AkReal32 &in_f)
Definition: AkVectors.h:998
AkMatrix4x4 & operator=(AkReal32 *in_Data)
Definition: AkVectors.h:910
void Update(const TVectorType &in_point)
Definition: AkVectors.h:1774
static AkQuaternion FromAngleAndAxis(AkReal32 in_angle, const Ak3DVector &in_axis)
Definition: AkVectors.h:1135
AkForceInline TDataType LengthSquared() const
Definition: AkVectors.h:635
AkReal32 GetVolume() const
Definition: AkVectors.h:1878
AkReal32 GetD() const
Definition: AkVectors.h:1561
AkForceInline TDataType Dot(const T3DVector &v2) const
Definition: AkVectors.h:612
AkReal32 X
X Position.
Definition: AkTypes.h:422
TDataType data_type
Definition: AkVectors.h:214
AkForceInline bool operator!=(const T3DVector &b) const
Definition: AkVectors.h:342
Ak2DVector operator-(const Ak2DVector &b) const
Definition: AkVectors.h:742
#define AKSIMD_GETELEMENT_V4F32(__vName, __num__)
Get the element at index num in vector __vName.
Definition: AkSimd.h:37
AkReal32 m_Data[MAX_SIZE]
Definition: AkVectors.h:920
AkForceInline T3DVector operator+(const TDataType f) const
Definition: AkVectors.h:432
AkForceInline T3DVector< TDataType > operator*(const TDataType f, const T3DVector< TDataType > &v)
Definition: AkVectors.h:671
#define AKASSERT(Condition)
Definition: AkAssert.h:67
AkForceInline T3DVector operator-(const TDataType f) const
Definition: AkVectors.h:443
AkReal32 v[4]
Definition: AkVectors.h:105
Spherical coordinates.
Definition: AkTypes.h:746
static AkForceInline T3DVector Min(const T3DVector &A, const T3DVector &B)
Definition: AkVectors.h:486
AkForceInline T3DVector SphericalToCartesian(const TDataType azimuth, const TDataType elevation)
Definition: AkVectors.h:526
AkReal32 mint
Definition: AkVectors.h:1374
AkForceInline AKSIMD_V4F32 PointV4F32() const
Definition: AkVectors.h:308
AkMatrix3x3()=default
AkReal32 Z
Z Position.
Definition: AkTypes.h:424
static AkForceInline void OuterProduct(AkMatrix3x3 &out_mat, const Ak3DVector &in_v0, const Ak3DVector &in_v1)
Definition: AkVectors.h:1021
AkForceInline void Convert(TReal &out_to, TReal in_from)
Definition: AkVectors.h:199
Ak3DVector GetFront() const
Definition: AkVectors.h:1874
Ak3DVector GetUy() const
Definition: AkVectors.h:1871
AkForceInline T3DVector operator+(const T3DVector &b) const
Definition: AkVectors.h:454
AkReal32 Y
Definition: AkVectors.h:886
static AkForceInline void Add(AkMatrix3x3 &out_res, const AkMatrix3x3 &in_m0, const AkMatrix3x3 &in_m1)
Definition: AkVectors.h:989
TVectorType Cast() const
Definition: AkVectors.h:701
AkMatrix4x4 & operator/=(const AkReal32 f)
Definition: AkVectors.h:902
TBoundingBox< AkReal64 > AkBoundingBox64
Definition: AkVectors.h:1837
Ak3DIntVector()=default
AkForceInline Ak3DVector UnrotateVector(const Ak3DVector32 &in_v) const
Definition: AkVectors.h:1262
AkForceInline AkReal32 & operator()(const AkUInt32 row, const AkUInt32 column)
Definition: AkVectors.h:964
AkReal32 W
Definition: AkVectors.h:1270
AkQuaternion(AkReal32 in_angle, const Ak3DVector &in_axis)
Definition: AkVectors.h:1215
AkForceInline T3DVector< TDataType > operator/(const TDataType f, const T3DVector< TDataType > &v)
Definition: AkVectors.h:677
AkLine(Ak3DVector in_L, Ak3DVector in_P)
Definition: AkVectors.h:1291
static AkQuaternion FromEulers(AkReal32 in_x, AkReal32 in_y, AkReal32 in_z)
Definition: AkVectors.h:1113
double AkReal64
64-bit floating point
static AkForceInline void CrossProductMatrix(AkMatrix3x3 &out_mat, const Ak3DVector &in_u)
Definition: AkVectors.h:1014
bool DoesRayIntersect(const Ak3DVector &in_Origin, const Ak3DVector &in_Destination, Ak3DVector &out_Intersection) const
Definition: AkVectors.h:1424
Ak3DVector P
Definition: AkVectors.h:1372
AkReal32 Z
Definition: AkVectors.h:1273
AkForceInline Ak3DVector32 operator*(const Ak3DVector32 &in_v) const
Definition: AkVectors.h:1234
AkBox()=default
AkForceInline bool operator<(const T3DVector &b) const
Definition: AkVectors.h:347
static AkReal32 Cos(AkReal32 in_value)
Definition: AkVectors.h:139
AkForceInline Ak2DVector NormalizeSpherical() const
Definition: AkVectors.h:829
AkForceInline bool IsWithin(const TVectorType &in_Point) const
Definition: AkVectors.h:1795
uint64_t AkUInt64
Unsigned 64-bit integer.
AkReal64 Y
Y Position.
Definition: AkTypes.h:363
#define ADD(i, j)
void Zero()
Definition: AkVectors.h:328
AkForceInline void NormalizeSpherical()
Definition: AkVectors.h:858
static AkForceInline void Rotation(AkMatrix3x3 &out_mat, AkReal32 in_angle, const Ak3DVector &in_axis)
Definition: AkVectors.h:1028
Ak3DVector GetUp() const
Definition: AkVectors.h:1875
#define AKVECTORS_EPSILON
Definition: AkVectors.h:48
TVectorType m_Max
Definition: AkVectors.h:1833
AkForceInline T3DVector Rotate180X_90Y() const
Definition: AkVectors.h:515
static AkReal32 Sin(AkReal32 in_value)
Definition: AkVectors.h:140
void Init(const Ak3DVector &in_center, const Ak3DVector &in_extent, const Ak3DVector &in_Front, const Ak3DVector &in_Up)
Definition: AkVectors.h:1844
AkReal32 theta
Azimuth.
Definition: AkTypes.h:741
AkForceInline AkMatrix3x3 & operator+=(const AkMatrix3x3 &in_rhs)
Definition: AkVectors.h:983
AkReal32 Y
Definition: AkVectors.h:1272
AkForceInline bool IsValid() const
Definition: AkVectors.h:1827
Ak3DVector GetP2() const
Definition: AkVectors.h:1716
AkForceInline const AkReal32 & operator()(const AkUInt32 row, const AkUInt32 column) const
Definition: AkVectors.h:969
AkForceInline bool operator>=(const T3DVector &b) const
Definition: AkVectors.h:362
AkForceInline T3DVector operator/(const TDataType f) const
Definition: AkVectors.h:419
3D 64-bit vector. Intended as storage for world positions of sounds and objects, benefiting from 64-b...
Definition: AkTypes.h:334
AkForceInline Ak2DVector & CartesianToSpherical(const Ak3DVector &in_Cartesian)
Definition: AkVectors.h:786
AkPlane(Ak3DVector in_p1, Ak3DVector in_p2, Ak3DVector in_p4)
Definition: AkVectors.h:1383
uint32_t AkUInt32
Unsigned 32-bit integer.
AkQuaternion(const Ak3DVector &in_v0, const Ak3DVector &in_v1)
Definition: AkVectors.h:1178
static AkReal32 ACos(AkReal32 in_value)
Definition: AkVectors.h:142
AkInt32 X
X Position.
Definition: AkVectors.h:120
AkForceInline T3DVector operator/(const T3DVector in_rhs) const
Definition: AkVectors.h:408
#define EPSILON
Definition: AkVectors.h:1423
TDataType Z
Definition: AkVectors.h:667
3D vector for some operations in 3D space. Typically intended only for localized calculations due to ...
Definition: AkTypes.h:369
Ak3DVector GetSize() const
Definition: AkVectors.h:1867
Ak3DVector GetP1() const
Definition: AkVectors.h:1715
T3DVector(const AKSIMD_V4F32 &in_v4f32)
Definition: AkVectors.h:301
AkForceInline bool IsAllPositive() const
Definition: AkVectors.h:641
AkForceInline TDataType HorizontalMax() const
Definition: AkVectors.h:481
Ak3DVector GetP4() const
Definition: AkVectors.h:1717
AkForceInline void Convert(TToReal &out_to, TFromReal in_from)
Definition: AkVectors.h:182
AkForceInline TDataType L2_Norm() const
Definition: AkVectors.h:602
AkForceInline AkReal32 Length() const
Definition: AkVectors.h:1148
AkForceInline bool Equals(const T3DVector &b, const TDataType tolerance=static_cast< TDataType >(0.0)) const
Definition: AkVectors.h:508
AkReal64 Z
Z Position.
Definition: AkTypes.h:364
AkInt32 Z
Z Position.
Definition: AkVectors.h:122
AkForceInline T3DVector operator*(const TDataType f) const
Definition: AkVectors.h:397
#define AkForceInline
Definition: AkTypes.h:63
static AkForceInline T3DVector Max(const T3DVector &A, const T3DVector &B)
Definition: AkVectors.h:497
void SetReflection(AkReal32 *out_mat) const
Definition: AkVectors.h:1535
AkForceInline bool operator<=(const T3DVector &b) const
Definition: AkVectors.h:352
AkForceInline Ak3DVector operator*(const Ak3DVector &in_rhs) const
Definition: AkVectors.h:974
Ak4DVector(const AkVector &b)
Definition: AkVectors.h:63
AkForceInline T3DVector & Normalize()
Definition: AkVectors.h:584
Ak3DVector L
Definition: AkVectors.h:1371
Ak2DVector & operator*=(const AkReal32 f)
Definition: AkVectors.h:752
AkForceInline Ak3DVector RotateVector(const Ak3DVector32 &in_v) const
Definition: AkVectors.h:1239
T3DVector(const T3DVector< TFromDataType > &in_vector)
Definition: AkVectors.h:239
AkForceInline T3DVector Cross(const T3DVector &v) const
Definition: AkVectors.h:617
AkForceInline Ak2DVector operator=(const AkSphericalCoord &b)
Definition: AkVectors.h:734
AkForceInline bool operator>(const T3DVector b) const
Definition: AkVectors.h:357
AkForceInline TDataType HorizontalMin() const
Definition: AkVectors.h:476
AkForceInline Ak2DVector LinearCombination(const Ak2DVector &A, const Ak2DVector &B) const
Definition: AkVectors.h:800
static bool IsFinite(AkReal32 in_val)
Definition: AkVectors.h:143
AkReal64 X
X Position.
Definition: AkTypes.h:362
AkQuaternion(AkReal32 in_W, AkReal32 in_X, AkReal32 in_Y, AkReal32 in_Z)
Definition: AkVectors.h:1057
TVectorType m_Min
Definition: AkVectors.h:1832
AkReal32 m_Data[3][3]
Definition: AkVectors.h:1048
AkForceInline TDataType Length() const
Definition: AkVectors.h:630
T3DVector(const AkVector64 &in_vector)
Definition: AkVectors.h:259
AkForceInline AKSIMD_V4F32 VectorV4F32() const
Definition: AkVectors.h:318
TBoundingBox(const TVectorType &in_min, const TVectorType &in_max)
Definition: AkVectors.h:1764

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise