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