Matrix.h 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __MATH_MATRIX_H__
  21. #define __MATH_MATRIX_H__
  22. /*
  23. ===============================================================================
  24. Matrix classes, all matrices are row-major except idMat3
  25. ===============================================================================
  26. */
  27. #define MATRIX_INVERSE_EPSILON 1e-14
  28. #define MATRIX_EPSILON 1e-6
  29. class idAngles;
  30. class idQuat;
  31. class idCQuat;
  32. class idRotation;
  33. class idMat4;
  34. //===============================================================
  35. //
  36. // idMat2 - 2x2 matrix
  37. //
  38. //===============================================================
  39. class idMat2 {
  40. public:
  41. idMat2( void );
  42. explicit idMat2( const idVec2 &x, const idVec2 &y );
  43. explicit idMat2( const float xx, const float xy, const float yx, const float yy );
  44. explicit idMat2( const float src[ 2 ][ 2 ] );
  45. const idVec2 & operator[]( int index ) const;
  46. idVec2 & operator[]( int index );
  47. idMat2 operator-() const;
  48. idMat2 operator*( const float a ) const;
  49. idVec2 operator*( const idVec2 &vec ) const;
  50. idMat2 operator*( const idMat2 &a ) const;
  51. idMat2 operator+( const idMat2 &a ) const;
  52. idMat2 operator-( const idMat2 &a ) const;
  53. idMat2 & operator*=( const float a );
  54. idMat2 & operator*=( const idMat2 &a );
  55. idMat2 & operator+=( const idMat2 &a );
  56. idMat2 & operator-=( const idMat2 &a );
  57. friend idMat2 operator*( const float a, const idMat2 &mat );
  58. friend idVec2 operator*( const idVec2 &vec, const idMat2 &mat );
  59. friend idVec2 & operator*=( idVec2 &vec, const idMat2 &mat );
  60. bool Compare( const idMat2 &a ) const; // exact compare, no epsilon
  61. bool Compare( const idMat2 &a, const float epsilon ) const; // compare with epsilon
  62. bool operator==( const idMat2 &a ) const; // exact compare, no epsilon
  63. bool operator!=( const idMat2 &a ) const; // exact compare, no epsilon
  64. void Zero( void );
  65. void Identity( void );
  66. bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
  67. bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
  68. bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  69. float Trace( void ) const;
  70. float Determinant( void ) const;
  71. idMat2 Transpose( void ) const; // returns transpose
  72. idMat2 & TransposeSelf( void );
  73. idMat2 Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  74. bool InverseSelf( void ); // returns false if determinant is zero
  75. idMat2 InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  76. bool InverseFastSelf( void ); // returns false if determinant is zero
  77. int GetDimension( void ) const;
  78. const float * ToFloatPtr( void ) const;
  79. float * ToFloatPtr( void );
  80. const char * ToString( int precision = 2 ) const;
  81. private:
  82. idVec2 mat[ 2 ];
  83. };
  84. extern idMat2 mat2_zero;
  85. extern idMat2 mat2_identity;
  86. #define mat2_default mat2_identity
  87. ID_INLINE idMat2::idMat2( void ) {
  88. }
  89. ID_INLINE idMat2::idMat2( const idVec2 &x, const idVec2 &y ) {
  90. mat[ 0 ].x = x.x; mat[ 0 ].y = x.y;
  91. mat[ 1 ].x = y.x; mat[ 1 ].y = y.y;
  92. }
  93. ID_INLINE idMat2::idMat2( const float xx, const float xy, const float yx, const float yy ) {
  94. mat[ 0 ].x = xx; mat[ 0 ].y = xy;
  95. mat[ 1 ].x = yx; mat[ 1 ].y = yy;
  96. }
  97. ID_INLINE idMat2::idMat2( const float src[ 2 ][ 2 ] ) {
  98. memcpy( mat, src, 2 * 2 * sizeof( float ) );
  99. }
  100. ID_INLINE const idVec2 &idMat2::operator[]( int index ) const {
  101. //assert( ( index >= 0 ) && ( index < 2 ) );
  102. return mat[ index ];
  103. }
  104. ID_INLINE idVec2 &idMat2::operator[]( int index ) {
  105. //assert( ( index >= 0 ) && ( index < 2 ) );
  106. return mat[ index ];
  107. }
  108. ID_INLINE idMat2 idMat2::operator-() const {
  109. return idMat2( -mat[0][0], -mat[0][1],
  110. -mat[1][0], -mat[1][1] );
  111. }
  112. ID_INLINE idVec2 idMat2::operator*( const idVec2 &vec ) const {
  113. return idVec2(
  114. mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y,
  115. mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y );
  116. }
  117. ID_INLINE idMat2 idMat2::operator*( const idMat2 &a ) const {
  118. return idMat2(
  119. mat[0].x * a[0].x + mat[0].y * a[1].x,
  120. mat[0].x * a[0].y + mat[0].y * a[1].y,
  121. mat[1].x * a[0].x + mat[1].y * a[1].x,
  122. mat[1].x * a[0].y + mat[1].y * a[1].y );
  123. }
  124. ID_INLINE idMat2 idMat2::operator*( const float a ) const {
  125. return idMat2(
  126. mat[0].x * a, mat[0].y * a,
  127. mat[1].x * a, mat[1].y * a );
  128. }
  129. ID_INLINE idMat2 idMat2::operator+( const idMat2 &a ) const {
  130. return idMat2(
  131. mat[0].x + a[0].x, mat[0].y + a[0].y,
  132. mat[1].x + a[1].x, mat[1].y + a[1].y );
  133. }
  134. ID_INLINE idMat2 idMat2::operator-( const idMat2 &a ) const {
  135. return idMat2(
  136. mat[0].x - a[0].x, mat[0].y - a[0].y,
  137. mat[1].x - a[1].x, mat[1].y - a[1].y );
  138. }
  139. ID_INLINE idMat2 &idMat2::operator*=( const float a ) {
  140. mat[0].x *= a; mat[0].y *= a;
  141. mat[1].x *= a; mat[1].y *= a;
  142. return *this;
  143. }
  144. ID_INLINE idMat2 &idMat2::operator*=( const idMat2 &a ) {
  145. float x, y;
  146. x = mat[0].x; y = mat[0].y;
  147. mat[0].x = x * a[0].x + y * a[1].x;
  148. mat[0].y = x * a[0].y + y * a[1].y;
  149. x = mat[1].x; y = mat[1].y;
  150. mat[1].x = x * a[0].x + y * a[1].x;
  151. mat[1].y = x * a[0].y + y * a[1].y;
  152. return *this;
  153. }
  154. ID_INLINE idMat2 &idMat2::operator+=( const idMat2 &a ) {
  155. mat[0].x += a[0].x; mat[0].y += a[0].y;
  156. mat[1].x += a[1].x; mat[1].y += a[1].y;
  157. return *this;
  158. }
  159. ID_INLINE idMat2 &idMat2::operator-=( const idMat2 &a ) {
  160. mat[0].x -= a[0].x; mat[0].y -= a[0].y;
  161. mat[1].x -= a[1].x; mat[1].y -= a[1].y;
  162. return *this;
  163. }
  164. ID_INLINE idVec2 operator*( const idVec2 &vec, const idMat2 &mat ) {
  165. return mat * vec;
  166. }
  167. ID_INLINE idMat2 operator*( const float a, idMat2 const &mat ) {
  168. return mat * a;
  169. }
  170. ID_INLINE idVec2 &operator*=( idVec2 &vec, const idMat2 &mat ) {
  171. vec = mat * vec;
  172. return vec;
  173. }
  174. ID_INLINE bool idMat2::Compare( const idMat2 &a ) const {
  175. if ( mat[0].Compare( a[0] ) &&
  176. mat[1].Compare( a[1] ) ) {
  177. return true;
  178. }
  179. return false;
  180. }
  181. ID_INLINE bool idMat2::Compare( const idMat2 &a, const float epsilon ) const {
  182. if ( mat[0].Compare( a[0], epsilon ) &&
  183. mat[1].Compare( a[1], epsilon ) ) {
  184. return true;
  185. }
  186. return false;
  187. }
  188. ID_INLINE bool idMat2::operator==( const idMat2 &a ) const {
  189. return Compare( a );
  190. }
  191. ID_INLINE bool idMat2::operator!=( const idMat2 &a ) const {
  192. return !Compare( a );
  193. }
  194. ID_INLINE void idMat2::Zero( void ) {
  195. mat[0].Zero();
  196. mat[1].Zero();
  197. }
  198. ID_INLINE void idMat2::Identity( void ) {
  199. *this = mat2_identity;
  200. }
  201. ID_INLINE bool idMat2::IsIdentity( const float epsilon ) const {
  202. return Compare( mat2_identity, epsilon );
  203. }
  204. ID_INLINE bool idMat2::IsSymmetric( const float epsilon ) const {
  205. return ( idMath::Fabs( mat[0][1] - mat[1][0] ) < epsilon );
  206. }
  207. ID_INLINE bool idMat2::IsDiagonal( const float epsilon ) const {
  208. if ( idMath::Fabs( mat[0][1] ) > epsilon ||
  209. idMath::Fabs( mat[1][0] ) > epsilon ) {
  210. return false;
  211. }
  212. return true;
  213. }
  214. ID_INLINE float idMat2::Trace( void ) const {
  215. return ( mat[0][0] + mat[1][1] );
  216. }
  217. ID_INLINE float idMat2::Determinant( void ) const {
  218. return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
  219. }
  220. ID_INLINE idMat2 idMat2::Transpose( void ) const {
  221. return idMat2( mat[0][0], mat[1][0],
  222. mat[0][1], mat[1][1] );
  223. }
  224. ID_INLINE idMat2 &idMat2::TransposeSelf( void ) {
  225. float tmp;
  226. tmp = mat[0][1];
  227. mat[0][1] = mat[1][0];
  228. mat[1][0] = tmp;
  229. return *this;
  230. }
  231. ID_INLINE idMat2 idMat2::Inverse( void ) const {
  232. idMat2 invMat;
  233. invMat = *this;
  234. int r = invMat.InverseSelf();
  235. assert( r );
  236. return invMat;
  237. }
  238. ID_INLINE idMat2 idMat2::InverseFast( void ) const {
  239. idMat2 invMat;
  240. invMat = *this;
  241. int r = invMat.InverseFastSelf();
  242. assert( r );
  243. return invMat;
  244. }
  245. ID_INLINE int idMat2::GetDimension( void ) const {
  246. return 4;
  247. }
  248. ID_INLINE const float *idMat2::ToFloatPtr( void ) const {
  249. return mat[0].ToFloatPtr();
  250. }
  251. ID_INLINE float *idMat2::ToFloatPtr( void ) {
  252. return mat[0].ToFloatPtr();
  253. }
  254. //===============================================================
  255. //
  256. // idMat3 - 3x3 matrix
  257. //
  258. // NOTE: matrix is column-major
  259. //
  260. //===============================================================
  261. class idMat3 {
  262. public:
  263. idMat3( void );
  264. explicit idMat3( const idVec3 &x, const idVec3 &y, const idVec3 &z );
  265. explicit idMat3( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz );
  266. explicit idMat3( const float src[ 3 ][ 3 ] );
  267. const idVec3 & operator[]( int index ) const;
  268. idVec3 & operator[]( int index );
  269. idMat3 operator-() const;
  270. idMat3 operator*( const float a ) const;
  271. idVec3 operator*( const idVec3 &vec ) const;
  272. idMat3 operator*( const idMat3 &a ) const;
  273. idMat3 operator+( const idMat3 &a ) const;
  274. idMat3 operator-( const idMat3 &a ) const;
  275. idMat3 & operator*=( const float a );
  276. idMat3 & operator*=( const idMat3 &a );
  277. idMat3 & operator+=( const idMat3 &a );
  278. idMat3 & operator-=( const idMat3 &a );
  279. friend idMat3 operator*( const float a, const idMat3 &mat );
  280. friend idVec3 operator*( const idVec3 &vec, const idMat3 &mat );
  281. friend idVec3 & operator*=( idVec3 &vec, const idMat3 &mat );
  282. bool Compare( const idMat3 &a ) const; // exact compare, no epsilon
  283. bool Compare( const idMat3 &a, const float epsilon ) const; // compare with epsilon
  284. bool operator==( const idMat3 &a ) const; // exact compare, no epsilon
  285. bool operator!=( const idMat3 &a ) const; // exact compare, no epsilon
  286. void Zero( void );
  287. void Identity( void );
  288. bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
  289. bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
  290. bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  291. bool IsRotated( void ) const;
  292. void ProjectVector( const idVec3 &src, idVec3 &dst ) const;
  293. void UnprojectVector( const idVec3 &src, idVec3 &dst ) const;
  294. bool FixDegeneracies( void ); // fix degenerate axial cases
  295. bool FixDenormals( void ); // change tiny numbers to zero
  296. float Trace( void ) const;
  297. float Determinant( void ) const;
  298. idMat3 OrthoNormalize( void ) const;
  299. idMat3 & OrthoNormalizeSelf( void );
  300. idMat3 Transpose( void ) const; // returns transpose
  301. idMat3 & TransposeSelf( void );
  302. idMat3 Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  303. bool InverseSelf( void ); // returns false if determinant is zero
  304. idMat3 InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  305. bool InverseFastSelf( void ); // returns false if determinant is zero
  306. idMat3 TransposeMultiply( const idMat3 &b ) const;
  307. idMat3 InertiaTranslate( const float mass, const idVec3 &centerOfMass, const idVec3 &translation ) const;
  308. idMat3 & InertiaTranslateSelf( const float mass, const idVec3 &centerOfMass, const idVec3 &translation );
  309. idMat3 InertiaRotate( const idMat3 &rotation ) const;
  310. idMat3 & InertiaRotateSelf( const idMat3 &rotation );
  311. int GetDimension( void ) const;
  312. idAngles ToAngles( void ) const;
  313. idQuat ToQuat( void ) const;
  314. idCQuat ToCQuat( void ) const;
  315. idRotation ToRotation( void ) const;
  316. idMat4 ToMat4( void ) const;
  317. idVec3 ToAngularVelocity( void ) const;
  318. const float * ToFloatPtr( void ) const;
  319. float * ToFloatPtr( void );
  320. const char * ToString( int precision = 2 ) const;
  321. friend void TransposeMultiply( const idMat3 &inv, const idMat3 &b, idMat3 &dst );
  322. friend idMat3 SkewSymmetric( idVec3 const &src );
  323. private:
  324. idVec3 mat[ 3 ];
  325. };
  326. extern idMat3 mat3_zero;
  327. extern idMat3 mat3_identity;
  328. #define mat3_default mat3_identity
  329. ID_INLINE idMat3::idMat3( void ) {
  330. }
  331. ID_INLINE idMat3::idMat3( const idVec3 &x, const idVec3 &y, const idVec3 &z ) {
  332. mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z;
  333. mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z;
  334. mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z;
  335. }
  336. ID_INLINE idMat3::idMat3( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) {
  337. mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz;
  338. mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz;
  339. mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz;
  340. }
  341. ID_INLINE idMat3::idMat3( const float src[ 3 ][ 3 ] ) {
  342. memcpy( mat, src, 3 * 3 * sizeof( float ) );
  343. }
  344. ID_INLINE const idVec3 &idMat3::operator[]( int index ) const {
  345. //assert( ( index >= 0 ) && ( index < 3 ) );
  346. return mat[ index ];
  347. }
  348. ID_INLINE idVec3 &idMat3::operator[]( int index ) {
  349. //assert( ( index >= 0 ) && ( index < 3 ) );
  350. return mat[ index ];
  351. }
  352. ID_INLINE idMat3 idMat3::operator-() const {
  353. return idMat3( -mat[0][0], -mat[0][1], -mat[0][2],
  354. -mat[1][0], -mat[1][1], -mat[1][2],
  355. -mat[2][0], -mat[2][1], -mat[2][2] );
  356. }
  357. ID_INLINE idVec3 idMat3::operator*( const idVec3 &vec ) const {
  358. return idVec3(
  359. mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
  360. mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
  361. mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
  362. }
  363. ID_INLINE idMat3 idMat3::operator*( const idMat3 &a ) const {
  364. int i, j;
  365. const float *m1Ptr, *m2Ptr;
  366. float *dstPtr;
  367. idMat3 dst;
  368. m1Ptr = reinterpret_cast<const float *>(this);
  369. m2Ptr = reinterpret_cast<const float *>(&a);
  370. dstPtr = reinterpret_cast<float *>(&dst);
  371. for ( i = 0; i < 3; i++ ) {
  372. for ( j = 0; j < 3; j++ ) {
  373. *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 3 + j ]
  374. + m1Ptr[1] * m2Ptr[ 1 * 3 + j ]
  375. + m1Ptr[2] * m2Ptr[ 2 * 3 + j ];
  376. dstPtr++;
  377. }
  378. m1Ptr += 3;
  379. }
  380. return dst;
  381. }
  382. ID_INLINE idMat3 idMat3::operator*( const float a ) const {
  383. return idMat3(
  384. mat[0].x * a, mat[0].y * a, mat[0].z * a,
  385. mat[1].x * a, mat[1].y * a, mat[1].z * a,
  386. mat[2].x * a, mat[2].y * a, mat[2].z * a );
  387. }
  388. ID_INLINE idMat3 idMat3::operator+( const idMat3 &a ) const {
  389. return idMat3(
  390. mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z,
  391. mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z,
  392. mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z );
  393. }
  394. ID_INLINE idMat3 idMat3::operator-( const idMat3 &a ) const {
  395. return idMat3(
  396. mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z,
  397. mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z,
  398. mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z );
  399. }
  400. ID_INLINE idMat3 &idMat3::operator*=( const float a ) {
  401. mat[0].x *= a; mat[0].y *= a; mat[0].z *= a;
  402. mat[1].x *= a; mat[1].y *= a; mat[1].z *= a;
  403. mat[2].x *= a; mat[2].y *= a; mat[2].z *= a;
  404. return *this;
  405. }
  406. ID_INLINE idMat3 &idMat3::operator*=( const idMat3 &a ) {
  407. int i, j;
  408. const float *m2Ptr;
  409. float *m1Ptr, dst[3];
  410. m1Ptr = reinterpret_cast<float *>(this);
  411. m2Ptr = reinterpret_cast<const float *>(&a);
  412. for ( i = 0; i < 3; i++ ) {
  413. for ( j = 0; j < 3; j++ ) {
  414. dst[j] = m1Ptr[0] * m2Ptr[ 0 * 3 + j ]
  415. + m1Ptr[1] * m2Ptr[ 1 * 3 + j ]
  416. + m1Ptr[2] * m2Ptr[ 2 * 3 + j ];
  417. }
  418. m1Ptr[0] = dst[0]; m1Ptr[1] = dst[1]; m1Ptr[2] = dst[2];
  419. m1Ptr += 3;
  420. }
  421. return *this;
  422. }
  423. ID_INLINE idMat3 &idMat3::operator+=( const idMat3 &a ) {
  424. mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z;
  425. mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z;
  426. mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z;
  427. return *this;
  428. }
  429. ID_INLINE idMat3 &idMat3::operator-=( const idMat3 &a ) {
  430. mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z;
  431. mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z;
  432. mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z;
  433. return *this;
  434. }
  435. ID_INLINE idVec3 operator*( const idVec3 &vec, const idMat3 &mat ) {
  436. return mat * vec;
  437. }
  438. ID_INLINE idMat3 operator*( const float a, const idMat3 &mat ) {
  439. return mat * a;
  440. }
  441. ID_INLINE idVec3 &operator*=( idVec3 &vec, const idMat3 &mat ) {
  442. float x = mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z;
  443. float y = mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z;
  444. vec.z = mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z;
  445. vec.x = x;
  446. vec.y = y;
  447. return vec;
  448. }
  449. ID_INLINE bool idMat3::Compare( const idMat3 &a ) const {
  450. if ( mat[0].Compare( a[0] ) &&
  451. mat[1].Compare( a[1] ) &&
  452. mat[2].Compare( a[2] ) ) {
  453. return true;
  454. }
  455. return false;
  456. }
  457. ID_INLINE bool idMat3::Compare( const idMat3 &a, const float epsilon ) const {
  458. if ( mat[0].Compare( a[0], epsilon ) &&
  459. mat[1].Compare( a[1], epsilon ) &&
  460. mat[2].Compare( a[2], epsilon ) ) {
  461. return true;
  462. }
  463. return false;
  464. }
  465. ID_INLINE bool idMat3::operator==( const idMat3 &a ) const {
  466. return Compare( a );
  467. }
  468. ID_INLINE bool idMat3::operator!=( const idMat3 &a ) const {
  469. return !Compare( a );
  470. }
  471. ID_INLINE void idMat3::Zero( void ) {
  472. memset( mat, 0, sizeof( idMat3 ) );
  473. }
  474. ID_INLINE void idMat3::Identity( void ) {
  475. *this = mat3_identity;
  476. }
  477. ID_INLINE bool idMat3::IsIdentity( const float epsilon ) const {
  478. return Compare( mat3_identity, epsilon );
  479. }
  480. ID_INLINE bool idMat3::IsSymmetric( const float epsilon ) const {
  481. if ( idMath::Fabs( mat[0][1] - mat[1][0] ) > epsilon ) {
  482. return false;
  483. }
  484. if ( idMath::Fabs( mat[0][2] - mat[2][0] ) > epsilon ) {
  485. return false;
  486. }
  487. if ( idMath::Fabs( mat[1][2] - mat[2][1] ) > epsilon ) {
  488. return false;
  489. }
  490. return true;
  491. }
  492. ID_INLINE bool idMat3::IsDiagonal( const float epsilon ) const {
  493. if ( idMath::Fabs( mat[0][1] ) > epsilon ||
  494. idMath::Fabs( mat[0][2] ) > epsilon ||
  495. idMath::Fabs( mat[1][0] ) > epsilon ||
  496. idMath::Fabs( mat[1][2] ) > epsilon ||
  497. idMath::Fabs( mat[2][0] ) > epsilon ||
  498. idMath::Fabs( mat[2][1] ) > epsilon ) {
  499. return false;
  500. }
  501. return true;
  502. }
  503. ID_INLINE bool idMat3::IsRotated( void ) const {
  504. return !Compare( mat3_identity );
  505. }
  506. ID_INLINE void idMat3::ProjectVector( const idVec3 &src, idVec3 &dst ) const {
  507. dst.x = src * mat[ 0 ];
  508. dst.y = src * mat[ 1 ];
  509. dst.z = src * mat[ 2 ];
  510. }
  511. ID_INLINE void idMat3::UnprojectVector( const idVec3 &src, idVec3 &dst ) const {
  512. dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z;
  513. }
  514. ID_INLINE bool idMat3::FixDegeneracies( void ) {
  515. bool r = mat[0].FixDegenerateNormal();
  516. r |= mat[1].FixDegenerateNormal();
  517. r |= mat[2].FixDegenerateNormal();
  518. return r;
  519. }
  520. ID_INLINE bool idMat3::FixDenormals( void ) {
  521. bool r = mat[0].FixDenormals();
  522. r |= mat[1].FixDenormals();
  523. r |= mat[2].FixDenormals();
  524. return r;
  525. }
  526. ID_INLINE float idMat3::Trace( void ) const {
  527. return ( mat[0][0] + mat[1][1] + mat[2][2] );
  528. }
  529. ID_INLINE idMat3 idMat3::OrthoNormalize( void ) const {
  530. idMat3 ortho;
  531. ortho = *this;
  532. ortho[ 0 ].Normalize();
  533. ortho[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
  534. ortho[ 2 ].Normalize();
  535. ortho[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
  536. ortho[ 1 ].Normalize();
  537. return ortho;
  538. }
  539. ID_INLINE idMat3 &idMat3::OrthoNormalizeSelf( void ) {
  540. mat[ 0 ].Normalize();
  541. mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
  542. mat[ 2 ].Normalize();
  543. mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
  544. mat[ 1 ].Normalize();
  545. return *this;
  546. }
  547. ID_INLINE idMat3 idMat3::Transpose( void ) const {
  548. return idMat3( mat[0][0], mat[1][0], mat[2][0],
  549. mat[0][1], mat[1][1], mat[2][1],
  550. mat[0][2], mat[1][2], mat[2][2] );
  551. }
  552. ID_INLINE idMat3 &idMat3::TransposeSelf( void ) {
  553. float tmp0, tmp1, tmp2;
  554. tmp0 = mat[0][1];
  555. mat[0][1] = mat[1][0];
  556. mat[1][0] = tmp0;
  557. tmp1 = mat[0][2];
  558. mat[0][2] = mat[2][0];
  559. mat[2][0] = tmp1;
  560. tmp2 = mat[1][2];
  561. mat[1][2] = mat[2][1];
  562. mat[2][1] = tmp2;
  563. return *this;
  564. }
  565. ID_INLINE idMat3 idMat3::Inverse( void ) const {
  566. idMat3 invMat;
  567. invMat = *this;
  568. int r = invMat.InverseSelf();
  569. assert( r );
  570. return invMat;
  571. }
  572. ID_INLINE idMat3 idMat3::InverseFast( void ) const {
  573. idMat3 invMat;
  574. invMat = *this;
  575. int r = invMat.InverseFastSelf();
  576. assert( r );
  577. return invMat;
  578. }
  579. ID_INLINE idMat3 idMat3::TransposeMultiply( const idMat3 &b ) const {
  580. return idMat3( mat[0].x * b[0].x + mat[1].x * b[1].x + mat[2].x * b[2].x,
  581. mat[0].x * b[0].y + mat[1].x * b[1].y + mat[2].x * b[2].y,
  582. mat[0].x * b[0].z + mat[1].x * b[1].z + mat[2].x * b[2].z,
  583. mat[0].y * b[0].x + mat[1].y * b[1].x + mat[2].y * b[2].x,
  584. mat[0].y * b[0].y + mat[1].y * b[1].y + mat[2].y * b[2].y,
  585. mat[0].y * b[0].z + mat[1].y * b[1].z + mat[2].y * b[2].z,
  586. mat[0].z * b[0].x + mat[1].z * b[1].x + mat[2].z * b[2].x,
  587. mat[0].z * b[0].y + mat[1].z * b[1].y + mat[2].z * b[2].y,
  588. mat[0].z * b[0].z + mat[1].z * b[1].z + mat[2].z * b[2].z );
  589. }
  590. ID_INLINE void TransposeMultiply( const idMat3 &transpose, const idMat3 &b, idMat3 &dst ) {
  591. dst[0].x = transpose[0].x * b[0].x + transpose[1].x * b[1].x + transpose[2].x * b[2].x;
  592. dst[0].y = transpose[0].x * b[0].y + transpose[1].x * b[1].y + transpose[2].x * b[2].y;
  593. dst[0].z = transpose[0].x * b[0].z + transpose[1].x * b[1].z + transpose[2].x * b[2].z;
  594. dst[1].x = transpose[0].y * b[0].x + transpose[1].y * b[1].x + transpose[2].y * b[2].x;
  595. dst[1].y = transpose[0].y * b[0].y + transpose[1].y * b[1].y + transpose[2].y * b[2].y;
  596. dst[1].z = transpose[0].y * b[0].z + transpose[1].y * b[1].z + transpose[2].y * b[2].z;
  597. dst[2].x = transpose[0].z * b[0].x + transpose[1].z * b[1].x + transpose[2].z * b[2].x;
  598. dst[2].y = transpose[0].z * b[0].y + transpose[1].z * b[1].y + transpose[2].z * b[2].y;
  599. dst[2].z = transpose[0].z * b[0].z + transpose[1].z * b[1].z + transpose[2].z * b[2].z;
  600. }
  601. ID_INLINE idMat3 SkewSymmetric( idVec3 const &src ) {
  602. return idMat3( 0.0f, -src.z, src.y, src.z, 0.0f, -src.x, -src.y, src.x, 0.0f );
  603. }
  604. ID_INLINE int idMat3::GetDimension( void ) const {
  605. return 9;
  606. }
  607. ID_INLINE const float *idMat3::ToFloatPtr( void ) const {
  608. return mat[0].ToFloatPtr();
  609. }
  610. ID_INLINE float *idMat3::ToFloatPtr( void ) {
  611. return mat[0].ToFloatPtr();
  612. }
  613. //===============================================================
  614. //
  615. // idMat4 - 4x4 matrix
  616. //
  617. //===============================================================
  618. class idMat4 {
  619. public:
  620. idMat4( void );
  621. explicit idMat4( const idVec4 &x, const idVec4 &y, const idVec4 &z, const idVec4 &w );
  622. explicit idMat4(const float xx, const float xy, const float xz, const float xw,
  623. const float yx, const float yy, const float yz, const float yw,
  624. const float zx, const float zy, const float zz, const float zw,
  625. const float wx, const float wy, const float wz, const float ww );
  626. explicit idMat4( const idMat3 &rotation, const idVec3 &translation );
  627. explicit idMat4( const float src[ 4 ][ 4 ] );
  628. const idVec4 & operator[]( int index ) const;
  629. idVec4 & operator[]( int index );
  630. idMat4 operator*( const float a ) const;
  631. idVec4 operator*( const idVec4 &vec ) const;
  632. idVec3 operator*( const idVec3 &vec ) const;
  633. idMat4 operator*( const idMat4 &a ) const;
  634. idMat4 operator+( const idMat4 &a ) const;
  635. idMat4 operator-( const idMat4 &a ) const;
  636. idMat4 & operator*=( const float a );
  637. idMat4 & operator*=( const idMat4 &a );
  638. idMat4 & operator+=( const idMat4 &a );
  639. idMat4 & operator-=( const idMat4 &a );
  640. friend idMat4 operator*( const float a, const idMat4 &mat );
  641. friend idVec4 operator*( const idVec4 &vec, const idMat4 &mat );
  642. friend idVec3 operator*( const idVec3 &vec, const idMat4 &mat );
  643. friend idVec4 & operator*=( idVec4 &vec, const idMat4 &mat );
  644. friend idVec3 & operator*=( idVec3 &vec, const idMat4 &mat );
  645. bool Compare( const idMat4 &a ) const; // exact compare, no epsilon
  646. bool Compare( const idMat4 &a, const float epsilon ) const; // compare with epsilon
  647. bool operator==( const idMat4 &a ) const; // exact compare, no epsilon
  648. bool operator!=( const idMat4 &a ) const; // exact compare, no epsilon
  649. void Zero( void );
  650. void Identity( void );
  651. bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
  652. bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
  653. bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  654. bool IsRotated( void ) const;
  655. void ProjectVector( const idVec4 &src, idVec4 &dst ) const;
  656. void UnprojectVector( const idVec4 &src, idVec4 &dst ) const;
  657. float Trace( void ) const;
  658. float Determinant( void ) const;
  659. idMat4 Transpose( void ) const; // returns transpose
  660. idMat4 & TransposeSelf( void );
  661. idMat4 Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  662. bool InverseSelf( void ); // returns false if determinant is zero
  663. idMat4 InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  664. bool InverseFastSelf( void ); // returns false if determinant is zero
  665. idMat4 TransposeMultiply( const idMat4 &b ) const;
  666. int GetDimension( void ) const;
  667. const float * ToFloatPtr( void ) const;
  668. float * ToFloatPtr( void );
  669. const char * ToString( int precision = 2 ) const;
  670. private:
  671. idVec4 mat[ 4 ];
  672. };
  673. extern idMat4 mat4_zero;
  674. extern idMat4 mat4_identity;
  675. #define mat4_default mat4_identity
  676. ID_INLINE idMat4::idMat4( void ) {
  677. }
  678. ID_INLINE idMat4::idMat4( const idVec4 &x, const idVec4 &y, const idVec4 &z, const idVec4 &w ) {
  679. mat[ 0 ] = x;
  680. mat[ 1 ] = y;
  681. mat[ 2 ] = z;
  682. mat[ 3 ] = w;
  683. }
  684. ID_INLINE idMat4::idMat4( const float xx, const float xy, const float xz, const float xw,
  685. const float yx, const float yy, const float yz, const float yw,
  686. const float zx, const float zy, const float zz, const float zw,
  687. const float wx, const float wy, const float wz, const float ww ) {
  688. mat[0][0] = xx; mat[0][1] = xy; mat[0][2] = xz; mat[0][3] = xw;
  689. mat[1][0] = yx; mat[1][1] = yy; mat[1][2] = yz; mat[1][3] = yw;
  690. mat[2][0] = zx; mat[2][1] = zy; mat[2][2] = zz; mat[2][3] = zw;
  691. mat[3][0] = wx; mat[3][1] = wy; mat[3][2] = wz; mat[3][3] = ww;
  692. }
  693. ID_INLINE idMat4::idMat4( const idMat3 &rotation, const idVec3 &translation ) {
  694. // NOTE: idMat3 is transposed because it is column-major
  695. mat[ 0 ][ 0 ] = rotation[0][0];
  696. mat[ 0 ][ 1 ] = rotation[1][0];
  697. mat[ 0 ][ 2 ] = rotation[2][0];
  698. mat[ 0 ][ 3 ] = translation[0];
  699. mat[ 1 ][ 0 ] = rotation[0][1];
  700. mat[ 1 ][ 1 ] = rotation[1][1];
  701. mat[ 1 ][ 2 ] = rotation[2][1];
  702. mat[ 1 ][ 3 ] = translation[1];
  703. mat[ 2 ][ 0 ] = rotation[0][2];
  704. mat[ 2 ][ 1 ] = rotation[1][2];
  705. mat[ 2 ][ 2 ] = rotation[2][2];
  706. mat[ 2 ][ 3 ] = translation[2];
  707. mat[ 3 ][ 0 ] = 0.0f;
  708. mat[ 3 ][ 1 ] = 0.0f;
  709. mat[ 3 ][ 2 ] = 0.0f;
  710. mat[ 3 ][ 3 ] = 1.0f;
  711. }
  712. ID_INLINE idMat4::idMat4( const float src[ 4 ][ 4 ] ) {
  713. memcpy( mat, src, 4 * 4 * sizeof( float ) );
  714. }
  715. ID_INLINE const idVec4 &idMat4::operator[]( int index ) const {
  716. //assert( ( index >= 0 ) && ( index < 4 ) );
  717. return mat[ index ];
  718. }
  719. ID_INLINE idVec4 &idMat4::operator[]( int index ) {
  720. //assert( ( index >= 0 ) && ( index < 4 ) );
  721. return mat[ index ];
  722. }
  723. ID_INLINE idMat4 idMat4::operator*( const float a ) const {
  724. return idMat4(
  725. mat[0].x * a, mat[0].y * a, mat[0].z * a, mat[0].w * a,
  726. mat[1].x * a, mat[1].y * a, mat[1].z * a, mat[1].w * a,
  727. mat[2].x * a, mat[2].y * a, mat[2].z * a, mat[2].w * a,
  728. mat[3].x * a, mat[3].y * a, mat[3].z * a, mat[3].w * a );
  729. }
  730. ID_INLINE idVec4 idMat4::operator*( const idVec4 &vec ) const {
  731. return idVec4(
  732. mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w * vec.w,
  733. mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w * vec.w,
  734. mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w * vec.w,
  735. mat[ 3 ].x * vec.x + mat[ 3 ].y * vec.y + mat[ 3 ].z * vec.z + mat[ 3 ].w * vec.w );
  736. }
  737. ID_INLINE idVec3 idMat4::operator*( const idVec3 &vec ) const {
  738. float s = mat[ 3 ].x * vec.x + mat[ 3 ].y * vec.y + mat[ 3 ].z * vec.z + mat[ 3 ].w;
  739. if ( s == 0.0f ) {
  740. return idVec3( 0.0f, 0.0f, 0.0f );
  741. }
  742. if ( s == 1.0f ) {
  743. return idVec3(
  744. mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w,
  745. mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w,
  746. mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w );
  747. }
  748. else {
  749. float invS = 1.0f / s;
  750. return idVec3(
  751. (mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w) * invS,
  752. (mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w) * invS,
  753. (mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w) * invS );
  754. }
  755. }
  756. ID_INLINE idMat4 idMat4::operator*( const idMat4 &a ) const {
  757. int i, j;
  758. const float *m1Ptr, *m2Ptr;
  759. float *dstPtr;
  760. idMat4 dst;
  761. m1Ptr = reinterpret_cast<const float *>(this);
  762. m2Ptr = reinterpret_cast<const float *>(&a);
  763. dstPtr = reinterpret_cast<float *>(&dst);
  764. for ( i = 0; i < 4; i++ ) {
  765. for ( j = 0; j < 4; j++ ) {
  766. *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 4 + j ]
  767. + m1Ptr[1] * m2Ptr[ 1 * 4 + j ]
  768. + m1Ptr[2] * m2Ptr[ 2 * 4 + j ]
  769. + m1Ptr[3] * m2Ptr[ 3 * 4 + j ];
  770. dstPtr++;
  771. }
  772. m1Ptr += 4;
  773. }
  774. return dst;
  775. }
  776. ID_INLINE idMat4 idMat4::operator+( const idMat4 &a ) const {
  777. return idMat4(
  778. mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, mat[0].w + a[0].w,
  779. mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, mat[1].w + a[1].w,
  780. mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z, mat[2].w + a[2].w,
  781. mat[3].x + a[3].x, mat[3].y + a[3].y, mat[3].z + a[3].z, mat[3].w + a[3].w );
  782. }
  783. ID_INLINE idMat4 idMat4::operator-( const idMat4 &a ) const {
  784. return idMat4(
  785. mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, mat[0].w - a[0].w,
  786. mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, mat[1].w - a[1].w,
  787. mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z, mat[2].w - a[2].w,
  788. mat[3].x - a[3].x, mat[3].y - a[3].y, mat[3].z - a[3].z, mat[3].w - a[3].w );
  789. }
  790. ID_INLINE idMat4 &idMat4::operator*=( const float a ) {
  791. mat[0].x *= a; mat[0].y *= a; mat[0].z *= a; mat[0].w *= a;
  792. mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; mat[1].w *= a;
  793. mat[2].x *= a; mat[2].y *= a; mat[2].z *= a; mat[2].w *= a;
  794. mat[3].x *= a; mat[3].y *= a; mat[3].z *= a; mat[3].w *= a;
  795. return *this;
  796. }
  797. ID_INLINE idMat4 &idMat4::operator*=( const idMat4 &a ) {
  798. *this = (*this) * a;
  799. return *this;
  800. }
  801. ID_INLINE idMat4 &idMat4::operator+=( const idMat4 &a ) {
  802. mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z; mat[0].w += a[0].w;
  803. mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z; mat[1].w += a[1].w;
  804. mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z; mat[2].w += a[2].w;
  805. mat[3].x += a[3].x; mat[3].y += a[3].y; mat[3].z += a[3].z; mat[3].w += a[3].w;
  806. return *this;
  807. }
  808. ID_INLINE idMat4 &idMat4::operator-=( const idMat4 &a ) {
  809. mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z; mat[0].w -= a[0].w;
  810. mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z; mat[1].w -= a[1].w;
  811. mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z; mat[2].w -= a[2].w;
  812. mat[3].x -= a[3].x; mat[3].y -= a[3].y; mat[3].z -= a[3].z; mat[3].w -= a[3].w;
  813. return *this;
  814. }
  815. ID_INLINE idMat4 operator*( const float a, const idMat4 &mat ) {
  816. return mat * a;
  817. }
  818. ID_INLINE idVec4 operator*( const idVec4 &vec, const idMat4 &mat ) {
  819. return mat * vec;
  820. }
  821. ID_INLINE idVec3 operator*( const idVec3 &vec, const idMat4 &mat ) {
  822. return mat * vec;
  823. }
  824. ID_INLINE idVec4 &operator*=( idVec4 &vec, const idMat4 &mat ) {
  825. vec = mat * vec;
  826. return vec;
  827. }
  828. ID_INLINE idVec3 &operator*=( idVec3 &vec, const idMat4 &mat ) {
  829. vec = mat * vec;
  830. return vec;
  831. }
  832. ID_INLINE bool idMat4::Compare( const idMat4 &a ) const {
  833. dword i;
  834. const float *ptr1, *ptr2;
  835. ptr1 = reinterpret_cast<const float *>(mat);
  836. ptr2 = reinterpret_cast<const float *>(a.mat);
  837. for ( i = 0; i < 4*4; i++ ) {
  838. if ( ptr1[i] != ptr2[i] ) {
  839. return false;
  840. }
  841. }
  842. return true;
  843. }
  844. ID_INLINE bool idMat4::Compare( const idMat4 &a, const float epsilon ) const {
  845. dword i;
  846. const float *ptr1, *ptr2;
  847. ptr1 = reinterpret_cast<const float *>(mat);
  848. ptr2 = reinterpret_cast<const float *>(a.mat);
  849. for ( i = 0; i < 4*4; i++ ) {
  850. if ( idMath::Fabs( ptr1[i] - ptr2[i] ) > epsilon ) {
  851. return false;
  852. }
  853. }
  854. return true;
  855. }
  856. ID_INLINE bool idMat4::operator==( const idMat4 &a ) const {
  857. return Compare( a );
  858. }
  859. ID_INLINE bool idMat4::operator!=( const idMat4 &a ) const {
  860. return !Compare( a );
  861. }
  862. ID_INLINE void idMat4::Zero( void ) {
  863. memset( mat, 0, sizeof( idMat4 ) );
  864. }
  865. ID_INLINE void idMat4::Identity( void ) {
  866. *this = mat4_identity;
  867. }
  868. ID_INLINE bool idMat4::IsIdentity( const float epsilon ) const {
  869. return Compare( mat4_identity, epsilon );
  870. }
  871. ID_INLINE bool idMat4::IsSymmetric( const float epsilon ) const {
  872. for ( int i = 1; i < 4; i++ ) {
  873. for ( int j = 0; j < i; j++ ) {
  874. if ( idMath::Fabs( mat[i][j] - mat[j][i] ) > epsilon ) {
  875. return false;
  876. }
  877. }
  878. }
  879. return true;
  880. }
  881. ID_INLINE bool idMat4::IsDiagonal( const float epsilon ) const {
  882. for ( int i = 0; i < 4; i++ ) {
  883. for ( int j = 0; j < 4; j++ ) {
  884. if ( i != j && idMath::Fabs( mat[i][j] ) > epsilon ) {
  885. return false;
  886. }
  887. }
  888. }
  889. return true;
  890. }
  891. ID_INLINE bool idMat4::IsRotated( void ) const {
  892. if ( !mat[ 0 ][ 1 ] && !mat[ 0 ][ 2 ] &&
  893. !mat[ 1 ][ 0 ] && !mat[ 1 ][ 2 ] &&
  894. !mat[ 2 ][ 0 ] && !mat[ 2 ][ 1 ] ) {
  895. return false;
  896. }
  897. return true;
  898. }
  899. ID_INLINE void idMat4::ProjectVector( const idVec4 &src, idVec4 &dst ) const {
  900. dst.x = src * mat[ 0 ];
  901. dst.y = src * mat[ 1 ];
  902. dst.z = src * mat[ 2 ];
  903. dst.w = src * mat[ 3 ];
  904. }
  905. ID_INLINE void idMat4::UnprojectVector( const idVec4 &src, idVec4 &dst ) const {
  906. dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z + mat[ 3 ] * src.w;
  907. }
  908. ID_INLINE float idMat4::Trace( void ) const {
  909. return ( mat[0][0] + mat[1][1] + mat[2][2] + mat[3][3] );
  910. }
  911. ID_INLINE idMat4 idMat4::Inverse( void ) const {
  912. idMat4 invMat;
  913. invMat = *this;
  914. int r = invMat.InverseSelf();
  915. assert( r );
  916. return invMat;
  917. }
  918. ID_INLINE idMat4 idMat4::InverseFast( void ) const {
  919. idMat4 invMat;
  920. invMat = *this;
  921. int r = invMat.InverseFastSelf();
  922. assert( r );
  923. return invMat;
  924. }
  925. ID_INLINE idMat4 idMat3::ToMat4( void ) const {
  926. // NOTE: idMat3 is transposed because it is column-major
  927. return idMat4( mat[0][0], mat[1][0], mat[2][0], 0.0f,
  928. mat[0][1], mat[1][1], mat[2][1], 0.0f,
  929. mat[0][2], mat[1][2], mat[2][2], 0.0f,
  930. 0.0f, 0.0f, 0.0f, 1.0f );
  931. }
  932. ID_INLINE int idMat4::GetDimension( void ) const {
  933. return 16;
  934. }
  935. ID_INLINE const float *idMat4::ToFloatPtr( void ) const {
  936. return mat[0].ToFloatPtr();
  937. }
  938. ID_INLINE float *idMat4::ToFloatPtr( void ) {
  939. return mat[0].ToFloatPtr();
  940. }
  941. //===============================================================
  942. //
  943. // idMat5 - 5x5 matrix
  944. //
  945. //===============================================================
  946. class idMat5 {
  947. public:
  948. idMat5( void );
  949. explicit idMat5( const idVec5 &v0, const idVec5 &v1, const idVec5 &v2, const idVec5 &v3, const idVec5 &v4 );
  950. explicit idMat5( const float src[ 5 ][ 5 ] );
  951. const idVec5 & operator[]( int index ) const;
  952. idVec5 & operator[]( int index );
  953. idMat5 operator*( const float a ) const;
  954. idVec5 operator*( const idVec5 &vec ) const;
  955. idMat5 operator*( const idMat5 &a ) const;
  956. idMat5 operator+( const idMat5 &a ) const;
  957. idMat5 operator-( const idMat5 &a ) const;
  958. idMat5 & operator*=( const float a );
  959. idMat5 & operator*=( const idMat5 &a );
  960. idMat5 & operator+=( const idMat5 &a );
  961. idMat5 & operator-=( const idMat5 &a );
  962. friend idMat5 operator*( const float a, const idMat5 &mat );
  963. friend idVec5 operator*( const idVec5 &vec, const idMat5 &mat );
  964. friend idVec5 & operator*=( idVec5 &vec, const idMat5 &mat );
  965. bool Compare( const idMat5 &a ) const; // exact compare, no epsilon
  966. bool Compare( const idMat5 &a, const float epsilon ) const; // compare with epsilon
  967. bool operator==( const idMat5 &a ) const; // exact compare, no epsilon
  968. bool operator!=( const idMat5 &a ) const; // exact compare, no epsilon
  969. void Zero( void );
  970. void Identity( void );
  971. bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
  972. bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
  973. bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  974. float Trace( void ) const;
  975. float Determinant( void ) const;
  976. idMat5 Transpose( void ) const; // returns transpose
  977. idMat5 & TransposeSelf( void );
  978. idMat5 Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  979. bool InverseSelf( void ); // returns false if determinant is zero
  980. idMat5 InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  981. bool InverseFastSelf( void ); // returns false if determinant is zero
  982. int GetDimension( void ) const;
  983. const float * ToFloatPtr( void ) const;
  984. float * ToFloatPtr( void );
  985. const char * ToString( int precision = 2 ) const;
  986. private:
  987. idVec5 mat[ 5 ];
  988. };
  989. extern idMat5 mat5_zero;
  990. extern idMat5 mat5_identity;
  991. #define mat5_default mat5_identity
  992. ID_INLINE idMat5::idMat5( void ) {
  993. }
  994. ID_INLINE idMat5::idMat5( const float src[ 5 ][ 5 ] ) {
  995. memcpy( mat, src, 5 * 5 * sizeof( float ) );
  996. }
  997. ID_INLINE idMat5::idMat5( const idVec5 &v0, const idVec5 &v1, const idVec5 &v2, const idVec5 &v3, const idVec5 &v4 ) {
  998. mat[0] = v0;
  999. mat[1] = v1;
  1000. mat[2] = v2;
  1001. mat[3] = v3;
  1002. mat[4] = v4;
  1003. }
  1004. ID_INLINE const idVec5 &idMat5::operator[]( int index ) const {
  1005. //assert( ( index >= 0 ) && ( index < 5 ) );
  1006. return mat[ index ];
  1007. }
  1008. ID_INLINE idVec5 &idMat5::operator[]( int index ) {
  1009. //assert( ( index >= 0 ) && ( index < 5 ) );
  1010. return mat[ index ];
  1011. }
  1012. ID_INLINE idMat5 idMat5::operator*( const idMat5 &a ) const {
  1013. int i, j;
  1014. const float *m1Ptr, *m2Ptr;
  1015. float *dstPtr;
  1016. idMat5 dst;
  1017. m1Ptr = reinterpret_cast<const float *>(this);
  1018. m2Ptr = reinterpret_cast<const float *>(&a);
  1019. dstPtr = reinterpret_cast<float *>(&dst);
  1020. for ( i = 0; i < 5; i++ ) {
  1021. for ( j = 0; j < 5; j++ ) {
  1022. *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 5 + j ]
  1023. + m1Ptr[1] * m2Ptr[ 1 * 5 + j ]
  1024. + m1Ptr[2] * m2Ptr[ 2 * 5 + j ]
  1025. + m1Ptr[3] * m2Ptr[ 3 * 5 + j ]
  1026. + m1Ptr[4] * m2Ptr[ 4 * 5 + j ];
  1027. dstPtr++;
  1028. }
  1029. m1Ptr += 5;
  1030. }
  1031. return dst;
  1032. }
  1033. ID_INLINE idMat5 idMat5::operator*( const float a ) const {
  1034. return idMat5(
  1035. idVec5( mat[0][0] * a, mat[0][1] * a, mat[0][2] * a, mat[0][3] * a, mat[0][4] * a ),
  1036. idVec5( mat[1][0] * a, mat[1][1] * a, mat[1][2] * a, mat[1][3] * a, mat[1][4] * a ),
  1037. idVec5( mat[2][0] * a, mat[2][1] * a, mat[2][2] * a, mat[2][3] * a, mat[2][4] * a ),
  1038. idVec5( mat[3][0] * a, mat[3][1] * a, mat[3][2] * a, mat[3][3] * a, mat[3][4] * a ),
  1039. idVec5( mat[4][0] * a, mat[4][1] * a, mat[4][2] * a, mat[4][3] * a, mat[4][4] * a ) );
  1040. }
  1041. ID_INLINE idVec5 idMat5::operator*( const idVec5 &vec ) const {
  1042. return idVec5(
  1043. mat[0][0] * vec[0] + mat[0][1] * vec[1] + mat[0][2] * vec[2] + mat[0][3] * vec[3] + mat[0][4] * vec[4],
  1044. mat[1][0] * vec[0] + mat[1][1] * vec[1] + mat[1][2] * vec[2] + mat[1][3] * vec[3] + mat[1][4] * vec[4],
  1045. mat[2][0] * vec[0] + mat[2][1] * vec[1] + mat[2][2] * vec[2] + mat[2][3] * vec[3] + mat[2][4] * vec[4],
  1046. mat[3][0] * vec[0] + mat[3][1] * vec[1] + mat[3][2] * vec[2] + mat[3][3] * vec[3] + mat[3][4] * vec[4],
  1047. mat[4][0] * vec[0] + mat[4][1] * vec[1] + mat[4][2] * vec[2] + mat[4][3] * vec[3] + mat[4][4] * vec[4] );
  1048. }
  1049. ID_INLINE idMat5 idMat5::operator+( const idMat5 &a ) const {
  1050. return idMat5(
  1051. idVec5( mat[0][0] + a[0][0], mat[0][1] + a[0][1], mat[0][2] + a[0][2], mat[0][3] + a[0][3], mat[0][4] + a[0][4] ),
  1052. idVec5( mat[1][0] + a[1][0], mat[1][1] + a[1][1], mat[1][2] + a[1][2], mat[1][3] + a[1][3], mat[1][4] + a[1][4] ),
  1053. idVec5( mat[2][0] + a[2][0], mat[2][1] + a[2][1], mat[2][2] + a[2][2], mat[2][3] + a[2][3], mat[2][4] + a[2][4] ),
  1054. idVec5( mat[3][0] + a[3][0], mat[3][1] + a[3][1], mat[3][2] + a[3][2], mat[3][3] + a[3][3], mat[3][4] + a[3][4] ),
  1055. idVec5( mat[4][0] + a[4][0], mat[4][1] + a[4][1], mat[4][2] + a[4][2], mat[4][3] + a[4][3], mat[4][4] + a[4][4] ) );
  1056. }
  1057. ID_INLINE idMat5 idMat5::operator-( const idMat5 &a ) const {
  1058. return idMat5(
  1059. idVec5( mat[0][0] - a[0][0], mat[0][1] - a[0][1], mat[0][2] - a[0][2], mat[0][3] - a[0][3], mat[0][4] - a[0][4] ),
  1060. idVec5( mat[1][0] - a[1][0], mat[1][1] - a[1][1], mat[1][2] - a[1][2], mat[1][3] - a[1][3], mat[1][4] - a[1][4] ),
  1061. idVec5( mat[2][0] - a[2][0], mat[2][1] - a[2][1], mat[2][2] - a[2][2], mat[2][3] - a[2][3], mat[2][4] - a[2][4] ),
  1062. idVec5( mat[3][0] - a[3][0], mat[3][1] - a[3][1], mat[3][2] - a[3][2], mat[3][3] - a[3][3], mat[3][4] - a[3][4] ),
  1063. idVec5( mat[4][0] - a[4][0], mat[4][1] - a[4][1], mat[4][2] - a[4][2], mat[4][3] - a[4][3], mat[4][4] - a[4][4] ) );
  1064. }
  1065. ID_INLINE idMat5 &idMat5::operator*=( const float a ) {
  1066. mat[0][0] *= a; mat[0][1] *= a; mat[0][2] *= a; mat[0][3] *= a; mat[0][4] *= a;
  1067. mat[1][0] *= a; mat[1][1] *= a; mat[1][2] *= a; mat[1][3] *= a; mat[1][4] *= a;
  1068. mat[2][0] *= a; mat[2][1] *= a; mat[2][2] *= a; mat[2][3] *= a; mat[2][4] *= a;
  1069. mat[3][0] *= a; mat[3][1] *= a; mat[3][2] *= a; mat[3][3] *= a; mat[3][4] *= a;
  1070. mat[4][0] *= a; mat[4][1] *= a; mat[4][2] *= a; mat[4][3] *= a; mat[4][4] *= a;
  1071. return *this;
  1072. }
  1073. ID_INLINE idMat5 &idMat5::operator*=( const idMat5 &a ) {
  1074. *this = *this * a;
  1075. return *this;
  1076. }
  1077. ID_INLINE idMat5 &idMat5::operator+=( const idMat5 &a ) {
  1078. mat[0][0] += a[0][0]; mat[0][1] += a[0][1]; mat[0][2] += a[0][2]; mat[0][3] += a[0][3]; mat[0][4] += a[0][4];
  1079. mat[1][0] += a[1][0]; mat[1][1] += a[1][1]; mat[1][2] += a[1][2]; mat[1][3] += a[1][3]; mat[1][4] += a[1][4];
  1080. mat[2][0] += a[2][0]; mat[2][1] += a[2][1]; mat[2][2] += a[2][2]; mat[2][3] += a[2][3]; mat[2][4] += a[2][4];
  1081. mat[3][0] += a[3][0]; mat[3][1] += a[3][1]; mat[3][2] += a[3][2]; mat[3][3] += a[3][3]; mat[3][4] += a[3][4];
  1082. mat[4][0] += a[4][0]; mat[4][1] += a[4][1]; mat[4][2] += a[4][2]; mat[4][3] += a[4][3]; mat[4][4] += a[4][4];
  1083. return *this;
  1084. }
  1085. ID_INLINE idMat5 &idMat5::operator-=( const idMat5 &a ) {
  1086. mat[0][0] -= a[0][0]; mat[0][1] -= a[0][1]; mat[0][2] -= a[0][2]; mat[0][3] -= a[0][3]; mat[0][4] -= a[0][4];
  1087. mat[1][0] -= a[1][0]; mat[1][1] -= a[1][1]; mat[1][2] -= a[1][2]; mat[1][3] -= a[1][3]; mat[1][4] -= a[1][4];
  1088. mat[2][0] -= a[2][0]; mat[2][1] -= a[2][1]; mat[2][2] -= a[2][2]; mat[2][3] -= a[2][3]; mat[2][4] -= a[2][4];
  1089. mat[3][0] -= a[3][0]; mat[3][1] -= a[3][1]; mat[3][2] -= a[3][2]; mat[3][3] -= a[3][3]; mat[3][4] -= a[3][4];
  1090. mat[4][0] -= a[4][0]; mat[4][1] -= a[4][1]; mat[4][2] -= a[4][2]; mat[4][3] -= a[4][3]; mat[4][4] -= a[4][4];
  1091. return *this;
  1092. }
  1093. ID_INLINE idVec5 operator*( const idVec5 &vec, const idMat5 &mat ) {
  1094. return mat * vec;
  1095. }
  1096. ID_INLINE idMat5 operator*( const float a, idMat5 const &mat ) {
  1097. return mat * a;
  1098. }
  1099. ID_INLINE idVec5 &operator*=( idVec5 &vec, const idMat5 &mat ) {
  1100. vec = mat * vec;
  1101. return vec;
  1102. }
  1103. ID_INLINE bool idMat5::Compare( const idMat5 &a ) const {
  1104. dword i;
  1105. const float *ptr1, *ptr2;
  1106. ptr1 = reinterpret_cast<const float *>(mat);
  1107. ptr2 = reinterpret_cast<const float *>(a.mat);
  1108. for ( i = 0; i < 5*5; i++ ) {
  1109. if ( ptr1[i] != ptr2[i] ) {
  1110. return false;
  1111. }
  1112. }
  1113. return true;
  1114. }
  1115. ID_INLINE bool idMat5::Compare( const idMat5 &a, const float epsilon ) const {
  1116. dword i;
  1117. const float *ptr1, *ptr2;
  1118. ptr1 = reinterpret_cast<const float *>(mat);
  1119. ptr2 = reinterpret_cast<const float *>(a.mat);
  1120. for ( i = 0; i < 5*5; i++ ) {
  1121. if ( idMath::Fabs( ptr1[i] - ptr2[i] ) > epsilon ) {
  1122. return false;
  1123. }
  1124. }
  1125. return true;
  1126. }
  1127. ID_INLINE bool idMat5::operator==( const idMat5 &a ) const {
  1128. return Compare( a );
  1129. }
  1130. ID_INLINE bool idMat5::operator!=( const idMat5 &a ) const {
  1131. return !Compare( a );
  1132. }
  1133. ID_INLINE void idMat5::Zero( void ) {
  1134. memset( mat, 0, sizeof( idMat5 ) );
  1135. }
  1136. ID_INLINE void idMat5::Identity( void ) {
  1137. *this = mat5_identity;
  1138. }
  1139. ID_INLINE bool idMat5::IsIdentity( const float epsilon ) const {
  1140. return Compare( mat5_identity, epsilon );
  1141. }
  1142. ID_INLINE bool idMat5::IsSymmetric( const float epsilon ) const {
  1143. for ( int i = 1; i < 5; i++ ) {
  1144. for ( int j = 0; j < i; j++ ) {
  1145. if ( idMath::Fabs( mat[i][j] - mat[j][i] ) > epsilon ) {
  1146. return false;
  1147. }
  1148. }
  1149. }
  1150. return true;
  1151. }
  1152. ID_INLINE bool idMat5::IsDiagonal( const float epsilon ) const {
  1153. for ( int i = 0; i < 5; i++ ) {
  1154. for ( int j = 0; j < 5; j++ ) {
  1155. if ( i != j && idMath::Fabs( mat[i][j] ) > epsilon ) {
  1156. return false;
  1157. }
  1158. }
  1159. }
  1160. return true;
  1161. }
  1162. ID_INLINE float idMat5::Trace( void ) const {
  1163. return ( mat[0][0] + mat[1][1] + mat[2][2] + mat[3][3] + mat[4][4] );
  1164. }
  1165. ID_INLINE idMat5 idMat5::Inverse( void ) const {
  1166. idMat5 invMat;
  1167. invMat = *this;
  1168. int r = invMat.InverseSelf();
  1169. assert( r );
  1170. return invMat;
  1171. }
  1172. ID_INLINE idMat5 idMat5::InverseFast( void ) const {
  1173. idMat5 invMat;
  1174. invMat = *this;
  1175. int r = invMat.InverseFastSelf();
  1176. assert( r );
  1177. return invMat;
  1178. }
  1179. ID_INLINE int idMat5::GetDimension( void ) const {
  1180. return 25;
  1181. }
  1182. ID_INLINE const float *idMat5::ToFloatPtr( void ) const {
  1183. return mat[0].ToFloatPtr();
  1184. }
  1185. ID_INLINE float *idMat5::ToFloatPtr( void ) {
  1186. return mat[0].ToFloatPtr();
  1187. }
  1188. //===============================================================
  1189. //
  1190. // idMat6 - 6x6 matrix
  1191. //
  1192. //===============================================================
  1193. class idMat6 {
  1194. public:
  1195. idMat6( void );
  1196. explicit idMat6( const idVec6 &v0, const idVec6 &v1, const idVec6 &v2, const idVec6 &v3, const idVec6 &v4, const idVec6 &v5 );
  1197. explicit idMat6( const idMat3 &m0, const idMat3 &m1, const idMat3 &m2, const idMat3 &m3 );
  1198. explicit idMat6( const float src[ 6 ][ 6 ] );
  1199. const idVec6 & operator[]( int index ) const;
  1200. idVec6 & operator[]( int index );
  1201. idMat6 operator*( const float a ) const;
  1202. idVec6 operator*( const idVec6 &vec ) const;
  1203. idMat6 operator*( const idMat6 &a ) const;
  1204. idMat6 operator+( const idMat6 &a ) const;
  1205. idMat6 operator-( const idMat6 &a ) const;
  1206. idMat6 & operator*=( const float a );
  1207. idMat6 & operator*=( const idMat6 &a );
  1208. idMat6 & operator+=( const idMat6 &a );
  1209. idMat6 & operator-=( const idMat6 &a );
  1210. friend idMat6 operator*( const float a, const idMat6 &mat );
  1211. friend idVec6 operator*( const idVec6 &vec, const idMat6 &mat );
  1212. friend idVec6 & operator*=( idVec6 &vec, const idMat6 &mat );
  1213. bool Compare( const idMat6 &a ) const; // exact compare, no epsilon
  1214. bool Compare( const idMat6 &a, const float epsilon ) const; // compare with epsilon
  1215. bool operator==( const idMat6 &a ) const; // exact compare, no epsilon
  1216. bool operator!=( const idMat6 &a ) const; // exact compare, no epsilon
  1217. void Zero( void );
  1218. void Identity( void );
  1219. bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
  1220. bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
  1221. bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  1222. idMat3 SubMat3( int n ) const;
  1223. float Trace( void ) const;
  1224. float Determinant( void ) const;
  1225. idMat6 Transpose( void ) const; // returns transpose
  1226. idMat6 & TransposeSelf( void );
  1227. idMat6 Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  1228. bool InverseSelf( void ); // returns false if determinant is zero
  1229. idMat6 InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  1230. bool InverseFastSelf( void ); // returns false if determinant is zero
  1231. int GetDimension( void ) const;
  1232. const float * ToFloatPtr( void ) const;
  1233. float * ToFloatPtr( void );
  1234. const char * ToString( int precision = 2 ) const;
  1235. private:
  1236. idVec6 mat[ 6 ];
  1237. };
  1238. extern idMat6 mat6_zero;
  1239. extern idMat6 mat6_identity;
  1240. #define mat6_default mat6_identity
  1241. ID_INLINE idMat6::idMat6( void ) {
  1242. }
  1243. ID_INLINE idMat6::idMat6( const idMat3 &m0, const idMat3 &m1, const idMat3 &m2, const idMat3 &m3 ) {
  1244. mat[0] = idVec6( m0[0][0], m0[0][1], m0[0][2], m1[0][0], m1[0][1], m1[0][2] );
  1245. mat[1] = idVec6( m0[1][0], m0[1][1], m0[1][2], m1[1][0], m1[1][1], m1[1][2] );
  1246. mat[2] = idVec6( m0[2][0], m0[2][1], m0[2][2], m1[2][0], m1[2][1], m1[2][2] );
  1247. mat[3] = idVec6( m2[0][0], m2[0][1], m2[0][2], m3[0][0], m3[0][1], m3[0][2] );
  1248. mat[4] = idVec6( m2[1][0], m2[1][1], m2[1][2], m3[1][0], m3[1][1], m3[1][2] );
  1249. mat[5] = idVec6( m2[2][0], m2[2][1], m2[2][2], m3[2][0], m3[2][1], m3[2][2] );
  1250. }
  1251. ID_INLINE idMat6::idMat6( const idVec6 &v0, const idVec6 &v1, const idVec6 &v2, const idVec6 &v3, const idVec6 &v4, const idVec6 &v5 ) {
  1252. mat[0] = v0;
  1253. mat[1] = v1;
  1254. mat[2] = v2;
  1255. mat[3] = v3;
  1256. mat[4] = v4;
  1257. mat[5] = v5;
  1258. }
  1259. ID_INLINE idMat6::idMat6( const float src[ 6 ][ 6 ] ) {
  1260. memcpy( mat, src, 6 * 6 * sizeof( float ) );
  1261. }
  1262. ID_INLINE const idVec6 &idMat6::operator[]( int index ) const {
  1263. //assert( ( index >= 0 ) && ( index < 6 ) );
  1264. return mat[ index ];
  1265. }
  1266. ID_INLINE idVec6 &idMat6::operator[]( int index ) {
  1267. //assert( ( index >= 0 ) && ( index < 6 ) );
  1268. return mat[ index ];
  1269. }
  1270. ID_INLINE idMat6 idMat6::operator*( const idMat6 &a ) const {
  1271. int i, j;
  1272. const float *m1Ptr, *m2Ptr;
  1273. float *dstPtr;
  1274. idMat6 dst;
  1275. m1Ptr = reinterpret_cast<const float *>(this);
  1276. m2Ptr = reinterpret_cast<const float *>(&a);
  1277. dstPtr = reinterpret_cast<float *>(&dst);
  1278. for ( i = 0; i < 6; i++ ) {
  1279. for ( j = 0; j < 6; j++ ) {
  1280. *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 6 + j ]
  1281. + m1Ptr[1] * m2Ptr[ 1 * 6 + j ]
  1282. + m1Ptr[2] * m2Ptr[ 2 * 6 + j ]
  1283. + m1Ptr[3] * m2Ptr[ 3 * 6 + j ]
  1284. + m1Ptr[4] * m2Ptr[ 4 * 6 + j ]
  1285. + m1Ptr[5] * m2Ptr[ 5 * 6 + j ];
  1286. dstPtr++;
  1287. }
  1288. m1Ptr += 6;
  1289. }
  1290. return dst;
  1291. }
  1292. ID_INLINE idMat6 idMat6::operator*( const float a ) const {
  1293. return idMat6(
  1294. idVec6( mat[0][0] * a, mat[0][1] * a, mat[0][2] * a, mat[0][3] * a, mat[0][4] * a, mat[0][5] * a ),
  1295. idVec6( mat[1][0] * a, mat[1][1] * a, mat[1][2] * a, mat[1][3] * a, mat[1][4] * a, mat[1][5] * a ),
  1296. idVec6( mat[2][0] * a, mat[2][1] * a, mat[2][2] * a, mat[2][3] * a, mat[2][4] * a, mat[2][5] * a ),
  1297. idVec6( mat[3][0] * a, mat[3][1] * a, mat[3][2] * a, mat[3][3] * a, mat[3][4] * a, mat[3][5] * a ),
  1298. idVec6( mat[4][0] * a, mat[4][1] * a, mat[4][2] * a, mat[4][3] * a, mat[4][4] * a, mat[4][5] * a ),
  1299. idVec6( mat[5][0] * a, mat[5][1] * a, mat[5][2] * a, mat[5][3] * a, mat[5][4] * a, mat[5][5] * a ) );
  1300. }
  1301. ID_INLINE idVec6 idMat6::operator*( const idVec6 &vec ) const {
  1302. return idVec6(
  1303. mat[0][0] * vec[0] + mat[0][1] * vec[1] + mat[0][2] * vec[2] + mat[0][3] * vec[3] + mat[0][4] * vec[4] + mat[0][5] * vec[5],
  1304. mat[1][0] * vec[0] + mat[1][1] * vec[1] + mat[1][2] * vec[2] + mat[1][3] * vec[3] + mat[1][4] * vec[4] + mat[1][5] * vec[5],
  1305. mat[2][0] * vec[0] + mat[2][1] * vec[1] + mat[2][2] * vec[2] + mat[2][3] * vec[3] + mat[2][4] * vec[4] + mat[2][5] * vec[5],
  1306. mat[3][0] * vec[0] + mat[3][1] * vec[1] + mat[3][2] * vec[2] + mat[3][3] * vec[3] + mat[3][4] * vec[4] + mat[3][5] * vec[5],
  1307. mat[4][0] * vec[0] + mat[4][1] * vec[1] + mat[4][2] * vec[2] + mat[4][3] * vec[3] + mat[4][4] * vec[4] + mat[4][5] * vec[5],
  1308. mat[5][0] * vec[0] + mat[5][1] * vec[1] + mat[5][2] * vec[2] + mat[5][3] * vec[3] + mat[5][4] * vec[4] + mat[5][5] * vec[5] );
  1309. }
  1310. ID_INLINE idMat6 idMat6::operator+( const idMat6 &a ) const {
  1311. return idMat6(
  1312. idVec6( mat[0][0] + a[0][0], mat[0][1] + a[0][1], mat[0][2] + a[0][2], mat[0][3] + a[0][3], mat[0][4] + a[0][4], mat[0][5] + a[0][5] ),
  1313. idVec6( mat[1][0] + a[1][0], mat[1][1] + a[1][1], mat[1][2] + a[1][2], mat[1][3] + a[1][3], mat[1][4] + a[1][4], mat[1][5] + a[1][5] ),
  1314. idVec6( mat[2][0] + a[2][0], mat[2][1] + a[2][1], mat[2][2] + a[2][2], mat[2][3] + a[2][3], mat[2][4] + a[2][4], mat[2][5] + a[2][5] ),
  1315. idVec6( mat[3][0] + a[3][0], mat[3][1] + a[3][1], mat[3][2] + a[3][2], mat[3][3] + a[3][3], mat[3][4] + a[3][4], mat[3][5] + a[3][5] ),
  1316. idVec6( mat[4][0] + a[4][0], mat[4][1] + a[4][1], mat[4][2] + a[4][2], mat[4][3] + a[4][3], mat[4][4] + a[4][4], mat[4][5] + a[4][5] ),
  1317. idVec6( mat[5][0] + a[5][0], mat[5][1] + a[5][1], mat[5][2] + a[5][2], mat[5][3] + a[5][3], mat[5][4] + a[5][4], mat[5][5] + a[5][5] ) );
  1318. }
  1319. ID_INLINE idMat6 idMat6::operator-( const idMat6 &a ) const {
  1320. return idMat6(
  1321. idVec6( mat[0][0] - a[0][0], mat[0][1] - a[0][1], mat[0][2] - a[0][2], mat[0][3] - a[0][3], mat[0][4] - a[0][4], mat[0][5] - a[0][5] ),
  1322. idVec6( mat[1][0] - a[1][0], mat[1][1] - a[1][1], mat[1][2] - a[1][2], mat[1][3] - a[1][3], mat[1][4] - a[1][4], mat[1][5] - a[1][5] ),
  1323. idVec6( mat[2][0] - a[2][0], mat[2][1] - a[2][1], mat[2][2] - a[2][2], mat[2][3] - a[2][3], mat[2][4] - a[2][4], mat[2][5] - a[2][5] ),
  1324. idVec6( mat[3][0] - a[3][0], mat[3][1] - a[3][1], mat[3][2] - a[3][2], mat[3][3] - a[3][3], mat[3][4] - a[3][4], mat[3][5] - a[3][5] ),
  1325. idVec6( mat[4][0] - a[4][0], mat[4][1] - a[4][1], mat[4][2] - a[4][2], mat[4][3] - a[4][3], mat[4][4] - a[4][4], mat[4][5] - a[4][5] ),
  1326. idVec6( mat[5][0] - a[5][0], mat[5][1] - a[5][1], mat[5][2] - a[5][2], mat[5][3] - a[5][3], mat[5][4] - a[5][4], mat[5][5] - a[5][5] ) );
  1327. }
  1328. ID_INLINE idMat6 &idMat6::operator*=( const float a ) {
  1329. mat[0][0] *= a; mat[0][1] *= a; mat[0][2] *= a; mat[0][3] *= a; mat[0][4] *= a; mat[0][5] *= a;
  1330. mat[1][0] *= a; mat[1][1] *= a; mat[1][2] *= a; mat[1][3] *= a; mat[1][4] *= a; mat[1][5] *= a;
  1331. mat[2][0] *= a; mat[2][1] *= a; mat[2][2] *= a; mat[2][3] *= a; mat[2][4] *= a; mat[2][5] *= a;
  1332. mat[3][0] *= a; mat[3][1] *= a; mat[3][2] *= a; mat[3][3] *= a; mat[3][4] *= a; mat[3][5] *= a;
  1333. mat[4][0] *= a; mat[4][1] *= a; mat[4][2] *= a; mat[4][3] *= a; mat[4][4] *= a; mat[4][5] *= a;
  1334. mat[5][0] *= a; mat[5][1] *= a; mat[5][2] *= a; mat[5][3] *= a; mat[5][4] *= a; mat[5][5] *= a;
  1335. return *this;
  1336. }
  1337. ID_INLINE idMat6 &idMat6::operator*=( const idMat6 &a ) {
  1338. *this = *this * a;
  1339. return *this;
  1340. }
  1341. ID_INLINE idMat6 &idMat6::operator+=( const idMat6 &a ) {
  1342. mat[0][0] += a[0][0]; mat[0][1] += a[0][1]; mat[0][2] += a[0][2]; mat[0][3] += a[0][3]; mat[0][4] += a[0][4]; mat[0][5] += a[0][5];
  1343. mat[1][0] += a[1][0]; mat[1][1] += a[1][1]; mat[1][2] += a[1][2]; mat[1][3] += a[1][3]; mat[1][4] += a[1][4]; mat[1][5] += a[1][5];
  1344. mat[2][0] += a[2][0]; mat[2][1] += a[2][1]; mat[2][2] += a[2][2]; mat[2][3] += a[2][3]; mat[2][4] += a[2][4]; mat[2][5] += a[2][5];
  1345. mat[3][0] += a[3][0]; mat[3][1] += a[3][1]; mat[3][2] += a[3][2]; mat[3][3] += a[3][3]; mat[3][4] += a[3][4]; mat[3][5] += a[3][5];
  1346. mat[4][0] += a[4][0]; mat[4][1] += a[4][1]; mat[4][2] += a[4][2]; mat[4][3] += a[4][3]; mat[4][4] += a[4][4]; mat[4][5] += a[4][5];
  1347. mat[5][0] += a[5][0]; mat[5][1] += a[5][1]; mat[5][2] += a[5][2]; mat[5][3] += a[5][3]; mat[5][4] += a[5][4]; mat[5][5] += a[5][5];
  1348. return *this;
  1349. }
  1350. ID_INLINE idMat6 &idMat6::operator-=( const idMat6 &a ) {
  1351. mat[0][0] -= a[0][0]; mat[0][1] -= a[0][1]; mat[0][2] -= a[0][2]; mat[0][3] -= a[0][3]; mat[0][4] -= a[0][4]; mat[0][5] -= a[0][5];
  1352. mat[1][0] -= a[1][0]; mat[1][1] -= a[1][1]; mat[1][2] -= a[1][2]; mat[1][3] -= a[1][3]; mat[1][4] -= a[1][4]; mat[1][5] -= a[1][5];
  1353. mat[2][0] -= a[2][0]; mat[2][1] -= a[2][1]; mat[2][2] -= a[2][2]; mat[2][3] -= a[2][3]; mat[2][4] -= a[2][4]; mat[2][5] -= a[2][5];
  1354. mat[3][0] -= a[3][0]; mat[3][1] -= a[3][1]; mat[3][2] -= a[3][2]; mat[3][3] -= a[3][3]; mat[3][4] -= a[3][4]; mat[3][5] -= a[3][5];
  1355. mat[4][0] -= a[4][0]; mat[4][1] -= a[4][1]; mat[4][2] -= a[4][2]; mat[4][3] -= a[4][3]; mat[4][4] -= a[4][4]; mat[4][5] -= a[4][5];
  1356. mat[5][0] -= a[5][0]; mat[5][1] -= a[5][1]; mat[5][2] -= a[5][2]; mat[5][3] -= a[5][3]; mat[5][4] -= a[5][4]; mat[5][5] -= a[5][5];
  1357. return *this;
  1358. }
  1359. ID_INLINE idVec6 operator*( const idVec6 &vec, const idMat6 &mat ) {
  1360. return mat * vec;
  1361. }
  1362. ID_INLINE idMat6 operator*( const float a, idMat6 const &mat ) {
  1363. return mat * a;
  1364. }
  1365. ID_INLINE idVec6 &operator*=( idVec6 &vec, const idMat6 &mat ) {
  1366. vec = mat * vec;
  1367. return vec;
  1368. }
  1369. ID_INLINE bool idMat6::Compare( const idMat6 &a ) const {
  1370. dword i;
  1371. const float *ptr1, *ptr2;
  1372. ptr1 = reinterpret_cast<const float *>(mat);
  1373. ptr2 = reinterpret_cast<const float *>(a.mat);
  1374. for ( i = 0; i < 6*6; i++ ) {
  1375. if ( ptr1[i] != ptr2[i] ) {
  1376. return false;
  1377. }
  1378. }
  1379. return true;
  1380. }
  1381. ID_INLINE bool idMat6::Compare( const idMat6 &a, const float epsilon ) const {
  1382. dword i;
  1383. const float *ptr1, *ptr2;
  1384. ptr1 = reinterpret_cast<const float *>(mat);
  1385. ptr2 = reinterpret_cast<const float *>(a.mat);
  1386. for ( i = 0; i < 6*6; i++ ) {
  1387. if ( idMath::Fabs( ptr1[i] - ptr2[i] ) > epsilon ) {
  1388. return false;
  1389. }
  1390. }
  1391. return true;
  1392. }
  1393. ID_INLINE bool idMat6::operator==( const idMat6 &a ) const {
  1394. return Compare( a );
  1395. }
  1396. ID_INLINE bool idMat6::operator!=( const idMat6 &a ) const {
  1397. return !Compare( a );
  1398. }
  1399. ID_INLINE void idMat6::Zero( void ) {
  1400. memset( mat, 0, sizeof( idMat6 ) );
  1401. }
  1402. ID_INLINE void idMat6::Identity( void ) {
  1403. *this = mat6_identity;
  1404. }
  1405. ID_INLINE bool idMat6::IsIdentity( const float epsilon ) const {
  1406. return Compare( mat6_identity, epsilon );
  1407. }
  1408. ID_INLINE bool idMat6::IsSymmetric( const float epsilon ) const {
  1409. for ( int i = 1; i < 6; i++ ) {
  1410. for ( int j = 0; j < i; j++ ) {
  1411. if ( idMath::Fabs( mat[i][j] - mat[j][i] ) > epsilon ) {
  1412. return false;
  1413. }
  1414. }
  1415. }
  1416. return true;
  1417. }
  1418. ID_INLINE bool idMat6::IsDiagonal( const float epsilon ) const {
  1419. for ( int i = 0; i < 6; i++ ) {
  1420. for ( int j = 0; j < 6; j++ ) {
  1421. if ( i != j && idMath::Fabs( mat[i][j] ) > epsilon ) {
  1422. return false;
  1423. }
  1424. }
  1425. }
  1426. return true;
  1427. }
  1428. ID_INLINE idMat3 idMat6::SubMat3( int n ) const {
  1429. assert( n >= 0 && n < 4 );
  1430. int b0 = ((n & 2) >> 1) * 3;
  1431. int b1 = (n & 1) * 3;
  1432. return idMat3(
  1433. mat[b0 + 0][b1 + 0], mat[b0 + 0][b1 + 1], mat[b0 + 0][b1 + 2],
  1434. mat[b0 + 1][b1 + 0], mat[b0 + 1][b1 + 1], mat[b0 + 1][b1 + 2],
  1435. mat[b0 + 2][b1 + 0], mat[b0 + 2][b1 + 1], mat[b0 + 2][b1 + 2] );
  1436. }
  1437. ID_INLINE float idMat6::Trace( void ) const {
  1438. return ( mat[0][0] + mat[1][1] + mat[2][2] + mat[3][3] + mat[4][4] + mat[5][5] );
  1439. }
  1440. ID_INLINE idMat6 idMat6::Inverse( void ) const {
  1441. idMat6 invMat;
  1442. invMat = *this;
  1443. int r = invMat.InverseSelf();
  1444. assert( r );
  1445. return invMat;
  1446. }
  1447. ID_INLINE idMat6 idMat6::InverseFast( void ) const {
  1448. idMat6 invMat;
  1449. invMat = *this;
  1450. int r = invMat.InverseFastSelf();
  1451. assert( r );
  1452. return invMat;
  1453. }
  1454. ID_INLINE int idMat6::GetDimension( void ) const {
  1455. return 36;
  1456. }
  1457. ID_INLINE const float *idMat6::ToFloatPtr( void ) const {
  1458. return mat[0].ToFloatPtr();
  1459. }
  1460. ID_INLINE float *idMat6::ToFloatPtr( void ) {
  1461. return mat[0].ToFloatPtr();
  1462. }
  1463. //===============================================================
  1464. //
  1465. // idMatX - arbitrary sized dense real matrix
  1466. //
  1467. // The matrix lives on 16 byte aligned and 16 byte padded memory.
  1468. //
  1469. // NOTE: due to the temporary memory pool idMatX cannot be used by multiple threads.
  1470. //
  1471. //===============================================================
  1472. #define MATX_MAX_TEMP 1024
  1473. #define MATX_QUAD( x ) ( ( ( ( x ) + 3 ) & ~3 ) * sizeof( float ) )
  1474. #define MATX_CLEAREND() int s = numRows * numColumns; while( s < ( ( s + 3 ) & ~3 ) ) { mat[s++] = 0.0f; }
  1475. #define MATX_ALLOCA( n ) ( (float *) _alloca16( MATX_QUAD( n ) ) )
  1476. #define MATX_SIMD
  1477. class idMatX {
  1478. public:
  1479. idMatX( void );
  1480. explicit idMatX( int rows, int columns );
  1481. explicit idMatX( int rows, int columns, float *src );
  1482. ~idMatX( void );
  1483. void Set( int rows, int columns, const float *src );
  1484. void Set( const idMat3 &m1, const idMat3 &m2 );
  1485. void Set( const idMat3 &m1, const idMat3 &m2, const idMat3 &m3, const idMat3 &m4 );
  1486. const float * operator[]( int index ) const;
  1487. float * operator[]( int index );
  1488. idMatX & operator=( const idMatX &a );
  1489. idMatX operator*( const float a ) const;
  1490. idVecX operator*( const idVecX &vec ) const;
  1491. idMatX operator*( const idMatX &a ) const;
  1492. idMatX operator+( const idMatX &a ) const;
  1493. idMatX operator-( const idMatX &a ) const;
  1494. idMatX & operator*=( const float a );
  1495. idMatX & operator*=( const idMatX &a );
  1496. idMatX & operator+=( const idMatX &a );
  1497. idMatX & operator-=( const idMatX &a );
  1498. friend idMatX operator*( const float a, const idMatX &m );
  1499. friend idVecX operator*( const idVecX &vec, const idMatX &m );
  1500. friend idVecX & operator*=( idVecX &vec, const idMatX &m );
  1501. bool Compare( const idMatX &a ) const; // exact compare, no epsilon
  1502. bool Compare( const idMatX &a, const float epsilon ) const; // compare with epsilon
  1503. bool operator==( const idMatX &a ) const; // exact compare, no epsilon
  1504. bool operator!=( const idMatX &a ) const; // exact compare, no epsilon
  1505. void SetSize( int rows, int columns ); // set the number of rows/columns
  1506. void ChangeSize( int rows, int columns, bool makeZero = false ); // change the size keeping data intact where possible
  1507. int GetNumRows( void ) const { return numRows; } // get the number of rows
  1508. int GetNumColumns( void ) const { return numColumns; } // get the number of columns
  1509. void SetData( int rows, int columns, float *data ); // set float array pointer
  1510. void Zero( void ); // clear matrix
  1511. void Zero( int rows, int columns ); // set size and clear matrix
  1512. void Identity( void ); // clear to identity matrix
  1513. void Identity( int rows, int columns ); // set size and clear to identity matrix
  1514. void Diag( const idVecX &v ); // create diagonal matrix from vector
  1515. void Random( int seed, float l = 0.0f, float u = 1.0f ); // fill matrix with random values
  1516. void Random( int rows, int columns, int seed, float l = 0.0f, float u = 1.0f );
  1517. void Negate( void ); // (*this) = - (*this)
  1518. void Clamp( float min, float max ); // clamp all values
  1519. idMatX & SwapRows( int r1, int r2 ); // swap rows
  1520. idMatX & SwapColumns( int r1, int r2 ); // swap columns
  1521. idMatX & SwapRowsColumns( int r1, int r2 ); // swap rows and columns
  1522. idMatX & RemoveRow( int r ); // remove a row
  1523. idMatX & RemoveColumn( int r ); // remove a column
  1524. idMatX & RemoveRowColumn( int r ); // remove a row and column
  1525. void ClearUpperTriangle( void ); // clear the upper triangle
  1526. void ClearLowerTriangle( void ); // clear the lower triangle
  1527. void SquareSubMatrix( const idMatX &m, int size ); // get square sub-matrix from 0,0 to size,size
  1528. float MaxDifference( const idMatX &m ) const; // return maximum element difference between this and m
  1529. bool IsSquare( void ) const { return ( numRows == numColumns ); }
  1530. bool IsZero( const float epsilon = MATRIX_EPSILON ) const;
  1531. bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
  1532. bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  1533. bool IsTriDiagonal( const float epsilon = MATRIX_EPSILON ) const;
  1534. bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
  1535. bool IsOrthogonal( const float epsilon = MATRIX_EPSILON ) const;
  1536. bool IsOrthonormal( const float epsilon = MATRIX_EPSILON ) const;
  1537. bool IsPMatrix( const float epsilon = MATRIX_EPSILON ) const;
  1538. bool IsZMatrix( const float epsilon = MATRIX_EPSILON ) const;
  1539. bool IsPositiveDefinite( const float epsilon = MATRIX_EPSILON ) const;
  1540. bool IsSymmetricPositiveDefinite( const float epsilon = MATRIX_EPSILON ) const;
  1541. bool IsPositiveSemiDefinite( const float epsilon = MATRIX_EPSILON ) const;
  1542. bool IsSymmetricPositiveSemiDefinite( const float epsilon = MATRIX_EPSILON ) const;
  1543. float Trace( void ) const; // returns product of diagonal elements
  1544. float Determinant( void ) const; // returns determinant of matrix
  1545. idMatX Transpose( void ) const; // returns transpose
  1546. idMatX & TransposeSelf( void ); // transposes the matrix itself
  1547. idMatX Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  1548. bool InverseSelf( void ); // returns false if determinant is zero
  1549. idMatX InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
  1550. bool InverseFastSelf( void ); // returns false if determinant is zero
  1551. bool LowerTriangularInverse( void ); // in-place inversion, returns false if determinant is zero
  1552. bool UpperTriangularInverse( void ); // in-place inversion, returns false if determinant is zero
  1553. idVecX Multiply( const idVecX &vec ) const; // (*this) * vec
  1554. idVecX TransposeMultiply( const idVecX &vec ) const; // this->Transpose() * vec
  1555. idMatX Multiply( const idMatX &a ) const; // (*this) * a
  1556. idMatX TransposeMultiply( const idMatX &a ) const; // this->Transpose() * a
  1557. void Multiply( idVecX &dst, const idVecX &vec ) const; // dst = (*this) * vec
  1558. void MultiplyAdd( idVecX &dst, const idVecX &vec ) const; // dst += (*this) * vec
  1559. void MultiplySub( idVecX &dst, const idVecX &vec ) const; // dst -= (*this) * vec
  1560. void TransposeMultiply( idVecX &dst, const idVecX &vec ) const; // dst = this->Transpose() * vec
  1561. void TransposeMultiplyAdd( idVecX &dst, const idVecX &vec ) const; // dst += this->Transpose() * vec
  1562. void TransposeMultiplySub( idVecX &dst, const idVecX &vec ) const; // dst -= this->Transpose() * vec
  1563. void Multiply( idMatX &dst, const idMatX &a ) const; // dst = (*this) * a
  1564. void TransposeMultiply( idMatX &dst, const idMatX &a ) const; // dst = this->Transpose() * a
  1565. int GetDimension( void ) const; // returns total number of values in matrix
  1566. const idVec6 & SubVec6( int row ) const; // interpret beginning of row as a const idVec6
  1567. idVec6 & SubVec6( int row ); // interpret beginning of row as an idVec6
  1568. const idVecX SubVecX( int row ) const; // interpret complete row as a const idVecX
  1569. idVecX SubVecX( int row ); // interpret complete row as an idVecX
  1570. const float * ToFloatPtr( void ) const; // pointer to const matrix float array
  1571. float * ToFloatPtr( void ); // pointer to matrix float array
  1572. const char * ToString( int precision = 2 ) const;
  1573. void Update_RankOne( const idVecX &v, const idVecX &w, float alpha );
  1574. void Update_RankOneSymmetric( const idVecX &v, float alpha );
  1575. void Update_RowColumn( const idVecX &v, const idVecX &w, int r );
  1576. void Update_RowColumnSymmetric( const idVecX &v, int r );
  1577. void Update_Increment( const idVecX &v, const idVecX &w );
  1578. void Update_IncrementSymmetric( const idVecX &v );
  1579. void Update_Decrement( int r );
  1580. bool Inverse_GaussJordan( void ); // invert in-place with Gauss-Jordan elimination
  1581. bool Inverse_UpdateRankOne( const idVecX &v, const idVecX &w, float alpha );
  1582. bool Inverse_UpdateRowColumn( const idVecX &v, const idVecX &w, int r );
  1583. bool Inverse_UpdateIncrement( const idVecX &v, const idVecX &w );
  1584. bool Inverse_UpdateDecrement( const idVecX &v, const idVecX &w, int r );
  1585. void Inverse_Solve( idVecX &x, const idVecX &b ) const;
  1586. bool LU_Factor( int *index, float *det = NULL ); // factor in-place: L * U
  1587. bool LU_UpdateRankOne( const idVecX &v, const idVecX &w, float alpha, int *index );
  1588. bool LU_UpdateRowColumn( const idVecX &v, const idVecX &w, int r, int *index );
  1589. bool LU_UpdateIncrement( const idVecX &v, const idVecX &w, int *index );
  1590. bool LU_UpdateDecrement( const idVecX &v, const idVecX &w, const idVecX &u, int r, int *index );
  1591. void LU_Solve( idVecX &x, const idVecX &b, const int *index ) const;
  1592. void LU_Inverse( idMatX &inv, const int *index ) const;
  1593. void LU_UnpackFactors( idMatX &L, idMatX &U ) const;
  1594. void LU_MultiplyFactors( idMatX &m, const int *index ) const;
  1595. bool QR_Factor( idVecX &c, idVecX &d ); // factor in-place: Q * R
  1596. bool QR_UpdateRankOne( idMatX &R, const idVecX &v, const idVecX &w, float alpha );
  1597. bool QR_UpdateRowColumn( idMatX &R, const idVecX &v, const idVecX &w, int r );
  1598. bool QR_UpdateIncrement( idMatX &R, const idVecX &v, const idVecX &w );
  1599. bool QR_UpdateDecrement( idMatX &R, const idVecX &v, const idVecX &w, int r );
  1600. void QR_Solve( idVecX &x, const idVecX &b, const idVecX &c, const idVecX &d ) const;
  1601. void QR_Solve( idVecX &x, const idVecX &b, const idMatX &R ) const;
  1602. void QR_Inverse( idMatX &inv, const idVecX &c, const idVecX &d ) const;
  1603. void QR_UnpackFactors( idMatX &Q, idMatX &R, const idVecX &c, const idVecX &d ) const;
  1604. void QR_MultiplyFactors( idMatX &m, const idVecX &c, const idVecX &d ) const;
  1605. bool SVD_Factor( idVecX &w, idMatX &V ); // factor in-place: U * Diag(w) * V.Transpose()
  1606. void SVD_Solve( idVecX &x, const idVecX &b, const idVecX &w, const idMatX &V ) const;
  1607. void SVD_Inverse( idMatX &inv, const idVecX &w, const idMatX &V ) const;
  1608. void SVD_MultiplyFactors( idMatX &m, const idVecX &w, const idMatX &V ) const;
  1609. bool Cholesky_Factor( void ); // factor in-place: L * L.Transpose()
  1610. bool Cholesky_UpdateRankOne( const idVecX &v, float alpha, int offset = 0 );
  1611. bool Cholesky_UpdateRowColumn( const idVecX &v, int r );
  1612. bool Cholesky_UpdateIncrement( const idVecX &v );
  1613. bool Cholesky_UpdateDecrement( const idVecX &v, int r );
  1614. void Cholesky_Solve( idVecX &x, const idVecX &b ) const;
  1615. void Cholesky_Inverse( idMatX &inv ) const;
  1616. void Cholesky_MultiplyFactors( idMatX &m ) const;
  1617. bool LDLT_Factor( void ); // factor in-place: L * D * L.Transpose()
  1618. bool LDLT_UpdateRankOne( const idVecX &v, float alpha, int offset = 0 );
  1619. bool LDLT_UpdateRowColumn( const idVecX &v, int r );
  1620. bool LDLT_UpdateIncrement( const idVecX &v );
  1621. bool LDLT_UpdateDecrement( const idVecX &v, int r );
  1622. void LDLT_Solve( idVecX &x, const idVecX &b ) const;
  1623. void LDLT_Inverse( idMatX &inv ) const;
  1624. void LDLT_UnpackFactors( idMatX &L, idMatX &D ) const;
  1625. void LDLT_MultiplyFactors( idMatX &m ) const;
  1626. void TriDiagonal_ClearTriangles( void );
  1627. bool TriDiagonal_Solve( idVecX &x, const idVecX &b ) const;
  1628. void TriDiagonal_Inverse( idMatX &inv ) const;
  1629. bool Eigen_SolveSymmetricTriDiagonal( idVecX &eigenValues );
  1630. bool Eigen_SolveSymmetric( idVecX &eigenValues );
  1631. bool Eigen_Solve( idVecX &realEigenValues, idVecX &imaginaryEigenValues );
  1632. void Eigen_SortIncreasing( idVecX &eigenValues );
  1633. void Eigen_SortDecreasing( idVecX &eigenValues );
  1634. static void Test( void );
  1635. private:
  1636. int numRows; // number of rows
  1637. int numColumns; // number of columns
  1638. int alloced; // floats allocated, if -1 then mat points to data set with SetData
  1639. float * mat; // memory the matrix is stored
  1640. static float temp[MATX_MAX_TEMP+4]; // used to store intermediate results
  1641. static float * tempPtr; // pointer to 16 byte aligned temporary memory
  1642. static int tempIndex; // index into memory pool, wraps around
  1643. private:
  1644. void SetTempSize( int rows, int columns );
  1645. float DeterminantGeneric( void ) const;
  1646. bool InverseSelfGeneric( void );
  1647. void QR_Rotate( idMatX &R, int i, float a, float b );
  1648. float Pythag( float a, float b ) const;
  1649. void SVD_BiDiag( idVecX &w, idVecX &rv1, float &anorm );
  1650. void SVD_InitialWV( idVecX &w, idMatX &V, idVecX &rv1 );
  1651. void HouseholderReduction( idVecX &diag, idVecX &subd );
  1652. bool QL( idVecX &diag, idVecX &subd );
  1653. void HessenbergReduction( idMatX &H );
  1654. void ComplexDivision( float xr, float xi, float yr, float yi, float &cdivr, float &cdivi );
  1655. bool HessenbergToRealSchur( idMatX &H, idVecX &realEigenValues, idVecX &imaginaryEigenValues );
  1656. };
  1657. ID_INLINE idMatX::idMatX( void ) {
  1658. numRows = numColumns = alloced = 0;
  1659. mat = NULL;
  1660. }
  1661. ID_INLINE idMatX::~idMatX( void ) {
  1662. // if not temp memory
  1663. if ( mat != NULL && ( mat < idMatX::tempPtr || mat > idMatX::tempPtr + MATX_MAX_TEMP ) && alloced != -1 ) {
  1664. Mem_Free16( mat );
  1665. }
  1666. }
  1667. ID_INLINE idMatX::idMatX( int rows, int columns ) {
  1668. numRows = numColumns = alloced = 0;
  1669. mat = NULL;
  1670. SetSize( rows, columns );
  1671. }
  1672. ID_INLINE idMatX::idMatX( int rows, int columns, float *src ) {
  1673. numRows = numColumns = alloced = 0;
  1674. mat = NULL;
  1675. SetData( rows, columns, src );
  1676. }
  1677. ID_INLINE void idMatX::Set( int rows, int columns, const float *src ) {
  1678. SetSize( rows, columns );
  1679. memcpy( this->mat, src, rows * columns * sizeof( float ) );
  1680. }
  1681. ID_INLINE void idMatX::Set( const idMat3 &m1, const idMat3 &m2 ) {
  1682. int i, j;
  1683. SetSize( 3, 6 );
  1684. for ( i = 0; i < 3; i++ ) {
  1685. for ( j = 0; j < 3; j++ ) {
  1686. mat[(i+0) * numColumns + (j+0)] = m1[i][j];
  1687. mat[(i+0) * numColumns + (j+3)] = m2[i][j];
  1688. }
  1689. }
  1690. }
  1691. ID_INLINE void idMatX::Set( const idMat3 &m1, const idMat3 &m2, const idMat3 &m3, const idMat3 &m4 ) {
  1692. int i, j;
  1693. SetSize( 6, 6 );
  1694. for ( i = 0; i < 3; i++ ) {
  1695. for ( j = 0; j < 3; j++ ) {
  1696. mat[(i+0) * numColumns + (j+0)] = m1[i][j];
  1697. mat[(i+0) * numColumns + (j+3)] = m2[i][j];
  1698. mat[(i+3) * numColumns + (j+0)] = m3[i][j];
  1699. mat[(i+3) * numColumns + (j+3)] = m4[i][j];
  1700. }
  1701. }
  1702. }
  1703. ID_INLINE const float *idMatX::operator[]( int index ) const {
  1704. assert( ( index >= 0 ) && ( index < numRows ) );
  1705. return mat + index * numColumns;
  1706. }
  1707. ID_INLINE float *idMatX::operator[]( int index ) {
  1708. assert( ( index >= 0 ) && ( index < numRows ) );
  1709. return mat + index * numColumns;
  1710. }
  1711. ID_INLINE idMatX &idMatX::operator=( const idMatX &a ) {
  1712. SetSize( a.numRows, a.numColumns );
  1713. #ifdef MATX_SIMD
  1714. SIMDProcessor->Copy16( mat, a.mat, a.numRows * a.numColumns );
  1715. #else
  1716. memcpy( mat, a.mat, a.numRows * a.numColumns * sizeof( float ) );
  1717. #endif
  1718. idMatX::tempIndex = 0;
  1719. return *this;
  1720. }
  1721. ID_INLINE idMatX idMatX::operator*( const float a ) const {
  1722. idMatX m;
  1723. m.SetTempSize( numRows, numColumns );
  1724. #ifdef MATX_SIMD
  1725. SIMDProcessor->Mul16( m.mat, mat, a, numRows * numColumns );
  1726. #else
  1727. int i, s;
  1728. s = numRows * numColumns;
  1729. for ( i = 0; i < s; i++ ) {
  1730. m.mat[i] = mat[i] * a;
  1731. }
  1732. #endif
  1733. return m;
  1734. }
  1735. ID_INLINE idVecX idMatX::operator*( const idVecX &vec ) const {
  1736. idVecX dst;
  1737. assert( numColumns == vec.GetSize() );
  1738. dst.SetTempSize( numRows );
  1739. #ifdef MATX_SIMD
  1740. SIMDProcessor->MatX_MultiplyVecX( dst, *this, vec );
  1741. #else
  1742. Multiply( dst, vec );
  1743. #endif
  1744. return dst;
  1745. }
  1746. ID_INLINE idMatX idMatX::operator*( const idMatX &a ) const {
  1747. idMatX dst;
  1748. assert( numColumns == a.numRows );
  1749. dst.SetTempSize( numRows, a.numColumns );
  1750. #ifdef MATX_SIMD
  1751. SIMDProcessor->MatX_MultiplyMatX( dst, *this, a );
  1752. #else
  1753. Multiply( dst, a );
  1754. #endif
  1755. return dst;
  1756. }
  1757. ID_INLINE idMatX idMatX::operator+( const idMatX &a ) const {
  1758. idMatX m;
  1759. assert( numRows == a.numRows && numColumns == a.numColumns );
  1760. m.SetTempSize( numRows, numColumns );
  1761. #ifdef MATX_SIMD
  1762. SIMDProcessor->Add16( m.mat, mat, a.mat, numRows * numColumns );
  1763. #else
  1764. int i, s;
  1765. s = numRows * numColumns;
  1766. for ( i = 0; i < s; i++ ) {
  1767. m.mat[i] = mat[i] + a.mat[i];
  1768. }
  1769. #endif
  1770. return m;
  1771. }
  1772. ID_INLINE idMatX idMatX::operator-( const idMatX &a ) const {
  1773. idMatX m;
  1774. assert( numRows == a.numRows && numColumns == a.numColumns );
  1775. m.SetTempSize( numRows, numColumns );
  1776. #ifdef MATX_SIMD
  1777. SIMDProcessor->Sub16( m.mat, mat, a.mat, numRows * numColumns );
  1778. #else
  1779. int i, s;
  1780. s = numRows * numColumns;
  1781. for ( i = 0; i < s; i++ ) {
  1782. m.mat[i] = mat[i] - a.mat[i];
  1783. }
  1784. #endif
  1785. return m;
  1786. }
  1787. ID_INLINE idMatX &idMatX::operator*=( const float a ) {
  1788. #ifdef MATX_SIMD
  1789. SIMDProcessor->MulAssign16( mat, a, numRows * numColumns );
  1790. #else
  1791. int i, s;
  1792. s = numRows * numColumns;
  1793. for ( i = 0; i < s; i++ ) {
  1794. mat[i] *= a;
  1795. }
  1796. #endif
  1797. idMatX::tempIndex = 0;
  1798. return *this;
  1799. }
  1800. ID_INLINE idMatX &idMatX::operator*=( const idMatX &a ) {
  1801. *this = *this * a;
  1802. idMatX::tempIndex = 0;
  1803. return *this;
  1804. }
  1805. ID_INLINE idMatX &idMatX::operator+=( const idMatX &a ) {
  1806. assert( numRows == a.numRows && numColumns == a.numColumns );
  1807. #ifdef MATX_SIMD
  1808. SIMDProcessor->AddAssign16( mat, a.mat, numRows * numColumns );
  1809. #else
  1810. int i, s;
  1811. s = numRows * numColumns;
  1812. for ( i = 0; i < s; i++ ) {
  1813. mat[i] += a.mat[i];
  1814. }
  1815. #endif
  1816. idMatX::tempIndex = 0;
  1817. return *this;
  1818. }
  1819. ID_INLINE idMatX &idMatX::operator-=( const idMatX &a ) {
  1820. assert( numRows == a.numRows && numColumns == a.numColumns );
  1821. #ifdef MATX_SIMD
  1822. SIMDProcessor->SubAssign16( mat, a.mat, numRows * numColumns );
  1823. #else
  1824. int i, s;
  1825. s = numRows * numColumns;
  1826. for ( i = 0; i < s; i++ ) {
  1827. mat[i] -= a.mat[i];
  1828. }
  1829. #endif
  1830. idMatX::tempIndex = 0;
  1831. return *this;
  1832. }
  1833. ID_INLINE idMatX operator*( const float a, idMatX const &m ) {
  1834. return m * a;
  1835. }
  1836. ID_INLINE idVecX operator*( const idVecX &vec, const idMatX &m ) {
  1837. return m * vec;
  1838. }
  1839. ID_INLINE idVecX &operator*=( idVecX &vec, const idMatX &m ) {
  1840. vec = m * vec;
  1841. return vec;
  1842. }
  1843. ID_INLINE bool idMatX::Compare( const idMatX &a ) const {
  1844. int i, s;
  1845. assert( numRows == a.numRows && numColumns == a.numColumns );
  1846. s = numRows * numColumns;
  1847. for ( i = 0; i < s; i++ ) {
  1848. if ( mat[i] != a.mat[i] ) {
  1849. return false;
  1850. }
  1851. }
  1852. return true;
  1853. }
  1854. ID_INLINE bool idMatX::Compare( const idMatX &a, const float epsilon ) const {
  1855. int i, s;
  1856. assert( numRows == a.numRows && numColumns == a.numColumns );
  1857. s = numRows * numColumns;
  1858. for ( i = 0; i < s; i++ ) {
  1859. if ( idMath::Fabs( mat[i] - a.mat[i] ) > epsilon ) {
  1860. return false;
  1861. }
  1862. }
  1863. return true;
  1864. }
  1865. ID_INLINE bool idMatX::operator==( const idMatX &a ) const {
  1866. return Compare( a );
  1867. }
  1868. ID_INLINE bool idMatX::operator!=( const idMatX &a ) const {
  1869. return !Compare( a );
  1870. }
  1871. ID_INLINE void idMatX::SetSize( int rows, int columns ) {
  1872. assert( mat < idMatX::tempPtr || mat > idMatX::tempPtr + MATX_MAX_TEMP );
  1873. int alloc = ( rows * columns + 3 ) & ~3;
  1874. if ( alloc > alloced && alloced != -1 ) {
  1875. if ( mat != NULL ) {
  1876. Mem_Free16( mat );
  1877. }
  1878. mat = (float *) Mem_Alloc16( alloc * sizeof( float ) );
  1879. alloced = alloc;
  1880. }
  1881. numRows = rows;
  1882. numColumns = columns;
  1883. MATX_CLEAREND();
  1884. }
  1885. ID_INLINE void idMatX::SetTempSize( int rows, int columns ) {
  1886. int newSize;
  1887. newSize = ( rows * columns + 3 ) & ~3;
  1888. assert( newSize < MATX_MAX_TEMP );
  1889. if ( idMatX::tempIndex + newSize > MATX_MAX_TEMP ) {
  1890. idMatX::tempIndex = 0;
  1891. }
  1892. mat = idMatX::tempPtr + idMatX::tempIndex;
  1893. idMatX::tempIndex += newSize;
  1894. alloced = newSize;
  1895. numRows = rows;
  1896. numColumns = columns;
  1897. MATX_CLEAREND();
  1898. }
  1899. ID_INLINE void idMatX::SetData( int rows, int columns, float *data ) {
  1900. assert( mat < idMatX::tempPtr || mat > idMatX::tempPtr + MATX_MAX_TEMP );
  1901. if ( mat != NULL && alloced != -1 ) {
  1902. Mem_Free16( mat );
  1903. }
  1904. assert( ( ( (int) data ) & 15 ) == 0 ); // data must be 16 byte aligned
  1905. mat = data;
  1906. alloced = -1;
  1907. numRows = rows;
  1908. numColumns = columns;
  1909. MATX_CLEAREND();
  1910. }
  1911. ID_INLINE void idMatX::Zero( void ) {
  1912. #ifdef MATX_SIMD
  1913. SIMDProcessor->Zero16( mat, numRows * numColumns );
  1914. #else
  1915. memset( mat, 0, numRows * numColumns * sizeof( float ) );
  1916. #endif
  1917. }
  1918. ID_INLINE void idMatX::Zero( int rows, int columns ) {
  1919. SetSize( rows, columns );
  1920. #ifdef MATX_SIMD
  1921. SIMDProcessor->Zero16( mat, numRows * numColumns );
  1922. #else
  1923. memset( mat, 0, rows * columns * sizeof( float ) );
  1924. #endif
  1925. }
  1926. ID_INLINE void idMatX::Identity( void ) {
  1927. assert( numRows == numColumns );
  1928. #ifdef MATX_SIMD
  1929. SIMDProcessor->Zero16( mat, numRows * numColumns );
  1930. #else
  1931. memset( mat, 0, numRows * numColumns * sizeof( float ) );
  1932. #endif
  1933. for ( int i = 0; i < numRows; i++ ) {
  1934. mat[i * numColumns + i] = 1.0f;
  1935. }
  1936. }
  1937. ID_INLINE void idMatX::Identity( int rows, int columns ) {
  1938. assert( rows == columns );
  1939. SetSize( rows, columns );
  1940. idMatX::Identity();
  1941. }
  1942. ID_INLINE void idMatX::Diag( const idVecX &v ) {
  1943. Zero( v.GetSize(), v.GetSize() );
  1944. for ( int i = 0; i < v.GetSize(); i++ ) {
  1945. mat[i * numColumns + i] = v[i];
  1946. }
  1947. }
  1948. ID_INLINE void idMatX::Random( int seed, float l, float u ) {
  1949. int i, s;
  1950. float c;
  1951. idRandom rnd(seed);
  1952. c = u - l;
  1953. s = numRows * numColumns;
  1954. for ( i = 0; i < s; i++ ) {
  1955. mat[i] = l + rnd.RandomFloat() * c;
  1956. }
  1957. }
  1958. ID_INLINE void idMatX::Random( int rows, int columns, int seed, float l, float u ) {
  1959. int i, s;
  1960. float c;
  1961. idRandom rnd(seed);
  1962. SetSize( rows, columns );
  1963. c = u - l;
  1964. s = numRows * numColumns;
  1965. for ( i = 0; i < s; i++ ) {
  1966. mat[i] = l + rnd.RandomFloat() * c;
  1967. }
  1968. }
  1969. ID_INLINE void idMatX::Negate( void ) {
  1970. #ifdef MATX_SIMD
  1971. SIMDProcessor->Negate16( mat, numRows * numColumns );
  1972. #else
  1973. int i, s;
  1974. s = numRows * numColumns;
  1975. for ( i = 0; i < s; i++ ) {
  1976. mat[i] = -mat[i];
  1977. }
  1978. #endif
  1979. }
  1980. ID_INLINE void idMatX::Clamp( float min, float max ) {
  1981. int i, s;
  1982. s = numRows * numColumns;
  1983. for ( i = 0; i < s; i++ ) {
  1984. if ( mat[i] < min ) {
  1985. mat[i] = min;
  1986. } else if ( mat[i] > max ) {
  1987. mat[i] = max;
  1988. }
  1989. }
  1990. }
  1991. ID_INLINE idMatX &idMatX::SwapRows( int r1, int r2 ) {
  1992. float *ptr;
  1993. ptr = (float *) _alloca16( numColumns * sizeof( float ) );
  1994. memcpy( ptr, mat + r1 * numColumns, numColumns * sizeof( float ) );
  1995. memcpy( mat + r1 * numColumns, mat + r2 * numColumns, numColumns * sizeof( float ) );
  1996. memcpy( mat + r2 * numColumns, ptr, numColumns * sizeof( float ) );
  1997. return *this;
  1998. }
  1999. ID_INLINE idMatX &idMatX::SwapColumns( int r1, int r2 ) {
  2000. int i;
  2001. float tmp, *ptr;
  2002. for ( i = 0; i < numRows; i++ ) {
  2003. ptr = mat + i * numColumns;
  2004. tmp = ptr[r1];
  2005. ptr[r1] = ptr[r2];
  2006. ptr[r2] = tmp;
  2007. }
  2008. return *this;
  2009. }
  2010. ID_INLINE idMatX &idMatX::SwapRowsColumns( int r1, int r2 ) {
  2011. SwapRows( r1, r2 );
  2012. SwapColumns( r1, r2 );
  2013. return *this;
  2014. }
  2015. ID_INLINE void idMatX::ClearUpperTriangle( void ) {
  2016. assert( numRows == numColumns );
  2017. for ( int i = numRows-2; i >= 0; i-- ) {
  2018. memset( mat + i * numColumns + i + 1, 0, (numColumns - 1 - i) * sizeof(float) );
  2019. }
  2020. }
  2021. ID_INLINE void idMatX::ClearLowerTriangle( void ) {
  2022. assert( numRows == numColumns );
  2023. for ( int i = 1; i < numRows; i++ ) {
  2024. memset( mat + i * numColumns, 0, i * sizeof(float) );
  2025. }
  2026. }
  2027. ID_INLINE void idMatX::SquareSubMatrix( const idMatX &m, int size ) {
  2028. int i;
  2029. assert( size <= m.numRows && size <= m.numColumns );
  2030. SetSize( size, size );
  2031. for ( i = 0; i < size; i++ ) {
  2032. memcpy( mat + i * numColumns, m.mat + i * m.numColumns, size * sizeof( float ) );
  2033. }
  2034. }
  2035. ID_INLINE float idMatX::MaxDifference( const idMatX &m ) const {
  2036. int i, j;
  2037. float diff, maxDiff;
  2038. assert( numRows == m.numRows && numColumns == m.numColumns );
  2039. maxDiff = -1.0f;
  2040. for ( i = 0; i < numRows; i++ ) {
  2041. for ( j = 0; j < numColumns; j++ ) {
  2042. diff = idMath::Fabs( mat[ i * numColumns + j ] - m[i][j] );
  2043. if ( maxDiff < 0.0f || diff > maxDiff ) {
  2044. maxDiff = diff;
  2045. }
  2046. }
  2047. }
  2048. return maxDiff;
  2049. }
  2050. ID_INLINE bool idMatX::IsZero( const float epsilon ) const {
  2051. // returns true if (*this) == Zero
  2052. for ( int i = 0; i < numRows; i++ ) {
  2053. for ( int j = 0; j < numColumns; j++ ) {
  2054. if ( idMath::Fabs( mat[i * numColumns + j] ) > epsilon ) {
  2055. return false;
  2056. }
  2057. }
  2058. }
  2059. return true;
  2060. }
  2061. ID_INLINE bool idMatX::IsIdentity( const float epsilon ) const {
  2062. // returns true if (*this) == Identity
  2063. assert( numRows == numColumns );
  2064. for ( int i = 0; i < numRows; i++ ) {
  2065. for ( int j = 0; j < numColumns; j++ ) {
  2066. if ( idMath::Fabs( mat[i * numColumns + j] - (float)( i == j ) ) > epsilon ) {
  2067. return false;
  2068. }
  2069. }
  2070. }
  2071. return true;
  2072. }
  2073. ID_INLINE bool idMatX::IsDiagonal( const float epsilon ) const {
  2074. // returns true if all elements are zero except for the elements on the diagonal
  2075. assert( numRows == numColumns );
  2076. for ( int i = 0; i < numRows; i++ ) {
  2077. for ( int j = 0; j < numColumns; j++ ) {
  2078. if ( i != j && idMath::Fabs( mat[i * numColumns + j] ) > epsilon ) {
  2079. return false;
  2080. }
  2081. }
  2082. }
  2083. return true;
  2084. }
  2085. ID_INLINE bool idMatX::IsTriDiagonal( const float epsilon ) const {
  2086. // returns true if all elements are zero except for the elements on the diagonal plus or minus one column
  2087. if ( numRows != numColumns ) {
  2088. return false;
  2089. }
  2090. for ( int i = 0; i < numRows-2; i++ ) {
  2091. for ( int j = i+2; j < numColumns; j++ ) {
  2092. if ( idMath::Fabs( (*this)[i][j] ) > epsilon ) {
  2093. return false;
  2094. }
  2095. if ( idMath::Fabs( (*this)[j][i] ) > epsilon ) {
  2096. return false;
  2097. }
  2098. }
  2099. }
  2100. return true;
  2101. }
  2102. ID_INLINE bool idMatX::IsSymmetric( const float epsilon ) const {
  2103. // (*this)[i][j] == (*this)[j][i]
  2104. if ( numRows != numColumns ) {
  2105. return false;
  2106. }
  2107. for ( int i = 0; i < numRows; i++ ) {
  2108. for ( int j = 0; j < numColumns; j++ ) {
  2109. if ( idMath::Fabs( mat[ i * numColumns + j ] - mat[ j * numColumns + i ] ) > epsilon ) {
  2110. return false;
  2111. }
  2112. }
  2113. }
  2114. return true;
  2115. }
  2116. ID_INLINE float idMatX::Trace( void ) const {
  2117. float trace = 0.0f;
  2118. assert( numRows == numColumns );
  2119. // sum of elements on the diagonal
  2120. for ( int i = 0; i < numRows; i++ ) {
  2121. trace += mat[i * numRows + i];
  2122. }
  2123. return trace;
  2124. }
  2125. ID_INLINE float idMatX::Determinant( void ) const {
  2126. assert( numRows == numColumns );
  2127. switch( numRows ) {
  2128. case 1:
  2129. return mat[0];
  2130. case 2:
  2131. return reinterpret_cast<const idMat2 *>(mat)->Determinant();
  2132. case 3:
  2133. return reinterpret_cast<const idMat3 *>(mat)->Determinant();
  2134. case 4:
  2135. return reinterpret_cast<const idMat4 *>(mat)->Determinant();
  2136. case 5:
  2137. return reinterpret_cast<const idMat5 *>(mat)->Determinant();
  2138. case 6:
  2139. return reinterpret_cast<const idMat6 *>(mat)->Determinant();
  2140. default:
  2141. return DeterminantGeneric();
  2142. }
  2143. return 0.0f;
  2144. }
  2145. ID_INLINE idMatX idMatX::Transpose( void ) const {
  2146. idMatX transpose;
  2147. int i, j;
  2148. transpose.SetTempSize( numColumns, numRows );
  2149. for ( i = 0; i < numRows; i++ ) {
  2150. for ( j = 0; j < numColumns; j++ ) {
  2151. transpose.mat[j * transpose.numColumns + i] = mat[i * numColumns + j];
  2152. }
  2153. }
  2154. return transpose;
  2155. }
  2156. ID_INLINE idMatX &idMatX::TransposeSelf( void ) {
  2157. *this = Transpose();
  2158. return *this;
  2159. }
  2160. ID_INLINE idMatX idMatX::Inverse( void ) const {
  2161. idMatX invMat;
  2162. invMat.SetTempSize( numRows, numColumns );
  2163. memcpy( invMat.mat, mat, numRows * numColumns * sizeof( float ) );
  2164. int r = invMat.InverseSelf();
  2165. assert( r );
  2166. return invMat;
  2167. }
  2168. ID_INLINE bool idMatX::InverseSelf( void ) {
  2169. assert( numRows == numColumns );
  2170. switch( numRows ) {
  2171. case 1:
  2172. if ( idMath::Fabs( mat[0] ) < MATRIX_INVERSE_EPSILON ) {
  2173. return false;
  2174. }
  2175. mat[0] = 1.0f / mat[0];
  2176. return true;
  2177. case 2:
  2178. return reinterpret_cast<idMat2 *>(mat)->InverseSelf();
  2179. case 3:
  2180. return reinterpret_cast<idMat3 *>(mat)->InverseSelf();
  2181. case 4:
  2182. return reinterpret_cast<idMat4 *>(mat)->InverseSelf();
  2183. case 5:
  2184. return reinterpret_cast<idMat5 *>(mat)->InverseSelf();
  2185. case 6:
  2186. return reinterpret_cast<idMat6 *>(mat)->InverseSelf();
  2187. default:
  2188. return InverseSelfGeneric();
  2189. }
  2190. }
  2191. ID_INLINE idMatX idMatX::InverseFast( void ) const {
  2192. idMatX invMat;
  2193. invMat.SetTempSize( numRows, numColumns );
  2194. memcpy( invMat.mat, mat, numRows * numColumns * sizeof( float ) );
  2195. int r = invMat.InverseFastSelf();
  2196. assert( r );
  2197. return invMat;
  2198. }
  2199. ID_INLINE bool idMatX::InverseFastSelf( void ) {
  2200. assert( numRows == numColumns );
  2201. switch( numRows ) {
  2202. case 1:
  2203. if ( idMath::Fabs( mat[0] ) < MATRIX_INVERSE_EPSILON ) {
  2204. return false;
  2205. }
  2206. mat[0] = 1.0f / mat[0];
  2207. return true;
  2208. case 2:
  2209. return reinterpret_cast<idMat2 *>(mat)->InverseFastSelf();
  2210. case 3:
  2211. return reinterpret_cast<idMat3 *>(mat)->InverseFastSelf();
  2212. case 4:
  2213. return reinterpret_cast<idMat4 *>(mat)->InverseFastSelf();
  2214. case 5:
  2215. return reinterpret_cast<idMat5 *>(mat)->InverseFastSelf();
  2216. case 6:
  2217. return reinterpret_cast<idMat6 *>(mat)->InverseFastSelf();
  2218. default:
  2219. return InverseSelfGeneric();
  2220. }
  2221. return false;
  2222. }
  2223. ID_INLINE idVecX idMatX::Multiply( const idVecX &vec ) const {
  2224. idVecX dst;
  2225. assert( numColumns == vec.GetSize() );
  2226. dst.SetTempSize( numRows );
  2227. #ifdef MATX_SIMD
  2228. SIMDProcessor->MatX_MultiplyVecX( dst, *this, vec );
  2229. #else
  2230. Multiply( dst, vec );
  2231. #endif
  2232. return dst;
  2233. }
  2234. ID_INLINE idMatX idMatX::Multiply( const idMatX &a ) const {
  2235. idMatX dst;
  2236. assert( numColumns == a.numRows );
  2237. dst.SetTempSize( numRows, a.numColumns );
  2238. #ifdef MATX_SIMD
  2239. SIMDProcessor->MatX_MultiplyMatX( dst, *this, a );
  2240. #else
  2241. Multiply( dst, a );
  2242. #endif
  2243. return dst;
  2244. }
  2245. ID_INLINE idVecX idMatX::TransposeMultiply( const idVecX &vec ) const {
  2246. idVecX dst;
  2247. assert( numRows == vec.GetSize() );
  2248. dst.SetTempSize( numColumns );
  2249. #ifdef MATX_SIMD
  2250. SIMDProcessor->MatX_TransposeMultiplyVecX( dst, *this, vec );
  2251. #else
  2252. TransposeMultiply( dst, vec );
  2253. #endif
  2254. return dst;
  2255. }
  2256. ID_INLINE idMatX idMatX::TransposeMultiply( const idMatX &a ) const {
  2257. idMatX dst;
  2258. assert( numRows == a.numRows );
  2259. dst.SetTempSize( numColumns, a.numColumns );
  2260. #ifdef MATX_SIMD
  2261. SIMDProcessor->MatX_TransposeMultiplyMatX( dst, *this, a );
  2262. #else
  2263. TransposeMultiply( dst, a );
  2264. #endif
  2265. return dst;
  2266. }
  2267. ID_INLINE void idMatX::Multiply( idVecX &dst, const idVecX &vec ) const {
  2268. #ifdef MATX_SIMD
  2269. SIMDProcessor->MatX_MultiplyVecX( dst, *this, vec );
  2270. #else
  2271. int i, j;
  2272. const float *mPtr, *vPtr;
  2273. float *dstPtr;
  2274. mPtr = mat;
  2275. vPtr = vec.ToFloatPtr();
  2276. dstPtr = dst.ToFloatPtr();
  2277. for ( i = 0; i < numRows; i++ ) {
  2278. float sum = mPtr[0] * vPtr[0];
  2279. for ( j = 1; j < numColumns; j++ ) {
  2280. sum += mPtr[j] * vPtr[j];
  2281. }
  2282. dstPtr[i] = sum;
  2283. mPtr += numColumns;
  2284. }
  2285. #endif
  2286. }
  2287. ID_INLINE void idMatX::MultiplyAdd( idVecX &dst, const idVecX &vec ) const {
  2288. #ifdef MATX_SIMD
  2289. SIMDProcessor->MatX_MultiplyAddVecX( dst, *this, vec );
  2290. #else
  2291. int i, j;
  2292. const float *mPtr, *vPtr;
  2293. float *dstPtr;
  2294. mPtr = mat;
  2295. vPtr = vec.ToFloatPtr();
  2296. dstPtr = dst.ToFloatPtr();
  2297. for ( i = 0; i < numRows; i++ ) {
  2298. float sum = mPtr[0] * vPtr[0];
  2299. for ( j = 1; j < numColumns; j++ ) {
  2300. sum += mPtr[j] * vPtr[j];
  2301. }
  2302. dstPtr[i] += sum;
  2303. mPtr += numColumns;
  2304. }
  2305. #endif
  2306. }
  2307. ID_INLINE void idMatX::MultiplySub( idVecX &dst, const idVecX &vec ) const {
  2308. #ifdef MATX_SIMD
  2309. SIMDProcessor->MatX_MultiplySubVecX( dst, *this, vec );
  2310. #else
  2311. int i, j;
  2312. const float *mPtr, *vPtr;
  2313. float *dstPtr;
  2314. mPtr = mat;
  2315. vPtr = vec.ToFloatPtr();
  2316. dstPtr = dst.ToFloatPtr();
  2317. for ( i = 0; i < numRows; i++ ) {
  2318. float sum = mPtr[0] * vPtr[0];
  2319. for ( j = 1; j < numColumns; j++ ) {
  2320. sum += mPtr[j] * vPtr[j];
  2321. }
  2322. dstPtr[i] -= sum;
  2323. mPtr += numColumns;
  2324. }
  2325. #endif
  2326. }
  2327. ID_INLINE void idMatX::TransposeMultiply( idVecX &dst, const idVecX &vec ) const {
  2328. #ifdef MATX_SIMD
  2329. SIMDProcessor->MatX_TransposeMultiplyVecX( dst, *this, vec );
  2330. #else
  2331. int i, j;
  2332. const float *mPtr, *vPtr;
  2333. float *dstPtr;
  2334. vPtr = vec.ToFloatPtr();
  2335. dstPtr = dst.ToFloatPtr();
  2336. for ( i = 0; i < numColumns; i++ ) {
  2337. mPtr = mat + i;
  2338. float sum = mPtr[0] * vPtr[0];
  2339. for ( j = 1; j < numRows; j++ ) {
  2340. mPtr += numColumns;
  2341. sum += mPtr[0] * vPtr[j];
  2342. }
  2343. dstPtr[i] = sum;
  2344. }
  2345. #endif
  2346. }
  2347. ID_INLINE void idMatX::TransposeMultiplyAdd( idVecX &dst, const idVecX &vec ) const {
  2348. #ifdef MATX_SIMD
  2349. SIMDProcessor->MatX_TransposeMultiplyAddVecX( dst, *this, vec );
  2350. #else
  2351. int i, j;
  2352. const float *mPtr, *vPtr;
  2353. float *dstPtr;
  2354. vPtr = vec.ToFloatPtr();
  2355. dstPtr = dst.ToFloatPtr();
  2356. for ( i = 0; i < numColumns; i++ ) {
  2357. mPtr = mat + i;
  2358. float sum = mPtr[0] * vPtr[0];
  2359. for ( j = 1; j < numRows; j++ ) {
  2360. mPtr += numColumns;
  2361. sum += mPtr[0] * vPtr[j];
  2362. }
  2363. dstPtr[i] += sum;
  2364. }
  2365. #endif
  2366. }
  2367. ID_INLINE void idMatX::TransposeMultiplySub( idVecX &dst, const idVecX &vec ) const {
  2368. #ifdef MATX_SIMD
  2369. SIMDProcessor->MatX_TransposeMultiplySubVecX( dst, *this, vec );
  2370. #else
  2371. int i, j;
  2372. const float *mPtr, *vPtr;
  2373. float *dstPtr;
  2374. vPtr = vec.ToFloatPtr();
  2375. dstPtr = dst.ToFloatPtr();
  2376. for ( i = 0; i < numColumns; i++ ) {
  2377. mPtr = mat + i;
  2378. float sum = mPtr[0] * vPtr[0];
  2379. for ( j = 1; j < numRows; j++ ) {
  2380. mPtr += numColumns;
  2381. sum += mPtr[0] * vPtr[j];
  2382. }
  2383. dstPtr[i] -= sum;
  2384. }
  2385. #endif
  2386. }
  2387. ID_INLINE void idMatX::Multiply( idMatX &dst, const idMatX &a ) const {
  2388. #ifdef MATX_SIMD
  2389. SIMDProcessor->MatX_MultiplyMatX( dst, *this, a );
  2390. #else
  2391. int i, j, k, l, n;
  2392. float *dstPtr;
  2393. const float *m1Ptr, *m2Ptr;
  2394. double sum;
  2395. assert( numColumns == a.numRows );
  2396. dstPtr = dst.ToFloatPtr();
  2397. m1Ptr = ToFloatPtr();
  2398. m2Ptr = a.ToFloatPtr();
  2399. k = numRows;
  2400. l = a.GetNumColumns();
  2401. for ( i = 0; i < k; i++ ) {
  2402. for ( j = 0; j < l; j++ ) {
  2403. m2Ptr = a.ToFloatPtr() + j;
  2404. sum = m1Ptr[0] * m2Ptr[0];
  2405. for ( n = 1; n < numColumns; n++ ) {
  2406. m2Ptr += l;
  2407. sum += m1Ptr[n] * m2Ptr[0];
  2408. }
  2409. *dstPtr++ = sum;
  2410. }
  2411. m1Ptr += numColumns;
  2412. }
  2413. #endif
  2414. }
  2415. ID_INLINE void idMatX::TransposeMultiply( idMatX &dst, const idMatX &a ) const {
  2416. #ifdef MATX_SIMD
  2417. SIMDProcessor->MatX_TransposeMultiplyMatX( dst, *this, a );
  2418. #else
  2419. int i, j, k, l, n;
  2420. float *dstPtr;
  2421. const float *m1Ptr, *m2Ptr;
  2422. double sum;
  2423. assert( numRows == a.numRows );
  2424. dstPtr = dst.ToFloatPtr();
  2425. m1Ptr = ToFloatPtr();
  2426. k = numColumns;
  2427. l = a.numColumns;
  2428. for ( i = 0; i < k; i++ ) {
  2429. for ( j = 0; j < l; j++ ) {
  2430. m1Ptr = ToFloatPtr() + i;
  2431. m2Ptr = a.ToFloatPtr() + j;
  2432. sum = m1Ptr[0] * m2Ptr[0];
  2433. for ( n = 1; n < numRows; n++ ) {
  2434. m1Ptr += numColumns;
  2435. m2Ptr += a.numColumns;
  2436. sum += m1Ptr[0] * m2Ptr[0];
  2437. }
  2438. *dstPtr++ = sum;
  2439. }
  2440. }
  2441. #endif
  2442. }
  2443. ID_INLINE int idMatX::GetDimension( void ) const {
  2444. return numRows * numColumns;
  2445. }
  2446. ID_INLINE const idVec6 &idMatX::SubVec6( int row ) const {
  2447. assert( numColumns >= 6 && row >= 0 && row < numRows );
  2448. return *reinterpret_cast<const idVec6 *>(mat + row * numColumns);
  2449. }
  2450. ID_INLINE idVec6 &idMatX::SubVec6( int row ) {
  2451. assert( numColumns >= 6 && row >= 0 && row < numRows );
  2452. return *reinterpret_cast<idVec6 *>(mat + row * numColumns);
  2453. }
  2454. ID_INLINE const idVecX idMatX::SubVecX( int row ) const {
  2455. idVecX v;
  2456. assert( row >= 0 && row < numRows );
  2457. v.SetData( numColumns, mat + row * numColumns );
  2458. return v;
  2459. }
  2460. ID_INLINE idVecX idMatX::SubVecX( int row ) {
  2461. idVecX v;
  2462. assert( row >= 0 && row < numRows );
  2463. v.SetData( numColumns, mat + row * numColumns );
  2464. return v;
  2465. }
  2466. ID_INLINE const float *idMatX::ToFloatPtr( void ) const {
  2467. return mat;
  2468. }
  2469. ID_INLINE float *idMatX::ToFloatPtr( void ) {
  2470. return mat;
  2471. }
  2472. #endif /* !__MATH_MATRIX_H__ */