AkVectors.h 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943
  1. /*******************************************************************************
  2. The content of this file includes portions of the AUDIOKINETIC Wwise Technology
  3. released in source code form as part of the SDK installer package.
  4. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. // AkVectors.h
  21. //
  22. #pragma once
  23. #include <AK/SoundEngine/Common/AkTypes.h>
  24. #include <AK/SoundEngine/Common/AkSimd.h>
  25. #include <AK/SoundEngine/Common/AkSpeakerVolumes.h>
  26. #include <AK/SoundEngine/Common/IAkPluginMemAlloc.h>
  27. #include <AK/Tools/Common/AkArray.h>
  28. #include <AK/Tools/Common/AkObject.h>
  29. #include <math.h>
  30. #include <stdio.h>
  31. #include <float.h>
  32. //#define AKVBAP_DEBUG 1
  33. //#define AKPORTALS_DEBUG
  34. #define AKVECTORS_PI (3.1415926535897932384626433832795f)
  35. #define AKVECTORS_TWOPI (6.283185307179586476925286766559f)
  36. #define AKVECTORS_PIOVERTWO (1.5707963267948966192313216916398f)
  37. #define AKVECTORS_EPSILON (1.0e-38f) // epsilon value for fast log(0)
  38. class Ak4DVector
  39. {
  40. public:
  41. //-----------------------------------------------------------
  42. // Constructor/Destructor functions
  43. Ak4DVector()
  44. {
  45. v[0] = 0.0f;
  46. v[1] = 0.0f;
  47. v[2] = 0.0f;
  48. v[3] = 0.0f;
  49. }
  50. Ak4DVector(const AkVector& b)
  51. {
  52. v[0] = b.X;
  53. v[1] = b.Y;
  54. v[2] = b.Z;
  55. v[3] = 1;
  56. }
  57. //-----------------------------------------------------------
  58. // Basic vector operators
  59. Ak4DVector& operator=(const Ak4DVector& b)
  60. {
  61. v[0] = b.v[0];
  62. v[1] = b.v[1];
  63. v[2] = b.v[2];
  64. v[3] = b.v[3];
  65. return *this;
  66. }
  67. Ak4DVector& operator/=(const AkReal32 f)
  68. {
  69. v[0] = v[0] / f;
  70. v[1] = v[1] / f;
  71. v[2] = v[2] / f;
  72. v[3] = v[3] / f;
  73. return *this;
  74. }
  75. Ak4DVector operator-(const Ak4DVector& b) const
  76. {
  77. Ak4DVector p;
  78. p.v[0] = v[0] - b.v[0];
  79. p.v[1] = v[1] - b.v[1];
  80. p.v[2] = v[2] - b.v[2];
  81. p.v[3] = v[3] - b.v[3];
  82. return p;
  83. }
  84. AkReal32 v[4];
  85. };
  86. struct Ak3DIntVector
  87. {
  88. public:
  89. Ak3DIntVector() = default;
  90. Ak3DIntVector(AkInt32 x, AkInt32 y, AkInt32 z) :
  91. X(x),
  92. Y(y),
  93. Z(z)
  94. {
  95. }
  96. AkInt32 X; ///< X Position
  97. AkInt32 Y; ///< Y Position
  98. AkInt32 Z; ///< Z Position
  99. };
  100. ///
  101. /// Specialization must provide these methods. Could enforce that through static_assert...
  102. /// static TDataType Cos(TDataType in_value) const;
  103. /// static TDataType Sin(TDataType in_value) const;
  104. /// static TDataType Sqrt(TDataType in_value) const;
  105. /// static constexpr TDataType POSITIVE_EPSILON;
  106. /// static constexpr TDataType VECTOR_EPSILON;
  107. ///
  108. template<typename TDataType> class RealPrecision;
  109. template<>
  110. class RealPrecision<AkReal32>
  111. {
  112. public:
  113. static AkReal32 Cos(AkReal32 in_value) { return cosf(in_value); }
  114. static AkReal32 Sin(AkReal32 in_value) { return sinf(in_value); }
  115. static AkReal32 Sqrt(AkReal32 in_value) { return sqrtf(in_value); }
  116. static AkReal32 ACos(AkReal32 in_value) { return acosf(in_value); }
  117. static bool IsFinite(AkReal32 in_val)
  118. {
  119. // Purposely not using std::isnan() or isfinite because fastmath on clang & gcc may optimize them to be false always.
  120. return !(((*(AkUInt32*)&in_val) & 0x7fffffff) >= 0x7f800000);
  121. }
  122. static constexpr AkReal32 POSITIVE_EPSILON = 0.00001f;
  123. static constexpr AkReal32 VECTOR_EPSILON = AKVECTORS_EPSILON;
  124. static constexpr AkReal32 MAX_VALUE = FLT_MAX;
  125. };
  126. template<>
  127. class RealPrecision<AkReal64>
  128. {
  129. public:
  130. static AkReal64 Cos(AkReal64 in_value) { return cos(in_value); }
  131. static AkReal64 Sin(AkReal64 in_value) { return sin(in_value); }
  132. static AkReal64 Sqrt(AkReal64 in_value) { return sqrt(in_value); }
  133. static AkReal64 ACos(AkReal64 in_value) { return acos(in_value); }
  134. static bool IsFinite(AkReal64 in_val)
  135. {
  136. // Purposely not using std::isnan() or isfinite because fastmath on clang & gcc may optimize them to be false always.
  137. return !(((*(AkUInt64*)&in_val) & 0x7fffffffffffffff) >= 0x7ff0000000000000);
  138. }
  139. static constexpr AkReal64 POSITIVE_EPSILON = 0.000000000001f;
  140. static constexpr AkReal64 VECTOR_EPSILON = AKVECTORS_EPSILON;
  141. static constexpr AkReal64 MAX_VALUE = DBL_MAX;
  142. };
  143. // AkImplicitConversion
  144. // Permits automatic conversion from any real type to any other real type.
  145. // May result in loss of precision.
  146. class AkImplicitConversion
  147. {
  148. public:
  149. template<typename TFromReal, typename TToReal>
  150. AkForceInline void Convert(TToReal& out_to, TFromReal in_from)
  151. {
  152. out_to = static_cast<TToReal>(in_from);
  153. }
  154. };
  155. // AkSafeConversion
  156. // Permits automatic conversion only from 32-bit to 64-bit types.
  157. // Conversion from 64-bit to 32-bit is not permitted and will generate and error.
  158. class AkSafeConversion
  159. {
  160. public:
  161. AkForceInline void Convert(AkReal64& out_to, AkReal32 in_from)
  162. {
  163. out_to = in_from;
  164. }
  165. template<typename TReal>
  166. AkForceInline void Convert(TReal& out_to, TReal in_from)
  167. {
  168. out_to = in_from;
  169. }
  170. };
  171. // T3DVector<>
  172. // Template 3D vector class, to support both 32 and 64-bit vector types.
  173. // Ak3DVector32 and Ak3DVector64 typedefs are provided below for convenience.
  174. template<typename TDataType>
  175. class T3DVector
  176. {
  177. public:
  178. /// Expose the data type
  179. ///
  180. typedef TDataType data_type;
  181. // Conversion policy for conversions between 32 and 64 bit types.
  182. typedef AkSafeConversion TTypeConverter;
  183. public:
  184. //-----------------------------------------------------------
  185. // Constructor/Destructor functions
  186. T3DVector() :
  187. X(static_cast<TDataType>(0.0)),
  188. Y(static_cast<TDataType>(0.0)),
  189. Z(static_cast<TDataType>(0.0))
  190. {}
  191. T3DVector(TDataType in_x, TDataType in_y, TDataType in_z) :
  192. X(in_x),
  193. Y(in_y),
  194. Z(in_z)
  195. {}
  196. // Construct from another T3DVector<> type.
  197. // Conversion is (only) permitted in accordance to the conversion policy.
  198. template<typename TFromDataType>
  199. T3DVector(const T3DVector<TFromDataType>& in_vector)
  200. {
  201. TTypeConverter converter;
  202. converter.Convert(X, in_vector.X);
  203. converter.Convert(Y, in_vector.Y);
  204. converter.Convert(Z, in_vector.Z);
  205. }
  206. // Construct from an AkVector type.
  207. // Conversion is (only) permitted in accordance to the conversion policy.
  208. T3DVector(const AkVector& in_vector)
  209. {
  210. TTypeConverter converter;
  211. converter.Convert(X, in_vector.X);
  212. converter.Convert(Y, in_vector.Y);
  213. converter.Convert(Z, in_vector.Z);
  214. }
  215. // Construct from an AkVector64 type.
  216. // Conversion is (only) permitted in accordance to the conversion policy.
  217. T3DVector(const AkVector64& in_vector)
  218. {
  219. TTypeConverter converter;
  220. converter.Convert(X, in_vector.X);
  221. converter.Convert(Y, in_vector.Y);
  222. converter.Convert(Z, in_vector.Z);
  223. }
  224. // Implicit conversion to AkVector type, it the conversion policy permits it.
  225. operator AkVector() const
  226. {
  227. AkVector v;
  228. TTypeConverter converter;
  229. converter.Convert(v.X, X);
  230. converter.Convert(v.Y, Y);
  231. converter.Convert(v.Z, Z);
  232. return v;
  233. }
  234. // Implicit conversion to AkVector64 type, it the conversion policy permits it.
  235. operator AkVector64() const
  236. {
  237. AkVector64 v;
  238. TTypeConverter converter;
  239. converter.Convert(v.X, X);
  240. converter.Convert(v.Y, Y);
  241. converter.Convert(v.Z, Z);
  242. return v;
  243. }
  244. // Casting method for explicit conversion to another vector type.s
  245. template<typename TVectorType>
  246. TVectorType Cast() const;
  247. // Construct a vector from a scalar.
  248. explicit T3DVector(TDataType in_scalar)
  249. : X(in_scalar)
  250. , Y(in_scalar)
  251. , Z(in_scalar)
  252. {}
  253. // Convert from a vector from a AKSIMD_V4F32.
  254. explicit T3DVector(const AKSIMD_V4F32& in_v4f32)
  255. {
  256. X = static_cast<TDataType>(AKSIMD_GETELEMENT_V4F32(in_v4f32, 0));
  257. Y = static_cast<TDataType>(AKSIMD_GETELEMENT_V4F32(in_v4f32, 1));
  258. Z = static_cast<TDataType>(AKSIMD_GETELEMENT_V4F32(in_v4f32, 2));
  259. }
  260. AkForceInline AKSIMD_V4F32 PointV4F32() const
  261. {
  262. AKSIMD_V4F32 v4f32;
  263. AKSIMD_GETELEMENT_V4F32(v4f32, 0) = static_cast<AkReal32>(X);
  264. AKSIMD_GETELEMENT_V4F32(v4f32, 1) = static_cast<AkReal32>(Y);
  265. AKSIMD_GETELEMENT_V4F32(v4f32, 2) = static_cast<AkReal32>(Z);
  266. AKSIMD_GETELEMENT_V4F32(v4f32, 3) = 1.f;
  267. return v4f32;
  268. }
  269. AkForceInline AKSIMD_V4F32 VectorV4F32() const
  270. {
  271. AKSIMD_V4F32 v4f32;
  272. AKSIMD_GETELEMENT_V4F32(v4f32, 0) = static_cast<TDataType>(X);
  273. AKSIMD_GETELEMENT_V4F32(v4f32, 1) = static_cast<TDataType>(Y);
  274. AKSIMD_GETELEMENT_V4F32(v4f32, 2) = static_cast<TDataType>(Z);
  275. AKSIMD_GETELEMENT_V4F32(v4f32, 3) = static_cast<TDataType>(0.0);
  276. return v4f32;
  277. }
  278. void Zero()
  279. {
  280. X = static_cast<TDataType>(0.0);
  281. Y = static_cast<TDataType>(0.0);
  282. Z = static_cast<TDataType>(0.0);
  283. }
  284. //-----------------------------------------------------------
  285. // Basic vector operators
  286. AkForceInline bool operator==(const T3DVector& b) const
  287. {
  288. return X == b.X && Y == b.Y && Z == b.Z;
  289. }
  290. AkForceInline bool operator!=(const T3DVector& b) const
  291. {
  292. return X != b.X || Y != b.Y || Z != b.Z;
  293. }
  294. AkForceInline bool operator<(const T3DVector& b) const
  295. {
  296. return X < b.X && Y < b.Y && Z < b.Z;
  297. }
  298. AkForceInline bool operator<=(const T3DVector& b) const
  299. {
  300. return X <= b.X && Y <= b.Y && Z <= b.Z;
  301. }
  302. AkForceInline bool operator>(const T3DVector b) const
  303. {
  304. return X > b.X && Y > b.Y && Z > b.Z;
  305. }
  306. AkForceInline bool operator>=(const T3DVector& b) const
  307. {
  308. return X >= b.X && Y >= b.Y && Z >= b.Z;
  309. }
  310. AkForceInline T3DVector& operator*=(const TDataType f)
  311. {
  312. X = X * f;
  313. Y = Y * f;
  314. Z = Z * f;
  315. return *this;
  316. }
  317. AkForceInline T3DVector& operator/=(const TDataType f)
  318. {
  319. TDataType oneoverf = static_cast<TDataType>(1.0) / f;
  320. X = X * oneoverf;
  321. Y = Y * oneoverf;
  322. Z = Z * oneoverf;
  323. return *this;
  324. }
  325. AkForceInline T3DVector operator*(const T3DVector v2) const
  326. {
  327. T3DVector v;
  328. v.X = X * v2.X;
  329. v.Y = Y * v2.Y;
  330. v.Z = Z * v2.Z;
  331. return v;
  332. }
  333. AkForceInline T3DVector operator*(const TDataType f) const
  334. {
  335. T3DVector v;
  336. v.X = X * f;
  337. v.Y = Y * f;
  338. v.Z = Z * f;
  339. return v;
  340. }
  341. AkForceInline T3DVector operator/(const T3DVector in_rhs) const
  342. {
  343. T3DVector v;
  344. v.X = X / in_rhs.X;
  345. v.Y = Y / in_rhs.Y;
  346. v.Z = Z / in_rhs.Z;
  347. return v;
  348. }
  349. AkForceInline T3DVector operator/(const TDataType f) const
  350. {
  351. T3DVector v;
  352. TDataType oneoverf = static_cast<TDataType>(1.0) / f;
  353. v.X = X * oneoverf;
  354. v.Y = Y * oneoverf;
  355. v.Z = Z * oneoverf;
  356. return v;
  357. }
  358. AkForceInline T3DVector operator+(const TDataType f) const
  359. {
  360. T3DVector v;
  361. v.X = X + f;
  362. v.Y = Y + f;
  363. v.Z = Z + f;
  364. return v;
  365. }
  366. AkForceInline T3DVector operator-(const TDataType f) const
  367. {
  368. T3DVector v;
  369. v.X = X - f;
  370. v.Y = Y - f;
  371. v.Z = Z - f;
  372. return v;
  373. }
  374. AkForceInline T3DVector operator+(const T3DVector& b) const
  375. {
  376. T3DVector v;
  377. v.X = X + b.X;
  378. v.Y = Y + b.Y;
  379. v.Z = Z + b.Z;
  380. return v;
  381. }
  382. AkForceInline T3DVector operator-(const T3DVector& b) const
  383. {
  384. T3DVector v;
  385. v.X = X - b.X;
  386. v.Y = Y - b.Y;
  387. v.Z = Z - b.Z;
  388. return v;
  389. }
  390. AkForceInline TDataType HorizontalMin() const
  391. {
  392. return AkMin(X, AkMin(Y, Z));
  393. }
  394. AkForceInline TDataType HorizontalMax() const
  395. {
  396. return AkMax(X, AkMax(Y, Z));
  397. }
  398. AkForceInline static T3DVector Min(const T3DVector& A, const T3DVector& B)
  399. {
  400. T3DVector min;
  401. min.X = AkMin(A.X, B.X);
  402. min.Y = AkMin(A.Y, B.Y);
  403. min.Z = AkMin(A.Z, B.Z);
  404. return min;
  405. }
  406. AkForceInline static T3DVector Max(const T3DVector& A, const T3DVector& B)
  407. {
  408. T3DVector max;
  409. max.X = AkMax(A.X, B.X);
  410. max.Y = AkMax(A.Y, B.Y);
  411. max.Z = AkMax(A.Z, B.Z);
  412. return max;
  413. }
  414. //-----------------------------------------------------------
  415. // Conversion functions
  416. AkForceInline T3DVector Rotate180X_90Y() const
  417. {
  418. T3DVector v;
  419. v.X = -X;
  420. v.Y = Z;
  421. v.Z = -Y;
  422. return v;
  423. }
  424. AkForceInline T3DVector SphericalToCartesian(
  425. const TDataType azimuth,
  426. const TDataType elevation)
  427. {
  428. TDataType cosElevation = RealPrecision<TDataType>::Cos(elevation);
  429. X = RealPrecision<TDataType>::Cos(azimuth) * cosElevation;
  430. Y = RealPrecision<TDataType>::Sin(azimuth) * cosElevation;
  431. Z = RealPrecision<TDataType>::Sin(elevation);
  432. return *this;
  433. }
  434. // Determinant of 3 column vectors.
  435. static AkForceInline TDataType Determinant(
  436. const T3DVector& a,
  437. const T3DVector& b,
  438. const T3DVector& c)
  439. {
  440. return (a.X*b.Y*c.Z + a.Y*b.Z*c.X + a.Z*b.X*c.Y) -
  441. (a.Z*b.Y*c.X + a.Y*b.X*c.Z + a.X*b.Z*c.Y);
  442. }
  443. // Convert a vector to a different base
  444. AkForceInline T3DVector LinearCombination(
  445. const T3DVector& A,
  446. const T3DVector& B,
  447. const T3DVector& C) const
  448. {
  449. T3DVector v;
  450. TDataType d = Determinant(A, B, C);
  451. if (d < RealPrecision<TDataType>::VECTOR_EPSILON && d > -RealPrecision<TDataType>::VECTOR_EPSILON)
  452. {
  453. v.X = static_cast<TDataType>(0.0); v.Y = static_cast<TDataType>(0.0); v.Z = static_cast<TDataType>(0.0);
  454. return v;
  455. }
  456. // http://mathworld.wolfram.com/MatrixInverse.html
  457. T3DVector invA = T3DVector(B.Y*C.Z - B.Z*C.Y, A.Z*C.Y - A.Y*C.Z, A.Y*B.Z - A.Z*B.Y);
  458. T3DVector invB = T3DVector(B.Z*C.X - B.X*C.Z, A.X*C.Z - A.Z*C.X, A.Z*B.X - A.X*B.Z);
  459. T3DVector invC = T3DVector(B.X*C.Y - B.Y*C.X, A.Y*C.X - A.X*C.Y, A.X*B.Y - A.Y*B.X);
  460. TDataType oneover_d = static_cast<TDataType>(1.0) / d;
  461. invA *= oneover_d;
  462. invB *= oneover_d;
  463. invC *= oneover_d;
  464. // Project coordinates using a vector to matrix multiplication
  465. v.X = X * invA.X + Y * invB.X + Z * invC.X;
  466. v.Y = X * invA.Y + Y * invB.Y + Z * invC.Y;
  467. v.Z = X * invA.Z + Y * invB.Z + Z * invC.Z;
  468. // v /= v.Length();
  469. return v;
  470. }
  471. AkForceInline T3DVector& Normalize()
  472. {
  473. TDataType l = Length();
  474. if (l != static_cast<TDataType>(0.0))
  475. {
  476. X /= l;
  477. Y /= l;
  478. Z /= l;
  479. }
  480. else
  481. {
  482. X = static_cast<TDataType>(0.0);
  483. Y = static_cast<TDataType>(0.0);
  484. Z = static_cast<TDataType>(0.0);
  485. }
  486. return *this;
  487. }
  488. AkForceInline TDataType L2_Norm() const
  489. {
  490. return RealPrecision<TDataType>::Sqrt(X*X + Y*Y + Z*Z);
  491. }
  492. AkForceInline TDataType DotProduct(const T3DVector& v2) const
  493. {
  494. return X*v2.X + Y*v2.Y + Z*v2.Z;
  495. }
  496. AkForceInline TDataType Dot(const T3DVector& v2) const
  497. {
  498. return DotProduct(v2);
  499. }
  500. AkForceInline T3DVector Cross(const T3DVector& v) const
  501. {
  502. T3DVector uxv;
  503. const T3DVector& u = *this;
  504. uxv.X = u.Y*v.Z - u.Z*v.Y;
  505. uxv.Y = u.Z*v.X - u.X*v.Z;
  506. uxv.Z = u.X*v.Y - u.Y*v.X;
  507. return uxv;
  508. }
  509. AkForceInline TDataType Length() const
  510. {
  511. return RealPrecision<TDataType>::Sqrt(X*X + Y*Y + Z*Z);
  512. }
  513. AkForceInline TDataType LengthSquared() const
  514. {
  515. return X*X + Y*Y + Z*Z;
  516. }
  517. // Usefull in VBAP algorithm, only points that are a positive linear composition matters.
  518. AkForceInline bool IsAllPositive() const
  519. {
  520. return X >= -RealPrecision<TDataType>::POSITIVE_EPSILON &&
  521. Y >= -RealPrecision<TDataType>::POSITIVE_EPSILON &&
  522. Z >= -RealPrecision<TDataType>::POSITIVE_EPSILON;
  523. }
  524. AkForceInline T3DVector Abs() const
  525. {
  526. T3DVector abs = *this;
  527. abs.X = (TDataType)fabs(abs.X);
  528. abs.Y = (TDataType)fabs(abs.Y);
  529. abs.Z = (TDataType)fabs(abs.Z);
  530. return abs;
  531. }
  532. AkForceInline bool IsFinite() const
  533. {
  534. return
  535. RealPrecision<TDataType>::IsFinite(X) &&
  536. RealPrecision<TDataType>::IsFinite(Y) &&
  537. RealPrecision<TDataType>::IsFinite(Z);
  538. }
  539. TDataType X;
  540. TDataType Y;
  541. TDataType Z;
  542. };
  543. template<typename TDataType>
  544. AkForceInline T3DVector<TDataType> operator*(const TDataType f, const T3DVector<TDataType>& v)
  545. {
  546. return v * f;
  547. }
  548. template<typename TDataType>
  549. AkForceInline T3DVector<TDataType> operator/(const TDataType f, const T3DVector<TDataType>& v)
  550. {
  551. T3DVector<TDataType> res;
  552. res.X = f / v.X;
  553. res.Y = f / v.Y;
  554. res.Z = f / v.Z;
  555. return res;
  556. }
  557. // Ak3DVector typedefs
  558. // Ak3DVector32 - Can be implicitly converted to 64 but not the other way around.
  559. typedef T3DVector<AkReal32> Ak3DVector;
  560. typedef T3DVector<AkReal32> Ak3DVector32;
  561. // Ak3DVector64 - It is necessary to call vec.Cast<Ak3DVector64>() to convert to 32 bit vector type.
  562. typedef T3DVector<AkReal64> Ak3DVector64;
  563. // Casting methods.
  564. // Generic cast between two T3DVector<> types.
  565. template<typename TDataType>
  566. template<typename TVectorType>
  567. TVectorType T3DVector<TDataType>::Cast() const
  568. {
  569. TVectorType v;
  570. v.X = static_cast<typename TVectorType::data_type>(X);
  571. v.Y = static_cast<typename TVectorType::data_type>(Y);
  572. v.Z = static_cast<typename TVectorType::data_type>(Z);
  573. return v;
  574. }
  575. class Ak2DVector
  576. {
  577. public:
  578. //-----------------------------------------------------------
  579. // Constructor/Destructor functions
  580. Ak2DVector() = default;
  581. Ak2DVector(AkReal32 x, AkReal32 y) :
  582. X(x),
  583. Y(y)
  584. {
  585. }
  586. //-----------------------------------------------------------
  587. // Basic vector operators
  588. AkForceInline Ak2DVector operator=(const Ak2DVector& b)
  589. {
  590. X = b.X;
  591. Y = b.Y;
  592. return *this;
  593. }
  594. AkForceInline Ak2DVector operator=(const AkSphericalCoord& b)
  595. {
  596. X = b.theta;
  597. Y = b.phi;
  598. return *this;
  599. }
  600. Ak2DVector operator-(const Ak2DVector& b) const
  601. {
  602. Ak2DVector v;
  603. v.X = X - b.X;
  604. v.Y = Y - b.Y;
  605. return v;
  606. }
  607. Ak2DVector& operator*=(const AkReal32 f)
  608. {
  609. X = X * f;
  610. Y = Y * f;
  611. return *this;
  612. }
  613. Ak2DVector& operator/=(const AkReal32 f)
  614. {
  615. AkReal32 oneoverf = 1.f / f;
  616. X = X * oneoverf;
  617. Y = Y * oneoverf;
  618. return *this;
  619. }
  620. AkForceInline bool operator==(const Ak2DVector& b) const
  621. {
  622. return b.X == X && b.Y == Y;
  623. }
  624. AkForceInline bool operator!=(const Ak2DVector& b) const
  625. {
  626. return b.X != X && b.Y != Y;
  627. }
  628. AkForceInline AkReal32 Length() const
  629. {
  630. return sqrtf(X*X+Y*Y);
  631. }
  632. //-----------------------------------------------------------
  633. // Conversion functions
  634. AkForceInline Ak2DVector& CartesianToSpherical(const Ak3DVector& in_Cartesian)
  635. {
  636. // (radial, azimuth, elevation)
  637. AkReal32 r = sqrtf( in_Cartesian.X*in_Cartesian.X + in_Cartesian.Y*in_Cartesian.Y + in_Cartesian.Z*in_Cartesian.Z);
  638. AKASSERT( r != 0);
  639. X = atan2f(in_Cartesian.Y, in_Cartesian.X);
  640. Y = asinf(in_Cartesian.Z / r);
  641. NormalizeSpherical();
  642. return *this;
  643. }
  644. AkForceInline Ak2DVector LinearCombination(
  645. const Ak2DVector& A,
  646. const Ak2DVector& B) const
  647. {
  648. Ak2DVector v;
  649. // Project coordinates using a vector to matrix multiplication
  650. AkReal32 d = (A.X*B.Y - A.Y*B.X);
  651. if (d < AKVECTORS_EPSILON && d > -AKVECTORS_EPSILON)
  652. {
  653. v.X = 0.0f; v.Y = 0.0f;
  654. return v;
  655. }
  656. Ak2DVector invA = Ak2DVector( B.Y, -A.Y );
  657. Ak2DVector invB = Ak2DVector( -B.X, A.X );
  658. AkReal32 oneover_d = 1.f / d;
  659. invA *= oneover_d;
  660. invB *= oneover_d;
  661. v.X = X * invA.X + Y * invB.X;
  662. v.Y = X * invA.Y + Y * invB.Y;
  663. // v /= v.Length();
  664. return v;
  665. }
  666. AkForceInline Ak2DVector NormalizeSpherical() const
  667. {
  668. /*
  669. Normalise spherical coordinates.
  670. X (azimuthal) -> [-PI, PI], circle lies on xy plan, 0 is on X axix
  671. Y (elevation) -> [-PI/2, PI/2], half circle on Z axis, 0 on XY plan, PI/2 straigt up on Z axis.
  672. */
  673. Ak2DVector v;
  674. v.X = X;
  675. v.Y = Y;
  676. if (X > AKVECTORS_PI)
  677. v.X = X - AKVECTORS_TWOPI;
  678. else if (X < -AKVECTORS_PI)
  679. v.X = X + AKVECTORS_TWOPI;
  680. if (Y > AKVECTORS_PIOVERTWO)
  681. v.Y = Y - AKVECTORS_PI;
  682. else if (Y < -AKVECTORS_PIOVERTWO)
  683. v.Y = Y + AKVECTORS_PI;
  684. AKASSERT(X<AKVECTORS_PI);
  685. AKASSERT(Y<AKVECTORS_PIOVERTWO);
  686. return v;
  687. }
  688. AkForceInline void NormalizeSpherical()
  689. {
  690. /*
  691. Normalise spherical coordinates.
  692. X (azimuthal) -> [-PI, PI], circle lies on xy plan, 0 is on X axix
  693. Y (elevation) -> [-PI/2, PI/2], half circle on Z axis, 0 on XY plan, PI/2 straigt up on Z axis.
  694. */
  695. if (X > AKVECTORS_PI)
  696. X = X - AKVECTORS_TWOPI;
  697. else if (X < -AKVECTORS_PI)
  698. X = X + AKVECTORS_TWOPI;
  699. if (Y > AKVECTORS_PIOVERTWO)
  700. Y = Y - AKVECTORS_PI;
  701. else if (Y < -AKVECTORS_PIOVERTWO)
  702. Y = Y + AKVECTORS_PI;
  703. }
  704. // Useful in VBAP algorithm, only points that are a positive linear composition matters.
  705. AkForceInline bool IsAllPositive() const
  706. {
  707. const AkReal32 POSITIVE_TEST_EPSILON = 0.00001f; //0.005f;
  708. return X >= -POSITIVE_TEST_EPSILON &&
  709. Y >= -POSITIVE_TEST_EPSILON;
  710. }
  711. AkReal32 X;
  712. AkReal32 Y;
  713. };
  714. class AkMatrix4x4
  715. {
  716. static const int MAX_SIZE = 16;
  717. public:
  718. //-----------------------------------------------------------
  719. // Constructor/Destructor functions
  720. AkMatrix4x4() = default;
  721. //-----------------------------------------------------------
  722. // Basic vector operators
  723. AkMatrix4x4& operator/=(const AkReal32 f)
  724. {
  725. for (int i = 0; i < MAX_SIZE; i++)
  726. m_Data[i] /= f;
  727. return *this;
  728. }
  729. AkMatrix4x4& operator=(AkReal32 * in_Data)
  730. {
  731. for (int i = 0; i < MAX_SIZE; i++)
  732. {
  733. m_Data[i] = in_Data[i];
  734. }
  735. return *this;
  736. }
  737. AkReal32 m_Data[MAX_SIZE];
  738. };
  739. class AkMatrix3x3
  740. {
  741. public:
  742. //-----------------------------------------------------------
  743. // Constructor/Destructor functions
  744. AkMatrix3x3() = default;
  745. static AkMatrix3x3 FromColumnVectors(const Ak3DVector& in_col0, const Ak3DVector& in_col1, const Ak3DVector& in_col2)
  746. {
  747. AkMatrix3x3 m;
  748. m(0, 0) = in_col0.X;
  749. m(1, 0) = in_col0.Y;
  750. m(2, 0) = in_col0.Z;
  751. m(0, 1) = in_col1.X;
  752. m(1, 1) = in_col1.Y;
  753. m(2, 1) = in_col1.Z;
  754. m(0, 2) = in_col2.X;
  755. m(1, 2) = in_col2.Y;
  756. m(2, 2) = in_col2.Z;
  757. return m;
  758. }
  759. //-----------------------------------------------------------
  760. // Basic vector operators
  761. AkMatrix3x3& operator/=(const AkReal32 f)
  762. {
  763. for (int i = 0; i < 3; i++)
  764. {
  765. for (int j = 0; j < 3; j++)
  766. {
  767. m_Data[i][j] /= f;
  768. }
  769. }
  770. return *this;
  771. }
  772. AkForceInline AkReal32& operator()(const AkUInt32 row, const AkUInt32 column)
  773. {
  774. return m_Data[column][row];
  775. }
  776. AkForceInline const AkReal32& operator()(const AkUInt32 row, const AkUInt32 column) const
  777. {
  778. return m_Data[column][row];
  779. }
  780. AkForceInline Ak3DVector operator*(const Ak3DVector& in_rhs) const
  781. {
  782. Ak3DVector res;
  783. res.X = in_rhs.X * m_Data[0][0] + in_rhs.Y * m_Data[1][0] + in_rhs.Z * m_Data[2][0];
  784. res.Y = in_rhs.X * m_Data[0][1] + in_rhs.Y * m_Data[1][1] + in_rhs.Z * m_Data[2][1];
  785. res.Z = in_rhs.X * m_Data[0][2] + in_rhs.Y * m_Data[1][2] + in_rhs.Z * m_Data[2][2];
  786. return res;
  787. }
  788. AkForceInline AkMatrix3x3& operator+=(const AkMatrix3x3& in_rhs)
  789. {
  790. Add(*this, *this, in_rhs);
  791. return *this;
  792. }
  793. static AkForceInline void Add(AkMatrix3x3& out_res, const AkMatrix3x3& in_m0, const AkMatrix3x3& in_m1)
  794. {
  795. #define ADD(i,j) out_res(i,j) = in_m0(i,j) + in_m1(i,j)
  796. ADD(0, 0); ADD(0, 1); ADD(0, 2);
  797. ADD(1, 0); ADD(1, 1); ADD(1, 2);
  798. ADD(2, 0); ADD(2, 1); ADD(2, 2);
  799. #undef ADD
  800. }
  801. AkForceInline AkMatrix3x3& operator*=(const AkReal32& in_f)
  802. {
  803. m_Data[0][0] *= in_f; m_Data[0][1] *= in_f; m_Data[0][2] *= in_f;
  804. m_Data[1][0] *= in_f; m_Data[1][1] *= in_f; m_Data[1][2] *= in_f;
  805. m_Data[2][0] *= in_f; m_Data[2][1] *= in_f; m_Data[2][2] *= in_f;
  806. return *this;
  807. }
  808. static AkForceInline void Diagonal(AkMatrix3x3& out_mat, AkReal32 in_f)
  809. {
  810. out_mat(0, 0) = in_f; out_mat(0, 1) = 0.f; out_mat(0, 2) = 0.f;
  811. out_mat(1, 0) = 0.f; out_mat(1, 1) = in_f; out_mat(1, 2) = 0.f;
  812. out_mat(2, 0) = 0.f; out_mat(2, 1) = 0.f; out_mat(2, 2) = in_f;
  813. }
  814. // Creates the matrix Mu such that Mu*v = u X v
  815. static AkForceInline void CrossProductMatrix(AkMatrix3x3& out_mat, const Ak3DVector& in_u)
  816. {
  817. out_mat(0, 0) = 0.f; out_mat(0, 1) = -in_u.Z; out_mat(0, 2) = in_u.Y;
  818. out_mat(1, 0) = in_u.Z; out_mat(1, 1) = 0.f; out_mat(1, 2) = -in_u.X;
  819. out_mat(2, 0) = -in_u.Y; out_mat(2, 1) = in_u.X; out_mat(2, 2) = 0.f;
  820. }
  821. static AkForceInline void OuterProduct(AkMatrix3x3& out_mat, const Ak3DVector& in_v0, const Ak3DVector& in_v1)
  822. {
  823. 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;
  824. 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;
  825. 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;
  826. }
  827. static AkForceInline void Rotation(AkMatrix3x3& out_mat, AkReal32 in_angle, const Ak3DVector& in_axis)
  828. {
  829. Rotation(out_mat, sinf(in_angle), cosf(in_angle), in_axis);
  830. }
  831. static void Rotation(AkMatrix3x3& out_mat, AkReal32 in_sin, AkReal32 in_cos, const Ak3DVector& in_axis)
  832. {
  833. Diagonal(out_mat, in_cos);
  834. AkMatrix3x3 outer;
  835. OuterProduct(outer, in_axis, in_axis);
  836. outer *= (1.f - in_cos);
  837. out_mat += outer;
  838. AkMatrix3x3 cross;
  839. CrossProductMatrix(cross, in_axis*in_sin);
  840. out_mat += cross;
  841. }
  842. // [column][row]
  843. AkReal32 m_Data[3][3];
  844. };
  845. class AkQuaternion
  846. {
  847. public:
  848. // Identity quaternion
  849. AkQuaternion(): W(1.f), X(0.f), Y(0.f), Z(0.f) {}
  850. AkQuaternion(AkReal32 in_W, AkReal32 in_X, AkReal32 in_Y, AkReal32 in_Z) :
  851. W(in_W),
  852. X(in_X),
  853. Y(in_Y),
  854. Z(in_Z)
  855. {}
  856. // Create a quaternion from a 3x3 rotation matrix
  857. static AkQuaternion FromRotationMatrix(const AkMatrix3x3& in_mat)
  858. {
  859. AkQuaternion q;
  860. AkReal32 trace = in_mat(0,0) + in_mat(1, 1) + in_mat(2, 2);
  861. if (trace > 0.0f)
  862. {
  863. AkReal32 srt = sqrtf(trace + 1.f);
  864. AkReal32 s = 0.5f / srt;
  865. q.W = 0.5f * srt;
  866. q.X = (in_mat(2, 1) - in_mat(1, 2)) * s;
  867. q.Y = (in_mat(0, 2) - in_mat(2, 0)) * s;
  868. q.Z = (in_mat(1, 0) - in_mat(0, 1)) * s;
  869. }
  870. else
  871. {
  872. // diagonal is negative
  873. AkUInt32 i = 0;
  874. if (in_mat(1, 1) > in_mat(0, 0))
  875. i = 1;
  876. if (in_mat(2, 2) > in_mat(i, i))
  877. i = 2;
  878. AkUInt32 j = (i + 1) % 3;
  879. AkUInt32 k = (i + 2) % 3;
  880. AkReal32 s = sqrtf( in_mat(i, i) - in_mat(j, j) - in_mat(k, k) + 1.0f );
  881. AkReal32 t = (s == 0.f) ? 0.f : (0.5f / s);
  882. AkReal32 qt[4];
  883. qt[i] = 0.5f * s;
  884. qt[j] = (in_mat(j, i) + in_mat(i, j)) * t;
  885. qt[k] = (in_mat(k, i) + in_mat(i, k)) * t;
  886. qt[3] = (in_mat(k, j) - in_mat(j, k)) * t;
  887. q.X = qt[0];
  888. q.Y = qt[1];
  889. q.Z = qt[2];
  890. q.W = qt[3];
  891. }
  892. return q;
  893. }
  894. // Create a rotation quaternion from euler angles.
  895. static AkQuaternion FromEulers(
  896. AkReal32 in_x, // Rotation around the X axis, in radians.
  897. AkReal32 in_y, // Rotation around the Y axis, in radians.
  898. AkReal32 in_z // Rotation around the Z axis, in radians.
  899. )
  900. {
  901. AkReal32 sy = sinf(in_z / 2.f);
  902. AkReal32 cy = cosf(in_z / 2.f);
  903. AkReal32 sp = sinf(in_y / 2.f);
  904. AkReal32 cp = cosf(in_y / 2.f);
  905. AkReal32 sr = sinf(in_x / 2.f);
  906. AkReal32 cr = cosf(in_x / 2.f);
  907. AkQuaternion q;
  908. q.W = cr * cp * cy + sr * sp * sy;
  909. q.X = sr * cp * cy - cr * sp * sy;
  910. q.Y = cr * sp * cy + sr * cp * sy;
  911. q.Z = cr * cp * sy - sr * sp * cy;
  912. return q;
  913. }
  914. static AkQuaternion FromAngleAndAxis(AkReal32 in_angle, const Ak3DVector& in_axis)
  915. {
  916. AkQuaternion q;
  917. AkReal32 sa = sinf(in_angle / 2.f);
  918. q.W = cosf(in_angle / 2.f);
  919. q.X = in_axis.X * sa;
  920. q.Y = in_axis.Y * sa;
  921. q.Z = in_axis.Z * sa;
  922. return q;
  923. }
  924. AkForceInline AkReal32 Length() const
  925. {
  926. return sqrtf( W*W + X*X + Y*Y + Z*Z );
  927. }
  928. AkForceInline AkQuaternion& Normalize()
  929. {
  930. AkReal32 f = 1.0f / Length();
  931. W *= f;
  932. X *= f;
  933. Y *= f;
  934. Z *= f;
  935. return *this;
  936. }
  937. AkForceInline AkQuaternion Inverse() const
  938. {
  939. AkReal32 norm = W*W + X*X + Y*Y + Z*Z;
  940. if (norm > 0.0)
  941. {
  942. AkReal32 invNorm = 1.0f / norm;
  943. return AkQuaternion(W*invNorm, -X*invNorm, -Y*invNorm, -Z*invNorm);
  944. }
  945. else
  946. {
  947. return AkQuaternion();
  948. }
  949. }
  950. // Create a quaternion representing the shortest arc rotation between (normalized) vectors v0, v1
  951. AkQuaternion(const Ak3DVector& in_v0, const Ak3DVector& in_v1)
  952. {
  953. AkReal32 dot = in_v0.Dot(in_v1);
  954. if (dot >= 1.0f - AKVECTORS_EPSILON)
  955. {
  956. // No rotation - return unity quaternion.
  957. AkQuaternion();
  958. }
  959. if (dot <= -1.f - AKVECTORS_EPSILON)
  960. {
  961. // 180 degree rotation - can use any non-zero length axis.
  962. Ak3DVector axis = Ak3DVector(0.f, 0.f, 1.f).Cross(in_v0);
  963. AkReal32 len = axis.Length();
  964. if (len < AKVECTORS_EPSILON)
  965. {
  966. axis = Ak3DVector(0.f, 1.f, 0.f).Cross(in_v0);
  967. len = axis.Length();
  968. }
  969. axis.Normalize();
  970. AkQuaternion(AKVECTORS_PI, axis);
  971. }
  972. else
  973. {
  974. AkReal32 sqrt = sqrtf((1.f + dot) * 2.f);
  975. AkReal32 invs = 1.f / sqrt;
  976. Ak3DVector cross = in_v0.Cross(in_v1);
  977. X = cross.X * invs;
  978. Y = cross.Y * invs;
  979. Z = cross.Z * invs;
  980. W = sqrt * 0.5f;
  981. Normalize();
  982. }
  983. }
  984. // Build quaternion from an axis and angle representation.
  985. AkQuaternion(AkReal32 in_angle, const Ak3DVector& in_axis)
  986. {
  987. AkReal32 cosHalfAngle = cosf(in_angle / 2.f);
  988. W = cosHalfAngle;
  989. X = cosHalfAngle*in_axis.X;
  990. Y = cosHalfAngle*in_axis.Y;
  991. Z = cosHalfAngle*in_axis.Z;
  992. }
  993. /// Quaternion multiplication.
  994. AkForceInline AkQuaternion operator*(const AkQuaternion& Q) const
  995. {
  996. return AkQuaternion(
  997. W*Q.W - X*Q.X - Y*Q.Y - Z*Q.Z,
  998. W*Q.X + X*Q.W + Y*Q.Z - Z*Q.Y,
  999. W*Q.Y - X*Q.Z + Y*Q.W + Z*Q.X,
  1000. W*Q.Z + X*Q.Y - Y*Q.X + Z*Q.W);
  1001. }
  1002. AkForceInline Ak3DVector32 operator*(const Ak3DVector32& in_v) const
  1003. {
  1004. return RotateVector(in_v);
  1005. }
  1006. AkForceInline Ak3DVector RotateVector(const Ak3DVector32& in_v) const
  1007. {
  1008. /*
  1009. // impl 1
  1010. Ak3DVector uv, uuv;
  1011. Ak3DVector qvec(X, Y, Z);
  1012. uv = qvec.Cross(in_v);
  1013. uuv = qvec.Cross(uv);
  1014. uv *= (2.0f * W);
  1015. uuv *= 2.0f;
  1016. return in_v + uv + uuv;
  1017. */
  1018. // impl 2
  1019. Ak3DVector32 u(X, Y, Z);
  1020. Ak3DVector32 res =
  1021. u * u.Dot(in_v) * 2.f
  1022. + in_v * (W * W - u.Dot(u))
  1023. + u.Cross(in_v) * W * 2.0f;
  1024. return res;
  1025. }
  1026. AkForceInline Ak3DVector UnrotateVector(const Ak3DVector32& in_v) const
  1027. {
  1028. Ak3DVector32 u(-X, -Y, -Z);
  1029. Ak3DVector32 t = 2.f * u.Cross(in_v);
  1030. Ak3DVector32 res = in_v + (W * t) + u.Cross(t);
  1031. return res;
  1032. }
  1033. AkReal32 W;
  1034. AkReal32 X;
  1035. AkReal32 Y;
  1036. AkReal32 Z;
  1037. };
  1038. struct AkIntersectionPoints
  1039. {
  1040. Ak3DVector points[2];
  1041. AkUInt32 count;
  1042. };
  1043. class AkLine
  1044. {
  1045. public:
  1046. AkLine() :
  1047. mint(1.175494351e-38F),
  1048. maxt(3.402823466e+38F)
  1049. {
  1050. }
  1051. AkLine(Ak3DVector in_L, Ak3DVector in_P) :
  1052. L(in_L),
  1053. P(in_P),
  1054. mint(1.175494351e-38F),
  1055. maxt(3.402823466e+38F)
  1056. {
  1057. }
  1058. Ak3DVector PointAt(AkReal32 t) const
  1059. {
  1060. return P + L*t;
  1061. }
  1062. bool Intersect(Ak3DVector A, Ak3DVector B)
  1063. {
  1064. /*
  1065. a (V1 X V2) = (P2 - P1) X V2
  1066. If the lines intersect at a single point, then the resultant vectors
  1067. on each side of this equation must be parallel, and the left side must
  1068. not be the zero vector. We should check to make sure that this is
  1069. true. Once we have checked this, we can solve for 'a' by taking the
  1070. magnitude of each side and dividing. If the resultant vectors are
  1071. parallel, but in opposite directions, then 'a' is the negative of the
  1072. ratio of magnitudes. Once we have 'a' we can go back to the equation
  1073. for L1 to find the intersection point.
  1074. */
  1075. Ak3DVector V1 = L;
  1076. Ak3DVector V2 = B - A;
  1077. Ak3DVector P1 = P;
  1078. Ak3DVector P2 = A;
  1079. // k(V1 X V2) = (A - P) X V2
  1080. Ak3DVector v1CrossV2 = V1.Cross(V2);
  1081. AkReal32 det = Ak3DVector::Determinant(
  1082. P2 - P1,
  1083. V2,
  1084. v1CrossV2
  1085. );
  1086. AkReal32 t = det / v1CrossV2.LengthSquared();
  1087. det = Ak3DVector::Determinant(
  1088. P2 - P1,
  1089. V1,
  1090. v1CrossV2
  1091. );
  1092. AkReal32 s = det / v1CrossV2.LengthSquared();
  1093. AkReal32 distsqrd = ((P2 + V2*s) - (P1 + V1*t)).LengthSquared();
  1094. if ((AkReal32)fabs(v1CrossV2.L2_Norm()) >= AKVECTORS_EPSILON
  1095. && distsqrd < 0.001
  1096. && s <= 1.0f )
  1097. {
  1098. #ifdef AKPORTALS_DEBUG
  1099. Ak3DVector minPoint = PointAt(t);
  1100. char msg[256];
  1101. sprintf(msg, "L1a=[%0.2f,%0.2f,%0.2f];\n", P.X, P.Y, P.Z); AKPLATFORM::OutputDebugMsg(msg);
  1102. 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);
  1103. sprintf(msg, "L2a=[%0.2f,%0.2f,%0.2f];\n", A.X, A.Y, A.Z); AKPLATFORM::OutputDebugMsg(msg);
  1104. sprintf(msg, "L2b=[%0.2f,%0.2f,%0.2f];\n", B.X, B.Y, B.Z); AKPLATFORM::OutputDebugMsg(msg);
  1105. sprintf(msg, "%% t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
  1106. sprintf(msg, "intrPoint=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
  1107. sprintf(msg, "\n"); AKPLATFORM::OutputDebugMsg(msg);
  1108. #endif
  1109. mint = AkMin(mint, t);
  1110. maxt = AkMax(maxt, t);
  1111. return true;
  1112. }
  1113. #ifdef AKPORTALS_DEBUG
  1114. // char msg[256];
  1115. // sprintf(msg, "%% DISCARTED t=%0.2f Min t=%0.2f, Max t=%0.2f\n", t, mint, maxt); AKPLATFORM::OutputDebugMsg(msg);
  1116. #endif
  1117. return false;
  1118. }
  1119. Ak3DVector L;
  1120. Ak3DVector P;
  1121. AkReal32 mint;
  1122. AkReal32 maxt;
  1123. };
  1124. class AkPlane
  1125. {
  1126. public:
  1127. AkPlane() = default;
  1128. AkPlane(
  1129. Ak3DVector in_p1,
  1130. Ak3DVector in_p2,
  1131. Ak3DVector in_p4)
  1132. {
  1133. SetPlane(
  1134. in_p1,
  1135. in_p2,
  1136. in_p4);
  1137. }
  1138. void SetPlane(
  1139. Ak3DVector in_p1,
  1140. Ak3DVector in_p2,
  1141. Ak3DVector in_p4)
  1142. {
  1143. // Reorder A-B-C to clockwwise if necessary
  1144. AKASSERT(in_p1.X < 100000 && in_p1.X > -100000);
  1145. AKASSERT(in_p1.Y < 100000 && in_p1.Y > -100000);
  1146. AKASSERT(in_p1.Z < 100000 && in_p1.Z > -100000);
  1147. AKASSERT(in_p2.X < 100000 && in_p2.X > -100000);
  1148. AKASSERT(in_p2.Y < 100000 && in_p2.Y > -100000);
  1149. AKASSERT(in_p2.Z < 100000 && in_p2.Z > -100000);
  1150. AKASSERT(in_p4.X < 100000 && in_p4.X > -100000);
  1151. AKASSERT(in_p4.Y < 100000 && in_p4.Y > -100000);
  1152. AKASSERT(in_p4.Z < 100000 && in_p4.Z > -100000);
  1153. p1 = in_p1;
  1154. p2 = in_p2;
  1155. p4 = in_p4;
  1156. SetNormal();
  1157. // Ax + By + Cz + D = 0
  1158. // Find D using the normal and a point
  1159. D = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
  1160. }
  1161. #define EPSILON 0.01f
  1162. bool DoesRayIntersect(
  1163. const Ak3DVector& in_Origin,
  1164. const Ak3DVector& in_Destination,
  1165. Ak3DVector& out_Intersection
  1166. ) const
  1167. {
  1168. AkReal32 A = N.X;
  1169. AkReal32 B = N.Y;
  1170. AkReal32 C = N.Z;
  1171. Ak3DVector ray = in_Destination - in_Origin;
  1172. AkReal32 rayLength = ray.Length();
  1173. Ak3DVector intersect;
  1174. // If ray is < EPSILON, use on of the point directly for the test and skip the linear projection
  1175. if (rayLength <= EPSILON)
  1176. {
  1177. Ak3DVector temp = in_Origin - p1;
  1178. AkReal32 dot = temp.DotProduct(N);
  1179. if (dot < EPSILON && dot > -EPSILON)
  1180. {
  1181. intersect = in_Origin;
  1182. }
  1183. else
  1184. {
  1185. // For debug only, to remove
  1186. out_Intersection = p1;
  1187. return false;
  1188. }
  1189. }
  1190. else
  1191. {
  1192. // Normalize ray
  1193. ray.Normalize();
  1194. // 1) if ray len ~= 0, only check if one of the point is on target, ie: assign the intersect point
  1195. // Is ray parallel to the plane?
  1196. if ((A*ray.X + B*ray.Y + C*ray.Z) == 0.0f)
  1197. {
  1198. // For debug only, to remove
  1199. AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
  1200. intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
  1201. out_Intersection = intersect; // For debugging
  1202. return false;
  1203. }
  1204. // Distance along the ray where reflector is hit
  1205. AkReal32 t = -(A*in_Origin.X + B*in_Origin.Y + C*in_Origin.Z + D) / (A*ray.X + B*ray.Y + C*ray.Z);
  1206. // Is the ray going towards the plane? Is it long enough?
  1207. if (t < -EPSILON || t >(rayLength + EPSILON))
  1208. {
  1209. // For debug only, to remove
  1210. intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
  1211. out_Intersection = intersect; // For debugging
  1212. return false; // The ray doesn't intersect
  1213. }
  1214. // Find the coordinate of intersection on the plane
  1215. intersect = Ak3DVector(in_Origin.X + ray.X*t, in_Origin.Y + ray.Y*t, in_Origin.Z + ray.Z*t);
  1216. }
  1217. ///////////////////////////////////////
  1218. //
  1219. // p2____v3____p3
  1220. // | . |
  1221. // ^ inter v4
  1222. // v1 v
  1223. // | |
  1224. // p1__ v2>___p4
  1225. Ak3DVector v1 = p2 - p1;
  1226. Ak3DVector v2 = p4 - p1;
  1227. Ak3DVector vInter1 = intersect - p1;
  1228. Ak3DVector p3 = p4 + v1;
  1229. Ak3DVector v3 = p2 - p3;
  1230. Ak3DVector v4 = p4 - p3;
  1231. Ak3DVector vInter2 = intersect - p3;
  1232. v1.Normalize(); v2.Normalize(); v3.Normalize(); v4.Normalize(); vInter1.Normalize(); vInter2.Normalize();
  1233. // Since it's a square, the angle between the point of intersection and any segment of the pannel should be < 90 degree,
  1234. // therefore the dot product of the two normalized vectors should be > 0
  1235. AkReal32 dot1 = v1.DotProduct(vInter1);
  1236. AkReal32 dot2 = v2.DotProduct(vInter1);
  1237. AkReal32 dot3 = v3.DotProduct(vInter2);
  1238. AkReal32 dot4 = v4.DotProduct(vInter2);
  1239. out_Intersection = intersect;
  1240. return dot1 >= -EPSILON && dot2 >= -EPSILON && dot3 >= -EPSILON && dot4 >= -EPSILON;
  1241. }
  1242. AkReal32 DistPoint_to_Plane(
  1243. Ak3DVector in_P,
  1244. Ak3DVector& out_B) const
  1245. {
  1246. AkReal32 distance = (AkReal32)(AkReal32)fabs(N.X * in_P.X + N.Y * in_P.Y + N.Z * in_P.Z + D);
  1247. Ak3DVector pointToPlane = N;
  1248. pointToPlane *= distance;
  1249. out_B = in_P + pointToPlane;
  1250. return (AkReal32)fabs(distance);
  1251. }
  1252. void SetReflection(
  1253. AkReal32* out_mat) const
  1254. {
  1255. // http://ami.ektf.hu/uploads/papers/finalpdf/AMI_40_from175to186.pd
  1256. /* m_pReflectionMatrix
  1257. reflection on z axis
  1258. P0 (x0, y0, z0), P1 (x1, y1, z1) and P2 (x2, y2, z2),
  1259. normal = (cx, cy, cz)
  1260. d = -CxX0 - CyY0 - CzZ0
  1261. Reflect = 1-2Cx^2 -2CxCy -2CxCz -2Cxd
  1262. -2CxCy 1-2Cy^2 -2CyCz -2Cyd
  1263. -2CxCz -2CyCz 1-2Cz^2 -2Czd
  1264. 0 0 0 1
  1265. */
  1266. AkReal32 d = -(N.X*p1.X) - (N.Y*p1.Y) - (N.Z*p1.Z);
  1267. 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;
  1268. 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;
  1269. 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;
  1270. out_mat[0 + 12] = 0; out_mat[1 + 12] = 0; out_mat[2 + 12] = 0; out_mat[3 + 12] = 1;
  1271. }
  1272. Ak3DVector GetN() const { return N; }
  1273. AkReal32 GetD() const { return D; }
  1274. bool FindIntersectionPoints(
  1275. const AkPlane& in_PlaneB,
  1276. AkIntersectionPoints& out_Intrs) const
  1277. {
  1278. out_Intrs.count = 0;
  1279. // Use vector to solve A
  1280. Ak3DVector point;
  1281. Ak3DVector N1 = N;
  1282. Ak3DVector N2 = in_PlaneB.GetN();
  1283. AkReal32 D1 = D;
  1284. AkReal32 D2 = in_PlaneB.GetD();
  1285. Ak3DVector L = N1.Cross(N2);
  1286. if (L.Length() < 0.001f)
  1287. {
  1288. return false; // The two planes are parallel
  1289. }
  1290. AkUInt8 pivotAxis = 0;
  1291. if ((AkReal32)fabs(L.Y) > (AkReal32)fabs(L.X))
  1292. {
  1293. pivotAxis = 1;
  1294. if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.Y))
  1295. {
  1296. pivotAxis = 2;
  1297. }
  1298. }
  1299. else if ((AkReal32)fabs(L.Z) > (AkReal32)fabs(L.X))
  1300. {
  1301. pivotAxis = 2;
  1302. }
  1303. /*
  1304. Pu = ( N1v*D2 - N2v*D1 ) / Lw
  1305. Pv = ( N2u*D1 - N1u*D2 ) / Lw
  1306. Pz = 0
  1307. */
  1308. switch (pivotAxis)
  1309. {
  1310. case 0:
  1311. AKASSERT((AkReal32)fabs(L.X) > AKVECTORS_EPSILON);
  1312. point.X = 0.f;
  1313. point.Y = (N1.Z*D2 - N2.Z*D1) / L.X;
  1314. point.Z = (N2.Y*D1 - N1.Y*D2) / L.X;
  1315. break;
  1316. case 1:
  1317. AKASSERT((AkReal32)fabs(L.Y) > AKVECTORS_EPSILON);
  1318. point.X = (N1.Z*D2 - N2.Z*D1) / L.Y;
  1319. point.Y = 0.f;
  1320. point.Z = (N2.X*D1 - N1.X*D2) / L.Y;
  1321. break;
  1322. case 2:
  1323. AKASSERT((AkReal32)fabs(L.Z) > AKVECTORS_EPSILON);
  1324. point.X = (N1.Y*D2 - N2.Y*D1) / L.Z;
  1325. point.Y = (N2.X*D1 - N1.X*D2) / L.Z;
  1326. point.Z = 0.f;
  1327. break;
  1328. };
  1329. L.Normalize();
  1330. AkLine intrLine = AkLine(L, point);
  1331. AkLine intrLine2 = AkLine(L, point);
  1332. //in_PlaneB.GetP1()
  1333. // find min max
  1334. AkUInt32 cpt = 0;
  1335. AkUInt32 cpt2 = 0;
  1336. Ak3DVector p3 = GetP2() + (GetP4() - GetP1());
  1337. #ifdef AKPORTALS_DEBUG
  1338. char msg[256];
  1339. sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
  1340. sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
  1341. sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
  1342. 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);
  1343. 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);
  1344. 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);
  1345. 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);
  1346. 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);
  1347. sprintf(msg, "%% Plane intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
  1348. #endif
  1349. // for the four lines in rectangle
  1350. // Find where the line is crossing with plane A
  1351. if (intrLine.Intersect(GetP1(), GetP2())) cpt++;
  1352. if (intrLine.Intersect(GetP1(), GetP4())) cpt++;
  1353. if (intrLine.Intersect(GetP2(), p3)) cpt++;
  1354. if (intrLine.Intersect(p3, GetP4())) cpt++;
  1355. //AKASSERT(cpt == 2);
  1356. #ifdef AKPORTALS_DEBUG
  1357. sprintf(msg, "%% Portal intersec\n"); AKPLATFORM::OutputDebugMsg(msg);
  1358. #endif
  1359. // Find where the line is crossing with plane B
  1360. p3 = in_PlaneB.GetP2() + (in_PlaneB.GetP4() - in_PlaneB.GetP1());
  1361. if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP2())) cpt2++;
  1362. if (intrLine2.Intersect(in_PlaneB.GetP1(), in_PlaneB.GetP4())) cpt2++;
  1363. if (intrLine2.Intersect(in_PlaneB.GetP2(), p3)) cpt2++;
  1364. if (intrLine2.Intersect(p3, in_PlaneB.GetP4())) cpt2++;
  1365. // **AKASSERT(cpt2 == 2 || cpt == 2);
  1366. if (cpt < 2 || cpt2 < 2)
  1367. {
  1368. #ifdef AKPORTALS_DEBUG
  1369. sprintf(msg, "%% NON \n"); AKPLATFORM::OutputDebugMsg(msg);
  1370. sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
  1371. #endif
  1372. return false;
  1373. }
  1374. AkReal32 start = AkMax(intrLine.mint, intrLine2.mint);
  1375. AkReal32 end = AkMin(intrLine.maxt, intrLine2.maxt);
  1376. Ak3DVector minPoint = intrLine.PointAt(start);
  1377. Ak3DVector maxPoint = intrLine.PointAt(end);
  1378. #ifdef AKPORTALS_DEBUG
  1379. sprintf(msg, "P1a=[%0.2f,%0.2f,%0.2f];\n", GetP1().X, GetP1().Y, GetP1().Z); AKPLATFORM::OutputDebugMsg(msg);
  1380. sprintf(msg, "P2a=[%0.2f,%0.2f,%0.2f];\n", GetP2().X, GetP2().Y, GetP2().Z); AKPLATFORM::OutputDebugMsg(msg);
  1381. sprintf(msg, "P4a=[%0.2f,%0.2f,%0.2f];\n", GetP4().X, GetP4().Y, GetP4().Z); AKPLATFORM::OutputDebugMsg(msg);
  1382. 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);
  1383. 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);
  1384. 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);
  1385. 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);
  1386. 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);
  1387. sprintf(msg, "intr1=[%0.2f,%0.2f,%0.2f];\n", minPoint.X, minPoint.Y, minPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
  1388. sprintf(msg, "intr2=[%0.2f,%0.2f,%0.2f];\n", maxPoint.X, maxPoint.Y, maxPoint.Z); AKPLATFORM::OutputDebugMsg(msg);
  1389. sprintf(msg, "%% _______________________\n"); AKPLATFORM::OutputDebugMsg(msg);
  1390. #endif
  1391. out_Intrs.points[0] = minPoint;
  1392. out_Intrs.points[1] = maxPoint;
  1393. out_Intrs.count = 2;
  1394. return true;
  1395. }
  1396. Ak3DVector GetP1() const { return p1; }
  1397. Ak3DVector GetP2() const { return p2; }
  1398. Ak3DVector GetP4() const { return p4; }
  1399. private:
  1400. bool SetNormal()
  1401. {
  1402. //m_pNormal = (B-A) cross (C-A); normalize
  1403. Ak3DVector a = p2 - p1;
  1404. Ak3DVector b = p4 - p1;
  1405. 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);
  1406. AkReal32 len = N.Length();
  1407. AKASSERT(len > 0.f);
  1408. if (len > 0)
  1409. {
  1410. N /= len;
  1411. }
  1412. else
  1413. {
  1414. return false;
  1415. }
  1416. return true;
  1417. };
  1418. /*
  1419. p2__________p3
  1420. | . |
  1421. ^ inter v3
  1422. v1 v
  1423. | |
  1424. p1__ v2>___p4
  1425. */
  1426. Ak3DVector p1; // Bottom left
  1427. Ak3DVector p2; // Top left
  1428. Ak3DVector p4; // Tottom right
  1429. Ak3DVector N; // Normal vector
  1430. AkReal32 D; // Plane equation: Ax + By + Cz = D => N.Xx + N.Yy + N.Zz = D
  1431. };
  1432. template<typename TReal>
  1433. struct TBoundingBox
  1434. {
  1435. using TVectorType = T3DVector<TReal>;
  1436. TBoundingBox(const TVectorType& in_min, const TVectorType& in_max) :
  1437. m_Min(in_min),
  1438. m_Max(in_max)
  1439. {}
  1440. TBoundingBox() :
  1441. m_Min(TVectorType(RealPrecision<TReal>::MAX_VALUE, RealPrecision<TReal>::MAX_VALUE, RealPrecision<TReal>::MAX_VALUE)),
  1442. m_Max(TVectorType(-RealPrecision<TReal>::MAX_VALUE, -RealPrecision<TReal>::MAX_VALUE, -RealPrecision<TReal>::MAX_VALUE))
  1443. {}
  1444. void Update(const TVectorType& in_point)
  1445. {
  1446. if (m_Min.X > in_point.X)
  1447. m_Min.X = in_point.X;
  1448. if (m_Min.Y > in_point.Y)
  1449. m_Min.Y = in_point.Y;
  1450. if (m_Min.Z > in_point.Z)
  1451. m_Min.Z = in_point.Z;
  1452. if (m_Max.X < in_point.X)
  1453. m_Max.X = in_point.X;
  1454. if (m_Max.Y < in_point.Y)
  1455. m_Max.Y = in_point.Y;
  1456. if (m_Max.Z < in_point.Z)
  1457. m_Max.Z = in_point.Z;
  1458. }
  1459. AkForceInline bool IsWithin(const TVectorType& in_Point) const
  1460. {
  1461. return in_Point >= m_Min && in_Point <= m_Max;
  1462. }
  1463. AkForceInline bool IsWithin(const TBoundingBox& in_BB) const
  1464. {
  1465. return (m_Min.X <= in_BB.m_Max.X && m_Max.X >= in_BB.m_Min.X) &&
  1466. (m_Min.Y <= in_BB.m_Max.Y && m_Max.Y >= in_BB.m_Min.Y) &&
  1467. (m_Min.Z <= in_BB.m_Max.Z && m_Max.Z >= in_BB.m_Min.Z);
  1468. }
  1469. TBoundingBox Intersect(const TBoundingBox& in_BB) const
  1470. {
  1471. TBoundingBox result;
  1472. result.m_Max.X = AkMin(m_Max.X, in_BB.m_Max.X);
  1473. result.m_Max.Y = AkMin(m_Max.Y, in_BB.m_Max.Y);
  1474. result.m_Max.Z = AkMin(m_Max.Z, in_BB.m_Max.Z);
  1475. result.m_Min.X = AkMax(m_Min.X, in_BB.m_Min.X);
  1476. result.m_Min.Y = AkMax(m_Min.Y, in_BB.m_Min.Y);
  1477. result.m_Min.Z = AkMax(m_Min.Z, in_BB.m_Min.Z);
  1478. return result;
  1479. }
  1480. AkForceInline bool IsEmpty() const
  1481. {
  1482. return (m_Min.X >= m_Max.X) || (m_Min.Y >= m_Max.Y) || (m_Min.Z >= m_Max.Z);
  1483. }
  1484. AkForceInline bool IsValid() const
  1485. {
  1486. return (m_Min.X <= m_Max.X) && (m_Min.Y <= m_Max.Y) && (m_Min.Z <= m_Max.Z);
  1487. }
  1488. TVectorType m_Min;
  1489. TVectorType m_Max;
  1490. };
  1491. typedef TBoundingBox<AkReal32> AkBoundingBox;
  1492. typedef TBoundingBox<AkReal64> AkBoundingBox64;
  1493. class AkBox
  1494. {
  1495. public:
  1496. AkBox() = default;
  1497. void Init(
  1498. const Ak3DVector& in_center,
  1499. const Ak3DVector& in_extent,
  1500. const Ak3DVector& in_Front,
  1501. const Ak3DVector& in_Up)
  1502. {
  1503. AKASSERT(fabs(in_Front.Length() - 1.f) < 0.001 && fabs(in_Up.Length() - 1.f) < 0.001);//Must be unit vectors.
  1504. AKASSERT(fabs(in_Front.Dot(in_Up) - 0.f) < 0.001); //Must be orthogonal.
  1505. m_Center = in_center;
  1506. m_Extent = in_extent;
  1507. m_Z = in_Front;
  1508. m_Y = in_Up;
  1509. m_X = m_Z.Cross(m_Y);
  1510. }
  1511. bool IsPointInBox(const Ak3DVector& in_Point) const
  1512. {
  1513. Ak3DVector pt = in_Point - m_Center;
  1514. 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;
  1515. }
  1516. Ak3DVector GetSize() const { return m_Extent*2.f; }
  1517. Ak3DVector GetCenter() const { return m_Center; }
  1518. Ak3DVector GetUx() const { return m_X; }
  1519. Ak3DVector GetUy() const { return m_Y; }
  1520. Ak3DVector GetUz() const { return m_Z; }
  1521. Ak3DVector GetFront() const { return m_Z; }
  1522. Ak3DVector GetUp() const { return m_Y; }
  1523. Ak3DVector GetSide() const { return m_X; }
  1524. AkReal32 GetVolume() const
  1525. {
  1526. Ak3DVector size = GetSize();
  1527. return size.X * size.Y * size.Z;
  1528. }
  1529. bool SeparatingAxisExists(
  1530. const Ak3DVector& L,
  1531. const AkBox& B) const
  1532. {
  1533. // Separating Axis Theorem for Oriented Bounding Boxes by Johnny Huynh
  1534. const AkBox& A = *this;
  1535. Ak3DVector T = B.GetCenter() - A.GetCenter();
  1536. AkReal32 WA = A.m_Extent.X;
  1537. AkReal32 HA = A.m_Extent.Y;
  1538. AkReal32 DA = A.m_Extent.Z;
  1539. AkReal32 WB = B.m_Extent.X;
  1540. AkReal32 HB = B.m_Extent.Y;
  1541. AkReal32 DB = B.m_Extent.Z;
  1542. Ak3DVector Ax = A.GetUx();
  1543. Ak3DVector Ay = A.GetUy();
  1544. Ak3DVector Az = A.GetUz();
  1545. Ak3DVector Bx = B.GetUx();
  1546. Ak3DVector By = B.GetUy();
  1547. Ak3DVector Bz = B.GetUz();
  1548. /*
  1549. | T • L | > | (WA*Ax) • L | + | (HA*Ay) • L | + |(DA*Az) • L | +
  1550. | (WB*Bx) • L | +| (HB*By) • L | +| (DB*Bz) • L |*/
  1551. AkReal32 left = (AkReal32)fabs(T.DotProduct(L));
  1552. AkReal32 dpax = (AkReal32)fabs((Ax*WA).DotProduct(L));
  1553. AkReal32 dpay = (AkReal32)fabs((Ay*HA).DotProduct(L));
  1554. AkReal32 dpaz = (AkReal32)fabs((Az*DA).DotProduct(L));
  1555. AkReal32 dpbx = (AkReal32)fabs((Bx*WB).DotProduct(L));
  1556. AkReal32 dpby = (AkReal32)fabs((By*HB).DotProduct(L));
  1557. AkReal32 dpbz = (AkReal32)fabs((Bz*DB).DotProduct(L));
  1558. AkReal32 right = dpax + dpay + dpaz + dpbx + dpby + dpbz;
  1559. return left > right;
  1560. }
  1561. void UpdateBoundingBox(AkBoundingBox& out_aabb) const
  1562. {
  1563. Ak3DVector x = m_X * m_Extent.X;
  1564. out_aabb.Update(m_Center + x);
  1565. out_aabb.Update(m_Center - x);
  1566. Ak3DVector y = m_Y * m_Extent.Y;
  1567. out_aabb.Update(m_Center + y);
  1568. out_aabb.Update(m_Center - y);
  1569. Ak3DVector Z = m_Z * m_Extent.Z;
  1570. out_aabb.Update(m_Center + Z);
  1571. out_aabb.Update(m_Center - Z);
  1572. }
  1573. private:
  1574. Ak3DVector m_Center;
  1575. Ak3DVector m_Extent;
  1576. //Orthonormal Axes
  1577. Ak3DVector m_X;
  1578. Ak3DVector m_Y;
  1579. Ak3DVector m_Z;
  1580. };