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를 시작해 보세요