Version
menu_open
link

include/AK/Tools/Common/AkVectors.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
00003 released in source code form as part of the SDK installer package.
00004 
00005 Commercial License Usage
00006 
00007 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
00008 may use this file in accordance with the end user license agreement provided 
00009 with the software or, alternatively, in accordance with the terms contained in a
00010 written agreement between you and Audiokinetic Inc.
00011 
00012 Apache License Usage
00013 
00014 Alternatively, this file may be used under the Apache License, Version 2.0 (the 
00015 "Apache License"); you may not use this file except in compliance with the 
00016 Apache License. You may obtain a copy of the Apache License at 
00017 http://www.apache.org/licenses/LICENSE-2.0.
00018 
00019 Unless required by applicable law or agreed to in writing, software distributed
00020 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
00021 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
00022 the specific language governing permissions and limitations under the License.
00023 
00024   Version: <VERSION>  Build: <BUILDNUMBER>
00025   Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
00026 *******************************************************************************/
00027 
00028 // AkVectors.h
00029 //
00030 
00031 #pragma once
00032 
00033 #include <AK/SoundEngine/Common/AkTypes.h>
00034 #include <AK/SoundEngine/Common/AkSpeakerVolumes.h>
00035 #include <AK/SoundEngine/Common/IAkPluginMemAlloc.h>
00036 #include <AK/Tools/Common/AkArray.h>
00037 #include <AK/Tools/Common/AkObject.h>
00038 
00039 #include <math.h>
00040 #include <stdio.h>
00041 
00042 //#define AKVBAP_DEBUG 1
00043 //#define AKPORTALS_DEBUG
00044 
00045 #define AKVECTORS_PI                (3.1415926535897932384626433832795f)
00046 #define AKVECTORS_TWOPI             (6.283185307179586476925286766559f)
00047 #define AKVECTORS_PIOVERTWO         (1.5707963267948966192313216916398f)
00048 #define AKVECTORS_EPSILON           (1.0e-38f)                                  // epsilon value for fast log(0)
00049 
00050 
00051 class AkMatrix4x4
00052 {
00053     static const int MAX_SIZE = 16;
00054 
00055     public:
00056     //-----------------------------------------------------------
00057     // Constructor/Destructor functions
00058     AkMatrix4x4(){}
00059     ~AkMatrix4x4(){}
00060 
00061     //-----------------------------------------------------------
00062     // Basic vector operators
00063     AkMatrix4x4 operator/=(const AkReal32 f)
00064     {
00065         for (int i = 0; i < MAX_SIZE; i++)
00066             m_Data[i] /= f;
00067 
00068         return *this;
00069     }
00070 
00071     AkMatrix4x4 operator=(AkReal32 * in_Data)
00072     {
00073         for (int i = 0; i < MAX_SIZE; i++)
00074         {
00075             m_Data[i] = in_Data[i];
00076         }
00077 
00078         return *this;
00079     }
00080 
00081     AkReal32 m_Data[MAX_SIZE];
00082 };
00083 
00084 class AkMatrix3x3
00085 {
00086 
00087 public:
00088     //-----------------------------------------------------------
00089     // Constructor/Destructor functions
00090     AkMatrix3x3(){}
00091     ~AkMatrix3x3(){}
00092 
00093     //-----------------------------------------------------------
00094     // Basic vector operators
00095     AkMatrix3x3 operator/=(const AkReal32 f)
00096     {
00097         for (int i = 0; i < 3; i++)
00098         {
00099             for (int j = 0; j < 3; j++)
00100             {
00101                 m_Data[i][j] /= f;
00102             }
00103         }
00104         return *this;
00105     }
00106 
00107     AkReal32 m_Data[3][3];
00108 };
00109 
00110 class Ak4DVector
00111 {
00112 public:
00113     //-----------------------------------------------------------
00114     // Constructor/Destructor functions
00115     Ak4DVector()
00116     {
00117         v[0] = 0.0f;
00118         v[1] = 0.0f;
00119         v[2] = 0.0f;
00120         v[3] = 0.0f;
00121     }
00122 
00123     Ak4DVector(const AkVector& b)
00124     {
00125         v[0] = b.X;
00126         v[1] = b.Y;
00127         v[2] = b.Z;
00128         v[3] = 1;
00129     }
00130 
00131     ~Ak4DVector(){}
00132 
00133     //-----------------------------------------------------------
00134     // Basic vector operators
00135     Ak4DVector operator=(const Ak4DVector& b)
00136     {
00137         v[0] = b.v[0];
00138         v[1] = b.v[1];
00139         v[2] = b.v[2];
00140         v[3] = b.v[3];
00141 
00142         return *this;
00143     }
00144 
00145     Ak4DVector operator/=(const AkReal32 f)
00146     {
00147         v[0] = v[0] / f;
00148         v[1] = v[1] / f;
00149         v[2] = v[2] / f;
00150         v[3] = v[3] / f;
00151 
00152         return *this;
00153     }
00154 
00155     Ak4DVector operator-(const Ak4DVector& b) const
00156     {
00157         Ak4DVector p;
00158 
00159         p.v[0] = v[0] - b.v[0];
00160         p.v[1] = v[1] - b.v[1];
00161         p.v[2] = v[2] - b.v[2];
00162         p.v[3] = v[3] - b.v[3];
00163 
00164         return p;
00165     }
00166 
00167     AkReal32    v[4];
00168 };
00169 
00170 struct Ak3DIntVector
00171 {
00172 public:
00173     Ak3DIntVector(){}
00174     Ak3DIntVector(AkInt32 x, AkInt32 y, AkInt32 z)
00175     {
00176         X = x;
00177         Y = y;
00178         Z = z;
00179     }
00180 
00181     ~Ak3DIntVector(){}
00182 
00183     AkInt32     X;  
00184     AkInt32     Y;  
00185     AkInt32     Z;  
00186 };
00187 
00188 class Ak3DVector
00189 {
00190 public:
00191     //-----------------------------------------------------------
00192     // Constructor/Destructor functions
00193     Ak3DVector():
00194     X(0.f),
00195     Y(0.f),
00196     Z(0.f)
00197     {}
00198 
00199     Ak3DVector(
00200         AkReal32                    x,
00201         AkReal32                    y,
00202         AkReal32                    z)
00203     {
00204         X = x;
00205         Y = y;
00206         Z = z;
00207     }
00208     Ak3DVector(const AkVector& b)
00209     {
00210         X = b.X;
00211         Y = b.Y;
00212         Z = b.Z;
00213     }
00214     ~Ak3DVector(){}
00215 
00216     void Zero()
00217     {
00218         X = 0.f;
00219         Y = 0.f;
00220         Z = 0.f;
00221     }
00222 
00223 
00224     //-----------------------------------------------------------
00225     // Basic vector operators
00226     Ak3DVector operator=(const Ak3DVector& b)
00227     {
00228         X = b.X;
00229         Y = b.Y;
00230         Z = b.Z;
00231 
00232         return *this;
00233     }
00234 
00235     AkForceInline Ak3DVector operator=(const AkVector& b)
00236     {
00237         X = b.X;
00238         Y = b.Y;
00239         Z = b.Z;
00240 
00241         return *this;
00242     }
00243 
00244     bool operator<(const Ak3DVector& b) const
00245     {
00246         return X < b.X && Y < b.Y && Z < b.Z;
00247     }
00248 
00249     bool operator<=(const Ak3DVector& b) const
00250     {
00251         return X <= b.X && Y <= b.Y && Z <= b.Z;
00252     }
00253 
00254     bool operator>(const Ak3DVector b) const
00255     {
00256         return X > b.X && Y > b.Y && Z > b.Z;
00257     }
00258 
00259     bool operator>=(const Ak3DVector& b) const
00260     {
00261         return X >= b.X && Y >= b.Y && Z >= b.Z;
00262     }
00263 
00264     Ak3DVector operator*=(const AkReal32 f)
00265     {
00266         X = X * f;
00267         Y = Y * f;
00268         Z = Z * f;
00269 
00270         return *this;
00271     }
00272 
00273     Ak3DVector operator/=(const AkReal32 f)
00274     {
00275         AkReal32 oneoverf = 1.f / f;
00276         X = X * oneoverf;
00277         Y = Y * oneoverf;
00278         Z = Z * oneoverf;
00279 
00280         return *this;
00281     }
00282 
00283     AkForceInline Ak3DVector operator*(const Ak3DVector v2) const
00284     {
00285         Ak3DVector v;
00286 
00287         v.X = X * v2.X;
00288         v.Y = Y * v2.Y;
00289         v.Z = Z * v2.Z;
00290 
00291         return v;
00292     }
00293 
00294     Ak3DVector operator*(const AkReal32 f) const
00295     {
00296         Ak3DVector v;
00297 
00298         v.X = X * f;
00299         v.Y = Y * f;
00300         v.Z = Z * f;
00301 
00302         return v;
00303     }
00304 
00305     AkForceInline Ak3DVector operator/(const AkReal32 f) const
00306     {
00307         Ak3DVector v;
00308         AkReal32 oneoverf = 1.f / f;
00309 
00310         v.X = X * oneoverf;
00311         v.Y = Y * oneoverf;
00312         v.Z = Z * oneoverf;
00313 
00314         return v;
00315     }
00316 
00317     AkForceInline Ak3DVector operator+(const AkReal32 f) const
00318     {
00319         Ak3DVector v;
00320 
00321         v.X = X + f;
00322         v.Y = Y + f;
00323         v.Z = Z + f;
00324 
00325         return v;
00326     }
00327 
00328     Ak3DVector operator+(const Ak3DVector& b) const
00329     {
00330         Ak3DVector v;
00331 
00332         v.X = X + b.X;
00333         v.Y = Y + b.Y;
00334         v.Z = Z + b.Z;
00335 
00336         return v;
00337     }
00338 
00339     Ak3DVector operator-(const Ak3DVector& b) const
00340     {
00341         Ak3DVector v;
00342 
00343         v.X = X - b.X;
00344         v.Y = Y - b.Y;
00345         v.Z = Z - b.Z;
00346 
00347         return v;
00348     }
00349 
00350     operator AkVector()
00351     {
00352         AkVector v;
00353         v.X = X; v.Y = Y; v.Z = Z;
00354 
00355         return v;
00356     }
00357 
00358 
00359     static Ak3DVector Min(const Ak3DVector& A, const Ak3DVector& B)
00360     {
00361         Ak3DVector min;
00362 
00363         min.X = AkMin(A.X, B.X);
00364         min.Y = AkMin(A.Y, B.Y);
00365         min.Z = AkMin(A.Z, B.Z);
00366 
00367         return min;
00368     }
00369 
00370     static Ak3DVector Max(const Ak3DVector& A, const Ak3DVector& B)
00371     {
00372         Ak3DVector max;
00373 
00374         max.X = AkMax(A.X, B.X);
00375         max.Y = AkMax(A.Y, B.Y);
00376         max.Z = AkMax(A.Z, B.Z);
00377 
00378         return max;
00379     }
00380 
00381     //-----------------------------------------------------------
00382     // Conversion functions
00383     AkForceInline Ak3DVector Rotate180X_90Y() const
00384     {
00385         Ak3DVector v;
00386 
00387         v.X = -X;
00388         v.Y = Z;
00389         v.Z = -Y;
00390 
00391         return v;
00392     }
00393 
00394     AkForceInline Ak3DVector SphericalToCartesian(
00395         const AkReal32              azimuth,
00396         const AkReal32              elevation )
00397     {
00398         AkReal32 cosElevation = cosf(elevation);
00399         X = cosf(azimuth) * cosElevation;
00400         Y = sinf(azimuth) * cosElevation;
00401         Z =                 sinf(elevation);
00402 
00403         return *this;
00404     }
00405 
00406     // Determinant of 3 column vectors.
00407     static AkReal32 Determinant(
00408         const Ak3DVector &          a,
00409         const Ak3DVector &          b,
00410         const Ak3DVector &          c)
00411     {
00412         return  (a.X*b.Y*c.Z + a.Y*b.Z*c.X + a.Z*b.X*c.Y) -
00413                 (a.Z*b.Y*c.X + a.Y*b.X*c.Z + a.X*b.Z*c.Y);
00414     }
00415 
00416     // Convert a vector to a different base
00417     AkForceInline Ak3DVector LinearCombination(
00418         const Ak3DVector&           A,
00419         const Ak3DVector&           B,
00420         const Ak3DVector&           C) const
00421     {
00422         Ak3DVector v;
00423 
00424         AkReal32 d = Determinant(A, B, C);
00425 
00426         if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
00427         {
00428             v.X = 0.0f; v.Y = 0.0f; v.Z = 0.0f;
00429             return v;
00430         }
00431 
00432         // http://mathworld.wolfram.com/MatrixInverse.html
00433         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     );
00434         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     );
00435         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     );
00436 
00437         AkReal32 oneover_d = 1.f / d;
00438         invA *= oneover_d;
00439         invB *= oneover_d;
00440         invC *= oneover_d;
00441 
00442         // Project coordinates using a vector to matrix multiplication
00443         v.X = X * invA.X    + Y * invB.X    + Z * invC.X;
00444         v.Y = X * invA.Y    + Y * invB.Y    + Z * invC.Y;
00445         v.Z = X * invA.Z    + Y * invB.Z    + Z * invC.Z;
00446 
00447         // v /= v.Length();
00448 
00449         return v;
00450     }
00451 
00452     void Normalize()
00453     {
00454         AkReal32 l = Length();
00455         //AKASSERT(l != 0.0f);
00456 
00457         if (l == 0.f)
00458             X = Y = Z = 0;
00459 
00460         X /= l;
00461         Y /= l;
00462         Z /= l;
00463     }
00464 
00465     AkReal32 L2_Norm() const
00466     {
00467         return sqrtf(X*X + Y*Y + Z*Z);
00468     }
00469 
00470     AkReal32 DotProduct(const Ak3DVector& v2) const
00471     {
00472         return X*v2.X + Y*v2.Y + Z*v2.Z;
00473     }
00474 
00475     AkReal32 Dot(const Ak3DVector& v2) const
00476     {
00477         return DotProduct(v2);
00478     }
00479 
00480     Ak3DVector Cross(const Ak3DVector& v) const
00481     {
00482         Ak3DVector uxv;
00483         const Ak3DVector& u = *this;
00484 
00485         uxv.X = u.Y*v.Z - u.Z*v.Y;
00486         uxv.Y = u.X*v.Z - u.Z*v.X;
00487         uxv.Z = u.X*v.Y - u.Y*v.X;
00488 
00489         return uxv;
00490     }
00491     //
00492     AkForceInline AkReal32 Length() const
00493     {
00494         return sqrtf(X*X+Y*Y+Z*Z);
00495     }
00496 
00497     AkForceInline AkReal32 LengthSquared() const
00498     {
00499         return X*X + Y*Y + Z*Z;
00500     }
00501 
00502     // Usefull in VBAP algorithm, only points that are a positive linear composition matters.
00503     AkForceInline bool IsAllPositive() const
00504     {
00505         const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f;
00506         return X >= -POSITIVE_TEST_EPSILON &&
00507             Y >= -POSITIVE_TEST_EPSILON &&
00508             Z >= -POSITIVE_TEST_EPSILON;
00509     }
00510 
00511     AkReal32                        X;
00512     AkReal32                        Y;
00513     AkReal32                        Z;
00514 };
00515 
00516 class Ak2DVector
00517 {
00518 public:
00519     //-----------------------------------------------------------
00520     // Constructor/Destructor functions
00521     Ak2DVector(){}
00522     ~Ak2DVector(){}
00523 
00524     Ak2DVector(
00525         AkReal32                    x,
00526         AkReal32                    y)
00527     {
00528         X = x;
00529         Y = y;
00530     }
00531 
00532     //-----------------------------------------------------------
00533     // Basic vector operators
00534     AkForceInline Ak2DVector operator=(const Ak2DVector& b)
00535     {
00536         X = b.X;
00537         Y = b.Y;
00538 
00539         return *this;
00540     }
00541 
00542     AkForceInline Ak2DVector operator=(const AkSphericalCoord& b)
00543     {
00544         X = b.theta;
00545         Y = b.phi;
00546 
00547         return *this;
00548     }
00549 
00550     Ak2DVector operator-(const Ak2DVector& b) const
00551     {
00552         Ak2DVector v;
00553 
00554         v.X = X - b.X;
00555         v.Y = Y - b.Y;
00556 
00557         return v;
00558     }
00559 
00560     Ak2DVector operator*=(const AkReal32 f)
00561     {
00562         X = X * f;
00563         Y = Y * f;
00564 
00565         return *this;
00566     }
00567 
00568     Ak2DVector operator/=(const AkReal32 f)
00569     {
00570         AkReal32 oneoverf = 1.f / f;
00571         X = X * oneoverf;
00572         Y = Y * oneoverf;
00573 
00574         return *this;
00575     }
00576 
00577     AkForceInline bool operator==(const Ak2DVector& b) const
00578     {
00579         return b.X == X && b.Y == Y;
00580     }
00581 
00582     AkForceInline bool operator!=(const Ak2DVector& b) const
00583     {
00584         return b.X != X && b.Y != Y;
00585     }
00586 
00587     AkForceInline AkReal32 Length() const
00588     {
00589         return sqrtf(X*X+Y*Y);
00590     }
00591 
00592     //-----------------------------------------------------------
00593     // Conversion functions
00594     AkForceInline Ak2DVector CartesianToSpherical( const Ak3DVector& in_Cartesian )
00595     {
00596         // (radial, azimuth, elevation)
00597         AkReal32 r = sqrtf( in_Cartesian.X*in_Cartesian.X + in_Cartesian.Y*in_Cartesian.Y + in_Cartesian.Z*in_Cartesian.Z);
00598         AKASSERT( r != 0);
00599 
00600         X = atan2f(in_Cartesian.Y, in_Cartesian.X);
00601         Y = asinf(in_Cartesian.Z / r);
00602 
00603         NormalizeSpherical();
00604 
00605         return *this;
00606     }
00607 
00608     AkForceInline Ak2DVector LinearCombination(
00609         const Ak2DVector&           A,
00610         const Ak2DVector&           B) const
00611     {
00612         Ak2DVector v;
00613 
00614         // Project coordinates using a vector to matrix multiplication
00615         AkReal32 d = (A.X*B.Y - A.Y*B.X);
00616 
00617         if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
00618         {
00619             v.X = 0.0f; v.Y = 0.0f;
00620             return v;
00621         }
00622 
00623         Ak2DVector invA = Ak2DVector( B.Y, -A.Y );
00624         Ak2DVector invB = Ak2DVector( -B.X, A.X );
00625 
00626         AkReal32 oneover_d = 1.f / d;
00627         invA *= oneover_d;
00628         invB *= oneover_d;
00629 
00630         v.X = X * invA.X + Y * invB.X;
00631         v.Y = X * invA.Y + Y * invB.Y;
00632         // v /= v.Length();
00633 
00634         return v;
00635     }
00636 
00637     AkForceInline Ak2DVector NormalizeSpherical() const
00638     {
00639         /*
00640             Normalise spherical coordinates.
00641                 X (azimuthal)   -> [-PI, PI],       circle lies on xy plan,         0 is on X axix
00642                 Y (elevation)   -> [-PI/2, PI/2],   half circle on Z axis,          0 on XY plan, PI/2 straigt up on Z axis.
00643         */
00644 
00645         Ak2DVector v;
00646 
00647         v.X = X;
00648         v.Y = Y;
00649 
00650         if (X > AKVECTORS_PI)
00651             v.X = X - AKVECTORS_TWOPI;
00652 
00653         if (X < -AKVECTORS_PI)
00654             v.X = X + AKVECTORS_TWOPI;
00655 
00656         if (Y > AKVECTORS_PIOVERTWO)
00657             v.Y = Y - AKVECTORS_PI;
00658 
00659         if (Y < -AKVECTORS_PIOVERTWO)
00660             v.Y = Y + AKVECTORS_PI;
00661 
00662         AKASSERT(X<AKVECTORS_PI);
00663         AKASSERT(Y<AKVECTORS_PIOVERTWO);
00664 
00665         return v;
00666     }
00667 
00668     AkForceInline void NormalizeSpherical()
00669     {
00670         /*
00671             Normalise spherical coordinates.
00672                 X (azimuthal)   -> [-PI, PI],       circle lies on xy plan,     0 is on X axix
00673                 Y (elevation)   -> [-PI/2, PI/2],   half circle on Z axis,      0 on XY plan, PI/2 straigt up on Z axis.
00674         */
00675 
00676         if (X > AKVECTORS_PI)
00677             X = X - AKVECTORS_TWOPI;
00678 
00679         if (X < -AKVECTORS_PI)
00680             X = X + AKVECTORS_TWOPI;
00681 
00682         if (Y > AKVECTORS_PIOVERTWO)
00683             Y = Y - AKVECTORS_PI;
00684 
00685         if (Y < -AKVECTORS_PIOVERTWO)
00686             Y = Y + AKVECTORS_PI;
00687     }
00688 
00689     // Useful in VBAP algorithm, only points that are a positive linear composition matters.
00690     AkForceInline bool IsAllPositive() const
00691     {
00692         const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f; //0.005f;
00693         return X >= -POSITIVE_TEST_EPSILON &&
00694             Y >= -POSITIVE_TEST_EPSILON;
00695     }
00696 
00697     AkReal32                        X;
00698     AkReal32                        Y;
00699 };
00700 
00701 struct AkIntersectionPoints
00702 {
00703     Ak3DVector points[2];
00704     AkUInt32 count;
00705 };
00706 
00707 class AkLine
00708 {
00709 public:
00710     AkLine()
00711     {
00712         mint = 1.175494351e-38F;
00713         maxt = 3.402823466e+38F;
00714     }
00715 
00716     AkLine(
00717         Ak3DVector                  in_L,
00718         Ak3DVector                  in_P
00719         )
00720     {
00721         L = in_L;
00722         P = in_P;
00723         mint = 1.175494351e-38F;
00724         maxt = 3.402823466e+38F;
00725     }
00726 
00727     Ak3DVector PointAt(AkReal32 t) const
00728     {
00729         return P + L*t;
00730     }
00731 
00732     bool Intersect(
00733         Ak3DVector A,
00734         Ak3DVector B)
00735     {
00736         Ak3DVector L2 = B - A;
00737 
00738         /*
00739         a (V1 X V2) = (P2 - P1) X V2
00740         If the lines intersect at a single point, then the resultant vectors
00741         on each side of this equation must be parallel, and the left side must
00742         not be the zero vector. We should check to make sure that this is
00743         true. Once we have checked this, we can solve for 'a' by taking the
00744         magnitude of each side and dividing. If the resultant vectors are
00745         parallel, but in opposite directions, then 'a' is the negative of the
00746         ratio of magnitudes. Once we have 'a' we can go back to the equation
00747         for L1 to find the intersection point.
00748         */
00749         Ak3DVector V1 = L;
00750         Ak3DVector V2 = B - A;
00751         Ak3DVector P1 = P;
00752         Ak3DVector P2 = A;
00753 
00754         // k(V1 X V2) = (A - P) X V2
00755 
00756         Ak3DVector v1CrossV2 = V1.Cross(V2);
00757         AkReal32 det = Ak3DVector::Determinant(
00758             P2 - P1,
00759             V2,
00760             v1CrossV2
00761             );
00762         AkReal32 t = det / v1CrossV2.LengthSquared();
00763 
00764         det = Ak3DVector::Determinant(
00765             P2 - P1,
00766             V1,
00767             v1CrossV2
00768             );
00769         AkReal32 s = det / v1CrossV2.LengthSquared();
00770 
00771         AkReal32 distsqrd = ((P2 + V2*s) - (P1 + V1*t)).LengthSquared();
00772 
00773         if ((AkReal32)fabs(v1CrossV2.L2_Norm()) >= AKVECTORS_EPSILON
00774             && distsqrd < 0.001
00775             && s <= 1.0f )
00776         {
00777 #ifdef AKPORTALS_DEBUG
00778             Ak3DVector minPoint = PointAt(t);
00779 
00780             char msg[256];
00781             sprintf(msg, "L1a=[%0.2f,%0.2f,%0.2f];\n", P.X, P.Y, P.Z); AKPLATFORM::OutputDebugMsg(msg);
00782             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);
00783             sprintf(msg, "L2a=[%0.2f,%0.2f,%0.2f];\n", A.X, A.Y, A.Z); AKPLATFORM::OutputDebugMsg(msg);
00784             sprintf(msg, "L2b=[%0.2f,%0.2f,%0.2f];\n", B.X, B.Y, B.Z); AKPLATFORM::OutputDebugMsg(msg);
00785             sprintf(msg, "%% t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
00786             sprintf(msg, "intrPoint=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
00787             sprintf(msg, "\n"); AKPLATFORM::OutputDebugMsg(msg);
00788 #endif
00789 
00790             mint = AkMin(mint, t);
00791             maxt = AkMax(maxt, t);
00792             
00793             return true;
00794         }
00795 
00796 #ifdef AKPORTALS_DEBUG
00797     //  char msg[256];
00798     //  sprintf(msg, "%% DISCARTED t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
00799 #endif
00800         return false;
00801     }
00802 
00803     Ak3DVector L;
00804     Ak3DVector P;
00805 
00806     AkReal32 mint;
00807     AkReal32 maxt;
00808 };
00809 
00810 class AkPlane
00811 {
00812 public:
00813     AkPlane()
00814     {
00815     }
00816 
00817     AkPlane(
00818         Ak3DVector                  in_p1,
00819         Ak3DVector                  in_p2,
00820         Ak3DVector                  in_p4
00821         )
00822     {
00823         SetPlane(
00824             in_p1,
00825             in_p2,
00826             in_p4);
00827     }
00828 
00829     ~AkPlane()
00830     {
00831     }
00832 
00833     void SetPlane(
00834         Ak3DVector                  in_p1,
00835         Ak3DVector                  in_p2,
00836         Ak3DVector                  in_p4
00837         )
00838     {
00839         // Reorder A-B-C to clockwwise if necessary
00840         AKASSERT(in_p1.X < 100000 && in_p1.X > -100000);
00841         AKASSERT(in_p1.Y < 100000 && in_p1.Y > -100000);
00842         AKASSERT(in_p1.Z < 100000 && in_p1.Z > -100000);
00843 
00844         AKASSERT(in_p2.X < 100000 && in_p2.X > -100000);
00845         AKASSERT(in_p2.Y < 100000 && in_p2.Y > -100000);
00846         AKASSERT(in_p2.Z < 100000 && in_p2.Z > -100000);
00847 
00848         AKASSERT(in_p4.X < 100000 && in_p4.X > -100000);
00849         AKASSERT(in_p4.Y < 100000 && in_p4.Y > -100000);
00850         AKASSERT(in_p4.Z < 100000 && in_p4.Z > -100000);
00851 
00852         p1 = in_p1;
00853         p2 = in_p2;
00854         p4 = in_p4;
00855 
00856         SetNormal();
00857 
00858         // Ax + By + Cz + D = 0
00859         // Find D using the normal and a point
00860         D = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
00861     }
00862 
00863 #define EPSILON 0.01f
00864     bool DoesRayIntersect(
00865         const Ak3DVector&           in_Origin,
00866         const Ak3DVector&           in_Destination,
00867         Ak3DVector&                 out_Intersection
00868         ) const
00869     {
00870         AkReal32 A = N.X;
00871         AkReal32 B = N.Y;
00872         AkReal32 C = N.Z;
00873 
00874         Ak3DVector ray = in_Destination - in_Origin;
00875         AkReal32 rayLength = ray.Length();
00876 
00877         Ak3DVector intersect;
00878 
00879         // If ray is < EPSILON, use on of the point directly for the test and skip the linear projection
00880         if (rayLength <= EPSILON)
00881         {
00882             Ak3DVector temp = in_Origin - p1;
00883             AkReal32 dot = temp.DotProduct(N);
00884             if (dot < EPSILON && dot > -EPSILON)
00885             {
00886                 intersect = in_Origin;
00887             }
00888             else
00889             {
00890                 // For debug only, to remove
00891                 out_Intersection = p1;
00892                 return false;
00893             }
00894 
00895         }
00896         else
00897         {
00898             // Normalize ray
00899             ray.Normalize();
00900 
00901             // TODO: possible fix for all edge cases
00902             // 1) if ray len ~= 0, only check if one of the point is on target, ie: assign the intersect point
00903 
00904             // Is ray parallel to the plane?
00905             if ((A*ray.X + B*ray.Y + C*ray.Z) == 0.0f)
00906             {
00907                 // For debug only, to remove
00908                 AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
00909                 intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
00910                 out_Intersection = intersect; // For debugging
00911                 return false;
00912             }
00913 
00914 
00915             // Distance along the ray where reflector is hit
00916             AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
00917 
00918             // Is the ray going towards the plane? Is it long enough?
00919             if (t < -EPSILON || t >(rayLength + EPSILON))
00920             {
00921                 // For debug only, to remove
00922                 intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
00923                 out_Intersection = intersect; // For debugging
00924                 return false; // The ray doesn't intersect
00925             }
00926 
00927             // Find the coordinate of intersection on the plane
00928             intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
00929         }
00931         //
00932         //      p2____v3____p3
00933         //      |     .     |
00934         //      ^   inter   v4
00935         //      v1          v
00936         //      |           |
00937         //      p1__ v2>___p4
00938 
00939         Ak3DVector v1 = p2 - p1;
00940         Ak3DVector v2 = p4 - p1;
00941         Ak3DVector vInter1 = intersect - p1;
00942 
00943         Ak3DVector p3 = p4 + v1;
00944         Ak3DVector v3 = p2 - p3;
00945         Ak3DVector v4 = p4 - p3;
00946         Ak3DVector vInter2 = intersect - p3;
00947 
00948         v1.Normalize(); v2.Normalize(); v3.Normalize(); v4.Normalize(); vInter1.Normalize(); vInter2.Normalize();
00949 
00950         // Since it's a square, the angle between the point of intersection and any segment of the pannel should be < 90 degree,
00951         // therefore the dot product of the two normalized vectors should be > 0
00952         AkReal32 dot1 = v1.DotProduct(vInter1);
00953         AkReal32 dot2 = v2.DotProduct(vInter1);
00954         AkReal32 dot3 = v3.DotProduct(vInter2);
00955         AkReal32 dot4 = v4.DotProduct(vInter2);
00956 
00957         out_Intersection = intersect;
00958 
00959         return dot1 >= -EPSILON && dot2 >= -EPSILON && dot3 >= -EPSILON && dot4 >= -EPSILON;
00960     }
00961 
00962     AkReal32 DistPoint_to_Plane(
00963         Ak3DVector          in_P,
00964         Ak3DVector&         out_B) const
00965     {
00966         AkReal32 distance = (AkReal32)(AkReal32)fabs(N.X * in_P.X + N.Y * in_P.Y + N.Z * in_P.Z + D);
00967 
00968         Ak3DVector pointToPlane = N;
00969         pointToPlane *= distance;
00970 
00971         out_B = in_P + pointToPlane;
00972 
00973         return (AkReal32)fabs(distance);
00974     }
00975 
00976     void SetReflection(
00977         AkReal32*           out_mat) const
00978     {
00979         // http://ami.ektf.hu/uploads/papers/finalpdf/AMI_40_from175to186.pd
00980         /* m_pReflectionMatrix
00981         reflection on z axis
00982 
00983         P0 (x0, y0, z0), P1 (x1, y1, z1) and P2 (x2, y2, z2),
00984         normal = (cx, cy, cz)
00985         d = -CxX0 - CyY0 - CzZ0
00986 
00987         Reflect =   1-2Cx^2     -2CxCy      -2CxCz      -2Cxd
00988         -2CxCy      1-2Cy^2     -2CyCz      -2Cyd
00989         -2CxCz      -2CyCz      1-2Cz^2     -2Czd
00990         0           0           0           1
00991         */
00992 
00993         AkReal32 d = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
00994 
00995         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;
00996         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;
00997         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;
00998         out_mat[0 + 12] = 0;                out_mat[1 + 12] = 0;                    out_mat[2 + 12] = 0;                    out_mat[3 + 12] = 1;
00999     }
01000 
01001     Ak3DVector GetN() const { return N; }
01002     AkReal32 GetD() const { return D; }
01003 
01004     bool FindIntersectionPoints(
01005         const AkPlane& in_PlaneB,
01006         AkIntersectionPoints& out_Intrs) const
01007     {
01008         out_Intrs.count = 0;
01009 
01010         // Use vector to solve A
01011 
01012         Ak3DVector point;
01013 
01014         Ak3DVector N1 = N;
01015         Ak3DVector N2 = in_PlaneB.GetN();
01016         AkReal32 D1 = D;
01017         AkReal32 D2 = in_PlaneB.GetD();
01018 
01019         Ak3DVector L = N1.Cross(N2);
01020         if (L.Length() < 0.001f)
01021         {
01022             return false; // The two planes are parallel
01023         }
01024 
01025         AkUInt8 pivotAxis = 0;
01026 
01027         if ((AkReal32)fabs(L.Y) > (AkReal32)fabs(L.X))
01028         {
01029             pivotAxis = 1;
01030             if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.Y))
01031             {
01032                 pivotAxis = 2;
01033             }
01034         }
01035         else if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.X))
01036         {
01037             pivotAxis = 2;
01038         }
01039 
01040         /*
01041         Pu = ( N1v*D2 - N2v*D1 ) / Lw
01042         Pv = ( N2u*D1 - N1u*D2 ) / Lw
01043         Pz = 0
01044         */
01045 
01046         switch (pivotAxis)
01047         {
01048         case 0:
01049             AKASSERT((AkReal32)fabs(L.X) > AKVECTORS_EPSILON);
01050             point.X = 0.f;
01051             point.Y = (N1.Z*D2 - N2.Z*D1) / L.X;
01052             point.Z = (N2.Y*D1 - N1.Y*D2) / L.X;
01053             break;
01054         case 1:
01055             AKASSERT((AkReal32)fabs(L.Y) > AKVECTORS_EPSILON);
01056             point.X = (N1.Z*D2 - N2.Z*D1) / L.Y;
01057             point.Y = 0.f;
01058             point.Z = (N2.X*D1 - N1.X*D2) / L.Y;
01059             break;
01060         case 2:
01061             AKASSERT((AkReal32)fabs(L.Z) > AKVECTORS_EPSILON);
01062             point.X = (N1.Y*D2 - N2.Y*D1) / L.Z;
01063             point.Y = (N2.X*D1 - N1.X*D2) / L.Z;
01064             point.Z = 0.f;
01065             break;
01066         };
01067 
01068 
01069 
01070         L.Normalize();
01071 
01072         AkLine intrLine = AkLine(L, point);
01073         AkLine intrLine2 = AkLine(L, point);
01074 
01075         //in_PlaneB.GetP1()
01076 
01077         // find min max
01078         AkUInt32 cpt = 0;
01079         AkUInt32 cpt2 = 0;
01080         Ak3DVector p3 = GetP2() + (GetP4() - GetP1());
01081 
01082 #ifdef AKPORTALS_DEBUG
01083         char msg[256];
01084         sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
01085         sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
01086         sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
01087 
01088         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);
01089         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);
01090         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);
01091 
01092         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);
01093         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);
01094 
01095 
01096         sprintf(msg, "%% Plane intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
01097 #endif
01098         // for the four lines in rectangle
01099         // Find where the line is crossing with plane A
01100         if (intrLine.Intersect(GetP1(), GetP2())) cpt++;
01101         if (intrLine.Intersect(GetP1(), GetP4())) cpt++;
01102         if (intrLine.Intersect(GetP2(), p3)) cpt++;
01103         if (intrLine.Intersect(p3, GetP4())) cpt++;
01104         //AKASSERT(cpt == 2);
01105 
01106 #ifdef AKPORTALS_DEBUG
01107         sprintf(msg, "%% Portal intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
01108 #endif
01109 
01110         // Find where the line is crossing with plane B
01111         p3 = in_PlaneB.GetP2() + (in_PlaneB.GetP4() - in_PlaneB.GetP1());
01112         if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP2())) cpt2++;
01113         if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP4())) cpt2++;
01114         if (intrLine2.Intersect(in_PlaneB.GetP2(), p3)) cpt2++;
01115         if (intrLine2.Intersect(p3, in_PlaneB.GetP4())) cpt2++;
01116         // **AKASSERT(cpt2 == 2 || cpt == 2);
01117 
01118         if (cpt < 2 || cpt2 < 2)
01119         {
01120 #ifdef AKPORTALS_DEBUG
01121             sprintf(msg, "%% NON \n"); AKPLATFORM::OutputDebugMsg(msg);
01122             sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
01123 #endif
01124             return false;
01125         }
01126 
01127         AkReal32 start = AkMax(intrLine.mint, intrLine2.mint);
01128         AkReal32 end = AkMin(intrLine.maxt, intrLine2.maxt);
01129 
01130         Ak3DVector minPoint = intrLine.PointAt(start);
01131         Ak3DVector maxPoint = intrLine.PointAt(end);
01132 #ifdef AKPORTALS_DEBUG
01133         sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
01134         sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
01135         sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
01136 
01137         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);
01138         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);
01139         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);
01140 
01141         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);
01142         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);
01143 
01144         sprintf(msg, "intr1=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
01145         sprintf(msg, "intr2=[%0.2f,%0.2f,%0.2f];\n", maxPoint.X, maxPoint.Y, maxPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
01146 
01147         sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
01148 #endif
01149         out_Intrs.points[0] = minPoint;
01150         out_Intrs.points[1] = maxPoint;
01151         out_Intrs.count = 2;
01152 
01153         return true;
01154     }
01155 
01156     Ak3DVector GetP1() const { return p1; }
01157     Ak3DVector GetP2() const { return p2; }
01158     Ak3DVector GetP4() const { return p4; }
01159 
01160 private:
01161     bool SetNormal()
01162     {
01163         //m_pNormal = (B-A) cross (C-A); normalize
01164         Ak3DVector a = p2 - p1;
01165         Ak3DVector b = p4 - p1;
01166 
01167         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);
01168 
01169         AkReal32 len = N.Length();
01170         AKASSERT(len > 0.f);
01171 
01172         if (len > 0)
01173         {
01174             N /= len;
01175         }
01176         else
01177         {
01178             // TODO handle invalid reflectors
01179             return false;
01180         }
01181 
01182         return true;
01183     };
01184 
01185     /*
01186     p2__________p3
01187     |     .     |
01188     ^   inter   v3
01189     v1          v
01190     |           |
01191     p1__ v2>___p4
01192     */
01193 
01194     Ak3DVector                      p1;     // Bottom left
01195     Ak3DVector                      p2;     // Top left
01196     Ak3DVector                      p4;     // Tottom right
01197     Ak3DVector                      N;      // Normal vector
01198     AkReal32                        D;      // Plane equation: Ax + By + Cz = D => N.Xx + N.Yy + N.Zz = D
01199 };
01200 
01201 struct AkBoundingBox
01202 {
01203     AkBoundingBox() :
01204         m_Min(Ak3DVector(100000.f, 100000.f, 100000.f)),
01205         m_Max(Ak3DVector(-100000.f, -100000.f, -100000.f))
01206     {}
01207 
01208     void Update(
01209         const Ak3DVector &      in_point
01210         )
01211     {
01212         if (m_Min.X > in_point.X)
01213             m_Min.X = in_point.X;
01214 
01215         if (m_Min.Y > in_point.Y)
01216             m_Min.Y = in_point.Y;
01217 
01218         if (m_Min.Z > in_point.Z)
01219             m_Min.Z = in_point.Z;
01220 
01221         if (m_Max.X < in_point.X)
01222             m_Max.X = in_point.X;
01223 
01224         if (m_Max.Y < in_point.Y)
01225             m_Max.Y = in_point.Y;
01226 
01227         if (m_Max.Z < in_point.Z)
01228             m_Max.Z = in_point.Z;
01229     }
01230 
01231     bool IsWithin(
01232         const Ak3DVector &      in_Point
01233         ) const
01234     {
01235         return in_Point >= m_Min && in_Point <= m_Max;
01236     }
01237 
01238     bool IsWithin(
01239         const AkBoundingBox &   in_BB
01240         ) const
01241     {
01242         return (m_Min.X <= in_BB.m_Max.X && m_Max.X >= in_BB.m_Min.X) &&
01243             (m_Min.Y <= in_BB.m_Max.Y && m_Max.Y >= in_BB.m_Min.Y) &&
01244             (m_Min.Z <= in_BB.m_Max.Z && m_Max.Z >= in_BB.m_Min.Z);
01245     }
01246 
01247     // returns acos(in_fAngle)
01248     AkForceInline AkReal32 ACos(
01249         AkReal32            in_fAngle
01250         ) const
01251     {
01252         AKASSERT((in_fAngle <= 1.0f) && (in_fAngle >= -1.0f));
01253         return acosf(in_fAngle);
01254     }
01255 
01256     Ak3DVector                      m_Min;
01257     Ak3DVector                      m_Max;
01258 };
01259 
01260 class AkBox
01261 {
01262 public:
01263     AkBox()
01264     {
01265         m_Center = Ak3DVector();
01266         m_Size = Ak3DVector();
01267         m_Front = Ak3DVector();
01268         m_Up = Ak3DVector();
01269     }
01270 
01271     ~AkBox()
01272     {
01273     }
01274 
01275     void Init(
01276         const Ak3DVector &      in_center,
01277         const Ak3DVector &      in_size,
01278         const Ak3DVector &      in_Front,
01279         const Ak3DVector &      in_Up )
01280     {
01281         m_Center = in_center;
01282         m_Size = in_size;
01283 
01284         m_Front = in_Front,
01285         m_Up = in_Up;
01286     }
01287 
01288     void UpdateBoundingBox(
01289         const Ak3DVector &      in_point
01290         )
01291     {
01292         m_BB.Update(in_point);
01293     }
01294 
01295     bool IsPointInBoundingBox(
01296         const Ak3DVector &      in_Point
01297         ) const
01298     {
01299         return m_BB.IsWithin(in_Point);
01300     }
01301 
01302     AkBoundingBox GetBoundingBox() const { return m_BB; }
01303 
01304     bool IsBoxInBoundingBox(
01305         const AkBox &       in_Box
01306         ) const
01307     {
01308         return (m_BB.IsWithin(in_Box.GetBoundingBox()));
01309     }
01310 
01311     bool IsPointInBox(
01312         const Ak3DVector &      in_Point
01313         ) const
01314     {
01315         // Check bounding box
01316         if (IsPointInBoundingBox(in_Point))
01317         {
01318             /*
01319             // http://stackoverflow.com/questions/21037241/how-to-determine-a-point-is-inside-or-outside-a-cube
01320             down vote
01321             1. Pick Any One Out of Four Diagonals Of Cube
01322             2. Check Your Point is within the range of diagonal points.
01323             example. you picked diagonal having start(0,9,1) and end(10,3,-1)
01324 
01325             So for P1(5,6,0)
01326             P.x (5) > Start.x(0) & P.x(5) < End.x(10)
01327             P.y (6) < Start.x(9) & P.y(6) > End.x(3)
01328             P.z (0) < Start.x(1) & P.z(0) > End.x(-1)
01329 
01330             P1 is inside
01331 
01332             for P2(5,6,6)
01333             P.x (5) > Start.x(0) & P.x(5) < End.x(10)
01334             P.y (6) < Start.x(9) & P.y(6) > End.x(3)
01335             P.z (6) > Start.x(1) & P.z(6) > End.x(-1) <-- Not Within Range
01336             */
01337         }
01338         else
01339         {
01340             return false;
01341         }
01342 
01343         return true;
01344     }
01345 
01346     Ak3DVector GetSize() const { return m_Size; }
01347     Ak3DVector GetCenter() const { return m_Center; }
01348 
01349     Ak3DVector GetUx() const { return m_Front; }
01350     Ak3DVector GetUy() const { return m_Up; }
01351     Ak3DVector GetUz() const { return m_Front.Cross(m_Up); }
01352 
01353     Ak3DVector GetFront() const { return m_Front; }
01354     Ak3DVector GetUp() const { return m_Up; }
01355     Ak3DVector GetSide() const { return m_Front.Cross(m_Up); }
01356 
01357     AkReal32 GetVolume() const
01358     {
01359         return m_Size.X * m_Size.Y * m_Size.Z;
01360     }
01361 
01362     bool SeparatingAxisExists(
01363         const Ak3DVector&       L,
01364         const AkBox&            B
01365         ) const
01366     {
01367         // Separating Axis Theorem for Oriented Bounding Boxes by Johnny Huynh
01368         const AkBox& A = *this;
01369         Ak3DVector T = B.GetCenter() - A.GetCenter();
01370 
01371         AkReal32 WA = A.GetSize().X / 2.f;
01372         AkReal32 HA = A.GetSize().Y / 2.f;
01373         AkReal32 DA = A.GetSize().Z / 2.f;
01374 
01375         AkReal32 WB = B.GetSize().X / 2.f;
01376         AkReal32 HB = B.GetSize().Y / 2.f;
01377         AkReal32 DB = B.GetSize().Z / 2.f;
01378 
01379         Ak3DVector Ax = A.GetUx();
01380         Ak3DVector Ay = A.GetUy();
01381         Ak3DVector Az = A.GetUz();
01382 
01383         Ak3DVector Bx = B.GetUx();
01384         Ak3DVector By = B.GetUy();
01385         Ak3DVector Bz = B.GetUz();
01386 
01387         Ax.Normalize(); Ay.Normalize(); Az.Normalize();
01388         Bx.Normalize(); By.Normalize(); Bz.Normalize();
01389 
01390         /*
01391         | T • L | > | (WA*Ax) • L | + | (HA*Ay) • L | + |(DA*Az) • L | +
01392                     | (WB*Bx) • L | +| (HB*By) • L | +| (DB*Bz) • L |*/
01393 
01394         AkReal32 left = (AkReal32)fabs(T.DotProduct(L));
01395         AkReal32 dpax = (AkReal32)fabs((Ax*WA).DotProduct(L));
01396         AkReal32 dpay = (AkReal32)fabs((Ay*HA).DotProduct(L));
01397         AkReal32 dpaz = (AkReal32)fabs((Az*DA).DotProduct(L));
01398         AkReal32 dpbx = (AkReal32)fabs((Bx*WB).DotProduct(L));
01399         AkReal32 dpby = (AkReal32)fabs((By*HB).DotProduct(L));
01400         AkReal32 dpbz = (AkReal32)fabs((Bz*DB).DotProduct(L));
01401 
01402         AkReal32 right = dpax + dpay + dpaz + dpbx + dpby + dpbz;
01403 
01404         return left > right;
01405     }
01406 
01407 private:
01408 
01409     Ak3DVector                      m_Center;
01410     Ak3DVector                      m_Size;
01411     AkBoundingBox                   m_BB;
01412 
01413     Ak3DVector                      m_Front;
01414     Ak3DVector                      m_Up;
01415 };

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