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