版本

menu_open

include/AK/Tools/Common/AkVectors.h

浏览该文件的文档。
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/AkSimd.h>
00035 #include <AK/SoundEngine/Common/AkSpeakerVolumes.h>
00036 #include <AK/SoundEngine/Common/IAkPluginMemAlloc.h>
00037 #include <AK/Tools/Common/AkArray.h>
00038 #include <AK/Tools/Common/AkObject.h>
00039 
00040 #include <math.h>
00041 #include <stdio.h>
00042 #include <float.h>
00043 
00044 //#define AKVBAP_DEBUG 1
00045 //#define AKPORTALS_DEBUG
00046 
00047 #define AKVECTORS_PI                (3.1415926535897932384626433832795f)
00048 #define AKVECTORS_TWOPI             (6.283185307179586476925286766559f)
00049 #define AKVECTORS_PIOVERTWO         (1.5707963267948966192313216916398f)
00050 #define AKVECTORS_EPSILON           (1.0e-38f)                                  // epsilon value for fast log(0)
00051 
00052 class Ak4DVector
00053 {
00054 public:
00055     //-----------------------------------------------------------
00056     // Constructor/Destructor functions
00057     Ak4DVector()
00058     {
00059         v[0] = 0.0f;
00060         v[1] = 0.0f;
00061         v[2] = 0.0f;
00062         v[3] = 0.0f;
00063     }
00064 
00065     Ak4DVector(const AkVector& b)
00066     {
00067         v[0] = b.X;
00068         v[1] = b.Y;
00069         v[2] = b.Z;
00070         v[3] = 1;
00071     }
00072 
00073     ~Ak4DVector(){}
00074 
00075     //-----------------------------------------------------------
00076     // Basic vector operators
00077     Ak4DVector operator=(const Ak4DVector& b)
00078     {
00079         v[0] = b.v[0];
00080         v[1] = b.v[1];
00081         v[2] = b.v[2];
00082         v[3] = b.v[3];
00083 
00084         return *this;
00085     }
00086 
00087     Ak4DVector operator/=(const AkReal32 f)
00088     {
00089         v[0] = v[0] / f;
00090         v[1] = v[1] / f;
00091         v[2] = v[2] / f;
00092         v[3] = v[3] / f;
00093 
00094         return *this;
00095     }
00096 
00097     Ak4DVector operator-(const Ak4DVector& b) const
00098     {
00099         Ak4DVector p;
00100 
00101         p.v[0] = v[0] - b.v[0];
00102         p.v[1] = v[1] - b.v[1];
00103         p.v[2] = v[2] - b.v[2];
00104         p.v[3] = v[3] - b.v[3];
00105 
00106         return p;
00107     }
00108 
00109     AkReal32    v[4];
00110 };
00111 
00112 struct Ak3DIntVector
00113 {
00114 public:
00115     Ak3DIntVector(){}
00116     Ak3DIntVector(AkInt32 x, AkInt32 y, AkInt32 z)
00117     {
00118         X = x;
00119         Y = y;
00120         Z = z;
00121     }
00122 
00123     ~Ak3DIntVector(){}
00124 
00125     AkInt32     X;  ///< X Position
00126     AkInt32     Y;  ///< Y Position
00127     AkInt32     Z;  ///< Z Position
00128 };
00129 
00130 class Ak3DVector
00131 {
00132 public:
00133     //-----------------------------------------------------------
00134     // Constructor/Destructor functions
00135     Ak3DVector() :
00136         X(0.f),
00137         Y(0.f),
00138         Z(0.f)
00139     {}
00140 
00141     Ak3DVector(
00142         AkReal32                    x,
00143         AkReal32                    y,
00144         AkReal32                    z)
00145     {
00146         X = x;
00147         Y = y;
00148         Z = z;
00149     }
00150     Ak3DVector(const AkVector& b)
00151     {
00152         X = b.X;
00153         Y = b.Y;
00154         Z = b.Z;
00155     }
00156     explicit Ak3DVector(const AKSIMD_V4F32& in_v4f32)
00157     {
00158         X = AKSIMD_GETELEMENT_V4F32(in_v4f32, 0);
00159         Y = AKSIMD_GETELEMENT_V4F32(in_v4f32, 1);
00160         Z = AKSIMD_GETELEMENT_V4F32(in_v4f32, 2);
00161     }
00162     AkForceInline AKSIMD_V4F32 PointV4F32() const
00163     {
00164         AKSIMD_V4F32 v4f32;
00165         AKSIMD_GETELEMENT_V4F32(v4f32, 0) = X;
00166         AKSIMD_GETELEMENT_V4F32(v4f32, 1) = Y;
00167         AKSIMD_GETELEMENT_V4F32(v4f32, 2) = Z;
00168         AKSIMD_GETELEMENT_V4F32(v4f32, 3) = 1.f;
00169         return v4f32;
00170     }
00171     AkForceInline AKSIMD_V4F32 VectorV4F32() const
00172     {
00173         AKSIMD_V4F32 v4f32;
00174         AKSIMD_GETELEMENT_V4F32(v4f32, 0) = X;
00175         AKSIMD_GETELEMENT_V4F32(v4f32, 1) = Y;
00176         AKSIMD_GETELEMENT_V4F32(v4f32, 2) = Z;
00177         AKSIMD_GETELEMENT_V4F32(v4f32, 3) = 0.f;
00178         return v4f32;
00179     }
00180     ~Ak3DVector() {}
00181 
00182     void Zero()
00183     {
00184         X = 0.f;
00185         Y = 0.f;
00186         Z = 0.f;
00187     }
00188 
00189 
00190     //-----------------------------------------------------------
00191     // Basic vector operators
00192     AkForceInline bool operator==(const Ak3DVector& b) const
00193     {
00194         return X == b.X && Y == b.Y && Z == b.Z;
00195     }
00196 
00197     AkForceInline bool operator!=(const Ak3DVector& b) const
00198     {
00199         return X != b.X || Y != b.Y || Z != b.Z;
00200     }
00201 
00202     AkForceInline Ak3DVector operator=(const Ak3DVector& b)
00203     {
00204         X = b.X;
00205         Y = b.Y;
00206         Z = b.Z;
00207 
00208         return *this;
00209     }
00210 
00211     AkForceInline Ak3DVector operator=(const AkVector& b)
00212     {
00213         X = b.X;
00214         Y = b.Y;
00215         Z = b.Z;
00216 
00217         return *this;
00218     }
00219 
00220     AkForceInline bool operator<(const Ak3DVector& b) const
00221     {
00222         return X < b.X && Y < b.Y && Z < b.Z;
00223     }
00224 
00225     AkForceInline bool operator<=(const Ak3DVector& b) const
00226     {
00227         return X <= b.X && Y <= b.Y && Z <= b.Z;
00228     }
00229 
00230     AkForceInline bool operator>(const Ak3DVector b) const
00231     {
00232         return X > b.X && Y > b.Y && Z > b.Z;
00233     }
00234 
00235     AkForceInline bool operator>=(const Ak3DVector& b) const
00236     {
00237         return X >= b.X && Y >= b.Y && Z >= b.Z;
00238     }
00239 
00240     AkForceInline Ak3DVector operator*=(const AkReal32 f)
00241     {
00242         X = X * f;
00243         Y = Y * f;
00244         Z = Z * f;
00245 
00246         return *this;
00247     }
00248 
00249     AkForceInline Ak3DVector operator/=(const AkReal32 f)
00250     {
00251         AkReal32 oneoverf = 1.f / f;
00252         X = X * oneoverf;
00253         Y = Y * oneoverf;
00254         Z = Z * oneoverf;
00255 
00256         return *this;
00257     }
00258 
00259     AkForceInline Ak3DVector operator*(const Ak3DVector v2) const
00260     {
00261         Ak3DVector v;
00262 
00263         v.X = X * v2.X;
00264         v.Y = Y * v2.Y;
00265         v.Z = Z * v2.Z;
00266 
00267         return v;
00268     }
00269 
00270     AkForceInline Ak3DVector operator*(const AkReal32 f) const
00271     {
00272         Ak3DVector v;
00273 
00274         v.X = X * f;
00275         v.Y = Y * f;
00276         v.Z = Z * f;
00277 
00278         return v;
00279     }
00280 
00281     AkForceInline Ak3DVector operator/(const AkReal32 f) const
00282     {
00283         Ak3DVector v;
00284         AkReal32 oneoverf = 1.f / f;
00285 
00286         v.X = X * oneoverf;
00287         v.Y = Y * oneoverf;
00288         v.Z = Z * oneoverf;
00289 
00290         return v;
00291     }
00292 
00293     AkForceInline Ak3DVector operator+(const AkReal32 f) const
00294     {
00295         Ak3DVector v;
00296 
00297         v.X = X + f;
00298         v.Y = Y + f;
00299         v.Z = Z + f;
00300 
00301         return v;
00302     }
00303 
00304     AkForceInline Ak3DVector operator-(const AkReal32 f) const
00305     {
00306         Ak3DVector v;
00307 
00308         v.X = X - f;
00309         v.Y = Y - f;
00310         v.Z = Z - f;
00311 
00312         return v;
00313     }
00314 
00315     AkForceInline Ak3DVector operator+(const Ak3DVector& b) const
00316     {
00317         Ak3DVector v;
00318 
00319         v.X = X + b.X;
00320         v.Y = Y + b.Y;
00321         v.Z = Z + b.Z;
00322 
00323         return v;
00324     }
00325 
00326     AkForceInline Ak3DVector operator-(const Ak3DVector& b) const
00327     {
00328         Ak3DVector v;
00329 
00330         v.X = X - b.X;
00331         v.Y = Y - b.Y;
00332         v.Z = Z - b.Z;
00333 
00334         return v;
00335     }
00336 
00337     AkForceInline operator AkVector()
00338     {
00339         AkVector v;
00340         v.X = X; v.Y = Y; v.Z = Z;
00341 
00342         return v;
00343     }
00344 
00345 
00346     AkForceInline static Ak3DVector Min(const Ak3DVector& A, const Ak3DVector& B)
00347     {
00348         Ak3DVector min;
00349 
00350         min.X = AkMin(A.X, B.X);
00351         min.Y = AkMin(A.Y, B.Y);
00352         min.Z = AkMin(A.Z, B.Z);
00353 
00354         return min;
00355     }
00356 
00357     AkForceInline static Ak3DVector Max(const Ak3DVector& A, const Ak3DVector& B)
00358     {
00359         Ak3DVector max;
00360 
00361         max.X = AkMax(A.X, B.X);
00362         max.Y = AkMax(A.Y, B.Y);
00363         max.Z = AkMax(A.Z, B.Z);
00364 
00365         return max;
00366     }
00367 
00368     //-----------------------------------------------------------
00369     // Conversion functions
00370     AkForceInline Ak3DVector Rotate180X_90Y() const
00371     {
00372         Ak3DVector v;
00373 
00374         v.X = -X;
00375         v.Y = Z;
00376         v.Z = -Y;
00377 
00378         return v;
00379     }
00380 
00381     AkForceInline Ak3DVector SphericalToCartesian(
00382         const AkReal32              azimuth,
00383         const AkReal32              elevation)
00384     {
00385         AkReal32 cosElevation = cosf(elevation);
00386         X = cosf(azimuth) * cosElevation;
00387         Y = sinf(azimuth) * cosElevation;
00388         Z = sinf(elevation);
00389 
00390         return *this;
00391     }
00392 
00393     // Determinant of 3 column vectors.
00394     static AkReal32 Determinant(
00395         const Ak3DVector &          a,
00396         const Ak3DVector &          b,
00397         const Ak3DVector &          c)
00398     {
00399         return  (a.X*b.Y*c.Z + a.Y*b.Z*c.X + a.Z*b.X*c.Y) -
00400             (a.Z*b.Y*c.X + a.Y*b.X*c.Z + a.X*b.Z*c.Y);
00401     }
00402 
00403     // Convert a vector to a different base
00404     AkForceInline Ak3DVector LinearCombination(
00405         const Ak3DVector&           A,
00406         const Ak3DVector&           B,
00407         const Ak3DVector&           C) const
00408     {
00409         Ak3DVector v;
00410 
00411         AkReal32 d = Determinant(A, B, C);
00412 
00413         if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
00414         {
00415             v.X = 0.0f; v.Y = 0.0f; v.Z = 0.0f;
00416             return v;
00417         }
00418 
00419         // http://mathworld.wolfram.com/MatrixInverse.html
00420         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);
00421         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);
00422         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);
00423 
00424         AkReal32 oneover_d = 1.f / d;
00425         invA *= oneover_d;
00426         invB *= oneover_d;
00427         invC *= oneover_d;
00428 
00429         // Project coordinates using a vector to matrix multiplication
00430         v.X = X * invA.X + Y * invB.X + Z * invC.X;
00431         v.Y = X * invA.Y + Y * invB.Y + Z * invC.Y;
00432         v.Z = X * invA.Z + Y * invB.Z + Z * invC.Z;
00433 
00434         // v /= v.Length();
00435 
00436         return v;
00437     }
00438 
00439     AkForceInline const Ak3DVector& Normalize()
00440     {
00441         AkReal32 l = Length();
00442         if (l != 0.f)
00443         {
00444             X /= l;
00445             Y /= l;
00446             Z /= l;
00447         }
00448         else
00449         {
00450             X = 0.f;
00451             Y = 0.f;
00452             Z = 0.f;
00453         }
00454         return *this;
00455     }
00456 
00457     AkForceInline AkReal32 L2_Norm() const
00458     {
00459         return sqrtf(X*X + Y*Y + Z*Z);
00460     }
00461 
00462     AkForceInline AkReal32 DotProduct(const Ak3DVector& v2) const
00463     {
00464         return X*v2.X + Y*v2.Y + Z*v2.Z;
00465     }
00466 
00467     AkForceInline AkReal32 Dot(const Ak3DVector& v2) const
00468     {
00469         return DotProduct(v2);
00470     }
00471 
00472     AkForceInline Ak3DVector Cross(const Ak3DVector& v) const
00473     {
00474         Ak3DVector uxv;
00475         const Ak3DVector& u = *this;
00476 
00477         uxv.X = u.Y*v.Z - u.Z*v.Y;
00478         uxv.Y = u.Z*v.X - u.X*v.Z;
00479         uxv.Z = u.X*v.Y - u.Y*v.X;
00480 
00481         return uxv;
00482     }
00483     //
00484     AkForceInline AkReal32 Length() const
00485     {
00486         return sqrtf(X*X + Y*Y + Z*Z);
00487     }
00488 
00489     AkForceInline AkReal32 LengthSquared() const
00490     {
00491         return X*X + Y*Y + Z*Z;
00492     }
00493 
00494     // Usefull in VBAP algorithm, only points that are a positive linear composition matters.
00495     AkForceInline bool IsAllPositive() const
00496     {
00497         const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f;
00498         return X >= -POSITIVE_TEST_EPSILON &&
00499             Y >= -POSITIVE_TEST_EPSILON &&
00500             Z >= -POSITIVE_TEST_EPSILON;
00501     }
00502 
00503     AkForceInline Ak3DVector Abs() const
00504     {
00505         Ak3DVector abs = *this;
00506         abs.X = (AkReal32)fabs(abs.X);
00507         abs.Y = (AkReal32)fabs(abs.Y);
00508         abs.Z = (AkReal32)fabs(abs.Z);
00509         return abs;
00510     }
00511 
00512     AkReal32                        X;
00513     AkReal32                        Y;
00514     AkReal32                        Z;
00515 };
00516 
00517 class Ak2DVector
00518 {
00519 public:
00520     //-----------------------------------------------------------
00521     // Constructor/Destructor functions
00522     Ak2DVector(){}
00523     ~Ak2DVector(){}
00524 
00525     Ak2DVector(
00526         AkReal32                    x,
00527         AkReal32                    y)
00528     {
00529         X = x;
00530         Y = y;
00531     }
00532 
00533     //-----------------------------------------------------------
00534     // Basic vector operators
00535     AkForceInline Ak2DVector operator=(const Ak2DVector& b)
00536     {
00537         X = b.X;
00538         Y = b.Y;
00539 
00540         return *this;
00541     }
00542 
00543     AkForceInline Ak2DVector operator=(const AkSphericalCoord& b)
00544     {
00545         X = b.theta;
00546         Y = b.phi;
00547 
00548         return *this;
00549     }
00550 
00551     Ak2DVector operator-(const Ak2DVector& b) const
00552     {
00553         Ak2DVector v;
00554 
00555         v.X = X - b.X;
00556         v.Y = Y - b.Y;
00557 
00558         return v;
00559     }
00560 
00561     Ak2DVector operator*=(const AkReal32 f)
00562     {
00563         X = X * f;
00564         Y = Y * f;
00565 
00566         return *this;
00567     }
00568 
00569     Ak2DVector operator/=(const AkReal32 f)
00570     {
00571         AkReal32 oneoverf = 1.f / f;
00572         X = X * oneoverf;
00573         Y = Y * oneoverf;
00574 
00575         return *this;
00576     }
00577 
00578     AkForceInline bool operator==(const Ak2DVector& b) const
00579     {
00580         return b.X == X && b.Y == Y;
00581     }
00582 
00583     AkForceInline bool operator!=(const Ak2DVector& b) const
00584     {
00585         return b.X != X && b.Y != Y;
00586     }
00587 
00588     AkForceInline AkReal32 Length() const
00589     {
00590         return sqrtf(X*X+Y*Y);
00591     }
00592 
00593     //-----------------------------------------------------------
00594     // Conversion functions
00595     AkForceInline Ak2DVector CartesianToSpherical( const Ak3DVector& in_Cartesian )
00596     {
00597         // (radial, azimuth, elevation)
00598         AkReal32 r = sqrtf( in_Cartesian.X*in_Cartesian.X + in_Cartesian.Y*in_Cartesian.Y + in_Cartesian.Z*in_Cartesian.Z);
00599         AKASSERT( r != 0);
00600 
00601         X = atan2f(in_Cartesian.Y, in_Cartesian.X);
00602         Y = asinf(in_Cartesian.Z / r);
00603 
00604         NormalizeSpherical();
00605 
00606         return *this;
00607     }
00608 
00609     AkForceInline Ak2DVector LinearCombination(
00610         const Ak2DVector&           A,
00611         const Ak2DVector&           B) const
00612     {
00613         Ak2DVector v;
00614 
00615         // Project coordinates using a vector to matrix multiplication
00616         AkReal32 d = (A.X*B.Y - A.Y*B.X);
00617 
00618         if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
00619         {
00620             v.X = 0.0f; v.Y = 0.0f;
00621             return v;
00622         }
00623 
00624         Ak2DVector invA = Ak2DVector( B.Y, -A.Y );
00625         Ak2DVector invB = Ak2DVector( -B.X, A.X );
00626 
00627         AkReal32 oneover_d = 1.f / d;
00628         invA *= oneover_d;
00629         invB *= oneover_d;
00630 
00631         v.X = X * invA.X + Y * invB.X;
00632         v.Y = X * invA.Y + Y * invB.Y;
00633         // v /= v.Length();
00634 
00635         return v;
00636     }
00637 
00638     AkForceInline Ak2DVector NormalizeSpherical() const
00639     {
00640         /*
00641             Normalise spherical coordinates.
00642                 X (azimuthal)   -> [-PI, PI],       circle lies on xy plan,         0 is on X axix
00643                 Y (elevation)   -> [-PI/2, PI/2],   half circle on Z axis,          0 on XY plan, PI/2 straigt up on Z axis.
00644         */
00645 
00646         Ak2DVector v;
00647 
00648         v.X = X;
00649         v.Y = Y;
00650 
00651         if (X > AKVECTORS_PI)
00652             v.X = X - AKVECTORS_TWOPI;
00653 
00654         if (X < -AKVECTORS_PI)
00655             v.X = X + AKVECTORS_TWOPI;
00656 
00657         if (Y > AKVECTORS_PIOVERTWO)
00658             v.Y = Y - AKVECTORS_PI;
00659 
00660         if (Y < -AKVECTORS_PIOVERTWO)
00661             v.Y = Y + AKVECTORS_PI;
00662 
00663         AKASSERT(X<AKVECTORS_PI);
00664         AKASSERT(Y<AKVECTORS_PIOVERTWO);
00665 
00666         return v;
00667     }
00668 
00669     AkForceInline void NormalizeSpherical()
00670     {
00671         /*
00672             Normalise spherical coordinates.
00673                 X (azimuthal)   -> [-PI, PI],       circle lies on xy plan,     0 is on X axix
00674                 Y (elevation)   -> [-PI/2, PI/2],   half circle on Z axis,      0 on XY plan, PI/2 straigt up on Z axis.
00675         */
00676 
00677         if (X > AKVECTORS_PI)
00678             X = X - AKVECTORS_TWOPI;
00679 
00680         if (X < -AKVECTORS_PI)
00681             X = X + AKVECTORS_TWOPI;
00682 
00683         if (Y > AKVECTORS_PIOVERTWO)
00684             Y = Y - AKVECTORS_PI;
00685 
00686         if (Y < -AKVECTORS_PIOVERTWO)
00687             Y = Y + AKVECTORS_PI;
00688     }
00689 
00690     // Useful in VBAP algorithm, only points that are a positive linear composition matters.
00691     AkForceInline bool IsAllPositive() const
00692     {
00693         const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f; //0.005f;
00694         return X >= -POSITIVE_TEST_EPSILON &&
00695             Y >= -POSITIVE_TEST_EPSILON;
00696     }
00697 
00698     AkReal32                        X;
00699     AkReal32                        Y;
00700 };
00701 
00702 
00703 
00704 class AkMatrix4x4
00705 {
00706     static const int MAX_SIZE = 16;
00707 
00708 public:
00709     //-----------------------------------------------------------
00710     // Constructor/Destructor functions
00711     AkMatrix4x4() {}
00712     ~AkMatrix4x4() {}
00713 
00714     //-----------------------------------------------------------
00715     // Basic vector operators
00716     AkMatrix4x4 operator/=(const AkReal32 f)
00717     {
00718         for (int i = 0; i < MAX_SIZE; i++)
00719             m_Data[i] /= f;
00720 
00721         return *this;
00722     }
00723 
00724     AkMatrix4x4 operator=(AkReal32 * in_Data)
00725     {
00726         for (int i = 0; i < MAX_SIZE; i++)
00727         {
00728             m_Data[i] = in_Data[i];
00729         }
00730 
00731         return *this;
00732     }
00733 
00734     AkReal32 m_Data[MAX_SIZE];
00735 };
00736 
00737 class AkMatrix3x3
00738 {
00739 
00740 public:
00741     //-----------------------------------------------------------
00742     // Constructor/Destructor functions
00743     AkMatrix3x3() {}
00744     ~AkMatrix3x3() {}
00745 
00746     //-----------------------------------------------------------
00747     // Basic vector operators
00748     AkMatrix3x3 operator/=(const AkReal32 f)
00749     {
00750         for (int i = 0; i < 3; i++)
00751         {
00752             for (int j = 0; j < 3; j++)
00753             {
00754                 m_Data[i][j] /= f;
00755             }
00756         }
00757         return *this;
00758     }
00759 
00760     AkForceInline AkReal32& operator()(const AkUInt32 row, const AkUInt32 column)
00761     {
00762         return m_Data[column][row];
00763     }
00764 
00765     AkForceInline const AkReal32& operator()(const AkUInt32 row, const AkUInt32 column) const
00766     {
00767         return m_Data[column][row];
00768     }
00769 
00770     AkForceInline Ak3DVector operator*(const Ak3DVector& in_rhs)
00771     {
00772         Ak3DVector res;
00773         res.X = in_rhs.X * m_Data[0][0] + in_rhs.Y * m_Data[1][0] + in_rhs.Z * m_Data[2][0];
00774         res.Y = in_rhs.X * m_Data[0][1] + in_rhs.Y * m_Data[1][1] + in_rhs.Z * m_Data[2][1];
00775         res.Z = in_rhs.X * m_Data[0][2] + in_rhs.Y * m_Data[1][2] + in_rhs.Z * m_Data[2][2];
00776         return res;
00777     }
00778 
00779     AkForceInline AkMatrix3x3& operator+=(const AkMatrix3x3& in_rhs)
00780     {
00781         Add(*this, *this, in_rhs);
00782         return *this;
00783     }
00784 
00785     static AkForceInline void Add(AkMatrix3x3& out_res, const AkMatrix3x3& in_m0, const AkMatrix3x3& in_m1)
00786     {
00787 #define ADD(i,j) out_res(i,j) = in_m0(i,j) + in_m1(i,j)
00788         ADD(0, 0); ADD(0, 1); ADD(0, 2);
00789         ADD(1, 0); ADD(1, 1); ADD(1, 2);
00790         ADD(2, 0); ADD(2, 1); ADD(2, 2);
00791 #undef ADD
00792     }
00793 
00794     AkForceInline AkMatrix3x3& operator*=(const AkReal32& in_f)
00795     {
00796         m_Data[0][0] *= in_f; m_Data[0][1] *= in_f; m_Data[0][2] *= in_f;
00797         m_Data[1][0] *= in_f; m_Data[1][1] *= in_f; m_Data[1][2] *= in_f;
00798         m_Data[2][0] *= in_f; m_Data[2][1] *= in_f; m_Data[2][2] *= in_f;
00799         return *this;
00800     }
00801 
00802     static AkForceInline void Diagonal(AkMatrix3x3& out_mat, AkReal32 in_f)
00803     {
00804         out_mat(0, 0) = in_f;       out_mat(0, 1) = 0.f;        out_mat(0, 2) = 0.f;
00805         out_mat(1, 0) = 0.f;        out_mat(1, 1) = in_f;       out_mat(1, 2) = 0.f;
00806         out_mat(2, 0) = 0.f;        out_mat(2, 1) = 0.f;        out_mat(2, 2) = in_f;
00807     }
00808 
00809     // Creates the matrix Mu such that Mu*v = u X v
00810     static AkForceInline  void CrossProductMatrix(AkMatrix3x3& out_mat, const Ak3DVector& in_u)
00811     {
00812         out_mat(0, 0) = 0.f;        out_mat(0, 1) = -in_u.Z;        out_mat(0, 2) = in_u.Y;
00813         out_mat(1, 0) = in_u.Z;     out_mat(1, 1) = 0.f;            out_mat(1, 2) = -in_u.X;
00814         out_mat(2, 0) = -in_u.Y;    out_mat(2, 1) = in_u.X;         out_mat(2, 2) = 0.f;
00815     }
00816 
00817     static AkForceInline void OuterProduct(AkMatrix3x3& out_mat, const Ak3DVector& in_v0, const Ak3DVector& in_v1)
00818     {
00819         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;
00820         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;
00821         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;
00822     }
00823 
00824     static AkForceInline void Rotation(AkMatrix3x3& out_mat, AkReal32 in_angle, const Ak3DVector& in_axis)
00825     {
00826         Rotation(out_mat, sinf(in_angle), cosf(in_angle), in_axis);
00827     }
00828 
00829     static void Rotation(AkMatrix3x3& out_mat, AkReal32 in_sin, AkReal32 in_cos, const Ak3DVector& in_axis)
00830     {
00831         Diagonal(out_mat, in_cos);
00832 
00833         AkMatrix3x3 outer;
00834         OuterProduct(outer, in_axis, in_axis);
00835         outer *= (1.f - in_cos);
00836         out_mat += outer;
00837 
00838         AkMatrix3x3 cross;
00839         CrossProductMatrix(cross, in_axis*in_sin);
00840         out_mat += cross;
00841     }
00842 
00843     // [column][row]
00844     AkReal32 m_Data[3][3];
00845 };
00846 
00847 class AkQuaternion
00848 {
00849 public:
00850     // Identity quaternion
00851     AkQuaternion(): W(1.f), X(0.f), Y(0.f), Z(0.f) {}
00852 
00853     AkQuaternion(AkReal32 in_W, AkReal32 in_X, AkReal32 in_Y, AkReal32 in_Z) : 
00854             W(in_W), 
00855             X(in_X), 
00856             Y(in_Y), 
00857             Z(in_Z) 
00858     {}
00859 
00860     AkQuaternion(const Ak3DVector& in_fromVector): 
00861         W(0.f), 
00862         X(in_fromVector.X), 
00863         Y(in_fromVector.Y), 
00864         Z(in_fromVector.Z) 
00865     {}
00866 
00867     AkForceInline AkReal32 Length()
00868     {
00869         return sqrtf( W*W + X*X + Y*Y + Z*Z );
00870     }
00871 
00872     AkForceInline const AkQuaternion& Normalize()
00873     {
00874         AkReal32 f = 1.0f / Length();
00875         W *= f;
00876         X *= f;
00877         Y *= f;
00878         Z *= f;
00879         return *this;
00880     }
00881 
00882     AkForceInline AkQuaternion Inverse() const
00883     {
00884         AkReal32 norm = W*W + X*X + Y*Y + Z*Z;
00885         if (norm > 0.0)
00886         {
00887             AkReal32 invNorm = 1.0f / norm;
00888             return AkQuaternion(W*invNorm, -X*invNorm, -Y*invNorm, -Z*invNorm);
00889         }
00890         else
00891         {
00892             return AkQuaternion();
00893         }
00894     }
00895 
00896     // Create a quaternion representing the shortest arc rotation between (normalized) vectors v0, v1
00897     AkQuaternion(const Ak3DVector& in_v0, const Ak3DVector& in_v1)
00898     {
00899         AkReal32 dot = in_v0.Dot(in_v1);
00900         if (dot >= 1.0f - AKVECTORS_EPSILON)
00901         {
00902             // No rotation - return unity quaternion.
00903             AkQuaternion();
00904         }
00905         if (dot <= -1.f - AKVECTORS_EPSILON)
00906         {
00907             // 180 degree rotation - can use any non-zero length axis.
00908             Ak3DVector axis = Ak3DVector(0.f, 0.f, 1.f).Cross(in_v0);
00909             AkReal32 len = axis.Length();
00910             if (len < AKVECTORS_EPSILON)
00911             {
00912                 axis = Ak3DVector(0.f, 1.f, 0.f).Cross(in_v0);
00913                 len = axis.Length();
00914             }
00915             axis.Normalize();
00916             AkQuaternion(AKVECTORS_PI, axis);
00917         }
00918         else
00919         {
00920             AkReal32 sqrt = sqrtf((1.f + dot) * 2.f);
00921             AkReal32 invs = 1.f / sqrt;
00922 
00923             Ak3DVector cross = in_v0.Cross(in_v1);
00924 
00925             X = cross.X * invs;
00926             Y = cross.Y * invs;
00927             Z = cross.Z * invs;
00928             W = sqrt * 0.5f;
00929             Normalize();
00930         }
00931     }
00932     
00933     // Build quaternion from an axis and angle representation.
00934     AkQuaternion(AkReal32 in_angle, const Ak3DVector& in_axis)
00935     {
00936         AkReal32 sinHalfAngle = sinf(in_angle / 2.f);
00937         AkReal32 cosHalfAngle = cosf(in_angle / 2.f);
00938         W = cosHalfAngle;
00939         X = cosHalfAngle*in_axis.X;
00940         Y = cosHalfAngle*in_axis.Y;
00941         Z = cosHalfAngle*in_axis.Z;
00942     }
00943     
00944     /// Quaternion multiplication.
00945     AkForceInline AkQuaternion operator*(const AkQuaternion& Q) const
00946     {
00947         return AkQuaternion(
00948             W*Q.W - X*Q.X - Y*Q.Y - Z*Q.Z,
00949             W*Q.X + X*Q.W + Y*Q.Z - Z*Q.Y,
00950             W*Q.Y - X*Q.Z + Y*Q.W + Z*Q.X,
00951             W*Q.Z + X*Q.Y - Y*Q.X + Z*Q.W);
00952     }
00953     
00954     AkForceInline Ak3DVector operator* (const Ak3DVector& in_v) const
00955     {
00956         /*
00957         // impl 1
00958         Ak3DVector uv, uuv;
00959         Ak3DVector qvec(X, Y, Z);
00960         uv = qvec.Cross(in_v);
00961         uuv = qvec.Cross(uv);
00962         uv *= (2.0f * W);
00963         uuv *= 2.0f;
00964         return in_v + uv + uuv;
00965         */
00966 
00967         // impl 2
00968         Ak3DVector u(X, Y, Z);
00969         Ak3DVector res = 
00970             u * u.Dot(in_v) * 2.f
00971             + in_v * (W*W - u.Dot(u))
00972             + u.Cross(in_v) * W * 2.0f;
00973 
00974         return res;
00975     }
00976 
00977     AkReal32 W;
00978     AkReal32 X;
00979     AkReal32 Y;
00980     AkReal32 Z;
00981 };
00982 
00983 struct AkIntersectionPoints
00984 {
00985     Ak3DVector points[2];
00986     AkUInt32 count;
00987 };
00988 
00989 class AkLine
00990 {
00991 public:
00992     AkLine()
00993     {
00994         mint = 1.175494351e-38F;
00995         maxt = 3.402823466e+38F;
00996     }
00997 
00998     AkLine(
00999         Ak3DVector                  in_L,
01000         Ak3DVector                  in_P
01001         )
01002     {
01003         L = in_L;
01004         P = in_P;
01005         mint = 1.175494351e-38F;
01006         maxt = 3.402823466e+38F;
01007     }
01008 
01009     Ak3DVector PointAt(AkReal32 t) const
01010     {
01011         return P + L*t;
01012     }
01013 
01014     bool Intersect(
01015         Ak3DVector A,
01016         Ak3DVector B)
01017     {
01018         Ak3DVector L2 = B - A;
01019 
01020         /*
01021         a (V1 X V2) = (P2 - P1) X V2
01022         If the lines intersect at a single point, then the resultant vectors
01023         on each side of this equation must be parallel, and the left side must
01024         not be the zero vector. We should check to make sure that this is
01025         true. Once we have checked this, we can solve for 'a' by taking the
01026         magnitude of each side and dividing. If the resultant vectors are
01027         parallel, but in opposite directions, then 'a' is the negative of the
01028         ratio of magnitudes. Once we have 'a' we can go back to the equation
01029         for L1 to find the intersection point.
01030         */
01031         Ak3DVector V1 = L;
01032         Ak3DVector V2 = B - A;
01033         Ak3DVector P1 = P;
01034         Ak3DVector P2 = A;
01035 
01036         // k(V1 X V2) = (A - P) X V2
01037 
01038         Ak3DVector v1CrossV2 = V1.Cross(V2);
01039         AkReal32 det = Ak3DVector::Determinant(
01040             P2 - P1,
01041             V2,
01042             v1CrossV2
01043             );
01044         AkReal32 t = det / v1CrossV2.LengthSquared();
01045 
01046         det = Ak3DVector::Determinant(
01047             P2 - P1,
01048             V1,
01049             v1CrossV2
01050             );
01051         AkReal32 s = det / v1CrossV2.LengthSquared();
01052 
01053         AkReal32 distsqrd = ((P2 + V2*s) - (P1 + V1*t)).LengthSquared();
01054 
01055         if ((AkReal32)fabs(v1CrossV2.L2_Norm()) >= AKVECTORS_EPSILON
01056             && distsqrd < 0.001
01057             && s <= 1.0f )
01058         {
01059 #ifdef AKPORTALS_DEBUG
01060             Ak3DVector minPoint = PointAt(t);
01061 
01062             char msg[256];
01063             sprintf(msg, "L1a=[%0.2f,%0.2f,%0.2f];\n", P.X, P.Y, P.Z); AKPLATFORM::OutputDebugMsg(msg);
01064             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);
01065             sprintf(msg, "L2a=[%0.2f,%0.2f,%0.2f];\n", A.X, A.Y, A.Z); AKPLATFORM::OutputDebugMsg(msg);
01066             sprintf(msg, "L2b=[%0.2f,%0.2f,%0.2f];\n", B.X, B.Y, B.Z); AKPLATFORM::OutputDebugMsg(msg);
01067             sprintf(msg, "%% t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
01068             sprintf(msg, "intrPoint=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
01069             sprintf(msg, "\n"); AKPLATFORM::OutputDebugMsg(msg);
01070 #endif
01071 
01072             mint = AkMin(mint, t);
01073             maxt = AkMax(maxt, t);
01074             
01075             return true;
01076         }
01077 
01078 #ifdef AKPORTALS_DEBUG
01079     //  char msg[256];
01080     //  sprintf(msg, "%% DISCARTED t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
01081 #endif
01082         return false;
01083     }
01084 
01085     Ak3DVector L;
01086     Ak3DVector P;
01087 
01088     AkReal32 mint;
01089     AkReal32 maxt;
01090 };
01091 
01092 class AkPlane
01093 {
01094 public:
01095     AkPlane()
01096     {
01097     }
01098 
01099     AkPlane(
01100         Ak3DVector                  in_p1,
01101         Ak3DVector                  in_p2,
01102         Ak3DVector                  in_p4
01103         )
01104     {
01105         SetPlane(
01106             in_p1,
01107             in_p2,
01108             in_p4);
01109     }
01110 
01111     ~AkPlane()
01112     {
01113     }
01114 
01115     void SetPlane(
01116         Ak3DVector                  in_p1,
01117         Ak3DVector                  in_p2,
01118         Ak3DVector                  in_p4
01119         )
01120     {
01121         // Reorder A-B-C to clockwwise if necessary
01122         AKASSERT(in_p1.X < 100000 && in_p1.X > -100000);
01123         AKASSERT(in_p1.Y < 100000 && in_p1.Y > -100000);
01124         AKASSERT(in_p1.Z < 100000 && in_p1.Z > -100000);
01125 
01126         AKASSERT(in_p2.X < 100000 && in_p2.X > -100000);
01127         AKASSERT(in_p2.Y < 100000 && in_p2.Y > -100000);
01128         AKASSERT(in_p2.Z < 100000 && in_p2.Z > -100000);
01129 
01130         AKASSERT(in_p4.X < 100000 && in_p4.X > -100000);
01131         AKASSERT(in_p4.Y < 100000 && in_p4.Y > -100000);
01132         AKASSERT(in_p4.Z < 100000 && in_p4.Z > -100000);
01133 
01134         p1 = in_p1;
01135         p2 = in_p2;
01136         p4 = in_p4;
01137 
01138         SetNormal();
01139 
01140         // Ax + By + Cz + D = 0
01141         // Find D using the normal and a point
01142         D = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
01143     }
01144 
01145 #define EPSILON 0.01f
01146     bool DoesRayIntersect(
01147         const Ak3DVector&           in_Origin,
01148         const Ak3DVector&           in_Destination,
01149         Ak3DVector&                 out_Intersection
01150         ) const
01151     {
01152         AkReal32 A = N.X;
01153         AkReal32 B = N.Y;
01154         AkReal32 C = N.Z;
01155 
01156         Ak3DVector ray = in_Destination - in_Origin;
01157         AkReal32 rayLength = ray.Length();
01158 
01159         Ak3DVector intersect;
01160 
01161         // If ray is < EPSILON, use on of the point directly for the test and skip the linear projection
01162         if (rayLength <= EPSILON)
01163         {
01164             Ak3DVector temp = in_Origin - p1;
01165             AkReal32 dot = temp.DotProduct(N);
01166             if (dot < EPSILON && dot > -EPSILON)
01167             {
01168                 intersect = in_Origin;
01169             }
01170             else
01171             {
01172                 // For debug only, to remove
01173                 out_Intersection = p1;
01174                 return false;
01175             }
01176 
01177         }
01178         else
01179         {
01180             // Normalize ray
01181             ray.Normalize();
01182 
01183             // TODO: possible fix for all edge cases
01184             // 1) if ray len ~= 0, only check if one of the point is on target, ie: assign the intersect point
01185 
01186             // Is ray parallel to the plane?
01187             if ((A*ray.X + B*ray.Y + C*ray.Z) == 0.0f)
01188             {
01189                 // For debug only, to remove
01190                 AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
01191                 intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
01192                 out_Intersection = intersect; // For debugging
01193                 return false;
01194             }
01195 
01196 
01197             // Distance along the ray where reflector is hit
01198             AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
01199 
01200             // Is the ray going towards the plane? Is it long enough?
01201             if (t < -EPSILON || t >(rayLength + EPSILON))
01202             {
01203                 // For debug only, to remove
01204                 intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
01205                 out_Intersection = intersect; // For debugging
01206                 return false; // The ray doesn't intersect
01207             }
01208 
01209             // Find the coordinate of intersection on the plane
01210             intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
01211         }
01212         ///////////////////////////////////////
01213         //
01214         //      p2____v3____p3
01215         //      |     .     |
01216         //      ^   inter   v4
01217         //      v1          v
01218         //      |           |
01219         //      p1__ v2>___p4
01220 
01221         Ak3DVector v1 = p2 - p1;
01222         Ak3DVector v2 = p4 - p1;
01223         Ak3DVector vInter1 = intersect - p1;
01224 
01225         Ak3DVector p3 = p4 + v1;
01226         Ak3DVector v3 = p2 - p3;
01227         Ak3DVector v4 = p4 - p3;
01228         Ak3DVector vInter2 = intersect - p3;
01229 
01230         v1.Normalize(); v2.Normalize(); v3.Normalize(); v4.Normalize(); vInter1.Normalize(); vInter2.Normalize();
01231 
01232         // Since it's a square, the angle between the point of intersection and any segment of the pannel should be < 90 degree,
01233         // therefore the dot product of the two normalized vectors should be > 0
01234         AkReal32 dot1 = v1.DotProduct(vInter1);
01235         AkReal32 dot2 = v2.DotProduct(vInter1);
01236         AkReal32 dot3 = v3.DotProduct(vInter2);
01237         AkReal32 dot4 = v4.DotProduct(vInter2);
01238 
01239         out_Intersection = intersect;
01240 
01241         return dot1 >= -EPSILON && dot2 >= -EPSILON && dot3 >= -EPSILON && dot4 >= -EPSILON;
01242     }
01243 
01244     AkReal32 DistPoint_to_Plane(
01245         Ak3DVector          in_P,
01246         Ak3DVector&         out_B) const
01247     {
01248         AkReal32 distance = (AkReal32)(AkReal32)fabs(N.X * in_P.X + N.Y * in_P.Y + N.Z * in_P.Z + D);
01249 
01250         Ak3DVector pointToPlane = N;
01251         pointToPlane *= distance;
01252 
01253         out_B = in_P + pointToPlane;
01254 
01255         return (AkReal32)fabs(distance);
01256     }
01257 
01258     void SetReflection(
01259         AkReal32*           out_mat) const
01260     {
01261         // http://ami.ektf.hu/uploads/papers/finalpdf/AMI_40_from175to186.pd
01262         /* m_pReflectionMatrix
01263         reflection on z axis
01264 
01265         P0 (x0, y0, z0), P1 (x1, y1, z1) and P2 (x2, y2, z2),
01266         normal = (cx, cy, cz)
01267         d = -CxX0 - CyY0 - CzZ0
01268 
01269         Reflect =   1-2Cx^2     -2CxCy      -2CxCz      -2Cxd
01270         -2CxCy      1-2Cy^2     -2CyCz      -2Cyd
01271         -2CxCz      -2CyCz      1-2Cz^2     -2Czd
01272         0           0           0           1
01273         */
01274 
01275         AkReal32 d = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
01276 
01277         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;
01278         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;
01279         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;
01280         out_mat[0 + 12] = 0;                out_mat[1 + 12] = 0;                    out_mat[2 + 12] = 0;                    out_mat[3 + 12] = 1;
01281     }
01282 
01283     Ak3DVector GetN() const { return N; }
01284     AkReal32 GetD() const { return D; }
01285 
01286     bool FindIntersectionPoints(
01287         const AkPlane& in_PlaneB,
01288         AkIntersectionPoints& out_Intrs) const
01289     {
01290         out_Intrs.count = 0;
01291 
01292         // Use vector to solve A
01293 
01294         Ak3DVector point;
01295 
01296         Ak3DVector N1 = N;
01297         Ak3DVector N2 = in_PlaneB.GetN();
01298         AkReal32 D1 = D;
01299         AkReal32 D2 = in_PlaneB.GetD();
01300 
01301         Ak3DVector L = N1.Cross(N2);
01302         if (L.Length() < 0.001f)
01303         {
01304             return false; // The two planes are parallel
01305         }
01306 
01307         AkUInt8 pivotAxis = 0;
01308 
01309         if ((AkReal32)fabs(L.Y) > (AkReal32)fabs(L.X))
01310         {
01311             pivotAxis = 1;
01312             if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.Y))
01313             {
01314                 pivotAxis = 2;
01315             }
01316         }
01317         else if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.X))
01318         {
01319             pivotAxis = 2;
01320         }
01321 
01322         /*
01323         Pu = ( N1v*D2 - N2v*D1 ) / Lw
01324         Pv = ( N2u*D1 - N1u*D2 ) / Lw
01325         Pz = 0
01326         */
01327 
01328         switch (pivotAxis)
01329         {
01330         case 0:
01331             AKASSERT((AkReal32)fabs(L.X) > AKVECTORS_EPSILON);
01332             point.X = 0.f;
01333             point.Y = (N1.Z*D2 - N2.Z*D1) / L.X;
01334             point.Z = (N2.Y*D1 - N1.Y*D2) / L.X;
01335             break;
01336         case 1:
01337             AKASSERT((AkReal32)fabs(L.Y) > AKVECTORS_EPSILON);
01338             point.X = (N1.Z*D2 - N2.Z*D1) / L.Y;
01339             point.Y = 0.f;
01340             point.Z = (N2.X*D1 - N1.X*D2) / L.Y;
01341             break;
01342         case 2:
01343             AKASSERT((AkReal32)fabs(L.Z) > AKVECTORS_EPSILON);
01344             point.X = (N1.Y*D2 - N2.Y*D1) / L.Z;
01345             point.Y = (N2.X*D1 - N1.X*D2) / L.Z;
01346             point.Z = 0.f;
01347             break;
01348         };
01349 
01350 
01351 
01352         L.Normalize();
01353 
01354         AkLine intrLine = AkLine(L, point);
01355         AkLine intrLine2 = AkLine(L, point);
01356 
01357         //in_PlaneB.GetP1()
01358 
01359         // find min max
01360         AkUInt32 cpt = 0;
01361         AkUInt32 cpt2 = 0;
01362         Ak3DVector p3 = GetP2() + (GetP4() - GetP1());
01363 
01364 #ifdef AKPORTALS_DEBUG
01365         char msg[256];
01366         sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
01367         sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
01368         sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
01369 
01370         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);
01371         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);
01372         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);
01373 
01374         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);
01375         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);
01376 
01377 
01378         sprintf(msg, "%% Plane intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
01379 #endif
01380         // for the four lines in rectangle
01381         // Find where the line is crossing with plane A
01382         if (intrLine.Intersect(GetP1(), GetP2())) cpt++;
01383         if (intrLine.Intersect(GetP1(), GetP4())) cpt++;
01384         if (intrLine.Intersect(GetP2(), p3)) cpt++;
01385         if (intrLine.Intersect(p3, GetP4())) cpt++;
01386         //AKASSERT(cpt == 2);
01387 
01388 #ifdef AKPORTALS_DEBUG
01389         sprintf(msg, "%% Portal intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
01390 #endif
01391 
01392         // Find where the line is crossing with plane B
01393         p3 = in_PlaneB.GetP2() + (in_PlaneB.GetP4() - in_PlaneB.GetP1());
01394         if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP2())) cpt2++;
01395         if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP4())) cpt2++;
01396         if (intrLine2.Intersect(in_PlaneB.GetP2(), p3)) cpt2++;
01397         if (intrLine2.Intersect(p3, in_PlaneB.GetP4())) cpt2++;
01398         // **AKASSERT(cpt2 == 2 || cpt == 2);
01399 
01400         if (cpt < 2 || cpt2 < 2)
01401         {
01402 #ifdef AKPORTALS_DEBUG
01403             sprintf(msg, "%% NON \n"); AKPLATFORM::OutputDebugMsg(msg);
01404             sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
01405 #endif
01406             return false;
01407         }
01408 
01409         AkReal32 start = AkMax(intrLine.mint, intrLine2.mint);
01410         AkReal32 end = AkMin(intrLine.maxt, intrLine2.maxt);
01411 
01412         Ak3DVector minPoint = intrLine.PointAt(start);
01413         Ak3DVector maxPoint = intrLine.PointAt(end);
01414 #ifdef AKPORTALS_DEBUG
01415         sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
01416         sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
01417         sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
01418 
01419         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);
01420         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);
01421         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);
01422 
01423         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);
01424         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);
01425 
01426         sprintf(msg, "intr1=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
01427         sprintf(msg, "intr2=[%0.2f,%0.2f,%0.2f];\n", maxPoint.X, maxPoint.Y, maxPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
01428 
01429         sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
01430 #endif
01431         out_Intrs.points[0] = minPoint;
01432         out_Intrs.points[1] = maxPoint;
01433         out_Intrs.count = 2;
01434 
01435         return true;
01436     }
01437 
01438     Ak3DVector GetP1() const { return p1; }
01439     Ak3DVector GetP2() const { return p2; }
01440     Ak3DVector GetP4() const { return p4; }
01441 
01442 private:
01443     bool SetNormal()
01444     {
01445         //m_pNormal = (B-A) cross (C-A); normalize
01446         Ak3DVector a = p2 - p1;
01447         Ak3DVector b = p4 - p1;
01448 
01449         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);
01450 
01451         AkReal32 len = N.Length();
01452         AKASSERT(len > 0.f);
01453 
01454         if (len > 0)
01455         {
01456             N /= len;
01457         }
01458         else
01459         {
01460             // TODO handle invalid reflectors
01461             return false;
01462         }
01463 
01464         return true;
01465     };
01466 
01467     /*
01468     p2__________p3
01469     |     .     |
01470     ^   inter   v3
01471     v1          v
01472     |           |
01473     p1__ v2>___p4
01474     */
01475 
01476     Ak3DVector                      p1;     // Bottom left
01477     Ak3DVector                      p2;     // Top left
01478     Ak3DVector                      p4;     // Tottom right
01479     Ak3DVector                      N;      // Normal vector
01480     AkReal32                        D;      // Plane equation: Ax + By + Cz = D => N.Xx + N.Yy + N.Zz = D
01481 };
01482 
01483 struct AkBoundingBox
01484 {
01485     AkBoundingBox() :
01486         m_Min(Ak3DVector(FLT_MAX, FLT_MAX, FLT_MAX)),
01487         m_Max(Ak3DVector(-FLT_MAX, -FLT_MAX, -FLT_MAX))
01488     {}
01489 
01490     void Update(
01491         const Ak3DVector &      in_point
01492         )
01493     {
01494         if (m_Min.X > in_point.X)
01495             m_Min.X = in_point.X;
01496 
01497         if (m_Min.Y > in_point.Y)
01498             m_Min.Y = in_point.Y;
01499 
01500         if (m_Min.Z > in_point.Z)
01501             m_Min.Z = in_point.Z;
01502 
01503         if (m_Max.X < in_point.X)
01504             m_Max.X = in_point.X;
01505 
01506         if (m_Max.Y < in_point.Y)
01507             m_Max.Y = in_point.Y;
01508 
01509         if (m_Max.Z < in_point.Z)
01510             m_Max.Z = in_point.Z;
01511     }
01512 
01513     AkForceInline bool IsWithin(
01514         const Ak3DVector &      in_Point
01515         ) const
01516     {
01517         return in_Point >= m_Min && in_Point <= m_Max;
01518     }
01519 
01520     AkForceInline bool IsWithin(
01521         const AkBoundingBox &   in_BB
01522         ) const
01523     {
01524         return (m_Min.X <= in_BB.m_Max.X && m_Max.X >= in_BB.m_Min.X) &&
01525             (m_Min.Y <= in_BB.m_Max.Y && m_Max.Y >= in_BB.m_Min.Y) &&
01526             (m_Min.Z <= in_BB.m_Max.Z && m_Max.Z >= in_BB.m_Min.Z);
01527     }
01528 
01529     AkBoundingBox Intersect(
01530         const AkBoundingBox &   in_BB
01531     ) const
01532     {
01533         AkBoundingBox result;
01534         
01535         result.m_Max.X = AkMin(m_Max.X, in_BB.m_Max.X);
01536         result.m_Max.Y = AkMin(m_Max.Y, in_BB.m_Max.Y);
01537         result.m_Max.Z = AkMin(m_Max.Z, in_BB.m_Max.Z);
01538 
01539         result.m_Min.X = AkMax(m_Min.X, in_BB.m_Min.X);
01540         result.m_Min.Y = AkMax(m_Min.Y, in_BB.m_Min.Y);
01541         result.m_Min.Z = AkMax(m_Min.Z, in_BB.m_Min.Z);
01542         
01543         return result;
01544     }
01545 
01546     // returns acos(in_fAngle)
01547     AkForceInline AkReal32 ACos(
01548         AkReal32            in_fAngle
01549         ) const
01550     {
01551         AKASSERT((in_fAngle <= 1.0f) && (in_fAngle >= -1.0f));
01552         return acosf(in_fAngle);
01553     }
01554 
01555     AkForceInline bool IsEmpty() const
01556     {
01557         return (m_Min.X >= m_Max.X) || (m_Min.Y >= m_Max.Y) || (m_Min.Z >= m_Max.Z);
01558     }
01559 
01560     Ak3DVector                      m_Min;
01561     Ak3DVector                      m_Max;
01562 };
01563 
01564 class AkBox
01565 {
01566 public:
01567     AkBox()
01568     {
01569     }
01570 
01571     ~AkBox()
01572     {
01573     }
01574 
01575     void Init(
01576         const Ak3DVector &      in_center,
01577         const Ak3DVector &      in_extent,
01578         const Ak3DVector &      in_Front,
01579         const Ak3DVector &      in_Up)
01580     {
01581         AKASSERT(fabs(in_Front.Length() - 1.f) < 0.001 && fabs(in_Up.Length() - 1.f) < 0.001);//Must be unit vectors.
01582         AKASSERT(fabs(in_Front.Dot(in_Up) - 0.f) < 0.001); //Must be orthogonal.
01583 
01584         m_Center = in_center;
01585         m_Extent = in_extent;
01586 
01587         m_Z = in_Front,
01588         m_Y = in_Up;
01589         m_X = m_Z.Cross(m_Y);
01590     }
01591 
01592     bool IsPointInBox(
01593         const Ak3DVector &      in_Point
01594         ) const
01595     {
01596         Ak3DVector pt = in_Point - m_Center;
01597         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;
01598     }
01599 
01600     Ak3DVector GetSize() const { return m_Extent*2.f; }
01601     Ak3DVector GetCenter() const { return m_Center; }
01602 
01603     Ak3DVector GetUx() const { return m_X; }
01604     Ak3DVector GetUy() const { return m_Y; }
01605     Ak3DVector GetUz() const { return m_Z; }
01606 
01607     Ak3DVector GetFront() const { return m_Z; }
01608     Ak3DVector GetUp() const { return m_Y; }
01609     Ak3DVector GetSide() const { return m_X; }
01610 
01611     AkReal32 GetVolume() const
01612     {
01613         Ak3DVector size = GetSize();
01614         return size.X * size.Y * size.Z;
01615     }
01616 
01617     bool SeparatingAxisExists(
01618         const Ak3DVector&       L,
01619         const AkBox&            B
01620         ) const
01621     {
01622         // Separating Axis Theorem for Oriented Bounding Boxes by Johnny Huynh
01623         const AkBox& A = *this;
01624         Ak3DVector T = B.GetCenter() - A.GetCenter();
01625 
01626         AkReal32 WA = A.m_Extent.X;
01627         AkReal32 HA = A.m_Extent.Y;
01628         AkReal32 DA = A.m_Extent.Z;
01629 
01630         AkReal32 WB = B.m_Extent.X;
01631         AkReal32 HB = B.m_Extent.Y;
01632         AkReal32 DB = B.m_Extent.Z;
01633 
01634         Ak3DVector Ax = A.GetUx();
01635         Ak3DVector Ay = A.GetUy();
01636         Ak3DVector Az = A.GetUz();
01637 
01638         Ak3DVector Bx = B.GetUx();
01639         Ak3DVector By = B.GetUy();
01640         Ak3DVector Bz = B.GetUz();
01641 
01642         /*
01643         | T • L | > | (WA*Ax) • L | + | (HA*Ay) • L | + |(DA*Az) • L | +
01644                     | (WB*Bx) • L | +| (HB*By) • L | +| (DB*Bz) • L |*/
01645 
01646         AkReal32 left = (AkReal32)fabs(T.DotProduct(L));
01647         AkReal32 dpax = (AkReal32)fabs((Ax*WA).DotProduct(L));
01648         AkReal32 dpay = (AkReal32)fabs((Ay*HA).DotProduct(L));
01649         AkReal32 dpaz = (AkReal32)fabs((Az*DA).DotProduct(L));
01650         AkReal32 dpbx = (AkReal32)fabs((Bx*WB).DotProduct(L));
01651         AkReal32 dpby = (AkReal32)fabs((By*HB).DotProduct(L));
01652         AkReal32 dpbz = (AkReal32)fabs((Bz*DB).DotProduct(L));
01653 
01654         AkReal32 right = dpax + dpay + dpaz + dpbx + dpby + dpbz;
01655 
01656         return left > right;
01657     }
01658 
01659     void UpdateBoundingBox(AkBoundingBox& out_aabb) const
01660     {
01661         Ak3DVector x = m_X * m_Extent.X;
01662         out_aabb.Update(m_Center + x);
01663         out_aabb.Update(m_Center - x);
01664         Ak3DVector y = m_Y * m_Extent.Y;
01665         out_aabb.Update(m_Center + y);
01666         out_aabb.Update(m_Center - y);
01667         Ak3DVector Z = m_Z * m_Extent.Z;
01668         out_aabb.Update(m_Center + Z);
01669         out_aabb.Update(m_Center - Z);
01670     }
01671 
01672 
01673 private:
01674 
01675     Ak3DVector                      m_Center;
01676     Ak3DVector                      m_Extent;
01677 
01678     //Orthonormal Axes
01679     Ak3DVector                      m_X;
01680     Ak3DVector                      m_Y;
01681     Ak3DVector                      m_Z;
01682 };

此页面对您是否有帮助?

需要技术支持?

仍有疑问?或者问题?需要更多信息?欢迎联系我们,我们可以提供帮助!

查看我们的“技术支持”页面

介绍一下自己的项目。我们会竭力为您提供帮助。

来注册自己的项目,我们帮您快速入门,不带任何附加条件!

开始 Wwise 之旅