Version
Wwise SDK 2021.1.10
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  Version: v2021.1.10 Build: 7883
25  Copyright (c) 2006-2022 Audiokinetic Inc.
26 *******************************************************************************/
27 
28 // AkVectors.h
29 //
30 
31 #pragma once
32 
37 #include <AK/Tools/Common/AkArray.h>
39 
40 #include <math.h>
41 #include <stdio.h>
42 #include <float.h>
43 
44 //#define AKVBAP_DEBUG 1
45 //#define AKPORTALS_DEBUG
46 
47 #define AKVECTORS_PI (3.1415926535897932384626433832795f)
48 #define AKVECTORS_TWOPI (6.283185307179586476925286766559f)
49 #define AKVECTORS_PIOVERTWO (1.5707963267948966192313216916398f)
50 #define AKVECTORS_EPSILON (1.0e-38f) // epsilon value for fast log(0)
51 
52 class Ak4DVector
53 {
54 public:
55  //-----------------------------------------------------------
56  // Constructor/Destructor functions
58  {
59  v[0] = 0.0f;
60  v[1] = 0.0f;
61  v[2] = 0.0f;
62  v[3] = 0.0f;
63  }
64 
65  Ak4DVector(const AkVector& b)
66  {
67  v[0] = b.X;
68  v[1] = b.Y;
69  v[2] = b.Z;
70  v[3] = 1;
71  }
72 
74 
75  //-----------------------------------------------------------
76  // Basic vector operators
78  {
79  v[0] = b.v[0];
80  v[1] = b.v[1];
81  v[2] = b.v[2];
82  v[3] = b.v[3];
83 
84  return *this;
85  }
86 
88  {
89  v[0] = v[0] / f;
90  v[1] = v[1] / f;
91  v[2] = v[2] / f;
92  v[3] = v[3] / f;
93 
94  return *this;
95  }
96 
97  Ak4DVector operator-(const Ak4DVector& b) const
98  {
99  Ak4DVector p;
100 
101  p.v[0] = v[0] - b.v[0];
102  p.v[1] = v[1] - b.v[1];
103  p.v[2] = v[2] - b.v[2];
104  p.v[3] = v[3] - b.v[3];
105 
106  return p;
107  }
108 
110 };
111 
113 {
114 public:
117  {
118  X = x;
119  Y = y;
120  Z = z;
121  }
122 
124 
125  AkInt32 X; ///< X Position
126  AkInt32 Y; ///< Y Position
127  AkInt32 Z; ///< Z Position
128 };
129 
131 {
132 public:
133  //-----------------------------------------------------------
134  // Constructor/Destructor functions
136  X(0.f),
137  Y(0.f),
138  Z(0.f)
139  {}
140 
142  AkReal32 x,
143  AkReal32 y,
144  AkReal32 z)
145  {
146  X = x;
147  Y = y;
148  Z = z;
149  }
151  {
152  X = b.X;
153  Y = b.Y;
154  Z = b.Z;
155  }
156  explicit Ak3DVector(const AKSIMD_V4F32& in_v4f32)
157  {
158  X = AKSIMD_GETELEMENT_V4F32(in_v4f32, 0);
159  Y = AKSIMD_GETELEMENT_V4F32(in_v4f32, 1);
160  Z = AKSIMD_GETELEMENT_V4F32(in_v4f32, 2);
161  }
163  {
164  AKSIMD_V4F32 v4f32;
165  AKSIMD_GETELEMENT_V4F32(v4f32, 0) = X;
166  AKSIMD_GETELEMENT_V4F32(v4f32, 1) = Y;
167  AKSIMD_GETELEMENT_V4F32(v4f32, 2) = Z;
168  AKSIMD_GETELEMENT_V4F32(v4f32, 3) = 1.f;
169  return v4f32;
170  }
172  {
173  AKSIMD_V4F32 v4f32;
174  AKSIMD_GETELEMENT_V4F32(v4f32, 0) = X;
175  AKSIMD_GETELEMENT_V4F32(v4f32, 1) = Y;
176  AKSIMD_GETELEMENT_V4F32(v4f32, 2) = Z;
177  AKSIMD_GETELEMENT_V4F32(v4f32, 3) = 0.f;
178  return v4f32;
179  }
181 
182  void Zero()
183  {
184  X = 0.f;
185  Y = 0.f;
186  Z = 0.f;
187  }
188 
189 
190  //-----------------------------------------------------------
191  // Basic vector operators
192  AkForceInline bool operator==(const Ak3DVector& b) const
193  {
194  return X == b.X && Y == b.Y && Z == b.Z;
195  }
196 
197  AkForceInline bool operator!=(const Ak3DVector& b) const
198  {
199  return X != b.X || Y != b.Y || Z != b.Z;
200  }
201 
203  {
204  X = b.X;
205  Y = b.Y;
206  Z = b.Z;
207 
208  return *this;
209  }
210 
212  {
213  X = b.X;
214  Y = b.Y;
215  Z = b.Z;
216 
217  return *this;
218  }
219 
220  AkForceInline bool operator<(const Ak3DVector& b) const
221  {
222  return X < b.X && Y < b.Y && Z < b.Z;
223  }
224 
225  AkForceInline bool operator<=(const Ak3DVector& b) const
226  {
227  return X <= b.X && Y <= b.Y && Z <= b.Z;
228  }
229 
230  AkForceInline bool operator>(const Ak3DVector b) const
231  {
232  return X > b.X && Y > b.Y && Z > b.Z;
233  }
234 
235  AkForceInline bool operator>=(const Ak3DVector& b) const
236  {
237  return X >= b.X && Y >= b.Y && Z >= b.Z;
238  }
239 
241  {
242  X = X * f;
243  Y = Y * f;
244  Z = Z * f;
245 
246  return *this;
247  }
248 
250  {
251  AkReal32 oneoverf = 1.f / f;
252  X = X * oneoverf;
253  Y = Y * oneoverf;
254  Z = Z * oneoverf;
255 
256  return *this;
257  }
258 
260  {
261  Ak3DVector v;
262 
263  v.X = X * v2.X;
264  v.Y = Y * v2.Y;
265  v.Z = Z * v2.Z;
266 
267  return v;
268  }
269 
271  {
272  Ak3DVector v;
273 
274  v.X = X * f;
275  v.Y = Y * f;
276  v.Z = Z * f;
277 
278  return v;
279  }
280 
282  {
283  Ak3DVector v;
284  AkReal32 oneoverf = 1.f / f;
285 
286  v.X = X * oneoverf;
287  v.Y = Y * oneoverf;
288  v.Z = Z * oneoverf;
289 
290  return v;
291  }
292 
294  {
295  Ak3DVector v;
296 
297  v.X = X + f;
298  v.Y = Y + f;
299  v.Z = Z + f;
300 
301  return v;
302  }
303 
305  {
306  Ak3DVector v;
307 
308  v.X = X - f;
309  v.Y = Y - f;
310  v.Z = Z - f;
311 
312  return v;
313  }
314 
316  {
317  Ak3DVector v;
318 
319  v.X = X + b.X;
320  v.Y = Y + b.Y;
321  v.Z = Z + b.Z;
322 
323  return v;
324  }
325 
327  {
328  Ak3DVector v;
329 
330  v.X = X - b.X;
331  v.Y = Y - b.Y;
332  v.Z = Z - b.Z;
333 
334  return v;
335  }
336 
337  AkForceInline operator</span> AkVector()
338  {
339  AkVector v;
340  v.X = X; v.Y = Y; v.Z = Z;
341 
342  return v;
343  }
344 
345 
346  AkForceInline static Ak3DVector Min(const Ak3DVector& A, const Ak3DVector& B)
347  {
348  Ak3DVector min;
349 
350  min.X = AkMin(A.X, B.X);
351  min.Y = AkMin(A.Y, B.Y);
352  min.Z = AkMin(A.Z, B.Z);
353 
354  return min;
355  }
356 
357  AkForceInline static Ak3DVector Max(const Ak3DVector& A, const Ak3DVector& B)
358  {
359  Ak3DVector max;
360 
361  max.X = AkMax(A.X, B.X);
362  max.Y = AkMax(A.Y, B.Y);
363  max.Z = AkMax(A.Z, B.Z);
364 
365  return max;
366  }
367 
368  //-----------------------------------------------------------
369  // Conversion functions
371  {
372  Ak3DVector v;
373 
374  v.X = -X;
375  v.Y = Z;
376  v.Z = -Y;
377 
378  return v;
379  }
380 
382  const AkReal32 azimuth,
383  const AkReal32 elevation)
384  {
385  AkReal32 cosElevation = cosf(elevation);
386  X = cosf(azimuth) * cosElevation;
387  Y = sinf(azimuth) * cosElevation;
388  Z = sinf(elevation);
389 
390  return *this;
391  }
392 
393  // Determinant of 3 column vectors.
395  const Ak3DVector & a,
396  const Ak3DVector & b,
397  const Ak3DVector & c)
398  {
399  return (a.X*b.Y*c.Z + a.Y*b.Z*c.X + a.Z*b.X*c.Y) -
400  (a.Z*b.Y*c.X + a.Y*b.X*c.Z + a.X*b.Z*c.Y);
401  }
402 
403  // Convert a vector to a different base
405  const Ak3DVector& A,
406  const Ak3DVector& B,
407  const Ak3DVector& C) const
408  {
409  Ak3DVector v;
410 
411  AkReal32 d = Determinant(A, B, C);
412 
413  if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
414  {
415  v.X = 0.0f; v.Y = 0.0f; v.Z = 0.0f;
416  return v;
417  }
418 
419  // http://mathworld.wolfram.com/MatrixInverse.html
420  Ak3DVector invA = Ak3DVector(B.Y*C.Z - B.Z*C.Y, A.Z*C.Y - A.Y*C.Z, A.Y*B.Z - A.Z*B.Y);
421  Ak3DVector invB = Ak3DVector(B.Z*C.X - B.X*C.Z, A.X*C.Z - A.Z*C.X, A.Z*B.X - A.X*B.Z);
422  Ak3DVector invC = Ak3DVector(B.X*C.Y - B.Y*C.X, A.Y*C.X - A.X*C.Y, A.X*B.Y - A.Y*B.X);
423 
424  AkReal32 oneover_d = 1.f / d;
425  invA *= oneover_d;
426  invB *= oneover_d;
427  invC *= oneover_d;
428 
429  // Project coordinates using a vector to matrix multiplication
430  v.X = X * invA.X + Y * invB.X + Z * invC.X;
431  v.Y = X * invA.Y + Y * invB.Y + Z * invC.Y;
432  v.Z = X * invA.Z + Y * invB.Z + Z * invC.Z;
433 
434  // v /= v.Length();
435 
436  return v;
437  }
438 
440  {
441  AkReal32 l = Length();
442  if (l != 0.f)
443  {
444  X /= l;
445  Y /= l;
446  Z /= l;
447  }
448  else
449  {
450  X = 0.f;
451  Y = 0.f;
452  Z = 0.f;
453  }
454  return *this;
455  }
456 
458  {
459  return sqrtf(X*X + Y*Y + Z*Z);
460  }
461 
463  {
464  return X*v2.X + Y*v2.Y + Z*v2.Z;
465  }
466 
468  {
469  return DotProduct(v2);
470  }
471 
473  {
474  Ak3DVector uxv;
475  const Ak3DVector& u = *this;
476 
477  uxv.X = u.Y*v.Z - u.Z*v.Y;
478  uxv.Y = u.Z*v.X - u.X*v.Z;
479  uxv.Z = u.X*v.Y - u.Y*v.X;
480 
481  return uxv;
482  }
483  //
485  {
486  return sqrtf(X*X + Y*Y + Z*Z);
487  }
488 
490  {
491  return X*X + Y*Y + Z*Z;
492  }
493 
494  // Usefull in VBAP algorithm, only points that are a positive linear composition matters.
496  {
497  const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f;
498  return X >= -POSITIVE_TEST_EPSILON &&
499  Y >= -POSITIVE_TEST_EPSILON &&
500  Z >= -POSITIVE_TEST_EPSILON;
501  }
502 
504  {
505  Ak3DVector abs = *this;
506  abs.X = (AkReal32)fabs(abs.X);
507  abs.Y = (AkReal32)fabs(abs.Y);
508  abs.Z = (AkReal32)fabs(abs.Z);
509  return abs;
510  }
511 
515 };
516 
518 {
519 public:
520  //-----------------------------------------------------------
521  // Constructor/Destructor functions
524 
526  AkReal32 x,
527  AkReal32 y)
528  {
529  X = x;
530  Y = y;
531  }
532 
533  //-----------------------------------------------------------
534  // Basic vector operators
536  {
537  X = b.X;
538  Y = b.Y;
539 
540  return *this;
541  }
542 
544  {
545  X = b.theta;
546  Y = b.phi;
547 
548  return *this;
549  }
550 
551  Ak2DVector operator-(const Ak2DVector& b) const
552  {
553  Ak2DVector v;
554 
555  v.X = X - b.X;
556  v.Y = Y - b.Y;
557 
558  return v;
559  }
560 
562  {
563  X = X * f;
564  Y = Y * f;
565 
566  return *this;
567  }
568 
570  {
571  AkReal32 oneoverf = 1.f / f;
572  X = X * oneoverf;
573  Y = Y * oneoverf;
574 
575  return *this;
576  }
577 
578  AkForceInline bool operator==(const Ak2DVector& b) const
579  {
580  return b.X == X && b.Y == Y;
581  }
582 
583  AkForceInline bool operator!=(const Ak2DVector& b) const
584  {
585  return b.X != X && b.Y != Y;
586  }
587 
589  {
590  return sqrtf(X*X+Y*Y);
591  }
592 
593  //-----------------------------------------------------------
594  // Conversion functions
596  {
597  // (radial, azimuth, elevation)
598  AkReal32 r = sqrtf( in_Cartesian.X*in_Cartesian.X + in_Cartesian.Y*in_Cartesian.Y + in_Cartesian.Z*in_Cartesian.Z);
599  AKASSERT( r != 0);
600 
601  X = atan2f(in_Cartesian.Y, in_Cartesian.X);
602  Y = asinf(in_Cartesian.Z / r);
603 
605 
606  return *this;
607  }
608 
610  const Ak2DVector& A,
611  const Ak2DVector& B) const
612  {
613  Ak2DVector v;
614 
615  // Project coordinates using a vector to matrix multiplication
616  AkReal32 d = (A.X*B.Y - A.Y*B.X);
617 
618  if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
619  {
620  v.X = 0.0f; v.Y = 0.0f;
621  return v;
622  }
623 
624  Ak2DVector invA = Ak2DVector( B.Y, -A.Y );
625  Ak2DVector invB = Ak2DVector( -B.X, A.X );
626 
627  AkReal32 oneover_d = 1.f / d;
628  invA *= oneover_d;
629  invB *= oneover_d;
630 
631  v.X = X * invA.X + Y * invB.X;
632  v.Y = X * invA.Y + Y * invB.Y;
633  // v /= v.Length();
634 
635  return v;
636  }
637 
639  {
640  /*
641  Normalise spherical coordinates.
642  X (azimuthal) -> [-PI, PI], circle lies on xy plan, 0 is on X axix
643  Y (elevation) -> [-PI/2, PI/2], half circle on Z axis, 0 on XY plan, PI/2 straigt up on Z axis.
644  */
645 
646  Ak2DVector v;
647 
648  v.X = X;
649  v.Y = Y;
650 
651  if (X > AKVECTORS_PI)
652  v.X = X - AKVECTORS_TWOPI;
653  else if (X < -AKVECTORS_PI)
654  v.X = X + AKVECTORS_TWOPI;
655 
656  if (Y > AKVECTORS_PIOVERTWO)
657  v.Y = Y - AKVECTORS_PI;
658  else if (Y < -AKVECTORS_PIOVERTWO)
659  v.Y = Y + AKVECTORS_PI;
660 
663 
664  return v;
665  }
666 
668  {
669  /*
670  Normalise spherical coordinates.
671  X (azimuthal) -> [-PI, PI], circle lies on xy plan, 0 is on X axix
672  Y (elevation) -> [-PI/2, PI/2], half circle on Z axis, 0 on XY plan, PI/2 straigt up on Z axis.
673  */
674 
675  if (X > AKVECTORS_PI)
676  X = X - AKVECTORS_TWOPI;
677  else if (X < -AKVECTORS_PI)
678  X = X + AKVECTORS_TWOPI;
679 
680  if (Y > AKVECTORS_PIOVERTWO)
681  Y = Y - AKVECTORS_PI;
682  else if (Y < -AKVECTORS_PIOVERTWO)
683  Y = Y + AKVECTORS_PI;
684  }
685 
686  // Useful in VBAP algorithm, only points that are a positive linear composition matters.
688  {
689  const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f; //0.005f;
690  return X >= -POSITIVE_TEST_EPSILON &&
691  Y >= -POSITIVE_TEST_EPSILON;
692  }
693 
696 };
697 
698 
699 
701 {
702  static const int MAX_SIZE = 16;
703 
704 public:
705  //-----------------------------------------------------------
706  // Constructor/Destructor functions
709 
710  //-----------------------------------------------------------
711  // Basic vector operators
713  {
714  for (int i = 0; i < MAX_SIZE; i++)
715  m_Data[i] /= f;
716 
717  return *this;
718  }
719 
721  {
722  for (int i = 0; i < MAX_SIZE; i++)
723  {
724  m_Data[i] = in_Data[i];
725  }
726 
727  return *this;
728  }
729 
730  AkReal32 m_Data[MAX_SIZE];
731 };
732 
734 {
735 
736 public:
737  //-----------------------------------------------------------
738  // Constructor/Destructor functions
741 
742  //-----------------------------------------------------------
743  // Basic vector operators
745  {
746  for (int i = 0; i < 3; i++)
747  {
748  for (int j = 0; j < 3; j++)
749  {
750  m_Data[i][j] /= f;
751  }
752  }
753  return *this;
754  }
755 
757  {
758  return m_Data[column][row];
759  }
760 
761  AkForceInline const AkReal32& operator()(const AkUInt32 row, const AkUInt32 column) const
762  {
763  return m_Data[column][row];
764  }
765 
767  {
768  Ak3DVector res;
769  res.X = in_rhs.X * m_Data[0][0] + in_rhs.Y * m_Data[1][0] + in_rhs.Z * m_Data[2][0];
770  res.Y = in_rhs.X * m_Data[0][1] + in_rhs.Y * m_Data[1][1] + in_rhs.Z * m_Data[2][1];
771  res.Z = in_rhs.X * m_Data[0][2] + in_rhs.Y * m_Data[1][2] + in_rhs.Z * m_Data[2][2];
772  return res;
773  }
774 
776  {
777  Add(*this, *this, in_rhs);
778  return *this;
779  }
780 
781  static AkForceInline void Add(AkMatrix3x3& out_res, const AkMatrix3x3& in_m0, const AkMatrix3x3& in_m1)
782  {
783 #define ADD(i,j) out_res(i,j) = in_m0(i,j) + in_m1(i,j)
784  ADD(0, 0); ADD(0, 1); ADD(0, 2);
785  ADD(1, 0); ADD(1, 1); ADD(1, 2);
786  ADD(2, 0); ADD(2, 1); ADD(2, 2);
787 #undef ADD
788  }
789 
791  {
792  m_Data[0][0] *= in_f; m_Data[0][1] *= in_f; m_Data[0][2] *= in_f;
793  m_Data[1][0] *= in_f; m_Data[1][1] *= in_f; m_Data[1][2] *= in_f;
794  m_Data[2][0] *= in_f; m_Data[2][1] *= in_f; m_Data[2][2] *= in_f;
795  return *this;
796  }
797 
798  static AkForceInline void Diagonal(AkMatrix3x3& out_mat, AkReal32 in_f)
799  {
800  out_mat(0, 0) = in_f; out_mat(0, 1) = 0.f; out_mat(0, 2) = 0.f;
801  out_mat(1, 0) = 0.f; out_mat(1, 1) = in_f; out_mat(1, 2) = 0.f;
802  out_mat(2, 0) = 0.f; out_mat(2, 1) = 0.f; out_mat(2, 2) = in_f;
803  }
804 
805  // Creates the matrix Mu such that Mu*v = u X v
806  static AkForceInline void CrossProductMatrix(AkMatrix3x3& out_mat, const Ak3DVector& in_u)
807  {
808  out_mat(0, 0) = 0.f; out_mat(0, 1) = -in_u.Z; out_mat(0, 2) = in_u.Y;
809  out_mat(1, 0) = in_u.Z; out_mat(1, 1) = 0.f; out_mat(1, 2) = -in_u.X;
810  out_mat(2, 0) = -in_u.Y; out_mat(2, 1) = in_u.X; out_mat(2, 2) = 0.f;
811  }
812 
813  static AkForceInline void OuterProduct(AkMatrix3x3& out_mat, const Ak3DVector& in_v0, const Ak3DVector& in_v1)
814  {
815  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;
816  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;
817  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;
818  }
819 
820  static AkForceInline void Rotation(AkMatrix3x3& out_mat, AkReal32 in_angle, const Ak3DVector& in_axis)
821  {
822  Rotation(out_mat, sinf(in_angle), cosf(in_angle), in_axis);
823  }
824 
825  static void Rotation(AkMatrix3x3& out_mat, AkReal32 in_sin, AkReal32 in_cos, const Ak3DVector& in_axis)
826  {
827  Diagonal(out_mat, in_cos);
828 
829  AkMatrix3x3 outer;
830  OuterProduct(outer, in_axis, in_axis);
831  outer *= (1.f - in_cos);
832  out_mat += outer;
833 
834  AkMatrix3x3 cross;
835  CrossProductMatrix(cross, in_axis*in_sin);
836  out_mat += cross;
837  }
838 
839  // [column][row]
841 };
842 
844 {
845 public:
846  // Identity quaternion
847  AkQuaternion(): W(1.f), X(0.f), Y(0.f), Z(0.f) {}
848 
849  AkQuaternion(AkReal32 in_W, AkReal32 in_X, AkReal32 in_Y, AkReal32 in_Z) :
850  W(in_W),
851  X(in_X),
852  Y(in_Y),
853  Z(in_Z)
854  {}
855 
856  AkQuaternion(const Ak3DVector& in_fromVector):
857  W(0.f),
858  X(in_fromVector.X),
859  Y(in_fromVector.Y),
860  Z(in_fromVector.Z)
861  {}
862 
864  {
865  return sqrtf( W*W + X*X + Y*Y + Z*Z );
866  }
867 
869  {
870  AkReal32 f = 1.0f / Length();
871  W *= f;
872  X *= f;
873  Y *= f;
874  Z *= f;
875  return *this;
876  }
877 
879  {
880  AkReal32 norm = W*W + X*X + Y*Y + Z*Z;
881  if (norm > 0.0)
882  {
883  AkReal32 invNorm = 1.0f / norm;
884  return AkQuaternion(W*invNorm, -X*invNorm, -Y*invNorm, -Z*invNorm);
885  }
886  else
887  {
888  return AkQuaternion();
889  }
890  }
891 
892  // Create a quaternion representing the shortest arc rotation between (normalized) vectors v0, v1
893  AkQuaternion(const Ak3DVector& in_v0, const Ak3DVector& in_v1)
894  {
895  AkReal32 dot = in_v0.Dot(in_v1);
896  if (dot >= 1.0f - AKVECTORS_EPSILON)
897  {
898  // No rotation - return unity quaternion.
899  AkQuaternion();
900  }
901  if (dot <= -1.f - AKVECTORS_EPSILON)
902  {
903  // 180 degree rotation - can use any non-zero length axis.
904  Ak3DVector axis = Ak3DVector(0.f, 0.f, 1.f).Cross(in_v0);
905  AkReal32 len = axis.Length();
906  if (len < AKVECTORS_EPSILON)
907  {
908  axis = Ak3DVector(0.f, 1.f, 0.f).Cross(in_v0);
909  len = axis.Length();
910  }
911  axis.Normalize();
912  AkQuaternion(AKVECTORS_PI, axis);
913  }
914  else
915  {
916  AkReal32 sqrt = sqrtf((1.f + dot) * 2.f);
917  AkReal32 invs = 1.f / sqrt;
918 
919  Ak3DVector cross = in_v0.Cross(in_v1);
920 
921  X = cross.X * invs;
922  Y = cross.Y * invs;
923  Z = cross.Z * invs;
924  W = sqrt * 0.5f;
925  Normalize();
926  }
927  }
928 
929  // Build quaternion from an axis and angle representation.
930  AkQuaternion(AkReal32 in_angle, const Ak3DVector& in_axis)
931  {
932  AkReal32 cosHalfAngle = cosf(in_angle / 2.f);
933  W = cosHalfAngle;
934  X = cosHalfAngle*in_axis.X;
935  Y = cosHalfAngle*in_axis.Y;
936  Z = cosHalfAngle*in_axis.Z;
937  }
938 
939  /// Quaternion multiplication.
941  {
942  return AkQuaternion(
943  W*Q.W - X*Q.X - Y*Q.Y - Z*Q.Z,
944  W*Q.X + X*Q.W + Y*Q.Z - Z*Q.Y,
945  W*Q.Y - X*Q.Z + Y*Q.W + Z*Q.X,
946  W*Q.Z + X*Q.Y - Y*Q.X + Z*Q.W);
947  }
948 
950  {
951  /*
952  // impl 1
953  Ak3DVector uv, uuv;
954  Ak3DVector qvec(X, Y, Z);
955  uv = qvec.Cross(in_v);
956  uuv = qvec.Cross(uv);
957  uv *= (2.0f * W);
958  uuv *= 2.0f;
959  return in_v + uv + uuv;
960  */
961 
962  // impl 2
963  Ak3DVector u(X, Y, Z);
964  Ak3DVector res =
965  u * u.Dot(in_v) * 2.f
966  + in_v * (W*W - u.Dot(u))
967  + u.Cross(in_v) * W * 2.0f;
968 
969  return res;
970  }
971 
976 };
977 
979 {
982 };
983 
984 class AkLine
985 {
986 public:
988  {
989  mint = 1.175494351e-38F;
990  maxt = 3.402823466e+38F;
991  }
992 
994  Ak3DVector in_L,
995  Ak3DVector in_P
996  )
997  {
998  L = in_L;
999  P = in_P;
1000  mint = 1.175494351e-38F;
1001  maxt = 3.402823466e+38F;
1002  }
1003 
1005  {
1006  return P + L*t;
1007  }
1008 
1010  Ak3DVector A,
1011  Ak3DVector B)
1012  {
1013  /*
1014  a (V1 X V2) = (P2 - P1) X V2
1015  If the lines intersect at a single point, then the resultant vectors
1016  on each side of this equation must be parallel, and the left side must
1017  not be the zero vector. We should check to make sure that this is
1018  true. Once we have checked this, we can solve for 'a' by taking the
1019  magnitude of each side and dividing. If the resultant vectors are
1020  parallel, but in opposite directions, then 'a' is the negative of the
1021  ratio of magnitudes. Once we have 'a' we can go back to the equation
1022  for L1 to find the intersection point.
1023  */
1024  Ak3DVector V1 = L;
1025  Ak3DVector V2 = B - A;
1026  Ak3DVector P1 = P;
1027  Ak3DVector P2 = A;
1028 
1029  // k(V1 X V2) = (A - P) X V2
1030 
1031  Ak3DVector v1CrossV2 = V1.Cross(V2);
1033  P2 - P1,
1034  V2,
1035  v1CrossV2
1036  );
1037  AkReal32 t = det / v1CrossV2.LengthSquared();
1038 
1040  P2 - P1,
1041  V1,
1042  v1CrossV2
1043  );
1044  AkReal32 s = det / v1CrossV2.LengthSquared();
1045 
1046  AkReal32 distsqrd = ((P2 + V2*s) - (P1 + V1*t)).LengthSquared();
1047 
1048  if ((AkReal32)fabs(v1CrossV2.L2_Norm()) >= AKVECTORS_EPSILON
1049  && distsqrd < 0.001
1050  && s <= 1.0f )
1051  {
1052 #ifdef AKPORTALS_DEBUG
1053  Ak3DVector minPoint = PointAt(t);
1054 
1055  char msg[256];
1056  sprintf(msg, "L1a=[%0.2f,%0.2f,%0.2f];\n", P.X, P.Y, P.Z); AKPLATFORM::OutputDebugMsg(msg);
1057  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);
1058  sprintf(msg, "L2a=[%0.2f,%0.2f,%0.2f];\n", A.X, A.Y, A.Z); AKPLATFORM::OutputDebugMsg(msg);
1059  sprintf(msg, "L2b=[%0.2f,%0.2f,%0.2f];\n", B.X, B.Y, B.Z); AKPLATFORM::OutputDebugMsg(msg);
1060  sprintf(msg, "%% t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
1061  sprintf(msg, "intrPoint=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
1062  sprintf(msg, "\n"); AKPLATFORM::OutputDebugMsg(msg);
1063 #endif
1064 
1065  mint = AkMin(mint, t);
1066  maxt = AkMax(maxt, t);
1067 
1068  return true;
1069  }
1070 
1071 #ifdef AKPORTALS_DEBUG
1072  // char msg[256];
1073  // sprintf(msg, "%% DISCARTED t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
1074 #endif
1075  return false;
1076  }
1077 
1080 
1083 };
1084 
1085 class AkPlane
1086 {
1087 public:
1089  {
1090  }
1091 
1093  Ak3DVector in_p1,
1094  Ak3DVector in_p2,
1095  Ak3DVector in_p4
1096  )
1097  {
1098  SetPlane(
1099  in_p1,
1100  in_p2,
1101  in_p4);
1102  }
1103 
1105  {
1106  }
1107 
1108  void SetPlane(
1109  Ak3DVector in_p1,
1110  Ak3DVector in_p2,
1111  Ak3DVector in_p4
1112  )
1113  {
1114  // Reorder A-B-C to clockwwise if necessary
1115  AKASSERT(in_p1.X < 100000 && in_p1.X > -100000);
1116  AKASSERT(in_p1.Y < 100000 && in_p1.Y > -100000);
1117  AKASSERT(in_p1.Z < 100000 && in_p1.Z > -100000);
1118 
1119  AKASSERT(in_p2.X < 100000 && in_p2.X > -100000);
1120  AKASSERT(in_p2.Y < 100000 && in_p2.Y > -100000);
1121  AKASSERT(in_p2.Z < 100000 && in_p2.Z > -100000);
1122 
1123  AKASSERT(in_p4.X < 100000 && in_p4.X > -100000);
1124  AKASSERT(in_p4.Y < 100000 && in_p4.Y > -100000);
1125  AKASSERT(in_p4.Z < 100000 && in_p4.Z > -100000);
1126 
1127  p1 = in_p1;
1128  p2 = in_p2;
1129  p4 = in_p4;
1130 
1131  SetNormal();
1132 
1133  // Ax + By + Cz + D = 0
1134  // Find D using the normal and a point
1135  D = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
1136  }
1137 
1138 #define EPSILON 0.01f
1140  const Ak3DVector& in_Origin,
1141  const Ak3DVector& in_Destination,
1142  Ak3DVector& out_Intersection
1143  ) const
1144  {
1145  AkReal32 A = N.X;
1146  AkReal32 B = N.Y;
1147  AkReal32 C = N.Z;
1148 
1149  Ak3DVector ray = in_Destination - in_Origin;
1150  AkReal32 rayLength = ray.Length();
1151 
1152  Ak3DVector intersect;
1153 
1154  // If ray is < EPSILON, use on of the point directly for the test and skip the linear projection
1155  if (rayLength <= EPSILON)
1156  {
1157  Ak3DVector temp = in_Origin - p1;
1158  AkReal32 dot = temp.DotProduct(N);
1159  if (dot < EPSILON && dot > -EPSILON)
1160  {
1161  intersect = in_Origin;
1162  }
1163  else
1164  {
1165  // For debug only, to remove
1166  out_Intersection = p1;
1167  return false;
1168  }
1169 
1170  }
1171  else
1172  {
1173  // Normalize ray
1174  ray.Normalize();
1175 
1176  // 1) if ray len ~= 0, only check if one of the point is on target, ie: assign the intersect point
1177 
1178  // Is ray parallel to the plane?
1179  if ((A*ray.X + B*ray.Y + C*ray.Z) == 0.0f)
1180  {
1181  // For debug only, to remove
1182  AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
1183  intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
1184  out_Intersection = intersect; // For debugging
1185  return false;
1186  }
1187 
1188 
1189  // Distance along the ray where reflector is hit
1190  AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
1191 
1192  // Is the ray going towards the plane? Is it long enough?
1193  if (t < -EPSILON || t >(rayLength + EPSILON))
1194  {
1195  // For debug only, to remove
1196  intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
1197  out_Intersection = intersect; // For debugging
1198  return false; // The ray doesn't intersect
1199  }
1200 
1201  // Find the coordinate of intersection on the plane
1202  intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
1203  }
1204  ///////////////////////////////////////
1205  //
1206  // p2____v3____p3
1207  // | . |
1208  // ^ inter v4
1209  // v1 v
1210  // | |
1211  // p1__ v2>___p4
1212 
1213  Ak3DVector v1 = p2 - p1;
1214  Ak3DVector v2 = p4 - p1;
1215  Ak3DVector vInter1 = intersect - p1;
1216 
1217  Ak3DVector p3 = p4 + v1;
1218  Ak3DVector v3 = p2 - p3;
1219  Ak3DVector v4 = p4 - p3;
1220  Ak3DVector vInter2 = intersect - p3;
1221 
1222  v1.Normalize(); v2.Normalize(); v3.Normalize(); v4.Normalize(); vInter1.Normalize(); vInter2.Normalize();
1223 
1224  // Since it's a square, the angle between the point of intersection and any segment of the pannel should be < 90 degree,
1225  // therefore the dot product of the two normalized vectors should be > 0
1226  AkReal32 dot1 = v1.DotProduct(vInter1);
1227  AkReal32 dot2 = v2.DotProduct(vInter1);
1228  AkReal32 dot3 = v3.DotProduct(vInter2);
1229  AkReal32 dot4 = v4.DotProduct(vInter2);
1230 
1231  out_Intersection = intersect;
1232 
1233  return dot1 >= -EPSILON && dot2 >= -EPSILON && dot3 >= -EPSILON && dot4 >= -EPSILON;
1234  }
1235 
1237  Ak3DVector in_P,
1238  Ak3DVector& out_B) const
1239  {
1240  AkReal32 distance = (AkReal32)(AkReal32)fabs(N.X * in_P.X + N.Y * in_P.Y + N.Z * in_P.Z + D);
1241 
1242  Ak3DVector pointToPlane = N;
1243  pointToPlane *= distance;
1244 
1245  out_B = in_P + pointToPlane;
1246 
1247  return (AkReal32)fabs(distance);
1248  }
1249 
1251  AkReal32* out_mat) const
1252  {
1253  // http://ami.ektf.hu/uploads/papers/finalpdf/AMI_40_from175to186.pd
1254  /* m_pReflectionMatrix
1255  reflection on z axis
1256 
1257  P0 (x0, y0, z0), P1 (x1, y1, z1) and P2 (x2, y2, z2),
1258  normal = (cx, cy, cz)
1259  d = -CxX0 - CyY0 - CzZ0
1260 
1261  Reflect = 1-2Cx^2 -2CxCy -2CxCz -2Cxd
1262  -2CxCy 1-2Cy^2 -2CyCz -2Cyd
1263  -2CxCz -2CyCz 1-2Cz^2 -2Czd
1264  0 0 0 1
1265  */
1266 
1267  AkReal32 d = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
1268 
1269  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;
1270  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;
1271  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;
1272  out_mat[0 + 12] = 0; out_mat[1 + 12] = 0; out_mat[2 + 12] = 0; out_mat[3 + 12] = 1;
1273  }
1274 
1275  Ak3DVector GetN() const { return N; }
1276  AkReal32 GetD() const { return D; }
1277 
1279  const AkPlane& in_PlaneB,
1280  AkIntersectionPoints& out_Intrs) const
1281  {
1282  out_Intrs.count = 0;
1283 
1284  // Use vector to solve A
1285 
1286  Ak3DVector point;
1287 
1288  Ak3DVector N1 = N;
1289  Ak3DVector N2 = in_PlaneB.GetN();
1290  AkReal32 D1 = D;
1291  AkReal32 D2 = in_PlaneB.GetD();
1292 
1293  Ak3DVector L = N1.Cross(N2);
1294  if (L.Length() < 0.001f)
1295  {
1296  return false; // The two planes are parallel
1297  }
1298 
1299  AkUInt8 pivotAxis = 0;
1300 
1301  if ((AkReal32)fabs(L.Y) > (AkReal32)fabs(L.X))
1302  {
1303  pivotAxis = 1;
1304  if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.Y))
1305  {
1306  pivotAxis = 2;
1307  }
1308  }
1309  else if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.X))
1310  {
1311  pivotAxis = 2;
1312  }
1313 
1314  /*
1315  Pu = ( N1v*D2 - N2v*D1 ) / Lw
1316  Pv = ( N2u*D1 - N1u*D2 ) / Lw
1317  Pz = 0
1318  */
1319 
1320  switch (pivotAxis)
1321  {
1322  case 0:
1323  AKASSERT((AkReal32)fabs(L.X) > AKVECTORS_EPSILON);
1324  point.X = 0.f;
1325  point.Y = (N1.Z*D2 - N2.Z*D1) / L.X;
1326  point.Z = (N2.Y*D1 - N1.Y*D2) / L.X;
1327  break;
1328  case 1:
1329  AKASSERT((AkReal32)fabs(L.Y) > AKVECTORS_EPSILON);
1330  point.X = (N1.Z*D2 - N2.Z*D1) / L.Y;
1331  point.Y = 0.f;
1332  point.Z = (N2.X*D1 - N1.X*D2) / L.Y;
1333  break;
1334  case 2:
1335  AKASSERT((AkReal32)fabs(L.Z) > AKVECTORS_EPSILON);
1336  point.X = (N1.Y*D2 - N2.Y*D1) / L.Z;
1337  point.Y = (N2.X*D1 - N1.X*D2) / L.Z;
1338  point.Z = 0.f;
1339  break;
1340  };
1341 
1342 
1343 
1344  L.Normalize();
1345 
1346  AkLine intrLine = AkLine(L, point);
1347  AkLine intrLine2 = AkLine(L, point);
1348 
1349  //in_PlaneB.GetP1()
1350 
1351  // find min max
1352  AkUInt32 cpt = 0;
1353  AkUInt32 cpt2 = 0;
1354  Ak3DVector p3 = GetP2() + (GetP4() - GetP1());
1355 
1356 #ifdef AKPORTALS_DEBUG
1357  char msg[256];
1358  sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
1359  sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
1360  sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
1361 
1362  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);
1363  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);
1364  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);
1365 
1366  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);
1367  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);
1368 
1369 
1370  sprintf(msg, "%% Plane intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
1371 #endif
1372  // for the four lines in rectangle
1373  // Find where the line is crossing with plane A
1374  if (intrLine.Intersect(GetP1(), GetP2())) cpt++;
1375  if (intrLine.Intersect(GetP1(), GetP4())) cpt++;
1376  if (intrLine.Intersect(GetP2(), p3)) cpt++;
1377  if (intrLine.Intersect(p3, GetP4())) cpt++;
1378  //AKASSERT(cpt == 2);
1379 
1380 #ifdef AKPORTALS_DEBUG
1381  sprintf(msg, "%% Portal intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
1382 #endif
1383 
1384  // Find where the line is crossing with plane B
1385  p3 = in_PlaneB.GetP2() + (in_PlaneB.GetP4() - in_PlaneB.GetP1());
1386  if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP2())) cpt2++;
1387  if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP4())) cpt2++;
1388  if (intrLine2.Intersect(in_PlaneB.GetP2(), p3)) cpt2++;
1389  if (intrLine2.Intersect(p3, in_PlaneB.GetP4())) cpt2++;
1390  // **AKASSERT(cpt2 == 2 || cpt == 2);
1391 
1392  if (cpt < 2 || cpt2 < 2)
1393  {
1394 #ifdef AKPORTALS_DEBUG
1395  sprintf(msg, "%% NON \n"); AKPLATFORM::OutputDebugMsg(msg);
1396  sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
1397 #endif
1398  return false;
1399  }
1400 
1401  AkReal32 start = AkMax(intrLine.mint, intrLine2.mint);
1402  AkReal32 end = AkMin(intrLine.maxt, intrLine2.maxt);
1403 
1404  Ak3DVector minPoint = intrLine.PointAt(start);
1405  Ak3DVector maxPoint = intrLine.PointAt(end);
1406 #ifdef AKPORTALS_DEBUG
1407  sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
1408  sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
1409  sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
1410 
1411  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);
1412  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);
1413  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);
1414 
1415  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);
1416  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);
1417 
1418  sprintf(msg, "intr1=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
1419  sprintf(msg, "intr2=[%0.2f,%0.2f,%0.2f];\n", maxPoint.X, maxPoint.Y, maxPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
1420 
1421  sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
1422 #endif
1423  out_Intrs.points[0] = minPoint;
1424  out_Intrs.points[1] = maxPoint;
1425  out_Intrs.count = 2;
1426 
1427  return true;
1428  }
1429 
1430  Ak3DVector GetP1() const { return p1; }
1431  Ak3DVector GetP2() const { return p2; }
1432  Ak3DVector GetP4() const { return p4; }
1433 
1434 private:
1435  bool SetNormal()
1436  {
1437  //m_pNormal = (B-A) cross (C-A); normalize
1438  Ak3DVector a = p2 - p1;
1439  Ak3DVector b = p4 - p1;
1440 
1441  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);
1442 
1443  AkReal32 len = N.Length();
1444  AKASSERT(len > 0.f);
1445 
1446  if (len > 0)
1447  {
1448  N /= len;
1449  }
1450  else
1451  {
1452  return false;
1453  }
1454 
1455  return true;
1456  };
1457 
1458  /*
1459  p2__________p3
1460  | . |
1461  ^ inter v3
1462  v1 v
1463  | |
1464  p1__ v2>___p4
1465  */
1466 
1467  Ak3DVector p1; // Bottom left
1468  Ak3DVector p2; // Top left
1469  Ak3DVector p4; // Tottom right
1470  Ak3DVector N; // Normal vector
1471  AkReal32 D; // Plane equation: Ax + By + Cz = D => N.Xx + N.Yy + N.Zz = D
1472 };
1473 
1475 {
1477  m_Min(Ak3DVector(FLT_MAX, FLT_MAX, FLT_MAX)),
1478  m_Max(Ak3DVector(-FLT_MAX, -FLT_MAX, -FLT_MAX))
1479  {}
1480 
1481  void Update(
1482  const Ak3DVector & in_point
1483  )
1484  {
1485  if (m_Min.X > in_point.X)
1486  m_Min.X = in_point.X;
1487 
1488  if (m_Min.Y > in_point.Y)
1489  m_Min.Y = in_point.Y;
1490 
1491  if (m_Min.Z > in_point.Z)
1492  m_Min.Z = in_point.Z;
1493 
1494  if (m_Max.X < in_point.X)
1495  m_Max.X = in_point.X;
1496 
1497  if (m_Max.Y < in_point.Y)
1498  m_Max.Y = in_point.Y;
1499 
1500  if (m_Max.Z < in_point.Z)
1501  m_Max.Z = in_point.Z;
1502  }
1503 
1505  const Ak3DVector & in_Point
1506  ) const
1507  {
1508  return in_Point >= m_Min && in_Point <= m_Max;
1509  }
1510 
1512  const AkBoundingBox & in_BB
1513  ) const
1514  {
1515  return (m_Min.X <= in_BB.m_Max.X && m_Max.X >= in_BB.m_Min.X) &&
1516  (m_Min.Y <= in_BB.m_Max.Y && m_Max.Y >= in_BB.m_Min.Y) &&
1517  (m_Min.Z <= in_BB.m_Max.Z && m_Max.Z >= in_BB.m_Min.Z);
1518  }
1519 
1521  const AkBoundingBox & in_BB
1522  ) const
1523  {
1524  AkBoundingBox result;
1525 
1526  result.m_Max.X = AkMin(m_Max.X, in_BB.m_Max.X);
1527  result.m_Max.Y = AkMin(m_Max.Y, in_BB.m_Max.Y);
1528  result.m_Max.Z = AkMin(m_Max.Z, in_BB.m_Max.Z);
1529 
1530  result.m_Min.X = AkMax(m_Min.X, in_BB.m_Min.X);
1531  result.m_Min.Y = AkMax(m_Min.Y, in_BB.m_Min.Y);
1532  result.m_Min.Z = AkMax(m_Min.Z, in_BB.m_Min.Z);
1533 
1534  return result;
1535  }
1536 
1537  // returns acos(in_fAngle)
1539  AkReal32 in_fAngle
1540  ) const
1541  {
1542  AKASSERT((in_fAngle <= 1.0f) && (in_fAngle >= -1.0f));
1543  return acosf(in_fAngle);
1544  }
1545 
1546  AkForceInline bool IsEmpty() const
1547  {
1548  return (m_Min.X >= m_Max.X) || (m_Min.Y >= m_Max.Y) || (m_Min.Z >= m_Max.Z);
1549  }
1550 
1553 };
1554 
1555 class AkBox
1556 {
1557 public:
1559  {
1560  }
1561 
1563  {
1564  }
1565 
1566  void Init(
1567  const Ak3DVector & in_center,
1568  const Ak3DVector & in_extent,
1569  const Ak3DVector & in_Front,
1570  const Ak3DVector & in_Up)
1571  {
1572  AKASSERT(fabs(in_Front.Length() - 1.f) < 0.001 && fabs(in_Up.Length() - 1.f) < 0.001);//Must be unit vectors.
1573  AKASSERT(fabs(in_Front.Dot(in_Up) - 0.f) < 0.001); //Must be orthogonal.
1574 
1575  m_Center = in_center;
1576  m_Extent = in_extent;
1577 
1578  m_Z = in_Front;
1579  m_Y = in_Up;
1580  m_X = m_Z.Cross(m_Y);
1581  }
1582 
1584  const Ak3DVector & in_Point
1585  ) const
1586  {
1587  Ak3DVector pt = in_Point - m_Center;
1588  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;
1589  }
1590 
1591  Ak3DVector GetSize() const { return m_Extent*2.f; }
1592  Ak3DVector GetCenter() const { return m_Center; }
1593 
1594  Ak3DVector GetUx() const { return m_X; }
1595  Ak3DVector GetUy() const { return m_Y; }
1596  Ak3DVector GetUz() const { return m_Z; }
1597 
1598  Ak3DVector GetFront() const { return m_Z; }
1599  Ak3DVector GetUp() const { return m_Y; }
1600  Ak3DVector GetSide() const { return m_X; }
1601 
1603  {
1604  Ak3DVector size = GetSize();
1605  return size.X * size.Y * size.Z;
1606  }
1607 
1609  const Ak3DVector& L,
1610  const AkBox& B
1611  ) const
1612  {
1613  // Separating Axis Theorem for Oriented Bounding Boxes by Johnny Huynh
1614  const AkBox& A = *this;
1615  Ak3DVector T = B.GetCenter() - A.GetCenter();
1616 
1617  AkReal32 WA = A.m_Extent.X;
1618  AkReal32 HA = A.m_Extent.Y;
1619  AkReal32 DA = A.m_Extent.Z;
1620 
1621  AkReal32 WB = B.m_Extent.X;
1622  AkReal32 HB = B.m_Extent.Y;
1623  AkReal32 DB = B.m_Extent.Z;
1624 
1625  Ak3DVector Ax = A.GetUx();
1626  Ak3DVector Ay = A.GetUy();
1627  Ak3DVector Az = A.GetUz();
1628 
1629  Ak3DVector Bx = B.GetUx();
1630  Ak3DVector By = B.GetUy();
1631  Ak3DVector Bz = B.GetUz();
1632 
1633  /*
1634  | T • L | > | (WA*Ax) • L | + | (HA*Ay) • L | + |(DA*Az) • L | +
1635  | (WB*Bx) • L | +| (HB*By) • L | +| (DB*Bz) • L |*/
1636 
1637  AkReal32 left = (AkReal32)fabs(T.DotProduct(L));
1638  AkReal32 dpax = (AkReal32)fabs((Ax*WA).DotProduct(L));
1639  AkReal32 dpay = (AkReal32)fabs((Ay*HA).DotProduct(L));
1640  AkReal32 dpaz = (AkReal32)fabs((Az*DA).DotProduct(L));
1641  AkReal32 dpbx = (AkReal32)fabs((Bx*WB).DotProduct(L));
1642  AkReal32 dpby = (AkReal32)fabs((By*HB).DotProduct(L));
1643  AkReal32 dpbz = (AkReal32)fabs((Bz*DB).DotProduct(L));
1644 
1645  AkReal32 right = dpax + dpay + dpaz + dpbx + dpby + dpbz;
1646 
1647  return left > right;
1648  }
1649 
1650  void UpdateBoundingBox(AkBoundingBox& out_aabb) const
1651  {
1652  Ak3DVector x = m_X * m_Extent.X;
1653  out_aabb.Update(m_Center + x);
1654  out_aabb.Update(m_Center - x);
1655  Ak3DVector y = m_Y * m_Extent.Y;
1656  out_aabb.Update(m_Center + y);
1657  out_aabb.Update(m_Center - y);
1658  Ak3DVector Z = m_Z * m_Extent.Z;
1659  out_aabb.Update(m_Center + Z);
1660  out_aabb.Update(m_Center - Z);
1661  }
1662 
1663 
1664 private:
1665 
1666  Ak3DVector m_Center;
1667  Ak3DVector m_Extent;
1668 
1669  //Orthonormal Axes
1670  Ak3DVector m_X;
1671  Ak3DVector m_Y;
1672  Ak3DVector m_Z;
1673 };
#define AkMin(x1, x2)
Definition: AkPlatformFuncs.h:94
float AkReal32
32-bit floating point
Definition: AkTypes.h:70
bool FindIntersectionPoints(const AkPlane &in_PlaneB, AkIntersectionPoints &out_Intrs) const
Definition: AkVectors.h:1278
AkReal32 DistPoint_to_Plane(Ak3DVector in_P, Ak3DVector &out_B) const
Definition: AkVectors.h:1236
#define AKVECTORS_TWOPI
Definition: AkVectors.h:48
Ak3DVector GetUz() const
Definition: AkVectors.h:1596
Ak3DIntVector()
Definition: AkVectors.h:115
AkForceInline bool operator<(const Ak3DVector &b) const
Definition: AkVectors.h:220
AkForceInline Ak3DVector Cross(const Ak3DVector &v) const
Definition: AkVectors.h:472
AkInt32 Y
Y Position.
Definition: AkVectors.h:126
Ak3DVector points[2]
Definition: AkVectors.h:980
AkForceInline Ak2DVector CartesianToSpherical(const Ak3DVector &in_Cartesian)
Definition: AkVectors.h:595
Ak2DVector operator*=(const AkReal32 f)
Definition: AkVectors.h:561
AkForceInline Ak3DVector operator-(const Ak3DVector &b) const
Definition: AkVectors.h:326
float32x4_t AKSIMD_V4F32
Vector of 4 32-bit floats.
Definition: AkSimd.h:73
AkReal32 X
Definition: AkVectors.h:512
AkForceInline Ak3DVector operator*=(const AkReal32 f)
Definition: AkVectors.h:240
AkForceInline Ak2DVector operator=(const Ak2DVector &b)
Definition: AkVectors.h:535
AkReal32 Z
Definition: AkVectors.h:514
AkForceInline AKSIMD_V4F32 VectorV4F32() const
Definition: AkVectors.h:171
#define AKVECTORS_PI
Definition: AkVectors.h:47
#define AkMax(x1, x2)
Definition: AkPlatformFuncs.h:93
Ak3DVector GetN() const
Definition: AkVectors.h:1275
Ak3DVector PointAt(AkReal32 t) const
Definition: AkVectors.h:1004
Ak3DVector(const AKSIMD_V4F32 &in_v4f32)
Definition: AkVectors.h:156
bool Intersect(Ak3DVector A, Ak3DVector B)
Definition: AkVectors.h:1009
AkReal32 phi
Elevation.
Definition: AkTypes.h:478
AkReal32 X
Definition: AkVectors.h:973
Ak4DVector operator-(const Ak4DVector &b) const
Definition: AkVectors.h:97
bool SeparatingAxisExists(const Ak3DVector &L, const AkBox &B) const
Definition: AkVectors.h:1608
bool IsPointInBox(const Ak3DVector &in_Point) const
Definition: AkVectors.h:1583
Ak4DVector operator/=(const AkReal32 f)
Definition: AkVectors.h:87
AkForceInline bool operator==(const Ak3DVector &b) const
Definition: AkVectors.h:192
AkForceInline Ak3DVector Rotate180X_90Y() const
Definition: AkVectors.h:370
AkForceInline AkQuaternion Inverse() const
Definition: AkVectors.h:878
AkForceInline AkQuaternion operator*(const AkQuaternion &Q) const
Quaternion multiplication.
Definition: AkVectors.h:940
Ak3DIntVector(AkInt32 x, AkInt32 y, AkInt32 z)
Definition: AkVectors.h:116
void SetPlane(Ak3DVector in_p1, Ak3DVector in_p2, Ak3DVector in_p4)
Definition: AkVectors.h:1108
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
Definition: AkPlatformFuncs.h:121
~Ak2DVector()
Definition: AkVectors.h:523
AkForceInline AkReal32 DotProduct(const Ak3DVector &v2) const
Definition: AkVectors.h:462
AkForceInline AkReal32 Length() const
Definition: AkVectors.h:484
static AkForceInline AkReal32 Determinant(const Ak3DVector &a, const Ak3DVector &b, const Ak3DVector &c)
Definition: AkVectors.h:394
static AkForceInline void Diagonal(AkMatrix3x3 &out_mat, AkReal32 in_f)
Definition: AkVectors.h:798
uint8_t AkUInt8
Unsigned 8-bit integer.
Definition: AkTypes.h:57
void Zero()
Definition: AkVectors.h:182
AkForceInline AkReal32 Length()
Definition: AkVectors.h:863
AkMatrix4x4 operator=(AkReal32 *in_Data)
Definition: AkVectors.h:720
AkForceInline Ak3DVector operator=(const AkVector &b)
Definition: AkVectors.h:211
static void Rotation(AkMatrix3x3 &out_mat, AkReal32 in_sin, AkReal32 in_cos, const Ak3DVector &in_axis)
Definition: AkVectors.h:825
AkForceInline bool operator==(const Ak2DVector &b) const
Definition: AkVectors.h:578
AkForceInline Ak3DVector operator*(const Ak3DVector &in_rhs)
Definition: AkVectors.h:766
AkForceInline Ak3DVector operator-(const AkReal32 f) const
Definition: AkVectors.h:304
AkForceInline Ak3DVector operator+(const Ak3DVector &b) const
Definition: AkVectors.h:315
Ak3DVector GetUx() const
Definition: AkVectors.h:1594
void UpdateBoundingBox(AkBoundingBox &out_aabb) const
Definition: AkVectors.h:1650
AkUInt32 count
Definition: AkVectors.h:981
Ak3DVector GetCenter() const
Definition: AkVectors.h:1592
AkPlane()
Definition: AkVectors.h:1088
AkMatrix4x4()
Definition: AkVectors.h:707
AkReal32 X
Definition: AkVectors.h:694
AkReal32 maxt
Definition: AkVectors.h:1082
AkForceInline bool operator>=(const Ak3DVector &b) const
Definition: AkVectors.h:235
~Ak3DVector()
Definition: AkVectors.h:180
Ak3DVector()
Definition: AkVectors.h:135
#define AKVECTORS_PIOVERTWO
Definition: AkVectors.h:49
AkForceInline bool operator!=(const Ak2DVector &b) const
Definition: AkVectors.h:583
AkForceInline bool IsAllPositive() const
Definition: AkVectors.h:687
AkForceInline AkReal32 LengthSquared() const
Definition: AkVectors.h:489
AkForceInline AkReal32 Length() const
Definition: AkVectors.h:588
Ak4DVector()
Definition: AkVectors.h:57
Ak3DVector GetSide() const
Definition: AkVectors.h:1600
AkLine()
Definition: AkVectors.h:987
AkReal32 Y
Y Position.
Definition: AkTypes.h:324
Ak2DVector(AkReal32 x, AkReal32 y)
Definition: AkVectors.h:525
AkForceInline AkMatrix3x3 & operator*=(const AkReal32 &in_f)
Definition: AkVectors.h:790
AkReal32 GetVolume() const
Definition: AkVectors.h:1602
AkReal32 GetD() const
Definition: AkVectors.h:1276
AkReal32 X
X Position.
Definition: AkTypes.h:323
~AkBox()
Definition: AkVectors.h:1562
AkForceInline Ak3DVector operator*(const AkReal32 f) const
Definition: AkVectors.h:270
AkForceInline bool operator>(const Ak3DVector b) const
Definition: AkVectors.h:230
Ak2DVector operator-(const Ak2DVector &b) const
Definition: AkVectors.h:551
AkReal32 m_Data[MAX_SIZE]
Definition: AkVectors.h:730
AkForceInline AkReal32 ACos(AkReal32 in_fAngle) const
Definition: AkVectors.h:1538
AkBoundingBox Intersect(const AkBoundingBox &in_BB) const
Definition: AkVectors.h:1520
AkMatrix3x3()
Definition: AkVectors.h:739
Ak2DVector()
Definition: AkVectors.h:522
#define AKASSERT(Condition)
Definition: AkAssert.h:76
AkReal32 v[4]
Definition: AkVectors.h:109
Spherical coordinates.
Definition: AkTypes.h:477
AkReal32 mint
Definition: AkVectors.h:1081
~AkPlane()
Definition: AkVectors.h:1104
Ak3DVector(AkReal32 x, AkReal32 y, AkReal32 z)
Definition: AkVectors.h:141
AkReal32 Z
Z Position.
Definition: AkTypes.h:325
AkQuaternion()
Definition: AkVectors.h:847
static AkForceInline void OuterProduct(AkMatrix3x3 &out_mat, const Ak3DVector &in_v0, const Ak3DVector &in_v1)
Definition: AkVectors.h:813
Ak3DVector(const AkVector &b)
Definition: AkVectors.h:150
Ak3DVector GetFront() const
Definition: AkVectors.h:1598
Ak3DVector GetUy() const
Definition: AkVectors.h:1595
Ak4DVector operator=(const Ak4DVector &b)
Definition: AkVectors.h:77
AkForceInline bool IsWithin(const AkBoundingBox &in_BB) const
Definition: AkVectors.h:1511
AkReal32 Y
Definition: AkVectors.h:695
AkMatrix4x4 operator/=(const AkReal32 f)
Definition: AkVectors.h:712
AkForceInline bool operator!=(const Ak3DVector &b) const
Definition: AkVectors.h:197
static AkForceInline void Add(AkMatrix3x3 &out_res, const AkMatrix3x3 &in_m0, const AkMatrix3x3 &in_m1)
Definition: AkVectors.h:781
AkForceInline bool IsEmpty() const
Definition: AkVectors.h:1546
AkMatrix3x3 operator/=(const AkReal32 f)
Definition: AkVectors.h:744
AkForceInline Ak3DVector SphericalToCartesian(const AkReal32 azimuth, const AkReal32 elevation)
Definition: AkVectors.h:381
AkForceInline AkReal32 & operator()(const AkUInt32 row, const AkUInt32 column)
Definition: AkVectors.h:756
AkReal32 W
Definition: AkVectors.h:972
void Update(const Ak3DVector &in_point)
Definition: AkVectors.h:1481
Definition: AkVectors.h:1556
AkQuaternion(AkReal32 in_angle, const Ak3DVector &in_axis)
Definition: AkVectors.h:930
AkLine(Ak3DVector in_L, Ak3DVector in_P)
Definition: AkVectors.h:993
~AkMatrix4x4()
Definition: AkVectors.h:708
static AkForceInline void CrossProductMatrix(AkMatrix3x3 &out_mat, const Ak3DVector &in_u)
Definition: AkVectors.h:806
bool DoesRayIntersect(const Ak3DVector &in_Origin, const Ak3DVector &in_Destination, Ak3DVector &out_Intersection) const
Definition: AkVectors.h:1139
~Ak4DVector()
Definition: AkVectors.h:73
Ak3DVector P
Definition: AkVectors.h:1079
AkForceInline bool IsAllPositive() const
Definition: AkVectors.h:495
AkForceInline AkReal32 L2_Norm() const
Definition: AkVectors.h:457
AkReal32 Z
Definition: AkVectors.h:975
AkForceInline AKSIMD_V4F32 PointV4F32() const
Definition: AkVectors.h:162
AkForceInline const AkQuaternion & Normalize()
Definition: AkVectors.h:868
AkForceInline Ak2DVector NormalizeSpherical() const
Definition: AkVectors.h:638
Ak3DVector m_Min
Definition: AkVectors.h:1551
AkForceInline Ak3DVector operator/(const AkReal32 f) const
Definition: AkVectors.h:281
AkQuaternion(const Ak3DVector &in_fromVector)
Definition: AkVectors.h:856
#define ADD(i, j)
AkForceInline void NormalizeSpherical()
Definition: AkVectors.h:667
AkReal32 Y
Definition: AkVectors.h:513
static AkForceInline void Rotation(AkMatrix3x3 &out_mat, AkReal32 in_angle, const Ak3DVector &in_axis)
Definition: AkVectors.h:820
Ak3DVector GetUp() const
Definition: AkVectors.h:1599
AkBoundingBox()
Definition: AkVectors.h:1476
#define AKVECTORS_EPSILON
Definition: AkVectors.h:50
static AkForceInline Ak3DVector Max(const Ak3DVector &A, const Ak3DVector &B)
Definition: AkVectors.h:357
void Init(const Ak3DVector &in_center, const Ak3DVector &in_extent, const Ak3DVector &in_Front, const Ak3DVector &in_Up)
Definition: AkVectors.h:1566
AkReal32 theta
Azimuth.
Definition: AkTypes.h:472
AkForceInline AkMatrix3x3 & operator+=(const AkMatrix3x3 &in_rhs)
Definition: AkVectors.h:775
AkReal32 Y
Definition: AkVectors.h:974
Ak3DVector GetP2() const
Definition: AkVectors.h:1431
AkForceInline const AkReal32 & operator()(const AkUInt32 row, const AkUInt32 column) const
Definition: AkVectors.h:761
~AkMatrix3x3()
Definition: AkVectors.h:740
#define AKSIMD_GETELEMENT_V4F32(__vName, __num__)
Retrieve scalar element from vector.
Definition: AkSimd.h:38
AkForceInline Ak3DVector operator/=(const AkReal32 f)
Definition: AkVectors.h:249
uint32_t AkUInt32
Unsigned 32-bit integer.
Definition: AkTypes.h:59
AkForceInline bool operator<=(const Ak3DVector &b) const
Definition: AkVectors.h:225
AkPlane(Ak3DVector in_p1, Ak3DVector in_p2, Ak3DVector in_p4)
Definition: AkVectors.h:1092
AkQuaternion(const Ak3DVector &in_v0, const Ak3DVector &in_v1)
Definition: AkVectors.h:893
AkInt32 X
X Position.
Definition: AkVectors.h:125
AkForceInline Ak3DVector operator+(const AkReal32 f) const
Definition: AkVectors.h:293
#define EPSILON
Definition: AkVectors.h:1138
3D vector.
Definition: AkTypes.h:306
Ak3DVector GetSize() const
Definition: AkVectors.h:1591
AkForceInline AkReal32 Dot(const Ak3DVector &v2) const
Definition: AkVectors.h:467
Ak3DVector GetP1() const
Definition: AkVectors.h:1430
~Ak3DIntVector()
Definition: AkVectors.h:123
int32_t AkInt32
Signed 32-bit integer.
Definition: AkTypes.h:64
Ak3DVector GetP4() const
Definition: AkVectors.h:1432
AkInt32 Z
Z Position.
Definition: AkVectors.h:127
AkForceInline const Ak3DVector & Normalize()
Definition: AkVectors.h:439
AkForceInline Ak3DVector operator=(const Ak3DVector &b)
Definition: AkVectors.h:202
#define AkForceInline
Definition: AkTypes.h:60
Ak3DVector m_Max
Definition: AkVectors.h:1552
static AkForceInline Ak3DVector Min(const Ak3DVector &A, const Ak3DVector &B)
Definition: AkVectors.h:346
void SetReflection(AkReal32 *out_mat) const
Definition: AkVectors.h:1250
Ak4DVector(const AkVector &b)
Definition: AkVectors.h:65
Ak3DVector L
Definition: AkVectors.h:1078
AkForceInline bool IsWithin(const Ak3DVector &in_Point) const
Definition: AkVectors.h:1504
AkForceInline Ak2DVector operator=(const AkSphericalCoord &b)
Definition: AkVectors.h:543
Ak2DVector operator/=(const AkReal32 f)
Definition: AkVectors.h:569
AkForceInline Ak2DVector LinearCombination(const Ak2DVector &A, const Ak2DVector &B) const
Definition: AkVectors.h:609
AkQuaternion(AkReal32 in_W, AkReal32 in_X, AkReal32 in_Y, AkReal32 in_Z)
Definition: AkVectors.h:849
AkBox()
Definition: AkVectors.h:1558
AkForceInline Ak3DVector Abs() const
Definition: AkVectors.h:503
AkReal32 m_Data[3][3]
Definition: AkVectors.h:840
Definition: AkVectors.h:985
AkForceInline Ak3DVector operator*(const Ak3DVector v2) const
Definition: AkVectors.h:259
AkForceInline Ak3DVector LinearCombination(const Ak3DVector &A, const Ak3DVector &B, const Ak3DVector &C) const
Definition: AkVectors.h:404