math.vector.js 295 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451
  1. /* eslint-disable @typescript-eslint/naming-convention */
  2. import { Epsilon } from "./math.constants.js";
  3. import { ArrayTools } from "../Misc/arrayTools.js";
  4. import { RegisterClass } from "../Misc/typeStore.js";
  5. import { PerformanceConfigurator } from "../Engines/performanceConfigurator.js";
  6. import { EngineStore } from "../Engines/engineStore.js";
  7. import { Clamp, Lerp, NormalizeRadians, RandomRange, WithinEpsilon } from "./math.scalar.functions.js";
  8. // eslint-disable-next-line @typescript-eslint/naming-convention
  9. const _ExtractAsInt = (value) => {
  10. return parseInt(value.toString().replace(/\W/g, ""));
  11. };
  12. /**
  13. * Class representing a vector containing 2 coordinates
  14. * Example Playground - Overview - https://playground.babylonjs.com/#QYBWV4#9
  15. */
  16. export class Vector2 {
  17. /**
  18. * Creates a new Vector2 from the given x and y coordinates
  19. * @param x defines the first coordinate
  20. * @param y defines the second coordinate
  21. */
  22. constructor(
  23. /** defines the first coordinate */
  24. x = 0,
  25. /** defines the second coordinate */
  26. y = 0) {
  27. this.x = x;
  28. this.y = y;
  29. }
  30. /**
  31. * Gets a string with the Vector2 coordinates
  32. * @returns a string with the Vector2 coordinates
  33. */
  34. toString() {
  35. return `{X: ${this.x} Y: ${this.y}}`;
  36. }
  37. /**
  38. * Gets class name
  39. * @returns the string "Vector2"
  40. */
  41. getClassName() {
  42. return "Vector2";
  43. }
  44. /**
  45. * Gets current vector hash code
  46. * @returns the Vector2 hash code as a number
  47. */
  48. getHashCode() {
  49. const x = _ExtractAsInt(this.x);
  50. const y = _ExtractAsInt(this.y);
  51. let hash = x;
  52. hash = (hash * 397) ^ y;
  53. return hash;
  54. }
  55. // Operators
  56. /**
  57. * Sets the Vector2 coordinates in the given array or Float32Array from the given index.
  58. * Example Playground https://playground.babylonjs.com/#QYBWV4#15
  59. * @param array defines the source array
  60. * @param index defines the offset in source array
  61. * @returns the current Vector2
  62. */
  63. toArray(array, index = 0) {
  64. array[index] = this.x;
  65. array[index + 1] = this.y;
  66. return this;
  67. }
  68. /**
  69. * Update the current vector from an array
  70. * Example Playground https://playground.babylonjs.com/#QYBWV4#39
  71. * @param array defines the destination array
  72. * @param offset defines the offset in the destination array
  73. * @returns the current Vector2
  74. */
  75. fromArray(array, offset = 0) {
  76. Vector2.FromArrayToRef(array, offset, this);
  77. return this;
  78. }
  79. /**
  80. * Copy the current vector to an array
  81. * Example Playground https://playground.babylonjs.com/#QYBWV4#40
  82. * @returns a new array with 2 elements: the Vector2 coordinates.
  83. */
  84. asArray() {
  85. return [this.x, this.y];
  86. }
  87. /**
  88. * Sets the Vector2 coordinates with the given Vector2 coordinates
  89. * Example Playground https://playground.babylonjs.com/#QYBWV4#24
  90. * @param source defines the source Vector2
  91. * @returns the current updated Vector2
  92. */
  93. copyFrom(source) {
  94. this.x = source.x;
  95. this.y = source.y;
  96. return this;
  97. }
  98. /**
  99. * Sets the Vector2 coordinates with the given floats
  100. * Example Playground https://playground.babylonjs.com/#QYBWV4#25
  101. * @param x defines the first coordinate
  102. * @param y defines the second coordinate
  103. * @returns the current updated Vector2
  104. */
  105. copyFromFloats(x, y) {
  106. this.x = x;
  107. this.y = y;
  108. return this;
  109. }
  110. /**
  111. * Sets the Vector2 coordinates with the given floats
  112. * Example Playground https://playground.babylonjs.com/#QYBWV4#62
  113. * @param x defines the first coordinate
  114. * @param y defines the second coordinate
  115. * @returns the current updated Vector2
  116. */
  117. set(x, y) {
  118. return this.copyFromFloats(x, y);
  119. }
  120. /**
  121. * Copies the given float to the current Vector2 coordinates
  122. * @param v defines the x and y coordinates of the operand
  123. * @returns the current updated Vector2
  124. */
  125. setAll(v) {
  126. return this.copyFromFloats(v, v);
  127. }
  128. /**
  129. * Add another vector with the current one
  130. * Example Playground https://playground.babylonjs.com/#QYBWV4#11
  131. * @param otherVector defines the other vector
  132. * @returns a new Vector2 set with the addition of the current Vector2 and the given one coordinates
  133. */
  134. add(otherVector) {
  135. return new this.constructor(this.x + otherVector.x, this.y + otherVector.y);
  136. }
  137. /**
  138. * Sets the "result" coordinates with the addition of the current Vector2 and the given one coordinates
  139. * Example Playground https://playground.babylonjs.com/#QYBWV4#12
  140. * @param otherVector defines the other vector
  141. * @param result defines the target vector
  142. * @returns result input
  143. */
  144. addToRef(otherVector, result) {
  145. result.x = this.x + otherVector.x;
  146. result.y = this.y + otherVector.y;
  147. return result;
  148. }
  149. /**
  150. * Set the Vector2 coordinates by adding the given Vector2 coordinates
  151. * Example Playground https://playground.babylonjs.com/#QYBWV4#13
  152. * @param otherVector defines the other vector
  153. * @returns the current updated Vector2
  154. */
  155. addInPlace(otherVector) {
  156. this.x += otherVector.x;
  157. this.y += otherVector.y;
  158. return this;
  159. }
  160. /**
  161. * Adds the given coordinates to the current Vector2
  162. * @param x defines the x coordinate of the operand
  163. * @param y defines the y coordinate of the operand
  164. * @returns the current updated Vector2
  165. */
  166. addInPlaceFromFloats(x, y) {
  167. this.x += x;
  168. this.y += y;
  169. return this;
  170. }
  171. /**
  172. * Gets a new Vector2 by adding the current Vector2 coordinates to the given Vector3 x, y coordinates
  173. * Example Playground https://playground.babylonjs.com/#QYBWV4#14
  174. * @param otherVector defines the other vector
  175. * @returns a new Vector2
  176. */
  177. addVector3(otherVector) {
  178. return new this.constructor(this.x + otherVector.x, this.y + otherVector.y);
  179. }
  180. /**
  181. * Gets a new Vector2 set with the subtracted coordinates of the given one from the current Vector2
  182. * Example Playground https://playground.babylonjs.com/#QYBWV4#61
  183. * @param otherVector defines the other vector
  184. * @returns a new Vector2
  185. */
  186. subtract(otherVector) {
  187. return new this.constructor(this.x - otherVector.x, this.y - otherVector.y);
  188. }
  189. /**
  190. * Sets the "result" coordinates with the subtraction of the given one from the current Vector2 coordinates.
  191. * Example Playground https://playground.babylonjs.com/#QYBWV4#63
  192. * @param otherVector defines the other vector
  193. * @param result defines the target vector
  194. * @returns result input
  195. */
  196. subtractToRef(otherVector, result) {
  197. result.x = this.x - otherVector.x;
  198. result.y = this.y - otherVector.y;
  199. return result;
  200. }
  201. /**
  202. * Sets the current Vector2 coordinates by subtracting from it the given one coordinates
  203. * Example Playground https://playground.babylonjs.com/#QYBWV4#88
  204. * @param otherVector defines the other vector
  205. * @returns the current updated Vector2
  206. */
  207. subtractInPlace(otherVector) {
  208. this.x -= otherVector.x;
  209. this.y -= otherVector.y;
  210. return this;
  211. }
  212. /**
  213. * Multiplies in place the current Vector2 coordinates by the given ones
  214. * Example Playground https://playground.babylonjs.com/#QYBWV4#43
  215. * @param otherVector defines the other vector
  216. * @returns the current updated Vector2
  217. */
  218. multiplyInPlace(otherVector) {
  219. this.x *= otherVector.x;
  220. this.y *= otherVector.y;
  221. return this;
  222. }
  223. /**
  224. * Returns a new Vector2 set with the multiplication of the current Vector2 and the given one coordinates
  225. * Example Playground https://playground.babylonjs.com/#QYBWV4#42
  226. * @param otherVector defines the other vector
  227. * @returns a new Vector2
  228. */
  229. multiply(otherVector) {
  230. return new this.constructor(this.x * otherVector.x, this.y * otherVector.y);
  231. }
  232. /**
  233. * Sets "result" coordinates with the multiplication of the current Vector2 and the given one coordinates
  234. * Example Playground https://playground.babylonjs.com/#QYBWV4#44
  235. * @param otherVector defines the other vector
  236. * @param result defines the target vector
  237. * @returns result input
  238. */
  239. multiplyToRef(otherVector, result) {
  240. result.x = this.x * otherVector.x;
  241. result.y = this.y * otherVector.y;
  242. return result;
  243. }
  244. /**
  245. * Gets a new Vector2 set with the Vector2 coordinates multiplied by the given floats
  246. * Example Playground https://playground.babylonjs.com/#QYBWV4#89
  247. * @param x defines the first coordinate
  248. * @param y defines the second coordinate
  249. * @returns a new Vector2
  250. */
  251. multiplyByFloats(x, y) {
  252. return new this.constructor(this.x * x, this.y * y);
  253. }
  254. /**
  255. * Returns a new Vector2 set with the Vector2 coordinates divided by the given one coordinates
  256. * Example Playground https://playground.babylonjs.com/#QYBWV4#27
  257. * @param otherVector defines the other vector
  258. * @returns a new Vector2
  259. */
  260. divide(otherVector) {
  261. return new this.constructor(this.x / otherVector.x, this.y / otherVector.y);
  262. }
  263. /**
  264. * Sets the "result" coordinates with the Vector2 divided by the given one coordinates
  265. * Example Playground https://playground.babylonjs.com/#QYBWV4#30
  266. * @param otherVector defines the other vector
  267. * @param result defines the target vector
  268. * @returns result input
  269. */
  270. divideToRef(otherVector, result) {
  271. result.x = this.x / otherVector.x;
  272. result.y = this.y / otherVector.y;
  273. return result;
  274. }
  275. /**
  276. * Divides the current Vector2 coordinates by the given ones
  277. * Example Playground https://playground.babylonjs.com/#QYBWV4#28
  278. * @param otherVector defines the other vector
  279. * @returns the current updated Vector2
  280. */
  281. divideInPlace(otherVector) {
  282. this.x = this.x / otherVector.x;
  283. this.y = this.y / otherVector.y;
  284. return this;
  285. }
  286. /**
  287. * Updates the current Vector2 with the minimal coordinate values between its and the given vector ones
  288. * @param other defines the second operand
  289. * @returns the current updated Vector2
  290. */
  291. minimizeInPlace(other) {
  292. return this.minimizeInPlaceFromFloats(other.x, other.y);
  293. }
  294. /**
  295. * Updates the current Vector2 with the maximal coordinate values between its and the given vector ones.
  296. * @param other defines the second operand
  297. * @returns the current updated Vector2
  298. */
  299. maximizeInPlace(other) {
  300. return this.maximizeInPlaceFromFloats(other.x, other.y);
  301. }
  302. /**
  303. * Updates the current Vector2 with the minimal coordinate values between its and the given coordinates
  304. * @param x defines the x coordinate of the operand
  305. * @param y defines the y coordinate of the operand
  306. * @returns the current updated Vector2
  307. */
  308. minimizeInPlaceFromFloats(x, y) {
  309. this.x = Math.min(x, this.x);
  310. this.y = Math.min(y, this.y);
  311. return this;
  312. }
  313. /**
  314. * Updates the current Vector2 with the maximal coordinate values between its and the given coordinates.
  315. * @param x defines the x coordinate of the operand
  316. * @param y defines the y coordinate of the operand
  317. * @returns the current updated Vector2
  318. */
  319. maximizeInPlaceFromFloats(x, y) {
  320. this.x = Math.max(x, this.x);
  321. this.y = Math.max(y, this.y);
  322. return this;
  323. }
  324. /**
  325. * Returns a new Vector2 set with the subtraction of the given floats from the current Vector2 coordinates
  326. * @param x defines the x coordinate of the operand
  327. * @param y defines the y coordinate of the operand
  328. * @returns the resulting Vector2
  329. */
  330. subtractFromFloats(x, y) {
  331. return new this.constructor(this.x - x, this.y - y);
  332. }
  333. /**
  334. * Subtracts the given floats from the current Vector2 coordinates and set the given vector "result" with this result
  335. * @param x defines the x coordinate of the operand
  336. * @param y defines the y coordinate of the operand
  337. * @param result defines the Vector2 object where to store the result
  338. * @returns the result
  339. */
  340. subtractFromFloatsToRef(x, y, result) {
  341. return result.copyFromFloats(this.x - x, this.y - y);
  342. }
  343. /**
  344. * Gets a new Vector2 with current Vector2 negated coordinates
  345. * @returns a new Vector2
  346. */
  347. negate() {
  348. return new this.constructor(-this.x, -this.y);
  349. }
  350. /**
  351. * Negate this vector in place
  352. * Example Playground https://playground.babylonjs.com/#QYBWV4#23
  353. * @returns this
  354. */
  355. negateInPlace() {
  356. this.x *= -1;
  357. this.y *= -1;
  358. return this;
  359. }
  360. /**
  361. * Negate the current Vector2 and stores the result in the given vector "result" coordinates
  362. * Example Playground https://playground.babylonjs.com/#QYBWV4#41
  363. * @param result defines the Vector3 object where to store the result
  364. * @returns the result
  365. */
  366. negateToRef(result) {
  367. return result.copyFromFloats(this.x * -1, this.y * -1);
  368. }
  369. /**
  370. * Multiply the Vector2 coordinates by
  371. * Example Playground https://playground.babylonjs.com/#QYBWV4#59
  372. * @param scale defines the scaling factor
  373. * @returns the current updated Vector2
  374. */
  375. scaleInPlace(scale) {
  376. this.x *= scale;
  377. this.y *= scale;
  378. return this;
  379. }
  380. /**
  381. * Returns a new Vector2 scaled by "scale" from the current Vector2
  382. * Example Playground https://playground.babylonjs.com/#QYBWV4#52
  383. * @param scale defines the scaling factor
  384. * @returns a new Vector2
  385. */
  386. scale(scale) {
  387. return new this.constructor(this.x * scale, this.y * scale);
  388. }
  389. /**
  390. * Scale the current Vector2 values by a factor to a given Vector2
  391. * Example Playground https://playground.babylonjs.com/#QYBWV4#57
  392. * @param scale defines the scale factor
  393. * @param result defines the Vector2 object where to store the result
  394. * @returns result input
  395. */
  396. scaleToRef(scale, result) {
  397. result.x = this.x * scale;
  398. result.y = this.y * scale;
  399. return result;
  400. }
  401. /**
  402. * Scale the current Vector2 values by a factor and add the result to a given Vector2
  403. * Example Playground https://playground.babylonjs.com/#QYBWV4#58
  404. * @param scale defines the scale factor
  405. * @param result defines the Vector2 object where to store the result
  406. * @returns result input
  407. */
  408. scaleAndAddToRef(scale, result) {
  409. result.x += this.x * scale;
  410. result.y += this.y * scale;
  411. return result;
  412. }
  413. /**
  414. * Gets a boolean if two vectors are equals
  415. * Example Playground https://playground.babylonjs.com/#QYBWV4#31
  416. * @param otherVector defines the other vector
  417. * @returns true if the given vector coordinates strictly equal the current Vector2 ones
  418. */
  419. equals(otherVector) {
  420. return otherVector && this.x === otherVector.x && this.y === otherVector.y;
  421. }
  422. /**
  423. * Gets a boolean if two vectors are equals (using an epsilon value)
  424. * Example Playground https://playground.babylonjs.com/#QYBWV4#32
  425. * @param otherVector defines the other vector
  426. * @param epsilon defines the minimal distance to consider equality
  427. * @returns true if the given vector coordinates are close to the current ones by a distance of epsilon.
  428. */
  429. equalsWithEpsilon(otherVector, epsilon = Epsilon) {
  430. return otherVector && WithinEpsilon(this.x, otherVector.x, epsilon) && WithinEpsilon(this.y, otherVector.y, epsilon);
  431. }
  432. /**
  433. * Returns true if the current Vector2 coordinates equals the given floats
  434. * @param x defines the x coordinate of the operand
  435. * @param y defines the y coordinate of the operand
  436. * @returns true if both vectors are equal
  437. */
  438. equalsToFloats(x, y) {
  439. return this.x === x && this.y === y;
  440. }
  441. /**
  442. * Gets a new Vector2 from current Vector2 floored values
  443. * Example Playground https://playground.babylonjs.com/#QYBWV4#35
  444. * eg (1.2, 2.31) returns (1, 2)
  445. * @returns a new Vector2
  446. */
  447. floor() {
  448. return new this.constructor(Math.floor(this.x), Math.floor(this.y));
  449. }
  450. /**
  451. * Gets the current Vector2's floored values and stores them in result
  452. * @param result the Vector2 to store the result in
  453. * @returns the result Vector2
  454. */
  455. floorToRef(result) {
  456. result.x = Math.floor(this.x);
  457. result.y = Math.floor(this.y);
  458. return result;
  459. }
  460. /**
  461. * Gets a new Vector2 from current Vector2 fractional values
  462. * Example Playground https://playground.babylonjs.com/#QYBWV4#34
  463. * eg (1.2, 2.31) returns (0.2, 0.31)
  464. * @returns a new Vector2
  465. */
  466. fract() {
  467. return new this.constructor(this.x - Math.floor(this.x), this.y - Math.floor(this.y));
  468. }
  469. /**
  470. * Gets the current Vector2's fractional values and stores them in result
  471. * @param result the Vector2 to store the result in
  472. * @returns the result Vector2
  473. */
  474. fractToRef(result) {
  475. result.x = this.x - Math.floor(this.x);
  476. result.y = this.y - Math.floor(this.y);
  477. return result;
  478. }
  479. /**
  480. * Rotate the current vector into a given result vector
  481. * Example Playground https://playground.babylonjs.com/#QYBWV4#49
  482. * @param angle defines the rotation angle
  483. * @param result defines the result vector where to store the rotated vector
  484. * @returns result input
  485. */
  486. rotateToRef(angle, result) {
  487. const cos = Math.cos(angle);
  488. const sin = Math.sin(angle);
  489. const x = cos * this.x - sin * this.y;
  490. const y = sin * this.x + cos * this.y;
  491. result.x = x;
  492. result.y = y;
  493. return result;
  494. }
  495. // Properties
  496. /**
  497. * Gets the length of the vector
  498. * @returns the vector length (float)
  499. */
  500. length() {
  501. return Math.sqrt(this.x * this.x + this.y * this.y);
  502. }
  503. /**
  504. * Gets the vector squared length
  505. * @returns the vector squared length (float)
  506. */
  507. lengthSquared() {
  508. return this.x * this.x + this.y * this.y;
  509. }
  510. // Methods
  511. /**
  512. * Normalize the vector
  513. * Example Playground https://playground.babylonjs.com/#QYBWV4#48
  514. * @returns the current updated Vector2
  515. */
  516. normalize() {
  517. return this.normalizeFromLength(this.length());
  518. }
  519. /**
  520. * Normalize the current Vector2 with the given input length.
  521. * Please note that this is an in place operation.
  522. * @param len the length of the vector
  523. * @returns the current updated Vector2
  524. */
  525. normalizeFromLength(len) {
  526. if (len === 0 || len === 1.0) {
  527. return this;
  528. }
  529. return this.scaleInPlace(1.0 / len);
  530. }
  531. /**
  532. * Normalize the current Vector2 to a new vector
  533. * @returns the new Vector2
  534. */
  535. normalizeToNew() {
  536. const normalized = new this.constructor();
  537. this.normalizeToRef(normalized);
  538. return normalized;
  539. }
  540. /**
  541. * Normalize the current Vector2 to the reference
  542. * @param reference define the Vector to update
  543. * @returns the updated Vector2
  544. */
  545. normalizeToRef(reference) {
  546. const len = this.length();
  547. if (len === 0) {
  548. return reference.copyFrom(this);
  549. }
  550. return this.scaleToRef(1.0 / len, reference);
  551. }
  552. /**
  553. * Gets a new Vector2 copied from the Vector2
  554. * Example Playground https://playground.babylonjs.com/#QYBWV4#20
  555. * @returns a new Vector2
  556. */
  557. clone() {
  558. return new this.constructor(this.x, this.y);
  559. }
  560. /**
  561. * Gets the dot product of the current vector and the vector "otherVector"
  562. * @param otherVector defines second vector
  563. * @returns the dot product (float)
  564. */
  565. dot(otherVector) {
  566. return this.x * otherVector.x + this.y * otherVector.y;
  567. }
  568. // Statics
  569. /**
  570. * Gets a new Vector2(0, 0)
  571. * @returns a new Vector2
  572. */
  573. static Zero() {
  574. return new Vector2(0, 0);
  575. }
  576. /**
  577. * Gets a new Vector2(1, 1)
  578. * @returns a new Vector2
  579. */
  580. static One() {
  581. return new Vector2(1, 1);
  582. }
  583. /**
  584. * Returns a new Vector2 with random values between min and max
  585. * @param min the minimum random value
  586. * @param max the maximum random value
  587. * @returns a Vector2 with random values between min and max
  588. */
  589. static Random(min = 0, max = 1) {
  590. return new Vector2(RandomRange(min, max), RandomRange(min, max));
  591. }
  592. /**
  593. * Sets a Vector2 with random values between min and max
  594. * @param min the minimum random value
  595. * @param max the maximum random value
  596. * @param ref the ref to store the values in
  597. * @returns the ref with random values between min and max
  598. */
  599. static RandomToRef(min = 0, max = 1, ref) {
  600. return ref.copyFromFloats(RandomRange(min, max), RandomRange(min, max));
  601. }
  602. /**
  603. * Gets a zero Vector2 that must not be updated
  604. */
  605. static get ZeroReadOnly() {
  606. return Vector2._ZeroReadOnly;
  607. }
  608. /**
  609. * Gets a new Vector2 set from the given index element of the given array
  610. * Example Playground https://playground.babylonjs.com/#QYBWV4#79
  611. * @param array defines the data source
  612. * @param offset defines the offset in the data source
  613. * @returns a new Vector2
  614. */
  615. static FromArray(array, offset = 0) {
  616. return new Vector2(array[offset], array[offset + 1]);
  617. }
  618. /**
  619. * Sets "result" from the given index element of the given array
  620. * Example Playground https://playground.babylonjs.com/#QYBWV4#80
  621. * @param array defines the data source
  622. * @param offset defines the offset in the data source
  623. * @param result defines the target vector
  624. * @returns result input
  625. */
  626. static FromArrayToRef(array, offset, result) {
  627. result.x = array[offset];
  628. result.y = array[offset + 1];
  629. return result;
  630. }
  631. /**
  632. * Sets the given vector "result" with the given floats.
  633. * @param x defines the x coordinate of the source
  634. * @param y defines the y coordinate of the source
  635. * @param result defines the Vector2 where to store the result
  636. * @returns the result vector
  637. */
  638. static FromFloatsToRef(x, y, result) {
  639. result.copyFromFloats(x, y);
  640. return result;
  641. }
  642. /**
  643. * Gets a new Vector2 located for "amount" (float) on the CatmullRom spline defined by the given four Vector2
  644. * Example Playground https://playground.babylonjs.com/#QYBWV4#65
  645. * @param value1 defines 1st point of control
  646. * @param value2 defines 2nd point of control
  647. * @param value3 defines 3rd point of control
  648. * @param value4 defines 4th point of control
  649. * @param amount defines the interpolation factor
  650. * @returns a new Vector2
  651. */
  652. static CatmullRom(value1, value2, value3, value4, amount) {
  653. const squared = amount * amount;
  654. const cubed = amount * squared;
  655. const x = 0.5 *
  656. (2.0 * value2.x +
  657. (-value1.x + value3.x) * amount +
  658. (2.0 * value1.x - 5.0 * value2.x + 4.0 * value3.x - value4.x) * squared +
  659. (-value1.x + 3.0 * value2.x - 3.0 * value3.x + value4.x) * cubed);
  660. const y = 0.5 *
  661. (2.0 * value2.y +
  662. (-value1.y + value3.y) * amount +
  663. (2.0 * value1.y - 5.0 * value2.y + 4.0 * value3.y - value4.y) * squared +
  664. (-value1.y + 3.0 * value2.y - 3.0 * value3.y + value4.y) * cubed);
  665. return new value1.constructor(x, y);
  666. }
  667. /**
  668. * Sets reference with same the coordinates than "value" ones if the vector "value" is in the square defined by "min" and "max".
  669. * If a coordinate of "value" is lower than "min" coordinates, the returned Vector2 is given this "min" coordinate.
  670. * If a coordinate of "value" is greater than "max" coordinates, the returned Vector2 is given this "max" coordinate
  671. * @param value defines the value to clamp
  672. * @param min defines the lower limit
  673. * @param max defines the upper limit
  674. * @param ref the reference
  675. * @returns the reference
  676. */
  677. static ClampToRef(value, min, max, ref) {
  678. ref.x = Clamp(value.x, min.x, max.x);
  679. ref.y = Clamp(value.y, min.y, max.y);
  680. return ref;
  681. }
  682. /**
  683. * Returns a new Vector2 set with same the coordinates than "value" ones if the vector "value" is in the square defined by "min" and "max".
  684. * If a coordinate of "value" is lower than "min" coordinates, the returned Vector2 is given this "min" coordinate.
  685. * If a coordinate of "value" is greater than "max" coordinates, the returned Vector2 is given this "max" coordinate
  686. * Example Playground https://playground.babylonjs.com/#QYBWV4#76
  687. * @param value defines the value to clamp
  688. * @param min defines the lower limit
  689. * @param max defines the upper limit
  690. * @returns a new Vector2
  691. */
  692. static Clamp(value, min, max) {
  693. const x = Clamp(value.x, min.x, max.x);
  694. const y = Clamp(value.y, min.y, max.y);
  695. return new value.constructor(x, y);
  696. }
  697. /**
  698. * Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2"
  699. * Example Playground https://playground.babylonjs.com/#QYBWV4#81
  700. * @param value1 defines the 1st control point
  701. * @param tangent1 defines the outgoing tangent
  702. * @param value2 defines the 2nd control point
  703. * @param tangent2 defines the incoming tangent
  704. * @param amount defines the interpolation factor
  705. * @returns a new Vector2
  706. */
  707. static Hermite(value1, tangent1, value2, tangent2, amount) {
  708. const squared = amount * amount;
  709. const cubed = amount * squared;
  710. const part1 = 2.0 * cubed - 3.0 * squared + 1.0;
  711. const part2 = -2.0 * cubed + 3.0 * squared;
  712. const part3 = cubed - 2.0 * squared + amount;
  713. const part4 = cubed - squared;
  714. const x = value1.x * part1 + value2.x * part2 + tangent1.x * part3 + tangent2.x * part4;
  715. const y = value1.y * part1 + value2.y * part2 + tangent1.y * part3 + tangent2.y * part4;
  716. return new value1.constructor(x, y);
  717. }
  718. /**
  719. * Returns a new Vector2 which is the 1st derivative of the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2".
  720. * Example Playground https://playground.babylonjs.com/#QYBWV4#82
  721. * @param value1 defines the first control point
  722. * @param tangent1 defines the first tangent
  723. * @param value2 defines the second control point
  724. * @param tangent2 defines the second tangent
  725. * @param time define where the derivative must be done
  726. * @returns 1st derivative
  727. */
  728. static Hermite1stDerivative(value1, tangent1, value2, tangent2, time) {
  729. const result = new value1.constructor();
  730. this.Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result);
  731. return result;
  732. }
  733. /**
  734. * Returns a new Vector2 which is the 1st derivative of the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2".
  735. * Example Playground https://playground.babylonjs.com/#QYBWV4#83
  736. * @param value1 defines the first control point
  737. * @param tangent1 defines the first tangent
  738. * @param value2 defines the second control point
  739. * @param tangent2 defines the second tangent
  740. * @param time define where the derivative must be done
  741. * @param result define where the derivative will be stored
  742. * @returns result input
  743. */
  744. static Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result) {
  745. const t2 = time * time;
  746. result.x = (t2 - time) * 6 * value1.x + (3 * t2 - 4 * time + 1) * tangent1.x + (-t2 + time) * 6 * value2.x + (3 * t2 - 2 * time) * tangent2.x;
  747. result.y = (t2 - time) * 6 * value1.y + (3 * t2 - 4 * time + 1) * tangent1.y + (-t2 + time) * 6 * value2.y + (3 * t2 - 2 * time) * tangent2.y;
  748. return result;
  749. }
  750. /**
  751. * Returns a new Vector2 located for "amount" (float) on the linear interpolation between the vector "start" adn the vector "end".
  752. * Example Playground https://playground.babylonjs.com/#QYBWV4#84
  753. * @param start defines the start vector
  754. * @param end defines the end vector
  755. * @param amount defines the interpolation factor
  756. * @returns a new Vector2
  757. */
  758. static Lerp(start, end, amount) {
  759. const x = start.x + (end.x - start.x) * amount;
  760. const y = start.y + (end.y - start.y) * amount;
  761. return new start.constructor(x, y);
  762. }
  763. /**
  764. * Gets the dot product of the vector "left" and the vector "right"
  765. * Example Playground https://playground.babylonjs.com/#QYBWV4#90
  766. * @param left defines first vector
  767. * @param right defines second vector
  768. * @returns the dot product (float)
  769. */
  770. static Dot(left, right) {
  771. return left.x * right.x + left.y * right.y;
  772. }
  773. /**
  774. * Returns a new Vector2 equal to the normalized given vector
  775. * Example Playground https://playground.babylonjs.com/#QYBWV4#46
  776. * @param vector defines the vector to normalize
  777. * @returns a new Vector2
  778. */
  779. static Normalize(vector) {
  780. const result = new vector.constructor();
  781. Vector2.NormalizeToRef(vector, result);
  782. return result;
  783. }
  784. /**
  785. * Normalize a given vector into a second one
  786. * Example Playground https://playground.babylonjs.com/#QYBWV4#50
  787. * @param vector defines the vector to normalize
  788. * @param result defines the vector where to store the result
  789. * @returns result input
  790. */
  791. static NormalizeToRef(vector, result) {
  792. vector.normalizeToRef(result);
  793. return result;
  794. }
  795. /**
  796. * Gets a new Vector2 set with the minimal coordinate values from the "left" and "right" vectors
  797. * Example Playground https://playground.babylonjs.com/#QYBWV4#86
  798. * @param left defines 1st vector
  799. * @param right defines 2nd vector
  800. * @returns a new Vector2
  801. */
  802. static Minimize(left, right) {
  803. const x = left.x < right.x ? left.x : right.x;
  804. const y = left.y < right.y ? left.y : right.y;
  805. return new left.constructor(x, y);
  806. }
  807. /**
  808. * Gets a new Vector2 set with the maximal coordinate values from the "left" and "right" vectors
  809. * Example Playground https://playground.babylonjs.com/#QYBWV4#86
  810. * @param left defines 1st vector
  811. * @param right defines 2nd vector
  812. * @returns a new Vector2
  813. */
  814. static Maximize(left, right) {
  815. const x = left.x > right.x ? left.x : right.x;
  816. const y = left.y > right.y ? left.y : right.y;
  817. return new left.constructor(x, y);
  818. }
  819. /**
  820. * Gets a new Vector2 set with the transformed coordinates of the given vector by the given transformation matrix
  821. * Example Playground https://playground.babylonjs.com/#QYBWV4#17
  822. * @param vector defines the vector to transform
  823. * @param transformation defines the matrix to apply
  824. * @returns a new Vector2
  825. */
  826. static Transform(vector, transformation) {
  827. const result = new vector.constructor();
  828. Vector2.TransformToRef(vector, transformation, result);
  829. return result;
  830. }
  831. /**
  832. * Transforms the given vector coordinates by the given transformation matrix and stores the result in the vector "result" coordinates
  833. * Example Playground https://playground.babylonjs.com/#QYBWV4#19
  834. * @param vector defines the vector to transform
  835. * @param transformation defines the matrix to apply
  836. * @param result defines the target vector
  837. * @returns result input
  838. */
  839. static TransformToRef(vector, transformation, result) {
  840. const m = transformation.m;
  841. const x = vector.x * m[0] + vector.y * m[4] + m[12];
  842. const y = vector.x * m[1] + vector.y * m[5] + m[13];
  843. result.x = x;
  844. result.y = y;
  845. return result;
  846. }
  847. /**
  848. * Determines if a given vector is included in a triangle
  849. * Example Playground https://playground.babylonjs.com/#QYBWV4#87
  850. * @param p defines the vector to test
  851. * @param p0 defines 1st triangle point
  852. * @param p1 defines 2nd triangle point
  853. * @param p2 defines 3rd triangle point
  854. * @returns true if the point "p" is in the triangle defined by the vectors "p0", "p1", "p2"
  855. */
  856. static PointInTriangle(p, p0, p1, p2) {
  857. const a = (1 / 2) * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
  858. const sign = a < 0 ? -1 : 1;
  859. const s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
  860. const t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
  861. return s > 0 && t > 0 && s + t < 2 * a * sign;
  862. }
  863. /**
  864. * Gets the distance between the vectors "value1" and "value2"
  865. * Example Playground https://playground.babylonjs.com/#QYBWV4#71
  866. * @param value1 defines first vector
  867. * @param value2 defines second vector
  868. * @returns the distance between vectors
  869. */
  870. static Distance(value1, value2) {
  871. return Math.sqrt(Vector2.DistanceSquared(value1, value2));
  872. }
  873. /**
  874. * Returns the squared distance between the vectors "value1" and "value2"
  875. * Example Playground https://playground.babylonjs.com/#QYBWV4#72
  876. * @param value1 defines first vector
  877. * @param value2 defines second vector
  878. * @returns the squared distance between vectors
  879. */
  880. static DistanceSquared(value1, value2) {
  881. const x = value1.x - value2.x;
  882. const y = value1.y - value2.y;
  883. return x * x + y * y;
  884. }
  885. /**
  886. * Gets a new Vector2 located at the center of the vectors "value1" and "value2"
  887. * Example Playground https://playground.babylonjs.com/#QYBWV4#86
  888. * Example Playground https://playground.babylonjs.com/#QYBWV4#66
  889. * @param value1 defines first vector
  890. * @param value2 defines second vector
  891. * @returns a new Vector2
  892. */
  893. static Center(value1, value2) {
  894. const result = new value1.constructor();
  895. return Vector2.CenterToRef(value1, value2, result);
  896. }
  897. /**
  898. * Gets the center of the vectors "value1" and "value2" and stores the result in the vector "ref"
  899. * Example Playground https://playground.babylonjs.com/#QYBWV4#66
  900. * @param value1 defines first vector
  901. * @param value2 defines second vector
  902. * @param ref defines third vector
  903. * @returns ref
  904. */
  905. static CenterToRef(value1, value2, ref) {
  906. return ref.copyFromFloats((value1.x + value2.x) / 2, (value1.y + value2.y) / 2);
  907. }
  908. /**
  909. * Gets the shortest distance (float) between the point "p" and the segment defined by the two points "segA" and "segB".
  910. * Example Playground https://playground.babylonjs.com/#QYBWV4#77
  911. * @param p defines the middle point
  912. * @param segA defines one point of the segment
  913. * @param segB defines the other point of the segment
  914. * @returns the shortest distance
  915. */
  916. static DistanceOfPointFromSegment(p, segA, segB) {
  917. const l2 = Vector2.DistanceSquared(segA, segB);
  918. if (l2 === 0.0) {
  919. return Vector2.Distance(p, segA);
  920. }
  921. const v = segB.subtract(segA);
  922. const t = Math.max(0, Math.min(1, Vector2.Dot(p.subtract(segA), v) / l2));
  923. const proj = segA.add(v.multiplyByFloats(t, t));
  924. return Vector2.Distance(p, proj);
  925. }
  926. }
  927. Vector2._ZeroReadOnly = Vector2.Zero();
  928. Vector2;
  929. Object.defineProperties(Vector2.prototype, {
  930. dimension: { value: [2] },
  931. rank: { value: 1 },
  932. });
  933. /**
  934. * Class used to store (x,y,z) vector representation
  935. * A Vector3 is the main object used in 3D geometry
  936. * It can represent either the coordinates of a point the space, either a direction
  937. * Reminder: js uses a left handed forward facing system
  938. * Example Playground - Overview - https://playground.babylonjs.com/#R1F8YU
  939. */
  940. export class Vector3 {
  941. /** Gets or sets the x coordinate */
  942. get x() {
  943. return this._x;
  944. }
  945. set x(value) {
  946. this._x = value;
  947. this._isDirty = true;
  948. }
  949. /** Gets or sets the y coordinate */
  950. get y() {
  951. return this._y;
  952. }
  953. set y(value) {
  954. this._y = value;
  955. this._isDirty = true;
  956. }
  957. /** Gets or sets the z coordinate */
  958. get z() {
  959. return this._z;
  960. }
  961. set z(value) {
  962. this._z = value;
  963. this._isDirty = true;
  964. }
  965. /**
  966. * Creates a new Vector3 object from the given x, y, z (floats) coordinates.
  967. * @param x defines the first coordinates (on X axis)
  968. * @param y defines the second coordinates (on Y axis)
  969. * @param z defines the third coordinates (on Z axis)
  970. */
  971. constructor(x = 0, y = 0, z = 0) {
  972. /** @internal */
  973. this._isDirty = true;
  974. this._x = x;
  975. this._y = y;
  976. this._z = z;
  977. }
  978. /**
  979. * Creates a string representation of the Vector3
  980. * Example Playground https://playground.babylonjs.com/#R1F8YU#67
  981. * @returns a string with the Vector3 coordinates.
  982. */
  983. toString() {
  984. return `{X: ${this._x} Y: ${this._y} Z: ${this._z}}`;
  985. }
  986. /**
  987. * Gets the class name
  988. * @returns the string "Vector3"
  989. */
  990. getClassName() {
  991. return "Vector3";
  992. }
  993. /**
  994. * Creates the Vector3 hash code
  995. * @returns a number which tends to be unique between Vector3 instances
  996. */
  997. getHashCode() {
  998. const x = _ExtractAsInt(this._x);
  999. const y = _ExtractAsInt(this._y);
  1000. const z = _ExtractAsInt(this._z);
  1001. let hash = x;
  1002. hash = (hash * 397) ^ y;
  1003. hash = (hash * 397) ^ z;
  1004. return hash;
  1005. }
  1006. // Operators
  1007. /**
  1008. * Creates an array containing three elements : the coordinates of the Vector3
  1009. * Example Playground https://playground.babylonjs.com/#R1F8YU#10
  1010. * @returns a new array of numbers
  1011. */
  1012. asArray() {
  1013. return [this._x, this._y, this._z];
  1014. }
  1015. /**
  1016. * Populates the given array or Float32Array from the given index with the successive coordinates of the Vector3
  1017. * Example Playground https://playground.babylonjs.com/#R1F8YU#65
  1018. * @param array defines the destination array
  1019. * @param index defines the offset in the destination array
  1020. * @returns the current Vector3
  1021. */
  1022. toArray(array, index = 0) {
  1023. array[index] = this._x;
  1024. array[index + 1] = this._y;
  1025. array[index + 2] = this._z;
  1026. return this;
  1027. }
  1028. /**
  1029. * Update the current vector from an array
  1030. * Example Playground https://playground.babylonjs.com/#R1F8YU#24
  1031. * @param array defines the destination array
  1032. * @param offset defines the offset in the destination array
  1033. * @returns the current Vector3
  1034. */
  1035. fromArray(array, offset = 0) {
  1036. Vector3.FromArrayToRef(array, offset, this);
  1037. return this;
  1038. }
  1039. /**
  1040. * Converts the current Vector3 into a quaternion (considering that the Vector3 contains Euler angles representation of a rotation)
  1041. * Example Playground https://playground.babylonjs.com/#R1F8YU#66
  1042. * @returns a new Quaternion object, computed from the Vector3 coordinates
  1043. */
  1044. toQuaternion() {
  1045. return Quaternion.RotationYawPitchRoll(this._y, this._x, this._z);
  1046. }
  1047. /**
  1048. * Adds the given vector to the current Vector3
  1049. * Example Playground https://playground.babylonjs.com/#R1F8YU#4
  1050. * @param otherVector defines the second operand
  1051. * @returns the current updated Vector3
  1052. */
  1053. addInPlace(otherVector) {
  1054. this._x += otherVector._x;
  1055. this._y += otherVector._y;
  1056. this._z += otherVector._z;
  1057. this._isDirty = true;
  1058. return this;
  1059. }
  1060. /**
  1061. * Adds the given coordinates to the current Vector3
  1062. * Example Playground https://playground.babylonjs.com/#R1F8YU#5
  1063. * @param x defines the x coordinate of the operand
  1064. * @param y defines the y coordinate of the operand
  1065. * @param z defines the z coordinate of the operand
  1066. * @returns the current updated Vector3
  1067. */
  1068. addInPlaceFromFloats(x, y, z) {
  1069. this._x += x;
  1070. this._y += y;
  1071. this._z += z;
  1072. this._isDirty = true;
  1073. return this;
  1074. }
  1075. /**
  1076. * Gets a new Vector3, result of the addition the current Vector3 and the given vector
  1077. * Example Playground https://playground.babylonjs.com/#R1F8YU#3
  1078. * @param otherVector defines the second operand
  1079. * @returns the resulting Vector3
  1080. */
  1081. add(otherVector) {
  1082. return new this.constructor(this._x + otherVector._x, this._y + otherVector._y, this._z + otherVector._z);
  1083. }
  1084. /**
  1085. * Adds the current Vector3 to the given one and stores the result in the vector "result"
  1086. * Example Playground https://playground.babylonjs.com/#R1F8YU#6
  1087. * @param otherVector defines the second operand
  1088. * @param result defines the Vector3 object where to store the result
  1089. * @returns the result
  1090. */
  1091. addToRef(otherVector, result) {
  1092. return result.copyFromFloats(this._x + otherVector._x, this._y + otherVector._y, this._z + otherVector._z);
  1093. }
  1094. /**
  1095. * Subtract the given vector from the current Vector3
  1096. * Example Playground https://playground.babylonjs.com/#R1F8YU#61
  1097. * @param otherVector defines the second operand
  1098. * @returns the current updated Vector3
  1099. */
  1100. subtractInPlace(otherVector) {
  1101. this._x -= otherVector._x;
  1102. this._y -= otherVector._y;
  1103. this._z -= otherVector._z;
  1104. this._isDirty = true;
  1105. return this;
  1106. }
  1107. /**
  1108. * Returns a new Vector3, result of the subtraction of the given vector from the current Vector3
  1109. * Example Playground https://playground.babylonjs.com/#R1F8YU#60
  1110. * @param otherVector defines the second operand
  1111. * @returns the resulting Vector3
  1112. */
  1113. subtract(otherVector) {
  1114. return new this.constructor(this._x - otherVector._x, this._y - otherVector._y, this._z - otherVector._z);
  1115. }
  1116. /**
  1117. * Subtracts the given vector from the current Vector3 and stores the result in the vector "result".
  1118. * Example Playground https://playground.babylonjs.com/#R1F8YU#63
  1119. * @param otherVector defines the second operand
  1120. * @param result defines the Vector3 object where to store the result
  1121. * @returns the result
  1122. */
  1123. subtractToRef(otherVector, result) {
  1124. return this.subtractFromFloatsToRef(otherVector._x, otherVector._y, otherVector._z, result);
  1125. }
  1126. /**
  1127. * Returns a new Vector3 set with the subtraction of the given floats from the current Vector3 coordinates
  1128. * Example Playground https://playground.babylonjs.com/#R1F8YU#62
  1129. * @param x defines the x coordinate of the operand
  1130. * @param y defines the y coordinate of the operand
  1131. * @param z defines the z coordinate of the operand
  1132. * @returns the resulting Vector3
  1133. */
  1134. subtractFromFloats(x, y, z) {
  1135. return new this.constructor(this._x - x, this._y - y, this._z - z);
  1136. }
  1137. /**
  1138. * Subtracts the given floats from the current Vector3 coordinates and set the given vector "result" with this result
  1139. * Example Playground https://playground.babylonjs.com/#R1F8YU#64
  1140. * @param x defines the x coordinate of the operand
  1141. * @param y defines the y coordinate of the operand
  1142. * @param z defines the z coordinate of the operand
  1143. * @param result defines the Vector3 object where to store the result
  1144. * @returns the result
  1145. */
  1146. subtractFromFloatsToRef(x, y, z, result) {
  1147. return result.copyFromFloats(this._x - x, this._y - y, this._z - z);
  1148. }
  1149. /**
  1150. * Gets a new Vector3 set with the current Vector3 negated coordinates
  1151. * Example Playground https://playground.babylonjs.com/#R1F8YU#35
  1152. * @returns a new Vector3
  1153. */
  1154. negate() {
  1155. return new this.constructor(-this._x, -this._y, -this._z);
  1156. }
  1157. /**
  1158. * Negate this vector in place
  1159. * Example Playground https://playground.babylonjs.com/#R1F8YU#36
  1160. * @returns this
  1161. */
  1162. negateInPlace() {
  1163. this._x *= -1;
  1164. this._y *= -1;
  1165. this._z *= -1;
  1166. this._isDirty = true;
  1167. return this;
  1168. }
  1169. /**
  1170. * Negate the current Vector3 and stores the result in the given vector "result" coordinates
  1171. * Example Playground https://playground.babylonjs.com/#R1F8YU#37
  1172. * @param result defines the Vector3 object where to store the result
  1173. * @returns the result
  1174. */
  1175. negateToRef(result) {
  1176. return result.copyFromFloats(this._x * -1, this._y * -1, this._z * -1);
  1177. }
  1178. /**
  1179. * Multiplies the Vector3 coordinates by the float "scale"
  1180. * Example Playground https://playground.babylonjs.com/#R1F8YU#56
  1181. * @param scale defines the multiplier factor
  1182. * @returns the current updated Vector3
  1183. */
  1184. scaleInPlace(scale) {
  1185. this._x *= scale;
  1186. this._y *= scale;
  1187. this._z *= scale;
  1188. this._isDirty = true;
  1189. return this;
  1190. }
  1191. /**
  1192. * Returns a new Vector3 set with the current Vector3 coordinates multiplied by the float "scale"
  1193. * Example Playground https://playground.babylonjs.com/#R1F8YU#53
  1194. * @param scale defines the multiplier factor
  1195. * @returns a new Vector3
  1196. */
  1197. scale(scale) {
  1198. return new this.constructor(this._x * scale, this._y * scale, this._z * scale);
  1199. }
  1200. /**
  1201. * Multiplies the current Vector3 coordinates by the float "scale" and stores the result in the given vector "result" coordinates
  1202. * Example Playground https://playground.babylonjs.com/#R1F8YU#57
  1203. * @param scale defines the multiplier factor
  1204. * @param result defines the Vector3 object where to store the result
  1205. * @returns the result
  1206. */
  1207. scaleToRef(scale, result) {
  1208. return result.copyFromFloats(this._x * scale, this._y * scale, this._z * scale);
  1209. }
  1210. /**
  1211. * Creates a vector normal (perpendicular) to the current Vector3 and stores the result in the given vector
  1212. * Out of the infinite possibilities the normal chosen is the one formed by rotating the current vector
  1213. * 90 degrees about an axis which lies perpendicular to the current vector
  1214. * and its projection on the xz plane. In the case of a current vector in the xz plane
  1215. * the normal is calculated to be along the y axis.
  1216. * Example Playground https://playground.babylonjs.com/#R1F8YU#230
  1217. * Example Playground https://playground.babylonjs.com/#R1F8YU#231
  1218. * @param result defines the Vector3 object where to store the resultant normal
  1219. * @returns the result
  1220. */
  1221. getNormalToRef(result) {
  1222. /**
  1223. * Calculates the spherical coordinates of the current vector
  1224. * so saves on memory rather than importing whole Spherical Class
  1225. */
  1226. const radius = this.length();
  1227. let theta = Math.acos(this.y / radius);
  1228. const phi = Math.atan2(this.z, this.x);
  1229. //makes angle 90 degs to current vector
  1230. if (theta > Math.PI / 2) {
  1231. theta -= Math.PI / 2;
  1232. }
  1233. else {
  1234. theta += Math.PI / 2;
  1235. }
  1236. //Calculates resutant normal vector from spherical coordinate of perpendicular vector
  1237. const x = radius * Math.sin(theta) * Math.cos(phi);
  1238. const y = radius * Math.cos(theta);
  1239. const z = radius * Math.sin(theta) * Math.sin(phi);
  1240. result.set(x, y, z);
  1241. return result;
  1242. }
  1243. /**
  1244. * Rotates the vector using the given unit quaternion and stores the new vector in result
  1245. * Example Playground https://playground.babylonjs.com/#R1F8YU#9
  1246. * @param q the unit quaternion representing the rotation
  1247. * @param result the output vector
  1248. * @returns the result
  1249. */
  1250. applyRotationQuaternionToRef(q, result) {
  1251. // Derived from https://raw.org/proof/vector-rotation-using-quaternions/
  1252. const vx = this._x, vy = this._y, vz = this._z;
  1253. const qx = q._x, qy = q._y, qz = q._z, qw = q._w;
  1254. // t = 2q x v
  1255. const tx = 2 * (qy * vz - qz * vy);
  1256. const ty = 2 * (qz * vx - qx * vz);
  1257. const tz = 2 * (qx * vy - qy * vx);
  1258. // v + w t + q x t
  1259. result._x = vx + qw * tx + qy * tz - qz * ty;
  1260. result._y = vy + qw * ty + qz * tx - qx * tz;
  1261. result._z = vz + qw * tz + qx * ty - qy * tx;
  1262. result._isDirty = true;
  1263. return result;
  1264. }
  1265. /**
  1266. * Rotates the vector in place using the given unit quaternion
  1267. * Example Playground https://playground.babylonjs.com/#R1F8YU#8
  1268. * @param q the unit quaternion representing the rotation
  1269. * @returns the current updated Vector3
  1270. */
  1271. applyRotationQuaternionInPlace(q) {
  1272. return this.applyRotationQuaternionToRef(q, this);
  1273. }
  1274. /**
  1275. * Rotates the vector using the given unit quaternion and returns the new vector
  1276. * Example Playground https://playground.babylonjs.com/#R1F8YU#7
  1277. * @param q the unit quaternion representing the rotation
  1278. * @returns a new Vector3
  1279. */
  1280. applyRotationQuaternion(q) {
  1281. return this.applyRotationQuaternionToRef(q, new this.constructor());
  1282. }
  1283. /**
  1284. * Scale the current Vector3 values by a factor and add the result to a given Vector3
  1285. * Example Playground https://playground.babylonjs.com/#R1F8YU#55
  1286. * @param scale defines the scale factor
  1287. * @param result defines the Vector3 object where to store the result
  1288. * @returns result input
  1289. */
  1290. scaleAndAddToRef(scale, result) {
  1291. return result.addInPlaceFromFloats(this._x * scale, this._y * scale, this._z * scale);
  1292. }
  1293. /**
  1294. * Projects the current point Vector3 to a plane along a ray starting from a specified origin and passing through the current point Vector3.
  1295. * Example Playground https://playground.babylonjs.com/#R1F8YU#48
  1296. * @param plane defines the plane to project to
  1297. * @param origin defines the origin of the projection ray
  1298. * @returns the projected vector3
  1299. */
  1300. projectOnPlane(plane, origin) {
  1301. const result = new this.constructor();
  1302. this.projectOnPlaneToRef(plane, origin, result);
  1303. return result;
  1304. }
  1305. /**
  1306. * Projects the current point Vector3 to a plane along a ray starting from a specified origin and passing through the current point Vector3.
  1307. * Example Playground https://playground.babylonjs.com/#R1F8YU#49
  1308. * @param plane defines the plane to project to
  1309. * @param origin defines the origin of the projection ray
  1310. * @param result defines the Vector3 where to store the result
  1311. * @returns result input
  1312. */
  1313. projectOnPlaneToRef(plane, origin, result) {
  1314. const n = plane.normal;
  1315. const d = plane.d;
  1316. const V = MathTmp.Vector3[0];
  1317. // ray direction
  1318. this.subtractToRef(origin, V);
  1319. V.normalize();
  1320. const denom = Vector3.Dot(V, n);
  1321. //When the ray is close to parallel to the plane return infinity vector
  1322. if (Math.abs(denom) < 0.0000000001) {
  1323. result.setAll(Infinity);
  1324. }
  1325. else {
  1326. const t = -(Vector3.Dot(origin, n) + d) / denom;
  1327. // P = P0 + t*V
  1328. const scaledV = V.scaleInPlace(t);
  1329. origin.addToRef(scaledV, result);
  1330. }
  1331. return result;
  1332. }
  1333. /**
  1334. * Returns true if the current Vector3 and the given vector coordinates are strictly equal
  1335. * Example Playground https://playground.babylonjs.com/#R1F8YU#19
  1336. * @param otherVector defines the second operand
  1337. * @returns true if both vectors are equals
  1338. */
  1339. equals(otherVector) {
  1340. return otherVector && this._x === otherVector._x && this._y === otherVector._y && this._z === otherVector._z;
  1341. }
  1342. /**
  1343. * Returns true if the current Vector3 and the given vector coordinates are distant less than epsilon
  1344. * Example Playground https://playground.babylonjs.com/#R1F8YU#21
  1345. * @param otherVector defines the second operand
  1346. * @param epsilon defines the minimal distance to define values as equals
  1347. * @returns true if both vectors are distant less than epsilon
  1348. */
  1349. equalsWithEpsilon(otherVector, epsilon = Epsilon) {
  1350. return otherVector && WithinEpsilon(this._x, otherVector._x, epsilon) && WithinEpsilon(this._y, otherVector._y, epsilon) && WithinEpsilon(this._z, otherVector._z, epsilon);
  1351. }
  1352. /**
  1353. * Returns true if the current Vector3 coordinates equals the given floats
  1354. * Example Playground https://playground.babylonjs.com/#R1F8YU#20
  1355. * @param x defines the x coordinate of the operand
  1356. * @param y defines the y coordinate of the operand
  1357. * @param z defines the z coordinate of the operand
  1358. * @returns true if both vectors are equal
  1359. */
  1360. equalsToFloats(x, y, z) {
  1361. return this._x === x && this._y === y && this._z === z;
  1362. }
  1363. /**
  1364. * Multiplies the current Vector3 coordinates by the given ones
  1365. * Example Playground https://playground.babylonjs.com/#R1F8YU#32
  1366. * @param otherVector defines the second operand
  1367. * @returns the current updated Vector3
  1368. */
  1369. multiplyInPlace(otherVector) {
  1370. this._x *= otherVector._x;
  1371. this._y *= otherVector._y;
  1372. this._z *= otherVector._z;
  1373. this._isDirty = true;
  1374. return this;
  1375. }
  1376. /**
  1377. * Returns a new Vector3, result of the multiplication of the current Vector3 by the given vector
  1378. * Example Playground https://playground.babylonjs.com/#R1F8YU#31
  1379. * @param otherVector defines the second operand
  1380. * @returns the new Vector3
  1381. */
  1382. multiply(otherVector) {
  1383. return this.multiplyByFloats(otherVector._x, otherVector._y, otherVector._z);
  1384. }
  1385. /**
  1386. * Multiplies the current Vector3 by the given one and stores the result in the given vector "result"
  1387. * Example Playground https://playground.babylonjs.com/#R1F8YU#33
  1388. * @param otherVector defines the second operand
  1389. * @param result defines the Vector3 object where to store the result
  1390. * @returns the result
  1391. */
  1392. multiplyToRef(otherVector, result) {
  1393. return result.copyFromFloats(this._x * otherVector._x, this._y * otherVector._y, this._z * otherVector._z);
  1394. }
  1395. /**
  1396. * Returns a new Vector3 set with the result of the multiplication of the current Vector3 coordinates by the given floats
  1397. * Example Playground https://playground.babylonjs.com/#R1F8YU#34
  1398. * @param x defines the x coordinate of the operand
  1399. * @param y defines the y coordinate of the operand
  1400. * @param z defines the z coordinate of the operand
  1401. * @returns the new Vector3
  1402. */
  1403. multiplyByFloats(x, y, z) {
  1404. return new this.constructor(this._x * x, this._y * y, this._z * z);
  1405. }
  1406. /**
  1407. * Returns a new Vector3 set with the result of the division of the current Vector3 coordinates by the given ones
  1408. * Example Playground https://playground.babylonjs.com/#R1F8YU#16
  1409. * @param otherVector defines the second operand
  1410. * @returns the new Vector3
  1411. */
  1412. divide(otherVector) {
  1413. return new this.constructor(this._x / otherVector._x, this._y / otherVector._y, this._z / otherVector._z);
  1414. }
  1415. /**
  1416. * Divides the current Vector3 coordinates by the given ones and stores the result in the given vector "result"
  1417. * Example Playground https://playground.babylonjs.com/#R1F8YU#18
  1418. * @param otherVector defines the second operand
  1419. * @param result defines the Vector3 object where to store the result
  1420. * @returns the result
  1421. */
  1422. divideToRef(otherVector, result) {
  1423. return result.copyFromFloats(this._x / otherVector._x, this._y / otherVector._y, this._z / otherVector._z);
  1424. }
  1425. /**
  1426. * Divides the current Vector3 coordinates by the given ones.
  1427. * Example Playground https://playground.babylonjs.com/#R1F8YU#17
  1428. * @param otherVector defines the second operand
  1429. * @returns the current updated Vector3
  1430. */
  1431. divideInPlace(otherVector) {
  1432. this._x = this._x / otherVector._x;
  1433. this._y = this._y / otherVector._y;
  1434. this._z = this._z / otherVector._z;
  1435. this._isDirty = true;
  1436. return this;
  1437. }
  1438. /**
  1439. * Updates the current Vector3 with the minimal coordinate values between its and the given vector ones
  1440. * Example Playground https://playground.babylonjs.com/#R1F8YU#29
  1441. * @param other defines the second operand
  1442. * @returns the current updated Vector3
  1443. */
  1444. minimizeInPlace(other) {
  1445. return this.minimizeInPlaceFromFloats(other._x, other._y, other._z);
  1446. }
  1447. /**
  1448. * Updates the current Vector3 with the maximal coordinate values between its and the given vector ones.
  1449. * Example Playground https://playground.babylonjs.com/#R1F8YU#27
  1450. * @param other defines the second operand
  1451. * @returns the current updated Vector3
  1452. */
  1453. maximizeInPlace(other) {
  1454. return this.maximizeInPlaceFromFloats(other._x, other._y, other._z);
  1455. }
  1456. /**
  1457. * Updates the current Vector3 with the minimal coordinate values between its and the given coordinates
  1458. * Example Playground https://playground.babylonjs.com/#R1F8YU#30
  1459. * @param x defines the x coordinate of the operand
  1460. * @param y defines the y coordinate of the operand
  1461. * @param z defines the z coordinate of the operand
  1462. * @returns the current updated Vector3
  1463. */
  1464. minimizeInPlaceFromFloats(x, y, z) {
  1465. if (x < this._x) {
  1466. this.x = x;
  1467. }
  1468. if (y < this._y) {
  1469. this.y = y;
  1470. }
  1471. if (z < this._z) {
  1472. this.z = z;
  1473. }
  1474. return this;
  1475. }
  1476. /**
  1477. * Updates the current Vector3 with the maximal coordinate values between its and the given coordinates.
  1478. * Example Playground https://playground.babylonjs.com/#R1F8YU#28
  1479. * @param x defines the x coordinate of the operand
  1480. * @param y defines the y coordinate of the operand
  1481. * @param z defines the z coordinate of the operand
  1482. * @returns the current updated Vector3
  1483. */
  1484. maximizeInPlaceFromFloats(x, y, z) {
  1485. if (x > this._x) {
  1486. this.x = x;
  1487. }
  1488. if (y > this._y) {
  1489. this.y = y;
  1490. }
  1491. if (z > this._z) {
  1492. this.z = z;
  1493. }
  1494. return this;
  1495. }
  1496. /**
  1497. * Due to float precision, scale of a mesh could be uniform but float values are off by a small fraction
  1498. * Check if is non uniform within a certain amount of decimal places to account for this
  1499. * @param epsilon the amount the values can differ
  1500. * @returns if the vector is non uniform to a certain number of decimal places
  1501. */
  1502. isNonUniformWithinEpsilon(epsilon) {
  1503. const absX = Math.abs(this._x);
  1504. const absY = Math.abs(this._y);
  1505. if (!WithinEpsilon(absX, absY, epsilon)) {
  1506. return true;
  1507. }
  1508. const absZ = Math.abs(this._z);
  1509. if (!WithinEpsilon(absX, absZ, epsilon)) {
  1510. return true;
  1511. }
  1512. if (!WithinEpsilon(absY, absZ, epsilon)) {
  1513. return true;
  1514. }
  1515. return false;
  1516. }
  1517. /**
  1518. * Gets a boolean indicating that the vector is non uniform meaning x, y or z are not all the same
  1519. */
  1520. get isNonUniform() {
  1521. const absX = Math.abs(this._x);
  1522. const absY = Math.abs(this._y);
  1523. if (absX !== absY) {
  1524. return true;
  1525. }
  1526. const absZ = Math.abs(this._z);
  1527. if (absX !== absZ) {
  1528. return true;
  1529. }
  1530. return false;
  1531. }
  1532. /**
  1533. * Gets the current Vector3's floored values and stores them in result
  1534. * @param result the vector to store the result in
  1535. * @returns the result vector
  1536. */
  1537. floorToRef(result) {
  1538. result._x = Math.floor(this._x);
  1539. result._y = Math.floor(this._y);
  1540. result._z = Math.floor(this._z);
  1541. result._isDirty = true;
  1542. return result;
  1543. }
  1544. /**
  1545. * Gets a new Vector3 from current Vector3 floored values
  1546. * Example Playground https://playground.babylonjs.com/#R1F8YU#22
  1547. * @returns a new Vector3
  1548. */
  1549. floor() {
  1550. return new this.constructor(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z));
  1551. }
  1552. /**
  1553. * Gets the current Vector3's fractional values and stores them in result
  1554. * @param result the vector to store the result in
  1555. * @returns the result vector
  1556. */
  1557. fractToRef(result) {
  1558. result._x = this.x - Math.floor(this._x);
  1559. result._y = this.y - Math.floor(this._y);
  1560. result._z = this.z - Math.floor(this._z);
  1561. result._isDirty = true;
  1562. return result;
  1563. }
  1564. /**
  1565. * Gets a new Vector3 from current Vector3 fractional values
  1566. * Example Playground https://playground.babylonjs.com/#R1F8YU#23
  1567. * @returns a new Vector3
  1568. */
  1569. fract() {
  1570. return new this.constructor(this.x - Math.floor(this._x), this.y - Math.floor(this._y), this.z - Math.floor(this._z));
  1571. }
  1572. // Properties
  1573. /**
  1574. * Gets the length of the Vector3
  1575. * Example Playground https://playground.babylonjs.com/#R1F8YU#25
  1576. * @returns the length of the Vector3
  1577. */
  1578. length() {
  1579. return Math.sqrt(this.lengthSquared());
  1580. }
  1581. /**
  1582. * Gets the squared length of the Vector3
  1583. * Example Playground https://playground.babylonjs.com/#R1F8YU#26
  1584. * @returns squared length of the Vector3
  1585. */
  1586. lengthSquared() {
  1587. return this._x * this._x + this._y * this._y + this._z * this._z;
  1588. }
  1589. /**
  1590. * Gets a boolean indicating if the vector contains a zero in one of its components
  1591. * Example Playground https://playground.babylonjs.com/#R1F8YU#1
  1592. */
  1593. get hasAZeroComponent() {
  1594. return this._x * this._y * this._z === 0;
  1595. }
  1596. /**
  1597. * Normalize the current Vector3.
  1598. * Please note that this is an in place operation.
  1599. * Example Playground https://playground.babylonjs.com/#R1F8YU#122
  1600. * @returns the current updated Vector3
  1601. */
  1602. normalize() {
  1603. return this.normalizeFromLength(this.length());
  1604. }
  1605. /**
  1606. * Reorders the x y z properties of the vector in place
  1607. * Example Playground https://playground.babylonjs.com/#R1F8YU#44
  1608. * @param order new ordering of the properties (eg. for vector 1,2,3 with "ZYX" will produce 3,2,1)
  1609. * @returns the current updated vector
  1610. */
  1611. reorderInPlace(order) {
  1612. order = order.toLowerCase();
  1613. if (order === "xyz") {
  1614. return this;
  1615. }
  1616. const tem = MathTmp.Vector3[0].copyFrom(this);
  1617. this.x = tem[order[0]];
  1618. this.y = tem[order[1]];
  1619. this.z = tem[order[2]];
  1620. return this;
  1621. }
  1622. /**
  1623. * Rotates the vector around 0,0,0 by a quaternion
  1624. * Example Playground https://playground.babylonjs.com/#R1F8YU#47
  1625. * @param quaternion the rotation quaternion
  1626. * @param result vector to store the result
  1627. * @returns the resulting vector
  1628. */
  1629. rotateByQuaternionToRef(quaternion, result) {
  1630. quaternion.toRotationMatrix(MathTmp.Matrix[0]);
  1631. Vector3.TransformCoordinatesToRef(this, MathTmp.Matrix[0], result);
  1632. return result;
  1633. }
  1634. /**
  1635. * Rotates a vector around a given point
  1636. * Example Playground https://playground.babylonjs.com/#R1F8YU#46
  1637. * @param quaternion the rotation quaternion
  1638. * @param point the point to rotate around
  1639. * @param result vector to store the result
  1640. * @returns the resulting vector
  1641. */
  1642. rotateByQuaternionAroundPointToRef(quaternion, point, result) {
  1643. this.subtractToRef(point, MathTmp.Vector3[0]);
  1644. MathTmp.Vector3[0].rotateByQuaternionToRef(quaternion, MathTmp.Vector3[0]);
  1645. point.addToRef(MathTmp.Vector3[0], result);
  1646. return result;
  1647. }
  1648. /**
  1649. * Returns a new Vector3 as the cross product of the current vector and the "other" one
  1650. * The cross product is then orthogonal to both current and "other"
  1651. * Example Playground https://playground.babylonjs.com/#R1F8YU#14
  1652. * @param other defines the right operand
  1653. * @returns the cross product
  1654. */
  1655. cross(other) {
  1656. const result = new this.constructor();
  1657. return Vector3.CrossToRef(this, other, result);
  1658. }
  1659. /**
  1660. * Normalize the current Vector3 with the given input length.
  1661. * Please note that this is an in place operation.
  1662. * Example Playground https://playground.babylonjs.com/#R1F8YU#123
  1663. * @param len the length of the vector
  1664. * @returns the current updated Vector3
  1665. */
  1666. normalizeFromLength(len) {
  1667. if (len === 0 || len === 1.0) {
  1668. return this;
  1669. }
  1670. return this.scaleInPlace(1.0 / len);
  1671. }
  1672. /**
  1673. * Normalize the current Vector3 to a new vector
  1674. * Example Playground https://playground.babylonjs.com/#R1F8YU#124
  1675. * @returns the new Vector3
  1676. */
  1677. normalizeToNew() {
  1678. const normalized = new this.constructor(0, 0, 0);
  1679. this.normalizeToRef(normalized);
  1680. return normalized;
  1681. }
  1682. /**
  1683. * Normalize the current Vector3 to the reference
  1684. * Example Playground https://playground.babylonjs.com/#R1F8YU#125
  1685. * @param reference define the Vector3 to update
  1686. * @returns the updated Vector3
  1687. */
  1688. normalizeToRef(reference) {
  1689. const len = this.length();
  1690. if (len === 0 || len === 1.0) {
  1691. return reference.copyFrom(this);
  1692. }
  1693. return this.scaleToRef(1.0 / len, reference);
  1694. }
  1695. /**
  1696. * Creates a new Vector3 copied from the current Vector3
  1697. * Example Playground https://playground.babylonjs.com/#R1F8YU#11
  1698. * @returns the new Vector3
  1699. */
  1700. clone() {
  1701. return new this.constructor(this._x, this._y, this._z);
  1702. }
  1703. /**
  1704. * Copies the given vector coordinates to the current Vector3 ones
  1705. * Example Playground https://playground.babylonjs.com/#R1F8YU#12
  1706. * @param source defines the source Vector3
  1707. * @returns the current updated Vector3
  1708. */
  1709. copyFrom(source) {
  1710. return this.copyFromFloats(source._x, source._y, source._z);
  1711. }
  1712. /**
  1713. * Copies the given floats to the current Vector3 coordinates
  1714. * Example Playground https://playground.babylonjs.com/#R1F8YU#13
  1715. * @param x defines the x coordinate of the operand
  1716. * @param y defines the y coordinate of the operand
  1717. * @param z defines the z coordinate of the operand
  1718. * @returns the current updated Vector3
  1719. */
  1720. copyFromFloats(x, y, z) {
  1721. this._x = x;
  1722. this._y = y;
  1723. this._z = z;
  1724. this._isDirty = true;
  1725. return this;
  1726. }
  1727. /**
  1728. * Copies the given floats to the current Vector3 coordinates
  1729. * Example Playground https://playground.babylonjs.com/#R1F8YU#58
  1730. * @param x defines the x coordinate of the operand
  1731. * @param y defines the y coordinate of the operand
  1732. * @param z defines the z coordinate of the operand
  1733. * @returns the current updated Vector3
  1734. */
  1735. set(x, y, z) {
  1736. return this.copyFromFloats(x, y, z);
  1737. }
  1738. /**
  1739. * Copies the given float to the current Vector3 coordinates
  1740. * Example Playground https://playground.babylonjs.com/#R1F8YU#59
  1741. * @param v defines the x, y and z coordinates of the operand
  1742. * @returns the current updated Vector3
  1743. */
  1744. setAll(v) {
  1745. this._x = this._y = this._z = v;
  1746. this._isDirty = true;
  1747. return this;
  1748. }
  1749. // Statics
  1750. /**
  1751. * Get the clip factor between two vectors
  1752. * Example Playground https://playground.babylonjs.com/#R1F8YU#126
  1753. * @param vector0 defines the first operand
  1754. * @param vector1 defines the second operand
  1755. * @param axis defines the axis to use
  1756. * @param size defines the size along the axis
  1757. * @returns the clip factor
  1758. */
  1759. static GetClipFactor(vector0, vector1, axis, size) {
  1760. const d0 = Vector3.Dot(vector0, axis);
  1761. const d1 = Vector3.Dot(vector1, axis);
  1762. return (d0 - size) / (d0 - d1);
  1763. }
  1764. /**
  1765. * Get angle between two vectors
  1766. * Example Playground https://playground.babylonjs.com/#R1F8YU#86
  1767. * @param vector0 the starting point
  1768. * @param vector1 the ending point
  1769. * @param normal direction of the normal
  1770. * @returns the angle between vector0 and vector1
  1771. */
  1772. static GetAngleBetweenVectors(vector0, vector1, normal) {
  1773. const v0 = vector0.normalizeToRef(MathTmp.Vector3[1]);
  1774. const v1 = vector1.normalizeToRef(MathTmp.Vector3[2]);
  1775. let dot = Vector3.Dot(v0, v1);
  1776. // Vectors are normalized so dot will be in [-1, 1] (aside precision issues enough to break the result which explains the below clamp)
  1777. dot = Clamp(dot, -1, 1);
  1778. const angle = Math.acos(dot);
  1779. const n = MathTmp.Vector3[3];
  1780. Vector3.CrossToRef(v0, v1, n);
  1781. if (Vector3.Dot(n, normal) > 0) {
  1782. return isNaN(angle) ? 0 : angle;
  1783. }
  1784. return isNaN(angle) ? -Math.PI : -Math.acos(dot);
  1785. }
  1786. /**
  1787. * Get angle between two vectors projected on a plane
  1788. * Example Playground https://playground.babylonjs.com/#R1F8YU#87
  1789. * Expectation compute time: 0.01 ms (median) and 0.02 ms (percentile 95%)
  1790. * @param vector0 angle between vector0 and vector1
  1791. * @param vector1 angle between vector0 and vector1
  1792. * @param normal Normal of the projection plane
  1793. * @returns the angle in radians (float) between vector0 and vector1 projected on the plane with the specified normal
  1794. */
  1795. static GetAngleBetweenVectorsOnPlane(vector0, vector1, normal) {
  1796. MathTmp.Vector3[0].copyFrom(vector0);
  1797. const v0 = MathTmp.Vector3[0];
  1798. MathTmp.Vector3[1].copyFrom(vector1);
  1799. const v1 = MathTmp.Vector3[1];
  1800. MathTmp.Vector3[2].copyFrom(normal);
  1801. const vNormal = MathTmp.Vector3[2];
  1802. const right = MathTmp.Vector3[3];
  1803. const forward = MathTmp.Vector3[4];
  1804. v0.normalize();
  1805. v1.normalize();
  1806. vNormal.normalize();
  1807. Vector3.CrossToRef(vNormal, v0, right);
  1808. Vector3.CrossToRef(right, vNormal, forward);
  1809. const angle = Math.atan2(Vector3.Dot(v1, right), Vector3.Dot(v1, forward));
  1810. return NormalizeRadians(angle);
  1811. }
  1812. /**
  1813. * Gets the rotation that aligns the roll axis (Y) to the line joining the start point to the target point and stores it in the ref Vector3
  1814. * Example PG https://playground.babylonjs.com/#R1F8YU#189
  1815. * @param start the starting point
  1816. * @param target the target point
  1817. * @param ref the vector3 to store the result
  1818. * @returns ref in the form (pitch, yaw, 0)
  1819. */
  1820. static PitchYawRollToMoveBetweenPointsToRef(start, target, ref) {
  1821. const diff = TmpVectors.Vector3[0];
  1822. target.subtractToRef(start, diff);
  1823. ref._y = Math.atan2(diff.x, diff.z) || 0;
  1824. ref._x = Math.atan2(Math.sqrt(diff.x ** 2 + diff.z ** 2), diff.y) || 0;
  1825. ref._z = 0;
  1826. ref._isDirty = true;
  1827. return ref;
  1828. }
  1829. /**
  1830. * Gets the rotation that aligns the roll axis (Y) to the line joining the start point to the target point
  1831. * Example PG https://playground.babylonjs.com/#R1F8YU#188
  1832. * @param start the starting point
  1833. * @param target the target point
  1834. * @returns the rotation in the form (pitch, yaw, 0)
  1835. */
  1836. static PitchYawRollToMoveBetweenPoints(start, target) {
  1837. const ref = Vector3.Zero();
  1838. return Vector3.PitchYawRollToMoveBetweenPointsToRef(start, target, ref);
  1839. }
  1840. /**
  1841. * Slerp between two vectors. See also `SmoothToRef`
  1842. * Slerp is a spherical linear interpolation
  1843. * giving a slow in and out effect
  1844. * Example Playground 1 https://playground.babylonjs.com/#R1F8YU#108
  1845. * Example Playground 2 https://playground.babylonjs.com/#R1F8YU#109
  1846. * @param vector0 Start vector
  1847. * @param vector1 End vector
  1848. * @param slerp amount (will be clamped between 0 and 1)
  1849. * @param result The slerped vector
  1850. * @returns The slerped vector
  1851. */
  1852. static SlerpToRef(vector0, vector1, slerp, result) {
  1853. slerp = Clamp(slerp, 0, 1);
  1854. const vector0Dir = MathTmp.Vector3[0];
  1855. const vector1Dir = MathTmp.Vector3[1];
  1856. vector0Dir.copyFrom(vector0);
  1857. const vector0Length = vector0Dir.length();
  1858. vector0Dir.normalizeFromLength(vector0Length);
  1859. vector1Dir.copyFrom(vector1);
  1860. const vector1Length = vector1Dir.length();
  1861. vector1Dir.normalizeFromLength(vector1Length);
  1862. const dot = Vector3.Dot(vector0Dir, vector1Dir);
  1863. let scale0;
  1864. let scale1;
  1865. if (dot < 1 - Epsilon) {
  1866. const omega = Math.acos(dot);
  1867. const invSin = 1 / Math.sin(omega);
  1868. scale0 = Math.sin((1 - slerp) * omega) * invSin;
  1869. scale1 = Math.sin(slerp * omega) * invSin;
  1870. }
  1871. else {
  1872. // Use linear interpolation
  1873. scale0 = 1 - slerp;
  1874. scale1 = slerp;
  1875. }
  1876. vector0Dir.scaleInPlace(scale0);
  1877. vector1Dir.scaleInPlace(scale1);
  1878. result.copyFrom(vector0Dir).addInPlace(vector1Dir);
  1879. result.scaleInPlace(Lerp(vector0Length, vector1Length, slerp));
  1880. return result;
  1881. }
  1882. /**
  1883. * Smooth interpolation between two vectors using Slerp
  1884. * Example Playground https://playground.babylonjs.com/#R1F8YU#110
  1885. * @param source source vector
  1886. * @param goal goal vector
  1887. * @param deltaTime current interpolation frame
  1888. * @param lerpTime total interpolation time
  1889. * @param result the smoothed vector
  1890. * @returns the smoothed vector
  1891. */
  1892. static SmoothToRef(source, goal, deltaTime, lerpTime, result) {
  1893. Vector3.SlerpToRef(source, goal, lerpTime === 0 ? 1 : deltaTime / lerpTime, result);
  1894. return result;
  1895. }
  1896. /**
  1897. * Returns a new Vector3 set from the index "offset" of the given array
  1898. * Example Playground https://playground.babylonjs.com/#R1F8YU#83
  1899. * @param array defines the source array
  1900. * @param offset defines the offset in the source array
  1901. * @returns the new Vector3
  1902. */
  1903. static FromArray(array, offset = 0) {
  1904. return new Vector3(array[offset], array[offset + 1], array[offset + 2]);
  1905. }
  1906. /**
  1907. * Returns a new Vector3 set from the index "offset" of the given Float32Array
  1908. * @param array defines the source array
  1909. * @param offset defines the offset in the source array
  1910. * @returns the new Vector3
  1911. * @deprecated Please use FromArray instead.
  1912. */
  1913. static FromFloatArray(array, offset) {
  1914. return Vector3.FromArray(array, offset);
  1915. }
  1916. /**
  1917. * Sets the given vector "result" with the element values from the index "offset" of the given array
  1918. * Example Playground https://playground.babylonjs.com/#R1F8YU#84
  1919. * @param array defines the source array
  1920. * @param offset defines the offset in the source array
  1921. * @param result defines the Vector3 where to store the result
  1922. * @returns result input
  1923. */
  1924. static FromArrayToRef(array, offset, result) {
  1925. result._x = array[offset];
  1926. result._y = array[offset + 1];
  1927. result._z = array[offset + 2];
  1928. result._isDirty = true;
  1929. return result;
  1930. }
  1931. /**
  1932. * Sets the given vector "result" with the element values from the index "offset" of the given Float32Array
  1933. * @param array defines the source array
  1934. * @param offset defines the offset in the source array
  1935. * @param result defines the Vector3 where to store the result
  1936. * @deprecated Please use FromArrayToRef instead.
  1937. * @returns result input
  1938. */
  1939. static FromFloatArrayToRef(array, offset, result) {
  1940. return Vector3.FromArrayToRef(array, offset, result);
  1941. }
  1942. /**
  1943. * Sets the given vector "result" with the given floats.
  1944. * Example Playground https://playground.babylonjs.com/#R1F8YU#85
  1945. * @param x defines the x coordinate of the source
  1946. * @param y defines the y coordinate of the source
  1947. * @param z defines the z coordinate of the source
  1948. * @param result defines the Vector3 where to store the result
  1949. * @returns the result vector
  1950. */
  1951. static FromFloatsToRef(x, y, z, result) {
  1952. result.copyFromFloats(x, y, z);
  1953. return result;
  1954. }
  1955. /**
  1956. * Returns a new Vector3 set to (0.0, 0.0, 0.0)
  1957. * @returns a new empty Vector3
  1958. */
  1959. static Zero() {
  1960. return new Vector3(0.0, 0.0, 0.0);
  1961. }
  1962. /**
  1963. * Returns a new Vector3 set to (1.0, 1.0, 1.0)
  1964. * @returns a new Vector3
  1965. */
  1966. static One() {
  1967. return new Vector3(1.0, 1.0, 1.0);
  1968. }
  1969. /**
  1970. * Returns a new Vector3 set to (0.0, 1.0, 0.0)
  1971. * Example Playground https://playground.babylonjs.com/#R1F8YU#71
  1972. * @returns a new up Vector3
  1973. */
  1974. static Up() {
  1975. return new Vector3(0.0, 1.0, 0.0);
  1976. }
  1977. /**
  1978. * Gets an up Vector3 that must not be updated
  1979. */
  1980. static get UpReadOnly() {
  1981. return Vector3._UpReadOnly;
  1982. }
  1983. /**
  1984. * Gets a down Vector3 that must not be updated
  1985. */
  1986. static get DownReadOnly() {
  1987. return Vector3._DownReadOnly;
  1988. }
  1989. /**
  1990. * Gets a right Vector3 that must not be updated
  1991. */
  1992. static get RightReadOnly() {
  1993. return Vector3._RightReadOnly;
  1994. }
  1995. /**
  1996. * Gets a left Vector3 that must not be updated
  1997. */
  1998. static get LeftReadOnly() {
  1999. return Vector3._LeftReadOnly;
  2000. }
  2001. /**
  2002. * Gets a forward Vector3 that must not be updated
  2003. */
  2004. static get LeftHandedForwardReadOnly() {
  2005. return Vector3._LeftHandedForwardReadOnly;
  2006. }
  2007. /**
  2008. * Gets a forward Vector3 that must not be updated
  2009. */
  2010. static get RightHandedForwardReadOnly() {
  2011. return Vector3._RightHandedForwardReadOnly;
  2012. }
  2013. /**
  2014. * Gets a backward Vector3 that must not be updated
  2015. */
  2016. static get LeftHandedBackwardReadOnly() {
  2017. return Vector3._LeftHandedBackwardReadOnly;
  2018. }
  2019. /**
  2020. * Gets a backward Vector3 that must not be updated
  2021. */
  2022. static get RightHandedBackwardReadOnly() {
  2023. return Vector3._RightHandedBackwardReadOnly;
  2024. }
  2025. /**
  2026. * Gets a zero Vector3 that must not be updated
  2027. */
  2028. static get ZeroReadOnly() {
  2029. return Vector3._ZeroReadOnly;
  2030. }
  2031. /**
  2032. * Gets a one Vector3 that must not be updated
  2033. */
  2034. static get OneReadOnly() {
  2035. return Vector3._OneReadOnly;
  2036. }
  2037. /**
  2038. * Returns a new Vector3 set to (0.0, -1.0, 0.0)
  2039. * Example Playground https://playground.babylonjs.com/#R1F8YU#71
  2040. * @returns a new down Vector3
  2041. */
  2042. static Down() {
  2043. return new Vector3(0.0, -1.0, 0.0);
  2044. }
  2045. /**
  2046. * Returns a new Vector3 set to (0.0, 0.0, 1.0)
  2047. * Example Playground https://playground.babylonjs.com/#R1F8YU#71
  2048. * @param rightHandedSystem is the scene right-handed (negative z)
  2049. * @returns a new forward Vector3
  2050. */
  2051. static Forward(rightHandedSystem = false) {
  2052. return new Vector3(0.0, 0.0, rightHandedSystem ? -1.0 : 1.0);
  2053. }
  2054. /**
  2055. * Returns a new Vector3 set to (0.0, 0.0, -1.0)
  2056. * Example Playground https://playground.babylonjs.com/#R1F8YU#71
  2057. * @param rightHandedSystem is the scene right-handed (negative-z)
  2058. * @returns a new Backward Vector3
  2059. */
  2060. static Backward(rightHandedSystem = false) {
  2061. return new Vector3(0.0, 0.0, rightHandedSystem ? 1.0 : -1.0);
  2062. }
  2063. /**
  2064. * Returns a new Vector3 set to (1.0, 0.0, 0.0)
  2065. * Example Playground https://playground.babylonjs.com/#R1F8YU#71
  2066. * @returns a new right Vector3
  2067. */
  2068. static Right() {
  2069. return new Vector3(1.0, 0.0, 0.0);
  2070. }
  2071. /**
  2072. * Returns a new Vector3 set to (-1.0, 0.0, 0.0)
  2073. * Example Playground https://playground.babylonjs.com/#R1F8YU#71
  2074. * @returns a new left Vector3
  2075. */
  2076. static Left() {
  2077. return new Vector3(-1.0, 0.0, 0.0);
  2078. }
  2079. /**
  2080. * Returns a new Vector3 with random values between min and max
  2081. * @param min the minimum random value
  2082. * @param max the maximum random value
  2083. * @returns a Vector3 with random values between min and max
  2084. */
  2085. static Random(min = 0, max = 1) {
  2086. return new Vector3(RandomRange(min, max), RandomRange(min, max), RandomRange(min, max));
  2087. }
  2088. /**
  2089. * Sets a Vector3 with random values between min and max
  2090. * @param min the minimum random value
  2091. * @param max the maximum random value
  2092. * @param ref the ref to store the values in
  2093. * @returns the ref with random values between min and max
  2094. */
  2095. static RandomToRef(min = 0, max = 1, ref) {
  2096. return ref.copyFromFloats(RandomRange(min, max), RandomRange(min, max), RandomRange(min, max));
  2097. }
  2098. /**
  2099. * Returns a new Vector3 set with the result of the transformation by the given matrix of the given vector.
  2100. * This method computes transformed coordinates only, not transformed direction vectors (ie. it takes translation in account)
  2101. * Example Playground https://playground.babylonjs.com/#R1F8YU#111
  2102. * @param vector defines the Vector3 to transform
  2103. * @param transformation defines the transformation matrix
  2104. * @returns the transformed Vector3
  2105. */
  2106. static TransformCoordinates(vector, transformation) {
  2107. const result = Vector3.Zero();
  2108. Vector3.TransformCoordinatesToRef(vector, transformation, result);
  2109. return result;
  2110. }
  2111. /**
  2112. * Sets the given vector "result" coordinates with the result of the transformation by the given matrix of the given vector
  2113. * This method computes transformed coordinates only, not transformed direction vectors (ie. it takes translation in account)
  2114. * Example Playground https://playground.babylonjs.com/#R1F8YU#113
  2115. * @param vector defines the Vector3 to transform
  2116. * @param transformation defines the transformation matrix
  2117. * @param result defines the Vector3 where to store the result
  2118. * @returns result input
  2119. */
  2120. static TransformCoordinatesToRef(vector, transformation, result) {
  2121. Vector3.TransformCoordinatesFromFloatsToRef(vector._x, vector._y, vector._z, transformation, result);
  2122. return result;
  2123. }
  2124. /**
  2125. * Sets the given vector "result" coordinates with the result of the transformation by the given matrix of the given floats (x, y, z)
  2126. * This method computes transformed coordinates only, not transformed direction vectors
  2127. * Example Playground https://playground.babylonjs.com/#R1F8YU#115
  2128. * @param x define the x coordinate of the source vector
  2129. * @param y define the y coordinate of the source vector
  2130. * @param z define the z coordinate of the source vector
  2131. * @param transformation defines the transformation matrix
  2132. * @param result defines the Vector3 where to store the result
  2133. * @returns result input
  2134. */
  2135. static TransformCoordinatesFromFloatsToRef(x, y, z, transformation, result) {
  2136. const m = transformation.m;
  2137. const rx = x * m[0] + y * m[4] + z * m[8] + m[12];
  2138. const ry = x * m[1] + y * m[5] + z * m[9] + m[13];
  2139. const rz = x * m[2] + y * m[6] + z * m[10] + m[14];
  2140. const rw = 1 / (x * m[3] + y * m[7] + z * m[11] + m[15]);
  2141. result._x = rx * rw;
  2142. result._y = ry * rw;
  2143. result._z = rz * rw;
  2144. result._isDirty = true;
  2145. return result;
  2146. }
  2147. /**
  2148. * Returns a new Vector3 set with the result of the normal transformation by the given matrix of the given vector
  2149. * This methods computes transformed normalized direction vectors only (ie. it does not apply translation)
  2150. * Example Playground https://playground.babylonjs.com/#R1F8YU#112
  2151. * @param vector defines the Vector3 to transform
  2152. * @param transformation defines the transformation matrix
  2153. * @returns the new Vector3
  2154. */
  2155. static TransformNormal(vector, transformation) {
  2156. const result = Vector3.Zero();
  2157. Vector3.TransformNormalToRef(vector, transformation, result);
  2158. return result;
  2159. }
  2160. /**
  2161. * Sets the given vector "result" with the result of the normal transformation by the given matrix of the given vector
  2162. * This methods computes transformed normalized direction vectors only (ie. it does not apply translation)
  2163. * Example Playground https://playground.babylonjs.com/#R1F8YU#114
  2164. * @param vector defines the Vector3 to transform
  2165. * @param transformation defines the transformation matrix
  2166. * @param result defines the Vector3 where to store the result
  2167. * @returns result input
  2168. */
  2169. static TransformNormalToRef(vector, transformation, result) {
  2170. this.TransformNormalFromFloatsToRef(vector._x, vector._y, vector._z, transformation, result);
  2171. return result;
  2172. }
  2173. /**
  2174. * Sets the given vector "result" with the result of the normal transformation by the given matrix of the given floats (x, y, z)
  2175. * This methods computes transformed normalized direction vectors only (ie. it does not apply translation)
  2176. * Example Playground https://playground.babylonjs.com/#R1F8YU#116
  2177. * @param x define the x coordinate of the source vector
  2178. * @param y define the y coordinate of the source vector
  2179. * @param z define the z coordinate of the source vector
  2180. * @param transformation defines the transformation matrix
  2181. * @param result defines the Vector3 where to store the result
  2182. * @returns result input
  2183. */
  2184. static TransformNormalFromFloatsToRef(x, y, z, transformation, result) {
  2185. const m = transformation.m;
  2186. result._x = x * m[0] + y * m[4] + z * m[8];
  2187. result._y = x * m[1] + y * m[5] + z * m[9];
  2188. result._z = x * m[2] + y * m[6] + z * m[10];
  2189. result._isDirty = true;
  2190. return result;
  2191. }
  2192. /**
  2193. * Returns a new Vector3 located for "amount" on the CatmullRom interpolation spline defined by the vectors "value1", "value2", "value3", "value4"
  2194. * Example Playground https://playground.babylonjs.com/#R1F8YU#69
  2195. * @param value1 defines the first control point
  2196. * @param value2 defines the second control point
  2197. * @param value3 defines the third control point
  2198. * @param value4 defines the fourth control point
  2199. * @param amount defines the amount on the spline to use
  2200. * @returns the new Vector3
  2201. */
  2202. static CatmullRom(value1, value2, value3, value4, amount) {
  2203. const squared = amount * amount;
  2204. const cubed = amount * squared;
  2205. const x = 0.5 *
  2206. (2.0 * value2._x +
  2207. (-value1._x + value3._x) * amount +
  2208. (2.0 * value1._x - 5.0 * value2._x + 4.0 * value3._x - value4._x) * squared +
  2209. (-value1._x + 3.0 * value2._x - 3.0 * value3._x + value4._x) * cubed);
  2210. const y = 0.5 *
  2211. (2.0 * value2._y +
  2212. (-value1._y + value3._y) * amount +
  2213. (2.0 * value1._y - 5.0 * value2._y + 4.0 * value3._y - value4._y) * squared +
  2214. (-value1._y + 3.0 * value2._y - 3.0 * value3._y + value4._y) * cubed);
  2215. const z = 0.5 *
  2216. (2.0 * value2._z +
  2217. (-value1._z + value3._z) * amount +
  2218. (2.0 * value1._z - 5.0 * value2._z + 4.0 * value3._z - value4._z) * squared +
  2219. (-value1._z + 3.0 * value2._z - 3.0 * value3._z + value4._z) * cubed);
  2220. return new value1.constructor(x, y, z);
  2221. }
  2222. /**
  2223. * Returns a new Vector3 set with the coordinates of "value", if the vector "value" is in the cube defined by the vectors "min" and "max"
  2224. * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
  2225. * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
  2226. * Example Playground https://playground.babylonjs.com/#R1F8YU#76
  2227. * @param value defines the current value
  2228. * @param min defines the lower range value
  2229. * @param max defines the upper range value
  2230. * @returns the new Vector3
  2231. */
  2232. static Clamp(value, min, max) {
  2233. const result = new value.constructor();
  2234. Vector3.ClampToRef(value, min, max, result);
  2235. return result;
  2236. }
  2237. /**
  2238. * Sets the given vector "result" with the coordinates of "value", if the vector "value" is in the cube defined by the vectors "min" and "max"
  2239. * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
  2240. * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
  2241. * Example Playground https://playground.babylonjs.com/#R1F8YU#77
  2242. * @param value defines the current value
  2243. * @param min defines the lower range value
  2244. * @param max defines the upper range value
  2245. * @param result defines the Vector3 where to store the result
  2246. * @returns result input
  2247. */
  2248. static ClampToRef(value, min, max, result) {
  2249. let x = value._x;
  2250. x = x > max._x ? max._x : x;
  2251. x = x < min._x ? min._x : x;
  2252. let y = value._y;
  2253. y = y > max._y ? max._y : y;
  2254. y = y < min._y ? min._y : y;
  2255. let z = value._z;
  2256. z = z > max._z ? max._z : z;
  2257. z = z < min._z ? min._z : z;
  2258. result.copyFromFloats(x, y, z);
  2259. return result;
  2260. }
  2261. /**
  2262. * Checks if a given vector is inside a specific range
  2263. * Example Playground https://playground.babylonjs.com/#R1F8YU#75
  2264. * @param v defines the vector to test
  2265. * @param min defines the minimum range
  2266. * @param max defines the maximum range
  2267. */
  2268. static CheckExtends(v, min, max) {
  2269. min.minimizeInPlace(v);
  2270. max.maximizeInPlace(v);
  2271. }
  2272. /**
  2273. * Returns a new Vector3 located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2"
  2274. * Example Playground https://playground.babylonjs.com/#R1F8YU#89
  2275. * @param value1 defines the first control point
  2276. * @param tangent1 defines the first tangent vector
  2277. * @param value2 defines the second control point
  2278. * @param tangent2 defines the second tangent vector
  2279. * @param amount defines the amount on the interpolation spline (between 0 and 1)
  2280. * @returns the new Vector3
  2281. */
  2282. static Hermite(value1, tangent1, value2, tangent2, amount) {
  2283. const squared = amount * amount;
  2284. const cubed = amount * squared;
  2285. const part1 = 2.0 * cubed - 3.0 * squared + 1.0;
  2286. const part2 = -2.0 * cubed + 3.0 * squared;
  2287. const part3 = cubed - 2.0 * squared + amount;
  2288. const part4 = cubed - squared;
  2289. const x = value1._x * part1 + value2._x * part2 + tangent1._x * part3 + tangent2._x * part4;
  2290. const y = value1._y * part1 + value2._y * part2 + tangent1._y * part3 + tangent2._y * part4;
  2291. const z = value1._z * part1 + value2._z * part2 + tangent1._z * part3 + tangent2._z * part4;
  2292. return new value1.constructor(x, y, z);
  2293. }
  2294. /**
  2295. * Returns a new Vector3 which is the 1st derivative of the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2".
  2296. * Example Playground https://playground.babylonjs.com/#R1F8YU#90
  2297. * @param value1 defines the first control point
  2298. * @param tangent1 defines the first tangent
  2299. * @param value2 defines the second control point
  2300. * @param tangent2 defines the second tangent
  2301. * @param time define where the derivative must be done
  2302. * @returns 1st derivative
  2303. */
  2304. static Hermite1stDerivative(value1, tangent1, value2, tangent2, time) {
  2305. const result = new value1.constructor();
  2306. this.Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result);
  2307. return result;
  2308. }
  2309. /**
  2310. * Update a Vector3 with the 1st derivative of the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2".
  2311. * Example Playground https://playground.babylonjs.com/#R1F8YU#91
  2312. * @param value1 defines the first control point
  2313. * @param tangent1 defines the first tangent
  2314. * @param value2 defines the second control point
  2315. * @param tangent2 defines the second tangent
  2316. * @param time define where the derivative must be done
  2317. * @param result define where to store the derivative
  2318. * @returns result input
  2319. */
  2320. static Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result) {
  2321. const t2 = time * time;
  2322. result._x = (t2 - time) * 6 * value1._x + (3 * t2 - 4 * time + 1) * tangent1._x + (-t2 + time) * 6 * value2._x + (3 * t2 - 2 * time) * tangent2._x;
  2323. result._y = (t2 - time) * 6 * value1._y + (3 * t2 - 4 * time + 1) * tangent1._y + (-t2 + time) * 6 * value2._y + (3 * t2 - 2 * time) * tangent2._y;
  2324. result._z = (t2 - time) * 6 * value1._z + (3 * t2 - 4 * time + 1) * tangent1._z + (-t2 + time) * 6 * value2._z + (3 * t2 - 2 * time) * tangent2._z;
  2325. result._isDirty = true;
  2326. return result;
  2327. }
  2328. /**
  2329. * Returns a new Vector3 located for "amount" (float) on the linear interpolation between the vectors "start" and "end"
  2330. * Example Playground https://playground.babylonjs.com/#R1F8YU#95
  2331. * @param start defines the start value
  2332. * @param end defines the end value
  2333. * @param amount max defines amount between both (between 0 and 1)
  2334. * @returns the new Vector3
  2335. */
  2336. static Lerp(start, end, amount) {
  2337. const result = new start.constructor(0, 0, 0);
  2338. Vector3.LerpToRef(start, end, amount, result);
  2339. return result;
  2340. }
  2341. /**
  2342. * Sets the given vector "result" with the result of the linear interpolation from the vector "start" for "amount" to the vector "end"
  2343. * Example Playground https://playground.babylonjs.com/#R1F8YU#93
  2344. * @param start defines the start value
  2345. * @param end defines the end value
  2346. * @param amount max defines amount between both (between 0 and 1)
  2347. * @param result defines the Vector3 where to store the result
  2348. * @returns result input
  2349. */
  2350. static LerpToRef(start, end, amount, result) {
  2351. result._x = start._x + (end._x - start._x) * amount;
  2352. result._y = start._y + (end._y - start._y) * amount;
  2353. result._z = start._z + (end._z - start._z) * amount;
  2354. result._isDirty = true;
  2355. return result;
  2356. }
  2357. /**
  2358. * Returns the dot product (float) between the vectors "left" and "right"
  2359. * Example Playground https://playground.babylonjs.com/#R1F8YU#82
  2360. * @param left defines the left operand
  2361. * @param right defines the right operand
  2362. * @returns the dot product
  2363. */
  2364. static Dot(left, right) {
  2365. return left._x * right._x + left._y * right._y + left._z * right._z;
  2366. }
  2367. /**
  2368. * Returns the dot product (float) between the current vectors and "otherVector"
  2369. * @param otherVector defines the right operand
  2370. * @returns the dot product
  2371. */
  2372. dot(otherVector) {
  2373. return this._x * otherVector._x + this._y * otherVector._y + this._z * otherVector._z;
  2374. }
  2375. /**
  2376. * Returns a new Vector3 as the cross product of the vectors "left" and "right"
  2377. * The cross product is then orthogonal to both "left" and "right"
  2378. * Example Playground https://playground.babylonjs.com/#R1F8YU#15
  2379. * @param left defines the left operand
  2380. * @param right defines the right operand
  2381. * @returns the cross product
  2382. */
  2383. static Cross(left, right) {
  2384. const result = new left.constructor();
  2385. Vector3.CrossToRef(left, right, result);
  2386. return result;
  2387. }
  2388. /**
  2389. * Sets the given vector "result" with the cross product of "left" and "right"
  2390. * The cross product is then orthogonal to both "left" and "right"
  2391. * Example Playground https://playground.babylonjs.com/#R1F8YU#78
  2392. * @param left defines the left operand
  2393. * @param right defines the right operand
  2394. * @param result defines the Vector3 where to store the result
  2395. * @returns result input
  2396. */
  2397. static CrossToRef(left, right, result) {
  2398. const x = left._y * right._z - left._z * right._y;
  2399. const y = left._z * right._x - left._x * right._z;
  2400. const z = left._x * right._y - left._y * right._x;
  2401. result.copyFromFloats(x, y, z);
  2402. return result;
  2403. }
  2404. /**
  2405. * Returns a new Vector3 as the normalization of the given vector
  2406. * Example Playground https://playground.babylonjs.com/#R1F8YU#98
  2407. * @param vector defines the Vector3 to normalize
  2408. * @returns the new Vector3
  2409. */
  2410. static Normalize(vector) {
  2411. const result = Vector3.Zero();
  2412. Vector3.NormalizeToRef(vector, result);
  2413. return result;
  2414. }
  2415. /**
  2416. * Sets the given vector "result" with the normalization of the given first vector
  2417. * Example Playground https://playground.babylonjs.com/#R1F8YU#98
  2418. * @param vector defines the Vector3 to normalize
  2419. * @param result defines the Vector3 where to store the result
  2420. * @returns result input
  2421. */
  2422. static NormalizeToRef(vector, result) {
  2423. vector.normalizeToRef(result);
  2424. return result;
  2425. }
  2426. /**
  2427. * Project a Vector3 onto screen space
  2428. * Example Playground https://playground.babylonjs.com/#R1F8YU#101
  2429. * @param vector defines the Vector3 to project
  2430. * @param world defines the world matrix to use
  2431. * @param transform defines the transform (view x projection) matrix to use
  2432. * @param viewport defines the screen viewport to use
  2433. * @returns the new Vector3
  2434. */
  2435. static Project(vector, world, transform, viewport) {
  2436. const result = new vector.constructor();
  2437. Vector3.ProjectToRef(vector, world, transform, viewport, result);
  2438. return result;
  2439. }
  2440. /**
  2441. * Project a Vector3 onto screen space to reference
  2442. * Example Playground https://playground.babylonjs.com/#R1F8YU#102
  2443. * @param vector defines the Vector3 to project
  2444. * @param world defines the world matrix to use
  2445. * @param transform defines the transform (view x projection) matrix to use
  2446. * @param viewport defines the screen viewport to use
  2447. * @param result the vector in which the screen space will be stored
  2448. * @returns result input
  2449. */
  2450. static ProjectToRef(vector, world, transform, viewport, result) {
  2451. const cw = viewport.width;
  2452. const ch = viewport.height;
  2453. const cx = viewport.x;
  2454. const cy = viewport.y;
  2455. const viewportMatrix = MathTmp.Matrix[1];
  2456. const isNDCHalfZRange = EngineStore.LastCreatedEngine?.isNDCHalfZRange;
  2457. const zScale = isNDCHalfZRange ? 1 : 0.5;
  2458. const zOffset = isNDCHalfZRange ? 0 : 0.5;
  2459. Matrix.FromValuesToRef(cw / 2.0, 0, 0, 0, 0, -ch / 2.0, 0, 0, 0, 0, zScale, 0, cx + cw / 2.0, ch / 2.0 + cy, zOffset, 1, viewportMatrix);
  2460. const matrix = MathTmp.Matrix[0];
  2461. world.multiplyToRef(transform, matrix);
  2462. matrix.multiplyToRef(viewportMatrix, matrix);
  2463. Vector3.TransformCoordinatesToRef(vector, matrix, result);
  2464. return result;
  2465. }
  2466. /**
  2467. * Reflects a vector off the plane defined by a normalized normal
  2468. * @param inDirection defines the vector direction
  2469. * @param normal defines the normal - Must be normalized
  2470. * @returns the resulting vector
  2471. */
  2472. static Reflect(inDirection, normal) {
  2473. return this.ReflectToRef(inDirection, normal, new Vector3());
  2474. }
  2475. /**
  2476. * Reflects a vector off the plane defined by a normalized normal to reference
  2477. * @param inDirection defines the vector direction
  2478. * @param normal defines the normal - Must be normalized
  2479. * @param ref defines the Vector3 where to store the result
  2480. * @returns the resulting vector
  2481. */
  2482. static ReflectToRef(inDirection, normal, ref) {
  2483. const tmp = TmpVectors.Vector3[0];
  2484. tmp.copyFrom(normal).scaleInPlace(2 * Vector3.Dot(inDirection, normal));
  2485. return ref.copyFrom(inDirection).subtractInPlace(tmp);
  2486. }
  2487. /**
  2488. * @internal
  2489. */
  2490. static _UnprojectFromInvertedMatrixToRef(source, matrix, result) {
  2491. Vector3.TransformCoordinatesToRef(source, matrix, result);
  2492. const m = matrix.m;
  2493. const num = source._x * m[3] + source._y * m[7] + source._z * m[11] + m[15];
  2494. if (WithinEpsilon(num, 1.0)) {
  2495. result.scaleInPlace(1.0 / num);
  2496. }
  2497. return result;
  2498. }
  2499. /**
  2500. * Unproject from screen space to object space
  2501. * Example Playground https://playground.babylonjs.com/#R1F8YU#121
  2502. * @param source defines the screen space Vector3 to use
  2503. * @param viewportWidth defines the current width of the viewport
  2504. * @param viewportHeight defines the current height of the viewport
  2505. * @param world defines the world matrix to use (can be set to Identity to go to world space)
  2506. * @param transform defines the transform (view x projection) matrix to use
  2507. * @returns the new Vector3
  2508. */
  2509. static UnprojectFromTransform(source, viewportWidth, viewportHeight, world, transform) {
  2510. return this.Unproject(source, viewportWidth, viewportHeight, world, transform, Matrix.IdentityReadOnly);
  2511. }
  2512. /**
  2513. * Unproject from screen space to object space
  2514. * Example Playground https://playground.babylonjs.com/#R1F8YU#117
  2515. * @param source defines the screen space Vector3 to use
  2516. * @param viewportWidth defines the current width of the viewport
  2517. * @param viewportHeight defines the current height of the viewport
  2518. * @param world defines the world matrix to use (can be set to Identity to go to world space)
  2519. * @param view defines the view matrix to use
  2520. * @param projection defines the projection matrix to use
  2521. * @returns the new Vector3
  2522. */
  2523. static Unproject(source, viewportWidth, viewportHeight, world, view, projection) {
  2524. const result = new source.constructor();
  2525. Vector3.UnprojectToRef(source, viewportWidth, viewportHeight, world, view, projection, result);
  2526. return result;
  2527. }
  2528. /**
  2529. * Unproject from screen space to object space
  2530. * Example Playground https://playground.babylonjs.com/#R1F8YU#119
  2531. * @param source defines the screen space Vector3 to use
  2532. * @param viewportWidth defines the current width of the viewport
  2533. * @param viewportHeight defines the current height of the viewport
  2534. * @param world defines the world matrix to use (can be set to Identity to go to world space)
  2535. * @param view defines the view matrix to use
  2536. * @param projection defines the projection matrix to use
  2537. * @param result defines the Vector3 where to store the result
  2538. * @returns result input
  2539. */
  2540. static UnprojectToRef(source, viewportWidth, viewportHeight, world, view, projection, result) {
  2541. Vector3.UnprojectFloatsToRef(source._x, source._y, source._z, viewportWidth, viewportHeight, world, view, projection, result);
  2542. return result;
  2543. }
  2544. /**
  2545. * Unproject from screen space to object space
  2546. * Example Playground https://playground.babylonjs.com/#R1F8YU#120
  2547. * @param sourceX defines the screen space x coordinate to use
  2548. * @param sourceY defines the screen space y coordinate to use
  2549. * @param sourceZ defines the screen space z coordinate to use
  2550. * @param viewportWidth defines the current width of the viewport
  2551. * @param viewportHeight defines the current height of the viewport
  2552. * @param world defines the world matrix to use (can be set to Identity to go to world space)
  2553. * @param view defines the view matrix to use
  2554. * @param projection defines the projection matrix to use
  2555. * @param result defines the Vector3 where to store the result
  2556. * @returns result input
  2557. */
  2558. static UnprojectFloatsToRef(sourceX, sourceY, sourceZ, viewportWidth, viewportHeight, world, view, projection, result) {
  2559. const matrix = MathTmp.Matrix[0];
  2560. world.multiplyToRef(view, matrix);
  2561. matrix.multiplyToRef(projection, matrix);
  2562. matrix.invert();
  2563. const screenSource = MathTmp.Vector3[0];
  2564. screenSource.x = (sourceX / viewportWidth) * 2 - 1;
  2565. screenSource.y = -((sourceY / viewportHeight) * 2 - 1);
  2566. if (EngineStore.LastCreatedEngine?.isNDCHalfZRange) {
  2567. screenSource.z = sourceZ;
  2568. }
  2569. else {
  2570. screenSource.z = 2 * sourceZ - 1.0;
  2571. }
  2572. Vector3._UnprojectFromInvertedMatrixToRef(screenSource, matrix, result);
  2573. return result;
  2574. }
  2575. /**
  2576. * Gets the minimal coordinate values between two Vector3
  2577. * Example Playground https://playground.babylonjs.com/#R1F8YU#97
  2578. * @param left defines the first operand
  2579. * @param right defines the second operand
  2580. * @returns the new Vector3
  2581. */
  2582. static Minimize(left, right) {
  2583. const min = new left.constructor();
  2584. min.copyFrom(left);
  2585. min.minimizeInPlace(right);
  2586. return min;
  2587. }
  2588. /**
  2589. * Gets the maximal coordinate values between two Vector3
  2590. * Example Playground https://playground.babylonjs.com/#R1F8YU#96
  2591. * @param left defines the first operand
  2592. * @param right defines the second operand
  2593. * @returns the new Vector3
  2594. */
  2595. static Maximize(left, right) {
  2596. const max = new left.constructor();
  2597. max.copyFrom(left);
  2598. max.maximizeInPlace(right);
  2599. return max;
  2600. }
  2601. /**
  2602. * Returns the distance between the vectors "value1" and "value2"
  2603. * Example Playground https://playground.babylonjs.com/#R1F8YU#81
  2604. * @param value1 defines the first operand
  2605. * @param value2 defines the second operand
  2606. * @returns the distance
  2607. */
  2608. static Distance(value1, value2) {
  2609. return Math.sqrt(Vector3.DistanceSquared(value1, value2));
  2610. }
  2611. /**
  2612. * Returns the squared distance between the vectors "value1" and "value2"
  2613. * Example Playground https://playground.babylonjs.com/#R1F8YU#80
  2614. * @param value1 defines the first operand
  2615. * @param value2 defines the second operand
  2616. * @returns the squared distance
  2617. */
  2618. static DistanceSquared(value1, value2) {
  2619. const x = value1._x - value2._x;
  2620. const y = value1._y - value2._y;
  2621. const z = value1._z - value2._z;
  2622. return x * x + y * y + z * z;
  2623. }
  2624. /**
  2625. * Projects "vector" on the triangle determined by its extremities "p0", "p1" and "p2", stores the result in "ref"
  2626. * and returns the distance to the projected point.
  2627. * Example Playground https://playground.babylonjs.com/#R1F8YU#104
  2628. * From http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.4264&rep=rep1&type=pdf
  2629. *
  2630. * @param vector the vector to get distance from
  2631. * @param p0 extremity of the triangle
  2632. * @param p1 extremity of the triangle
  2633. * @param p2 extremity of the triangle
  2634. * @param ref variable to store the result to
  2635. * @returns The distance between "ref" and "vector"
  2636. */
  2637. static ProjectOnTriangleToRef(vector, p0, p1, p2, ref) {
  2638. const p1p0 = MathTmp.Vector3[0];
  2639. const p2p0 = MathTmp.Vector3[1];
  2640. const p2p1 = MathTmp.Vector3[2];
  2641. const normal = MathTmp.Vector3[3];
  2642. const vectorp0 = MathTmp.Vector3[4];
  2643. // Triangle vectors
  2644. p1.subtractToRef(p0, p1p0);
  2645. p2.subtractToRef(p0, p2p0);
  2646. p2.subtractToRef(p1, p2p1);
  2647. const p1p0L = p1p0.length();
  2648. const p2p0L = p2p0.length();
  2649. const p2p1L = p2p1.length();
  2650. if (p1p0L < Epsilon || p2p0L < Epsilon || p2p1L < Epsilon) {
  2651. // This is a degenerate triangle. As we assume this is part of a non-degenerate mesh,
  2652. // we will find a better intersection later.
  2653. // Let's just return one of the extremities
  2654. ref.copyFrom(p0);
  2655. return Vector3.Distance(vector, p0);
  2656. }
  2657. // Compute normal and vector to p0
  2658. vector.subtractToRef(p0, vectorp0);
  2659. Vector3.CrossToRef(p1p0, p2p0, normal);
  2660. const nl = normal.length();
  2661. if (nl < Epsilon) {
  2662. // Extremities are aligned, we are back on the case of a degenerate triangle
  2663. ref.copyFrom(p0);
  2664. return Vector3.Distance(vector, p0);
  2665. }
  2666. normal.normalizeFromLength(nl);
  2667. let l = vectorp0.length();
  2668. if (l < Epsilon) {
  2669. // Vector is p0
  2670. ref.copyFrom(p0);
  2671. return 0;
  2672. }
  2673. vectorp0.normalizeFromLength(l);
  2674. // Project to "proj" that lies on the triangle plane
  2675. const cosA = Vector3.Dot(normal, vectorp0);
  2676. const projVector = MathTmp.Vector3[5];
  2677. const proj = MathTmp.Vector3[6];
  2678. projVector.copyFrom(normal).scaleInPlace(-l * cosA);
  2679. proj.copyFrom(vector).addInPlace(projVector);
  2680. // Compute barycentric coordinates (v0, v1 and v2 are axis from barycenter to extremities)
  2681. const v0 = MathTmp.Vector3[4];
  2682. const v1 = MathTmp.Vector3[5];
  2683. const v2 = MathTmp.Vector3[7];
  2684. const tmp = MathTmp.Vector3[8];
  2685. v0.copyFrom(p1p0).scaleInPlace(1 / p1p0L);
  2686. tmp.copyFrom(p2p0).scaleInPlace(1 / p2p0L);
  2687. v0.addInPlace(tmp).scaleInPlace(-1);
  2688. v1.copyFrom(p1p0).scaleInPlace(-1 / p1p0L);
  2689. tmp.copyFrom(p2p1).scaleInPlace(1 / p2p1L);
  2690. v1.addInPlace(tmp).scaleInPlace(-1);
  2691. v2.copyFrom(p2p1).scaleInPlace(-1 / p2p1L);
  2692. tmp.copyFrom(p2p0).scaleInPlace(-1 / p2p0L);
  2693. v2.addInPlace(tmp).scaleInPlace(-1);
  2694. // Determines which edge of the triangle is closest to "proj"
  2695. const projP = MathTmp.Vector3[9];
  2696. let dot;
  2697. projP.copyFrom(proj).subtractInPlace(p0);
  2698. Vector3.CrossToRef(v0, projP, tmp);
  2699. dot = Vector3.Dot(tmp, normal);
  2700. const s0 = dot;
  2701. projP.copyFrom(proj).subtractInPlace(p1);
  2702. Vector3.CrossToRef(v1, projP, tmp);
  2703. dot = Vector3.Dot(tmp, normal);
  2704. const s1 = dot;
  2705. projP.copyFrom(proj).subtractInPlace(p2);
  2706. Vector3.CrossToRef(v2, projP, tmp);
  2707. dot = Vector3.Dot(tmp, normal);
  2708. const s2 = dot;
  2709. const edge = MathTmp.Vector3[10];
  2710. let e0, e1;
  2711. if (s0 > 0 && s1 < 0) {
  2712. edge.copyFrom(p1p0);
  2713. e0 = p0;
  2714. e1 = p1;
  2715. }
  2716. else if (s1 > 0 && s2 < 0) {
  2717. edge.copyFrom(p2p1);
  2718. e0 = p1;
  2719. e1 = p2;
  2720. }
  2721. else {
  2722. edge.copyFrom(p2p0).scaleInPlace(-1);
  2723. e0 = p2;
  2724. e1 = p0;
  2725. }
  2726. // Determines if "proj" lies inside the triangle
  2727. const tmp2 = MathTmp.Vector3[9];
  2728. const tmp3 = MathTmp.Vector3[4];
  2729. e0.subtractToRef(proj, tmp);
  2730. e1.subtractToRef(proj, tmp2);
  2731. Vector3.CrossToRef(tmp, tmp2, tmp3);
  2732. const isOutside = Vector3.Dot(tmp3, normal) < 0;
  2733. // If inside, we already found the projected point, "proj"
  2734. if (!isOutside) {
  2735. ref.copyFrom(proj);
  2736. return Math.abs(l * cosA);
  2737. }
  2738. // If outside, we find "triProj", the closest point from "proj" on the closest edge
  2739. const r = MathTmp.Vector3[5];
  2740. Vector3.CrossToRef(edge, tmp3, r);
  2741. r.normalize();
  2742. const e0proj = MathTmp.Vector3[9];
  2743. e0proj.copyFrom(e0).subtractInPlace(proj);
  2744. const e0projL = e0proj.length();
  2745. if (e0projL < Epsilon) {
  2746. // Proj is e0
  2747. ref.copyFrom(e0);
  2748. return Vector3.Distance(vector, e0);
  2749. }
  2750. e0proj.normalizeFromLength(e0projL);
  2751. const cosG = Vector3.Dot(r, e0proj);
  2752. const triProj = MathTmp.Vector3[7];
  2753. triProj.copyFrom(proj).addInPlace(r.scaleInPlace(e0projL * cosG));
  2754. // Now we clamp "triProj" so it lies between e0 and e1
  2755. tmp.copyFrom(triProj).subtractInPlace(e0);
  2756. l = edge.length();
  2757. edge.normalizeFromLength(l);
  2758. let t = Vector3.Dot(tmp, edge) / Math.max(l, Epsilon);
  2759. t = Clamp(t, 0, 1);
  2760. triProj.copyFrom(e0).addInPlace(edge.scaleInPlace(t * l));
  2761. ref.copyFrom(triProj);
  2762. return Vector3.Distance(vector, triProj);
  2763. }
  2764. /**
  2765. * Returns a new Vector3 located at the center between "value1" and "value2"
  2766. * Example Playground https://playground.babylonjs.com/#R1F8YU#72
  2767. * @param value1 defines the first operand
  2768. * @param value2 defines the second operand
  2769. * @returns the new Vector3
  2770. */
  2771. static Center(value1, value2) {
  2772. return Vector3.CenterToRef(value1, value2, Vector3.Zero());
  2773. }
  2774. /**
  2775. * Gets the center of the vectors "value1" and "value2" and stores the result in the vector "ref"
  2776. * Example Playground https://playground.babylonjs.com/#R1F8YU#73
  2777. * @param value1 defines first vector
  2778. * @param value2 defines second vector
  2779. * @param ref defines third vector
  2780. * @returns ref
  2781. */
  2782. static CenterToRef(value1, value2, ref) {
  2783. return ref.copyFromFloats((value1._x + value2._x) / 2, (value1._y + value2._y) / 2, (value1._z + value2._z) / 2);
  2784. }
  2785. /**
  2786. * Given three orthogonal normalized left-handed oriented Vector3 axis in space (target system),
  2787. * RotationFromAxis() returns the rotation Euler angles (ex : rotation.x, rotation.y, rotation.z) to apply
  2788. * to something in order to rotate it from its local system to the given target system
  2789. * Note: axis1, axis2 and axis3 are normalized during this operation
  2790. * Example Playground https://playground.babylonjs.com/#R1F8YU#106
  2791. * @param axis1 defines the first axis
  2792. * @param axis2 defines the second axis
  2793. * @param axis3 defines the third axis
  2794. * @returns a new Vector3
  2795. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/transforms/center_origin/target_align
  2796. */
  2797. static RotationFromAxis(axis1, axis2, axis3) {
  2798. const rotation = new axis1.constructor();
  2799. Vector3.RotationFromAxisToRef(axis1, axis2, axis3, rotation);
  2800. return rotation;
  2801. }
  2802. /**
  2803. * The same than RotationFromAxis but updates the given ref Vector3 parameter instead of returning a new Vector3
  2804. * Example Playground https://playground.babylonjs.com/#R1F8YU#107
  2805. * @param axis1 defines the first axis
  2806. * @param axis2 defines the second axis
  2807. * @param axis3 defines the third axis
  2808. * @param ref defines the Vector3 where to store the result
  2809. * @returns result input
  2810. */
  2811. static RotationFromAxisToRef(axis1, axis2, axis3, ref) {
  2812. const quat = MathTmp.Quaternion[0];
  2813. Quaternion.RotationQuaternionFromAxisToRef(axis1, axis2, axis3, quat);
  2814. quat.toEulerAnglesToRef(ref);
  2815. return ref;
  2816. }
  2817. }
  2818. Vector3._UpReadOnly = Vector3.Up();
  2819. Vector3._DownReadOnly = Vector3.Down();
  2820. Vector3._LeftHandedForwardReadOnly = Vector3.Forward(false);
  2821. Vector3._RightHandedForwardReadOnly = Vector3.Forward(true);
  2822. Vector3._LeftHandedBackwardReadOnly = Vector3.Backward(false);
  2823. Vector3._RightHandedBackwardReadOnly = Vector3.Backward(true);
  2824. Vector3._RightReadOnly = Vector3.Right();
  2825. Vector3._LeftReadOnly = Vector3.Left();
  2826. Vector3._ZeroReadOnly = Vector3.Zero();
  2827. Vector3._OneReadOnly = Vector3.One();
  2828. Vector3;
  2829. Object.defineProperties(Vector3.prototype, {
  2830. dimension: { value: [3] },
  2831. rank: { value: 1 },
  2832. });
  2833. /**
  2834. * Vector4 class created for EulerAngle class conversion to Quaternion
  2835. */
  2836. export class Vector4 {
  2837. /**
  2838. * Creates a Vector4 object from the given floats.
  2839. * @param x x value of the vector
  2840. * @param y y value of the vector
  2841. * @param z z value of the vector
  2842. * @param w w value of the vector
  2843. */
  2844. constructor(
  2845. /** x value of the vector */
  2846. x = 0,
  2847. /** y value of the vector */
  2848. y = 0,
  2849. /** z value of the vector */
  2850. z = 0,
  2851. /** w value of the vector */
  2852. w = 0) {
  2853. this.x = x;
  2854. this.y = y;
  2855. this.z = z;
  2856. this.w = w;
  2857. }
  2858. /**
  2859. * Returns the string with the Vector4 coordinates.
  2860. * @returns a string containing all the vector values
  2861. */
  2862. toString() {
  2863. return `{X: ${this.x} Y: ${this.y} Z: ${this.z} W: ${this.w}}`;
  2864. }
  2865. /**
  2866. * Returns the string "Vector4".
  2867. * @returns "Vector4"
  2868. */
  2869. getClassName() {
  2870. return "Vector4";
  2871. }
  2872. /**
  2873. * Returns the Vector4 hash code.
  2874. * @returns a unique hash code
  2875. */
  2876. getHashCode() {
  2877. const x = _ExtractAsInt(this.x);
  2878. const y = _ExtractAsInt(this.y);
  2879. const z = _ExtractAsInt(this.z);
  2880. const w = _ExtractAsInt(this.w);
  2881. let hash = x;
  2882. hash = (hash * 397) ^ y;
  2883. hash = (hash * 397) ^ z;
  2884. hash = (hash * 397) ^ w;
  2885. return hash;
  2886. }
  2887. // Operators
  2888. /**
  2889. * Returns a new array populated with 4 elements : the Vector4 coordinates.
  2890. * @returns the resulting array
  2891. */
  2892. asArray() {
  2893. return [this.x, this.y, this.z, this.w];
  2894. }
  2895. /**
  2896. * Populates the given array from the given index with the Vector4 coordinates.
  2897. * @param array array to populate
  2898. * @param index index of the array to start at (default: 0)
  2899. * @returns the Vector4.
  2900. */
  2901. toArray(array, index) {
  2902. if (index === undefined) {
  2903. index = 0;
  2904. }
  2905. array[index] = this.x;
  2906. array[index + 1] = this.y;
  2907. array[index + 2] = this.z;
  2908. array[index + 3] = this.w;
  2909. return this;
  2910. }
  2911. /**
  2912. * Update the current vector from an array
  2913. * @param array defines the destination array
  2914. * @param offset defines the offset in the destination array
  2915. * @returns the current Vector3
  2916. */
  2917. fromArray(array, offset = 0) {
  2918. Vector4.FromArrayToRef(array, offset, this);
  2919. return this;
  2920. }
  2921. /**
  2922. * Adds the given vector to the current Vector4.
  2923. * @param otherVector the vector to add
  2924. * @returns the updated Vector4.
  2925. */
  2926. addInPlace(otherVector) {
  2927. this.x += otherVector.x;
  2928. this.y += otherVector.y;
  2929. this.z += otherVector.z;
  2930. this.w += otherVector.w;
  2931. return this;
  2932. }
  2933. /**
  2934. * Adds the given coordinates to the current Vector4
  2935. * @param x defines the x coordinate of the operand
  2936. * @param y defines the y coordinate of the operand
  2937. * @param z defines the z coordinate of the operand
  2938. * @param w defines the w coordinate of the operand
  2939. * @returns the current updated Vector4
  2940. */
  2941. addInPlaceFromFloats(x, y, z, w) {
  2942. this.x += x;
  2943. this.y += y;
  2944. this.z += z;
  2945. this.w += w;
  2946. return this;
  2947. }
  2948. /**
  2949. * Returns a new Vector4 as the result of the addition of the current Vector4 and the given one.
  2950. * @param otherVector the vector to add
  2951. * @returns the resulting vector
  2952. */
  2953. add(otherVector) {
  2954. return new this.constructor(this.x + otherVector.x, this.y + otherVector.y, this.z + otherVector.z, this.w + otherVector.w);
  2955. }
  2956. /**
  2957. * Updates the given vector "result" with the result of the addition of the current Vector4 and the given one.
  2958. * @param otherVector the vector to add
  2959. * @param result the vector to store the result
  2960. * @returns result input
  2961. */
  2962. addToRef(otherVector, result) {
  2963. result.x = this.x + otherVector.x;
  2964. result.y = this.y + otherVector.y;
  2965. result.z = this.z + otherVector.z;
  2966. result.w = this.w + otherVector.w;
  2967. return result;
  2968. }
  2969. /**
  2970. * Subtract in place the given vector from the current Vector4.
  2971. * @param otherVector the vector to subtract
  2972. * @returns the updated Vector4.
  2973. */
  2974. subtractInPlace(otherVector) {
  2975. this.x -= otherVector.x;
  2976. this.y -= otherVector.y;
  2977. this.z -= otherVector.z;
  2978. this.w -= otherVector.w;
  2979. return this;
  2980. }
  2981. /**
  2982. * Returns a new Vector4 with the result of the subtraction of the given vector from the current Vector4.
  2983. * @param otherVector the vector to add
  2984. * @returns the new vector with the result
  2985. */
  2986. subtract(otherVector) {
  2987. return new this.constructor(this.x - otherVector.x, this.y - otherVector.y, this.z - otherVector.z, this.w - otherVector.w);
  2988. }
  2989. /**
  2990. * Sets the given vector "result" with the result of the subtraction of the given vector from the current Vector4.
  2991. * @param otherVector the vector to subtract
  2992. * @param result the vector to store the result
  2993. * @returns result input
  2994. */
  2995. subtractToRef(otherVector, result) {
  2996. result.x = this.x - otherVector.x;
  2997. result.y = this.y - otherVector.y;
  2998. result.z = this.z - otherVector.z;
  2999. result.w = this.w - otherVector.w;
  3000. return result;
  3001. }
  3002. /**
  3003. * Returns a new Vector4 set with the result of the subtraction of the given floats from the current Vector4 coordinates.
  3004. * @param x value to subtract
  3005. * @param y value to subtract
  3006. * @param z value to subtract
  3007. * @param w value to subtract
  3008. * @returns new vector containing the result
  3009. */
  3010. subtractFromFloats(x, y, z, w) {
  3011. return new this.constructor(this.x - x, this.y - y, this.z - z, this.w - w);
  3012. }
  3013. /**
  3014. * Sets the given vector "result" set with the result of the subtraction of the given floats from the current Vector4 coordinates.
  3015. * @param x value to subtract
  3016. * @param y value to subtract
  3017. * @param z value to subtract
  3018. * @param w value to subtract
  3019. * @param result the vector to store the result in
  3020. * @returns result input
  3021. */
  3022. subtractFromFloatsToRef(x, y, z, w, result) {
  3023. result.x = this.x - x;
  3024. result.y = this.y - y;
  3025. result.z = this.z - z;
  3026. result.w = this.w - w;
  3027. return result;
  3028. }
  3029. /**
  3030. * Returns a new Vector4 set with the current Vector4 negated coordinates.
  3031. * @returns a new vector with the negated values
  3032. */
  3033. negate() {
  3034. return new this.constructor(-this.x, -this.y, -this.z, -this.w);
  3035. }
  3036. /**
  3037. * Negate this vector in place
  3038. * @returns this
  3039. */
  3040. negateInPlace() {
  3041. this.x *= -1;
  3042. this.y *= -1;
  3043. this.z *= -1;
  3044. this.w *= -1;
  3045. return this;
  3046. }
  3047. /**
  3048. * Negate the current Vector4 and stores the result in the given vector "result" coordinates
  3049. * @param result defines the Vector3 object where to store the result
  3050. * @returns the result
  3051. */
  3052. negateToRef(result) {
  3053. return result.copyFromFloats(this.x * -1, this.y * -1, this.z * -1, this.w * -1);
  3054. }
  3055. /**
  3056. * Multiplies the current Vector4 coordinates by scale (float).
  3057. * @param scale the number to scale with
  3058. * @returns the updated Vector4.
  3059. */
  3060. scaleInPlace(scale) {
  3061. this.x *= scale;
  3062. this.y *= scale;
  3063. this.z *= scale;
  3064. this.w *= scale;
  3065. return this;
  3066. }
  3067. /**
  3068. * Returns a new Vector4 set with the current Vector4 coordinates multiplied by scale (float).
  3069. * @param scale the number to scale with
  3070. * @returns a new vector with the result
  3071. */
  3072. scale(scale) {
  3073. return new this.constructor(this.x * scale, this.y * scale, this.z * scale, this.w * scale);
  3074. }
  3075. /**
  3076. * Sets the given vector "result" with the current Vector4 coordinates multiplied by scale (float).
  3077. * @param scale the number to scale with
  3078. * @param result a vector to store the result in
  3079. * @returns result input
  3080. */
  3081. scaleToRef(scale, result) {
  3082. result.x = this.x * scale;
  3083. result.y = this.y * scale;
  3084. result.z = this.z * scale;
  3085. result.w = this.w * scale;
  3086. return result;
  3087. }
  3088. /**
  3089. * Scale the current Vector4 values by a factor and add the result to a given Vector4
  3090. * @param scale defines the scale factor
  3091. * @param result defines the Vector4 object where to store the result
  3092. * @returns result input
  3093. */
  3094. scaleAndAddToRef(scale, result) {
  3095. result.x += this.x * scale;
  3096. result.y += this.y * scale;
  3097. result.z += this.z * scale;
  3098. result.w += this.w * scale;
  3099. return result;
  3100. }
  3101. /**
  3102. * Boolean : True if the current Vector4 coordinates are stricly equal to the given ones.
  3103. * @param otherVector the vector to compare against
  3104. * @returns true if they are equal
  3105. */
  3106. equals(otherVector) {
  3107. return otherVector && this.x === otherVector.x && this.y === otherVector.y && this.z === otherVector.z && this.w === otherVector.w;
  3108. }
  3109. /**
  3110. * Boolean : True if the current Vector4 coordinates are each beneath the distance "epsilon" from the given vector ones.
  3111. * @param otherVector vector to compare against
  3112. * @param epsilon (Default: very small number)
  3113. * @returns true if they are equal
  3114. */
  3115. equalsWithEpsilon(otherVector, epsilon = Epsilon) {
  3116. return (otherVector &&
  3117. WithinEpsilon(this.x, otherVector.x, epsilon) &&
  3118. WithinEpsilon(this.y, otherVector.y, epsilon) &&
  3119. WithinEpsilon(this.z, otherVector.z, epsilon) &&
  3120. WithinEpsilon(this.w, otherVector.w, epsilon));
  3121. }
  3122. /**
  3123. * Boolean : True if the given floats are strictly equal to the current Vector4 coordinates.
  3124. * @param x x value to compare against
  3125. * @param y y value to compare against
  3126. * @param z z value to compare against
  3127. * @param w w value to compare against
  3128. * @returns true if equal
  3129. */
  3130. equalsToFloats(x, y, z, w) {
  3131. return this.x === x && this.y === y && this.z === z && this.w === w;
  3132. }
  3133. /**
  3134. * Multiplies in place the current Vector4 by the given one.
  3135. * @param otherVector vector to multiple with
  3136. * @returns the updated Vector4.
  3137. */
  3138. multiplyInPlace(otherVector) {
  3139. this.x *= otherVector.x;
  3140. this.y *= otherVector.y;
  3141. this.z *= otherVector.z;
  3142. this.w *= otherVector.w;
  3143. return this;
  3144. }
  3145. /**
  3146. * Returns a new Vector4 set with the multiplication result of the current Vector4 and the given one.
  3147. * @param otherVector vector to multiple with
  3148. * @returns resulting new vector
  3149. */
  3150. multiply(otherVector) {
  3151. return new this.constructor(this.x * otherVector.x, this.y * otherVector.y, this.z * otherVector.z, this.w * otherVector.w);
  3152. }
  3153. /**
  3154. * Updates the given vector "result" with the multiplication result of the current Vector4 and the given one.
  3155. * @param otherVector vector to multiple with
  3156. * @param result vector to store the result
  3157. * @returns result input
  3158. */
  3159. multiplyToRef(otherVector, result) {
  3160. result.x = this.x * otherVector.x;
  3161. result.y = this.y * otherVector.y;
  3162. result.z = this.z * otherVector.z;
  3163. result.w = this.w * otherVector.w;
  3164. return result;
  3165. }
  3166. /**
  3167. * Returns a new Vector4 set with the multiplication result of the given floats and the current Vector4 coordinates.
  3168. * @param x x value multiply with
  3169. * @param y y value multiply with
  3170. * @param z z value multiply with
  3171. * @param w w value multiply with
  3172. * @returns resulting new vector
  3173. */
  3174. multiplyByFloats(x, y, z, w) {
  3175. return new this.constructor(this.x * x, this.y * y, this.z * z, this.w * w);
  3176. }
  3177. /**
  3178. * Returns a new Vector4 set with the division result of the current Vector4 by the given one.
  3179. * @param otherVector vector to devide with
  3180. * @returns resulting new vector
  3181. */
  3182. divide(otherVector) {
  3183. return new this.constructor(this.x / otherVector.x, this.y / otherVector.y, this.z / otherVector.z, this.w / otherVector.w);
  3184. }
  3185. /**
  3186. * Updates the given vector "result" with the division result of the current Vector4 by the given one.
  3187. * @param otherVector vector to devide with
  3188. * @param result vector to store the result
  3189. * @returns result input
  3190. */
  3191. divideToRef(otherVector, result) {
  3192. result.x = this.x / otherVector.x;
  3193. result.y = this.y / otherVector.y;
  3194. result.z = this.z / otherVector.z;
  3195. result.w = this.w / otherVector.w;
  3196. return result;
  3197. }
  3198. /**
  3199. * Divides the current Vector3 coordinates by the given ones.
  3200. * @param otherVector vector to devide with
  3201. * @returns the updated Vector3.
  3202. */
  3203. divideInPlace(otherVector) {
  3204. return this.divideToRef(otherVector, this);
  3205. }
  3206. /**
  3207. * Updates the Vector4 coordinates with the minimum values between its own and the given vector ones
  3208. * @param other defines the second operand
  3209. * @returns the current updated Vector4
  3210. */
  3211. minimizeInPlace(other) {
  3212. if (other.x < this.x) {
  3213. this.x = other.x;
  3214. }
  3215. if (other.y < this.y) {
  3216. this.y = other.y;
  3217. }
  3218. if (other.z < this.z) {
  3219. this.z = other.z;
  3220. }
  3221. if (other.w < this.w) {
  3222. this.w = other.w;
  3223. }
  3224. return this;
  3225. }
  3226. /**
  3227. * Updates the Vector4 coordinates with the maximum values between its own and the given vector ones
  3228. * @param other defines the second operand
  3229. * @returns the current updated Vector4
  3230. */
  3231. maximizeInPlace(other) {
  3232. if (other.x > this.x) {
  3233. this.x = other.x;
  3234. }
  3235. if (other.y > this.y) {
  3236. this.y = other.y;
  3237. }
  3238. if (other.z > this.z) {
  3239. this.z = other.z;
  3240. }
  3241. if (other.w > this.w) {
  3242. this.w = other.w;
  3243. }
  3244. return this;
  3245. }
  3246. /**
  3247. * Updates the current Vector4 with the minimal coordinate values between its and the given coordinates
  3248. * @param x defines the x coordinate of the operand
  3249. * @param y defines the y coordinate of the operand
  3250. * @param z defines the z coordinate of the operand
  3251. * @param w defines the w coordinate of the operand
  3252. * @returns the current updated Vector4
  3253. */
  3254. minimizeInPlaceFromFloats(x, y, z, w) {
  3255. this.x = Math.min(x, this.x);
  3256. this.y = Math.min(y, this.y);
  3257. this.z = Math.min(z, this.z);
  3258. this.w = Math.min(w, this.w);
  3259. return this;
  3260. }
  3261. /**
  3262. * Updates the current Vector4 with the maximal coordinate values between its and the given coordinates.
  3263. * @param x defines the x coordinate of the operand
  3264. * @param y defines the y coordinate of the operand
  3265. * @param z defines the z coordinate of the operand
  3266. * @param w defines the w coordinate of the operand
  3267. * @returns the current updated Vector4
  3268. */
  3269. maximizeInPlaceFromFloats(x, y, z, w) {
  3270. this.x = Math.max(x, this.x);
  3271. this.y = Math.max(y, this.y);
  3272. this.z = Math.max(z, this.z);
  3273. this.w = Math.max(w, this.w);
  3274. return this;
  3275. }
  3276. /**
  3277. * Gets the current Vector4's floored values and stores them in result
  3278. * @param result the vector to store the result in
  3279. * @returns the result vector
  3280. */
  3281. floorToRef(result) {
  3282. result.x = Math.floor(this.x);
  3283. result.y = Math.floor(this.y);
  3284. result.z = Math.floor(this.z);
  3285. result.w = Math.floor(this.w);
  3286. return result;
  3287. }
  3288. /**
  3289. * Gets a new Vector4 from current Vector4 floored values
  3290. * @returns a new Vector4
  3291. */
  3292. floor() {
  3293. return new this.constructor(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z), Math.floor(this.w));
  3294. }
  3295. /**
  3296. * Gets the current Vector4's fractional values and stores them in result
  3297. * @param result the vector to store the result in
  3298. * @returns the result vector
  3299. */
  3300. fractToRef(result) {
  3301. result.x = this.x - Math.floor(this.x);
  3302. result.y = this.y - Math.floor(this.y);
  3303. result.z = this.z - Math.floor(this.z);
  3304. result.w = this.w - Math.floor(this.w);
  3305. return result;
  3306. }
  3307. /**
  3308. * Gets a new Vector4 from current Vector4 fractional values
  3309. * @returns a new Vector4
  3310. */
  3311. fract() {
  3312. return new this.constructor(this.x - Math.floor(this.x), this.y - Math.floor(this.y), this.z - Math.floor(this.z), this.w - Math.floor(this.w));
  3313. }
  3314. // Properties
  3315. /**
  3316. * Returns the Vector4 length (float).
  3317. * @returns the length
  3318. */
  3319. length() {
  3320. return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
  3321. }
  3322. /**
  3323. * Returns the Vector4 squared length (float).
  3324. * @returns the length squared
  3325. */
  3326. lengthSquared() {
  3327. return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
  3328. }
  3329. // Methods
  3330. /**
  3331. * Normalizes in place the Vector4.
  3332. * @returns the updated Vector4.
  3333. */
  3334. normalize() {
  3335. return this.normalizeFromLength(this.length());
  3336. }
  3337. /**
  3338. * Normalize the current Vector4 with the given input length.
  3339. * Please note that this is an in place operation.
  3340. * @param len the length of the vector
  3341. * @returns the current updated Vector4
  3342. */
  3343. normalizeFromLength(len) {
  3344. if (len === 0 || len === 1.0) {
  3345. return this;
  3346. }
  3347. return this.scaleInPlace(1.0 / len);
  3348. }
  3349. /**
  3350. * Normalize the current Vector4 to a new vector
  3351. * @returns the new Vector4
  3352. */
  3353. normalizeToNew() {
  3354. const normalized = new this.constructor();
  3355. this.normalizeToRef(normalized);
  3356. return normalized;
  3357. }
  3358. /**
  3359. * Normalize the current Vector4 to the reference
  3360. * @param reference define the Vector4 to update
  3361. * @returns the updated Vector4
  3362. */
  3363. normalizeToRef(reference) {
  3364. const len = this.length();
  3365. if (len === 0 || len === 1.0) {
  3366. return reference.copyFrom(this);
  3367. }
  3368. return this.scaleToRef(1.0 / len, reference);
  3369. }
  3370. /**
  3371. * Returns a new Vector3 from the Vector4 (x, y, z) coordinates.
  3372. * @returns this converted to a new vector3
  3373. */
  3374. toVector3() {
  3375. return new Vector3(this.x, this.y, this.z);
  3376. }
  3377. /**
  3378. * Returns a new Vector4 copied from the current one.
  3379. * @returns the new cloned vector
  3380. */
  3381. clone() {
  3382. return new this.constructor(this.x, this.y, this.z, this.w);
  3383. }
  3384. /**
  3385. * Updates the current Vector4 with the given one coordinates.
  3386. * @param source the source vector to copy from
  3387. * @returns the updated Vector4.
  3388. */
  3389. copyFrom(source) {
  3390. this.x = source.x;
  3391. this.y = source.y;
  3392. this.z = source.z;
  3393. this.w = source.w;
  3394. return this;
  3395. }
  3396. /**
  3397. * Updates the current Vector4 coordinates with the given floats.
  3398. * @param x float to copy from
  3399. * @param y float to copy from
  3400. * @param z float to copy from
  3401. * @param w float to copy from
  3402. * @returns the updated Vector4.
  3403. */
  3404. copyFromFloats(x, y, z, w) {
  3405. this.x = x;
  3406. this.y = y;
  3407. this.z = z;
  3408. this.w = w;
  3409. return this;
  3410. }
  3411. /**
  3412. * Updates the current Vector4 coordinates with the given floats.
  3413. * @param x float to set from
  3414. * @param y float to set from
  3415. * @param z float to set from
  3416. * @param w float to set from
  3417. * @returns the updated Vector4.
  3418. */
  3419. set(x, y, z, w) {
  3420. return this.copyFromFloats(x, y, z, w);
  3421. }
  3422. /**
  3423. * Copies the given float to the current Vector4 coordinates
  3424. * @param v defines the x, y, z and w coordinates of the operand
  3425. * @returns the current updated Vector4
  3426. */
  3427. setAll(v) {
  3428. this.x = this.y = this.z = this.w = v;
  3429. return this;
  3430. }
  3431. /**
  3432. * Returns the dot product (float) between the current vectors and "otherVector"
  3433. * @param otherVector defines the right operand
  3434. * @returns the dot product
  3435. */
  3436. dot(otherVector) {
  3437. return this.x * otherVector.x + this.y * otherVector.y + this.z * otherVector.z + this.w * otherVector.w;
  3438. }
  3439. // Statics
  3440. /**
  3441. * Returns a new Vector4 set from the starting index of the given array.
  3442. * @param array the array to pull values from
  3443. * @param offset the offset into the array to start at
  3444. * @returns the new vector
  3445. */
  3446. static FromArray(array, offset) {
  3447. if (!offset) {
  3448. offset = 0;
  3449. }
  3450. return new Vector4(array[offset], array[offset + 1], array[offset + 2], array[offset + 3]);
  3451. }
  3452. /**
  3453. * Updates the given vector "result" from the starting index of the given array.
  3454. * @param array the array to pull values from
  3455. * @param offset the offset into the array to start at
  3456. * @param result the vector to store the result in
  3457. * @returns result input
  3458. */
  3459. static FromArrayToRef(array, offset, result) {
  3460. result.x = array[offset];
  3461. result.y = array[offset + 1];
  3462. result.z = array[offset + 2];
  3463. result.w = array[offset + 3];
  3464. return result;
  3465. }
  3466. /**
  3467. * Updates the given vector "result" from the starting index of the given Float32Array.
  3468. * @param array the array to pull values from
  3469. * @param offset the offset into the array to start at
  3470. * @param result the vector to store the result in
  3471. * @returns result input
  3472. */
  3473. static FromFloatArrayToRef(array, offset, result) {
  3474. Vector4.FromArrayToRef(array, offset, result);
  3475. return result;
  3476. }
  3477. /**
  3478. * Updates the given vector "result" coordinates from the given floats.
  3479. * @param x float to set from
  3480. * @param y float to set from
  3481. * @param z float to set from
  3482. * @param w float to set from
  3483. * @param result the vector to the floats in
  3484. * @returns result input
  3485. */
  3486. static FromFloatsToRef(x, y, z, w, result) {
  3487. result.x = x;
  3488. result.y = y;
  3489. result.z = z;
  3490. result.w = w;
  3491. return result;
  3492. }
  3493. /**
  3494. * Returns a new Vector4 set to (0.0, 0.0, 0.0, 0.0)
  3495. * @returns the new vector
  3496. */
  3497. static Zero() {
  3498. return new Vector4(0.0, 0.0, 0.0, 0.0);
  3499. }
  3500. /**
  3501. * Returns a new Vector4 set to (1.0, 1.0, 1.0, 1.0)
  3502. * @returns the new vector
  3503. */
  3504. static One() {
  3505. return new Vector4(1.0, 1.0, 1.0, 1.0);
  3506. }
  3507. /**
  3508. * Returns a new Vector4 with random values between min and max
  3509. * @param min the minimum random value
  3510. * @param max the maximum random value
  3511. * @returns a Vector4 with random values between min and max
  3512. */
  3513. static Random(min = 0, max = 1) {
  3514. return new Vector4(RandomRange(min, max), RandomRange(min, max), RandomRange(min, max), RandomRange(min, max));
  3515. }
  3516. /**
  3517. * Sets a Vector4 with random values between min and max
  3518. * @param min the minimum random value
  3519. * @param max the maximum random value
  3520. * @param ref the ref to store the values in
  3521. * @returns the ref with random values between min and max
  3522. */
  3523. static RandomToRef(min = 0, max = 1, ref) {
  3524. return ref.copyFromFloats(RandomRange(min, max), RandomRange(min, max), RandomRange(min, max), RandomRange(min, max));
  3525. }
  3526. /**
  3527. * Returns a new Vector4 set with the coordinates of "value", if the vector "value" is in the cube defined by the vectors "min" and "max"
  3528. * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
  3529. * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
  3530. * @param value defines the current value
  3531. * @param min defines the lower range value
  3532. * @param max defines the upper range value
  3533. * @returns the new Vector4
  3534. */
  3535. static Clamp(value, min, max) {
  3536. const result = new value.constructor();
  3537. Vector4.ClampToRef(value, min, max, result);
  3538. return result;
  3539. }
  3540. /**
  3541. * Sets the given vector "result" with the coordinates of "value", if the vector "value" is in the cube defined by the vectors "min" and "max"
  3542. * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
  3543. * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
  3544. * @param value defines the current value
  3545. * @param min defines the lower range value
  3546. * @param max defines the upper range value
  3547. * @param result defines the Vector4 where to store the result
  3548. * @returns result input
  3549. */
  3550. static ClampToRef(value, min, max, result) {
  3551. return result.copyFromFloats(Clamp(value.x, min.x, max.x), Clamp(value.y, min.y, max.y), Clamp(value.z, min.z, max.z), Clamp(value.w, min.w, max.w));
  3552. }
  3553. /**
  3554. * Checks if a given vector is inside a specific range
  3555. * Example Playground https://playground.babylonjs.com/#R1F8YU#75
  3556. * @param v defines the vector to test
  3557. * @param min defines the minimum range
  3558. * @param max defines the maximum range
  3559. */
  3560. static CheckExtends(v, min, max) {
  3561. min.minimizeInPlace(v);
  3562. max.maximizeInPlace(v);
  3563. }
  3564. /**
  3565. * Gets a zero Vector4 that must not be updated
  3566. */
  3567. static get ZeroReadOnly() {
  3568. return Vector4._ZeroReadOnly;
  3569. }
  3570. /**
  3571. * Returns a new normalized Vector4 from the given one.
  3572. * @param vector the vector to normalize
  3573. * @returns the vector
  3574. */
  3575. static Normalize(vector) {
  3576. const result = Vector4.Zero();
  3577. Vector4.NormalizeToRef(vector, result);
  3578. return result;
  3579. }
  3580. /**
  3581. * Updates the given vector "result" from the normalization of the given one.
  3582. * @param vector the vector to normalize
  3583. * @param result the vector to store the result in
  3584. * @returns result input
  3585. */
  3586. static NormalizeToRef(vector, result) {
  3587. vector.normalizeToRef(result);
  3588. return result;
  3589. }
  3590. /**
  3591. * Returns a vector with the minimum values from the left and right vectors
  3592. * @param left left vector to minimize
  3593. * @param right right vector to minimize
  3594. * @returns a new vector with the minimum of the left and right vector values
  3595. */
  3596. static Minimize(left, right) {
  3597. const min = new left.constructor();
  3598. min.copyFrom(left);
  3599. min.minimizeInPlace(right);
  3600. return min;
  3601. }
  3602. /**
  3603. * Returns a vector with the maximum values from the left and right vectors
  3604. * @param left left vector to maximize
  3605. * @param right right vector to maximize
  3606. * @returns a new vector with the maximum of the left and right vector values
  3607. */
  3608. static Maximize(left, right) {
  3609. const max = new left.constructor();
  3610. max.copyFrom(left);
  3611. max.maximizeInPlace(right);
  3612. return max;
  3613. }
  3614. /**
  3615. * Returns the distance (float) between the vectors "value1" and "value2".
  3616. * @param value1 value to calulate the distance between
  3617. * @param value2 value to calulate the distance between
  3618. * @returns the distance between the two vectors
  3619. */
  3620. static Distance(value1, value2) {
  3621. return Math.sqrt(Vector4.DistanceSquared(value1, value2));
  3622. }
  3623. /**
  3624. * Returns the squared distance (float) between the vectors "value1" and "value2".
  3625. * @param value1 value to calulate the distance between
  3626. * @param value2 value to calulate the distance between
  3627. * @returns the distance between the two vectors squared
  3628. */
  3629. static DistanceSquared(value1, value2) {
  3630. const x = value1.x - value2.x;
  3631. const y = value1.y - value2.y;
  3632. const z = value1.z - value2.z;
  3633. const w = value1.w - value2.w;
  3634. return x * x + y * y + z * z + w * w;
  3635. }
  3636. /**
  3637. * Returns a new Vector4 located at the center between the vectors "value1" and "value2".
  3638. * @param value1 value to calulate the center between
  3639. * @param value2 value to calulate the center between
  3640. * @returns the center between the two vectors
  3641. */
  3642. static Center(value1, value2) {
  3643. return Vector4.CenterToRef(value1, value2, Vector4.Zero());
  3644. }
  3645. /**
  3646. * Gets the center of the vectors "value1" and "value2" and stores the result in the vector "ref"
  3647. * @param value1 defines first vector
  3648. * @param value2 defines second vector
  3649. * @param ref defines third vector
  3650. * @returns ref
  3651. */
  3652. static CenterToRef(value1, value2, ref) {
  3653. return ref.copyFromFloats((value1.x + value2.x) / 2, (value1.y + value2.y) / 2, (value1.z + value2.z) / 2, (value1.w + value2.w) / 2);
  3654. }
  3655. /**
  3656. * Returns a new Vector4 set with the result of the transformation by the given matrix of the given vector.
  3657. * This method computes tranformed coordinates only, not transformed direction vectors (ie. it takes translation in account)
  3658. * The difference with Vector3.TransformCoordinates is that the w component is not used to divide the other coordinates but is returned in the w coordinate instead
  3659. * @param vector defines the Vector3 to transform
  3660. * @param transformation defines the transformation matrix
  3661. * @returns the transformed Vector4
  3662. */
  3663. static TransformCoordinates(vector, transformation) {
  3664. const result = Vector4.Zero();
  3665. Vector4.TransformCoordinatesToRef(vector, transformation, result);
  3666. return result;
  3667. }
  3668. /**
  3669. * Sets the given vector "result" coordinates with the result of the transformation by the given matrix of the given vector
  3670. * This method computes tranformed coordinates only, not transformed direction vectors (ie. it takes translation in account)
  3671. * The difference with Vector3.TransformCoordinatesToRef is that the w component is not used to divide the other coordinates but is returned in the w coordinate instead
  3672. * @param vector defines the Vector3 to transform
  3673. * @param transformation defines the transformation matrix
  3674. * @param result defines the Vector4 where to store the result
  3675. * @returns result input
  3676. */
  3677. static TransformCoordinatesToRef(vector, transformation, result) {
  3678. Vector4.TransformCoordinatesFromFloatsToRef(vector._x, vector._y, vector._z, transformation, result);
  3679. return result;
  3680. }
  3681. /**
  3682. * Sets the given vector "result" coordinates with the result of the transformation by the given matrix of the given floats (x, y, z)
  3683. * This method computes tranformed coordinates only, not transformed direction vectors
  3684. * The difference with Vector3.TransformCoordinatesFromFloatsToRef is that the w component is not used to divide the other coordinates but is returned in the w coordinate instead
  3685. * @param x define the x coordinate of the source vector
  3686. * @param y define the y coordinate of the source vector
  3687. * @param z define the z coordinate of the source vector
  3688. * @param transformation defines the transformation matrix
  3689. * @param result defines the Vector4 where to store the result
  3690. * @returns result input
  3691. */
  3692. static TransformCoordinatesFromFloatsToRef(x, y, z, transformation, result) {
  3693. const m = transformation.m;
  3694. const rx = x * m[0] + y * m[4] + z * m[8] + m[12];
  3695. const ry = x * m[1] + y * m[5] + z * m[9] + m[13];
  3696. const rz = x * m[2] + y * m[6] + z * m[10] + m[14];
  3697. const rw = x * m[3] + y * m[7] + z * m[11] + m[15];
  3698. result.x = rx;
  3699. result.y = ry;
  3700. result.z = rz;
  3701. result.w = rw;
  3702. return result;
  3703. }
  3704. /**
  3705. * Returns a new Vector4 set with the result of the normal transformation by the given matrix of the given vector.
  3706. * This methods computes transformed normalized direction vectors only.
  3707. * @param vector the vector to transform
  3708. * @param transformation the transformation matrix to apply
  3709. * @returns the new vector
  3710. */
  3711. static TransformNormal(vector, transformation) {
  3712. const result = new vector.constructor();
  3713. Vector4.TransformNormalToRef(vector, transformation, result);
  3714. return result;
  3715. }
  3716. /**
  3717. * Sets the given vector "result" with the result of the normal transformation by the given matrix of the given vector.
  3718. * This methods computes transformed normalized direction vectors only.
  3719. * @param vector the vector to transform
  3720. * @param transformation the transformation matrix to apply
  3721. * @param result the vector to store the result in
  3722. * @returns result input
  3723. */
  3724. static TransformNormalToRef(vector, transformation, result) {
  3725. const m = transformation.m;
  3726. const x = vector.x * m[0] + vector.y * m[4] + vector.z * m[8];
  3727. const y = vector.x * m[1] + vector.y * m[5] + vector.z * m[9];
  3728. const z = vector.x * m[2] + vector.y * m[6] + vector.z * m[10];
  3729. result.x = x;
  3730. result.y = y;
  3731. result.z = z;
  3732. result.w = vector.w;
  3733. return result;
  3734. }
  3735. /**
  3736. * Sets the given vector "result" with the result of the normal transformation by the given matrix of the given floats (x, y, z, w).
  3737. * This methods computes transformed normalized direction vectors only.
  3738. * @param x value to transform
  3739. * @param y value to transform
  3740. * @param z value to transform
  3741. * @param w value to transform
  3742. * @param transformation the transformation matrix to apply
  3743. * @param result the vector to store the results in
  3744. * @returns result input
  3745. */
  3746. static TransformNormalFromFloatsToRef(x, y, z, w, transformation, result) {
  3747. const m = transformation.m;
  3748. result.x = x * m[0] + y * m[4] + z * m[8];
  3749. result.y = x * m[1] + y * m[5] + z * m[9];
  3750. result.z = x * m[2] + y * m[6] + z * m[10];
  3751. result.w = w;
  3752. return result;
  3753. }
  3754. /**
  3755. * Creates a new Vector4 from a Vector3
  3756. * @param source defines the source data
  3757. * @param w defines the 4th component (default is 0)
  3758. * @returns a new Vector4
  3759. */
  3760. static FromVector3(source, w = 0) {
  3761. return new Vector4(source._x, source._y, source._z, w);
  3762. }
  3763. /**
  3764. * Returns the dot product (float) between the vectors "left" and "right"
  3765. * @param left defines the left operand
  3766. * @param right defines the right operand
  3767. * @returns the dot product
  3768. */
  3769. static Dot(left, right) {
  3770. return left.dot(right);
  3771. }
  3772. }
  3773. Vector4._ZeroReadOnly = Vector4.Zero();
  3774. Vector4;
  3775. Object.defineProperties(Vector4.prototype, {
  3776. dimension: { value: [4] },
  3777. rank: { value: 1 },
  3778. });
  3779. /**
  3780. * Class used to store quaternion data
  3781. * Example Playground - Overview - https://playground.babylonjs.com/#L49EJ7#100
  3782. * @see https://en.wikipedia.org/wiki/Quaternion
  3783. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/transforms
  3784. */
  3785. export class Quaternion {
  3786. /** Gets or sets the x coordinate */
  3787. get x() {
  3788. return this._x;
  3789. }
  3790. set x(value) {
  3791. this._x = value;
  3792. this._isDirty = true;
  3793. }
  3794. /** Gets or sets the y coordinate */
  3795. get y() {
  3796. return this._y;
  3797. }
  3798. set y(value) {
  3799. this._y = value;
  3800. this._isDirty = true;
  3801. }
  3802. /** Gets or sets the z coordinate */
  3803. get z() {
  3804. return this._z;
  3805. }
  3806. set z(value) {
  3807. this._z = value;
  3808. this._isDirty = true;
  3809. }
  3810. /** Gets or sets the w coordinate */
  3811. get w() {
  3812. return this._w;
  3813. }
  3814. set w(value) {
  3815. this._w = value;
  3816. this._isDirty = true;
  3817. }
  3818. /**
  3819. * Creates a new Quaternion from the given floats
  3820. * @param x defines the first component (0 by default)
  3821. * @param y defines the second component (0 by default)
  3822. * @param z defines the third component (0 by default)
  3823. * @param w defines the fourth component (1.0 by default)
  3824. */
  3825. constructor(x = 0.0, y = 0.0, z = 0.0, w = 1.0) {
  3826. /** @internal */
  3827. this._isDirty = true;
  3828. this._x = x;
  3829. this._y = y;
  3830. this._z = z;
  3831. this._w = w;
  3832. }
  3833. /**
  3834. * Gets a string representation for the current quaternion
  3835. * @returns a string with the Quaternion coordinates
  3836. */
  3837. toString() {
  3838. return `{X: ${this._x} Y: ${this._y} Z: ${this._z} W: ${this._w}}`;
  3839. }
  3840. /**
  3841. * Gets the class name of the quaternion
  3842. * @returns the string "Quaternion"
  3843. */
  3844. getClassName() {
  3845. return "Quaternion";
  3846. }
  3847. /**
  3848. * Gets a hash code for this quaternion
  3849. * @returns the quaternion hash code
  3850. */
  3851. getHashCode() {
  3852. const x = _ExtractAsInt(this._x);
  3853. const y = _ExtractAsInt(this._y);
  3854. const z = _ExtractAsInt(this._z);
  3855. const w = _ExtractAsInt(this._w);
  3856. let hash = x;
  3857. hash = (hash * 397) ^ y;
  3858. hash = (hash * 397) ^ z;
  3859. hash = (hash * 397) ^ w;
  3860. return hash;
  3861. }
  3862. /**
  3863. * Copy the quaternion to an array
  3864. * Example Playground https://playground.babylonjs.com/#L49EJ7#13
  3865. * @returns a new array populated with 4 elements from the quaternion coordinates
  3866. */
  3867. asArray() {
  3868. return [this._x, this._y, this._z, this._w];
  3869. }
  3870. /**
  3871. * Stores from the starting index in the given array the Quaternion successive values
  3872. * Example Playground https://playground.babylonjs.com/#L49EJ7#59
  3873. * @param array defines the array where to store the x,y,z,w components
  3874. * @param index defines an optional index in the target array to define where to start storing values
  3875. * @returns the current Quaternion object
  3876. */
  3877. toArray(array, index = 0) {
  3878. array[index] = this._x;
  3879. array[index + 1] = this._y;
  3880. array[index + 2] = this._z;
  3881. array[index + 3] = this._w;
  3882. return this;
  3883. }
  3884. fromArray(array, index = 0) {
  3885. return Quaternion.FromArrayToRef(array, index, this);
  3886. }
  3887. /**
  3888. * Check if two quaternions are equals
  3889. * Example Playground https://playground.babylonjs.com/#L49EJ7#38
  3890. * @param otherQuaternion defines the second operand
  3891. * @returns true if the current quaternion and the given one coordinates are strictly equals
  3892. */
  3893. equals(otherQuaternion) {
  3894. return otherQuaternion && this._x === otherQuaternion._x && this._y === otherQuaternion._y && this._z === otherQuaternion._z && this._w === otherQuaternion._w;
  3895. }
  3896. /**
  3897. * Gets a boolean if two quaternions are equals (using an epsilon value)
  3898. * Example Playground https://playground.babylonjs.com/#L49EJ7#37
  3899. * @param otherQuaternion defines the other quaternion
  3900. * @param epsilon defines the minimal distance to consider equality
  3901. * @returns true if the given quaternion coordinates are close to the current ones by a distance of epsilon.
  3902. */
  3903. equalsWithEpsilon(otherQuaternion, epsilon = Epsilon) {
  3904. return (otherQuaternion &&
  3905. WithinEpsilon(this._x, otherQuaternion._x, epsilon) &&
  3906. WithinEpsilon(this._y, otherQuaternion._y, epsilon) &&
  3907. WithinEpsilon(this._z, otherQuaternion._z, epsilon) &&
  3908. WithinEpsilon(this._w, otherQuaternion._w, epsilon));
  3909. }
  3910. /**
  3911. * Clone the current quaternion
  3912. * Example Playground https://playground.babylonjs.com/#L49EJ7#12
  3913. * @returns a new quaternion copied from the current one
  3914. */
  3915. clone() {
  3916. return new this.constructor(this._x, this._y, this._z, this._w);
  3917. }
  3918. /**
  3919. * Copy a quaternion to the current one
  3920. * Example Playground https://playground.babylonjs.com/#L49EJ7#86
  3921. * @param other defines the other quaternion
  3922. * @returns the updated current quaternion
  3923. */
  3924. copyFrom(other) {
  3925. this._x = other._x;
  3926. this._y = other._y;
  3927. this._z = other._z;
  3928. this._w = other._w;
  3929. this._isDirty = true;
  3930. return this;
  3931. }
  3932. /**
  3933. * Updates the current quaternion with the given float coordinates
  3934. * Example Playground https://playground.babylonjs.com/#L49EJ7#87
  3935. * @param x defines the x coordinate
  3936. * @param y defines the y coordinate
  3937. * @param z defines the z coordinate
  3938. * @param w defines the w coordinate
  3939. * @returns the updated current quaternion
  3940. */
  3941. copyFromFloats(x, y, z, w) {
  3942. this._x = x;
  3943. this._y = y;
  3944. this._z = z;
  3945. this._w = w;
  3946. this._isDirty = true;
  3947. return this;
  3948. }
  3949. /**
  3950. * Updates the current quaternion from the given float coordinates
  3951. * Example Playground https://playground.babylonjs.com/#L49EJ7#56
  3952. * @param x defines the x coordinate
  3953. * @param y defines the y coordinate
  3954. * @param z defines the z coordinate
  3955. * @param w defines the w coordinate
  3956. * @returns the updated current quaternion
  3957. */
  3958. set(x, y, z, w) {
  3959. return this.copyFromFloats(x, y, z, w);
  3960. }
  3961. setAll(value) {
  3962. return this.copyFromFloats(value, value, value, value);
  3963. }
  3964. /**
  3965. * Adds two quaternions
  3966. * Example Playground https://playground.babylonjs.com/#L49EJ7#10
  3967. * @param other defines the second operand
  3968. * @returns a new quaternion as the addition result of the given one and the current quaternion
  3969. */
  3970. add(other) {
  3971. return new this.constructor(this._x + other._x, this._y + other._y, this._z + other._z, this._w + other._w);
  3972. }
  3973. /**
  3974. * Add a quaternion to the current one
  3975. * Example Playground https://playground.babylonjs.com/#L49EJ7#11
  3976. * @param other defines the quaternion to add
  3977. * @returns the current quaternion
  3978. */
  3979. addInPlace(other) {
  3980. this._x += other._x;
  3981. this._y += other._y;
  3982. this._z += other._z;
  3983. this._w += other._w;
  3984. this._isDirty = true;
  3985. return this;
  3986. }
  3987. addToRef(other, result) {
  3988. result._x = this._x + other._x;
  3989. result._y = this._y + other._y;
  3990. result._z = this._z + other._z;
  3991. result._w = this._w + other._w;
  3992. result._isDirty = true;
  3993. return result;
  3994. }
  3995. addInPlaceFromFloats(x, y, z, w) {
  3996. this._x += x;
  3997. this._y += y;
  3998. this._z += z;
  3999. this._w += w;
  4000. this._isDirty = true;
  4001. return this;
  4002. }
  4003. subtractToRef(other, result) {
  4004. result._x = this._x - other._x;
  4005. result._y = this._y - other._y;
  4006. result._z = this._z - other._z;
  4007. result._w = this._w - other._w;
  4008. result._isDirty = true;
  4009. return result;
  4010. }
  4011. subtractFromFloats(x, y, z, w) {
  4012. return this.subtractFromFloatsToRef(x, y, z, w, new this.constructor());
  4013. }
  4014. subtractFromFloatsToRef(x, y, z, w, result) {
  4015. result._x = this._x - x;
  4016. result._y = this._y - y;
  4017. result._z = this._z - z;
  4018. result._w = this._w - w;
  4019. result._isDirty = true;
  4020. return result;
  4021. }
  4022. /**
  4023. * Subtract two quaternions
  4024. * Example Playground https://playground.babylonjs.com/#L49EJ7#57
  4025. * @param other defines the second operand
  4026. * @returns a new quaternion as the subtraction result of the given one from the current one
  4027. */
  4028. subtract(other) {
  4029. return new this.constructor(this._x - other._x, this._y - other._y, this._z - other._z, this._w - other._w);
  4030. }
  4031. /**
  4032. * Subtract a quaternion to the current one
  4033. * Example Playground https://playground.babylonjs.com/#L49EJ7#58
  4034. * @param other defines the quaternion to subtract
  4035. * @returns the current quaternion
  4036. */
  4037. subtractInPlace(other) {
  4038. this._x -= other._x;
  4039. this._y -= other._y;
  4040. this._z -= other._z;
  4041. this._w -= other._w;
  4042. this._isDirty = true;
  4043. return this;
  4044. }
  4045. /**
  4046. * Multiplies the current quaternion by a scale factor
  4047. * Example Playground https://playground.babylonjs.com/#L49EJ7#88
  4048. * @param value defines the scale factor
  4049. * @returns a new quaternion set by multiplying the current quaternion coordinates by the float "scale"
  4050. */
  4051. scale(value) {
  4052. return new this.constructor(this._x * value, this._y * value, this._z * value, this._w * value);
  4053. }
  4054. /**
  4055. * Scale the current quaternion values by a factor and stores the result to a given quaternion
  4056. * Example Playground https://playground.babylonjs.com/#L49EJ7#89
  4057. * @param scale defines the scale factor
  4058. * @param result defines the Quaternion object where to store the result
  4059. * @returns result input
  4060. */
  4061. scaleToRef(scale, result) {
  4062. result._x = this._x * scale;
  4063. result._y = this._y * scale;
  4064. result._z = this._z * scale;
  4065. result._w = this._w * scale;
  4066. result._isDirty = true;
  4067. return result;
  4068. }
  4069. /**
  4070. * Multiplies in place the current quaternion by a scale factor
  4071. * Example Playground https://playground.babylonjs.com/#L49EJ7#90
  4072. * @param value defines the scale factor
  4073. * @returns the current modified quaternion
  4074. */
  4075. scaleInPlace(value) {
  4076. this._x *= value;
  4077. this._y *= value;
  4078. this._z *= value;
  4079. this._w *= value;
  4080. this._isDirty = true;
  4081. return this;
  4082. }
  4083. /**
  4084. * Scale the current quaternion values by a factor and add the result to a given quaternion
  4085. * Example Playground https://playground.babylonjs.com/#L49EJ7#91
  4086. * @param scale defines the scale factor
  4087. * @param result defines the Quaternion object where to store the result
  4088. * @returns result input
  4089. */
  4090. scaleAndAddToRef(scale, result) {
  4091. result._x += this._x * scale;
  4092. result._y += this._y * scale;
  4093. result._z += this._z * scale;
  4094. result._w += this._w * scale;
  4095. result._isDirty = true;
  4096. return result;
  4097. }
  4098. /**
  4099. * Multiplies two quaternions
  4100. * Example Playground https://playground.babylonjs.com/#L49EJ7#43
  4101. * @param q1 defines the second operand
  4102. * @returns a new quaternion set as the multiplication result of the current one with the given one "q1"
  4103. */
  4104. multiply(q1) {
  4105. const result = new this.constructor(0, 0, 0, 1.0);
  4106. this.multiplyToRef(q1, result);
  4107. return result;
  4108. }
  4109. /**
  4110. * Sets the given "result" as the multiplication result of the current one with the given one "q1"
  4111. * Example Playground https://playground.babylonjs.com/#L49EJ7#45
  4112. * @param q1 defines the second operand
  4113. * @param result defines the target quaternion
  4114. * @returns the current quaternion
  4115. */
  4116. multiplyToRef(q1, result) {
  4117. const x = this._x * q1._w + this._y * q1._z - this._z * q1._y + this._w * q1._x;
  4118. const y = -this._x * q1._z + this._y * q1._w + this._z * q1._x + this._w * q1._y;
  4119. const z = this._x * q1._y - this._y * q1._x + this._z * q1._w + this._w * q1._z;
  4120. const w = -this._x * q1._x - this._y * q1._y - this._z * q1._z + this._w * q1._w;
  4121. result.copyFromFloats(x, y, z, w);
  4122. return result;
  4123. }
  4124. /**
  4125. * Updates the current quaternion with the multiplication of itself with the given one "q1"
  4126. * Example Playground https://playground.babylonjs.com/#L49EJ7#46
  4127. * @param other defines the second operand
  4128. * @returns the currentupdated quaternion
  4129. */
  4130. multiplyInPlace(other) {
  4131. return this.multiplyToRef(other, this);
  4132. }
  4133. multiplyByFloats(x, y, z, w) {
  4134. this._x *= x;
  4135. this._y *= y;
  4136. this._z *= z;
  4137. this._w *= w;
  4138. this._isDirty = true;
  4139. return this;
  4140. }
  4141. /**
  4142. * @internal
  4143. * Do not use
  4144. */
  4145. divide(_other) {
  4146. throw new ReferenceError("Can not divide a quaternion");
  4147. }
  4148. /**
  4149. * @internal
  4150. * Do not use
  4151. */
  4152. divideToRef(_other, _result) {
  4153. throw new ReferenceError("Can not divide a quaternion");
  4154. }
  4155. /**
  4156. * @internal
  4157. * Do not use
  4158. */
  4159. divideInPlace(_other) {
  4160. throw new ReferenceError("Can not divide a quaternion");
  4161. }
  4162. /**
  4163. * @internal
  4164. * Do not use
  4165. */
  4166. minimizeInPlace() {
  4167. throw new ReferenceError("Can not minimize a quaternion");
  4168. }
  4169. /**
  4170. * @internal
  4171. * Do not use
  4172. */
  4173. minimizeInPlaceFromFloats() {
  4174. throw new ReferenceError("Can not minimize a quaternion");
  4175. }
  4176. /**
  4177. * @internal
  4178. * Do not use
  4179. */
  4180. maximizeInPlace() {
  4181. throw new ReferenceError("Can not maximize a quaternion");
  4182. }
  4183. /**
  4184. * @internal
  4185. * Do not use
  4186. */
  4187. maximizeInPlaceFromFloats() {
  4188. throw new ReferenceError("Can not maximize a quaternion");
  4189. }
  4190. negate() {
  4191. return this.negateToRef(new this.constructor());
  4192. }
  4193. negateInPlace() {
  4194. this._x = -this._x;
  4195. this._y = -this._y;
  4196. this._z = -this._z;
  4197. this._w = -this._w;
  4198. this._isDirty = true;
  4199. return this;
  4200. }
  4201. negateToRef(result) {
  4202. result._x = -this._x;
  4203. result._y = -this._y;
  4204. result._z = -this._z;
  4205. result._w = -this._w;
  4206. result._isDirty = true;
  4207. return result;
  4208. }
  4209. equalsToFloats(x, y, z, w) {
  4210. return this._x === x && this._y === y && this._z === z && this._w === w;
  4211. }
  4212. /**
  4213. * @internal
  4214. * Do not use
  4215. */
  4216. floorToRef(_result) {
  4217. throw new ReferenceError("Can not floor a quaternion");
  4218. }
  4219. /**
  4220. * @internal
  4221. * Do not use
  4222. */
  4223. floor() {
  4224. throw new ReferenceError("Can not floor a quaternion");
  4225. }
  4226. /**
  4227. * @internal
  4228. * Do not use
  4229. */
  4230. fractToRef(_result) {
  4231. throw new ReferenceError("Can not fract a quaternion");
  4232. }
  4233. /**
  4234. * @internal
  4235. * Do not use
  4236. */
  4237. fract() {
  4238. throw new ReferenceError("Can not fract a quaternion");
  4239. }
  4240. /**
  4241. * Conjugates the current quaternion and stores the result in the given quaternion
  4242. * Example Playground https://playground.babylonjs.com/#L49EJ7#81
  4243. * @param ref defines the target quaternion
  4244. * @returns result input
  4245. */
  4246. conjugateToRef(ref) {
  4247. ref.copyFromFloats(-this._x, -this._y, -this._z, this._w);
  4248. return ref;
  4249. }
  4250. /**
  4251. * Conjugates in place the current quaternion
  4252. * Example Playground https://playground.babylonjs.com/#L49EJ7#82
  4253. * @returns the current updated quaternion
  4254. */
  4255. conjugateInPlace() {
  4256. this._x *= -1;
  4257. this._y *= -1;
  4258. this._z *= -1;
  4259. this._isDirty = true;
  4260. return this;
  4261. }
  4262. /**
  4263. * Conjugates (1-q) the current quaternion
  4264. * Example Playground https://playground.babylonjs.com/#L49EJ7#83
  4265. * @returns a new quaternion
  4266. */
  4267. conjugate() {
  4268. return new this.constructor(-this._x, -this._y, -this._z, this._w);
  4269. }
  4270. /**
  4271. * Returns the inverse of the current quaternion
  4272. * Example Playground https://playground.babylonjs.com/#L49EJ7#84
  4273. * @returns a new quaternion
  4274. */
  4275. invert() {
  4276. const conjugate = this.conjugate();
  4277. const lengthSquared = this.lengthSquared();
  4278. if (lengthSquared == 0 || lengthSquared == 1) {
  4279. return conjugate;
  4280. }
  4281. conjugate.scaleInPlace(1 / lengthSquared);
  4282. return conjugate;
  4283. }
  4284. /**
  4285. * Invert in place the current quaternion
  4286. * Example Playground https://playground.babylonjs.com/#L49EJ7#85
  4287. * @returns this quaternion
  4288. */
  4289. invertInPlace() {
  4290. this.conjugateInPlace();
  4291. const lengthSquared = this.lengthSquared();
  4292. if (lengthSquared == 0 || lengthSquared == 1) {
  4293. return this;
  4294. }
  4295. this.scaleInPlace(1 / lengthSquared);
  4296. return this;
  4297. }
  4298. /**
  4299. * Gets squared length of current quaternion
  4300. * Example Playground https://playground.babylonjs.com/#L49EJ7#29
  4301. * @returns the quaternion length (float)
  4302. */
  4303. lengthSquared() {
  4304. return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
  4305. }
  4306. /**
  4307. * Gets length of current quaternion
  4308. * Example Playground https://playground.babylonjs.com/#L49EJ7#28
  4309. * @returns the quaternion length (float)
  4310. */
  4311. length() {
  4312. return Math.sqrt(this.lengthSquared());
  4313. }
  4314. /**
  4315. * Normalize in place the current quaternion
  4316. * Example Playground https://playground.babylonjs.com/#L49EJ7#54
  4317. * @returns the current updated quaternion
  4318. */
  4319. normalize() {
  4320. return this.normalizeFromLength(this.length());
  4321. }
  4322. /**
  4323. * Normalize the current quaternion with the given input length.
  4324. * Please note that this is an in place operation.
  4325. * @param len the length of the quaternion
  4326. * @returns the current updated Quaternion
  4327. */
  4328. normalizeFromLength(len) {
  4329. if (len === 0 || len === 1.0) {
  4330. return this;
  4331. }
  4332. return this.scaleInPlace(1.0 / len);
  4333. }
  4334. /**
  4335. * Normalize a copy of the current quaternion
  4336. * Example Playground https://playground.babylonjs.com/#L49EJ7#55
  4337. * @returns the normalized quaternion
  4338. */
  4339. normalizeToNew() {
  4340. const normalized = new this.constructor(0, 0, 0, 1);
  4341. this.normalizeToRef(normalized);
  4342. return normalized;
  4343. }
  4344. /**
  4345. * Normalize the current Quaternion to the reference
  4346. * @param reference define the Quaternion to update
  4347. * @returns the updated Quaternion
  4348. */
  4349. normalizeToRef(reference) {
  4350. const len = this.length();
  4351. if (len === 0 || len === 1.0) {
  4352. return reference.copyFromFloats(this._x, this._y, this._z, this._w);
  4353. }
  4354. return this.scaleToRef(1.0 / len, reference);
  4355. }
  4356. /**
  4357. * Returns a new Vector3 set with the Euler angles translated from the current quaternion
  4358. * Example Playground https://playground.babylonjs.com/#L49EJ7#32
  4359. * @returns a new Vector3 containing the Euler angles
  4360. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/transforms/center_origin/rotation_conventions
  4361. */
  4362. toEulerAngles() {
  4363. const result = Vector3.Zero();
  4364. this.toEulerAnglesToRef(result);
  4365. return result;
  4366. }
  4367. /**
  4368. * Sets the given vector3 "result" with the Euler angles translated from the current quaternion
  4369. * Example Playground https://playground.babylonjs.com/#L49EJ7#31
  4370. * @param result defines the vector which will be filled with the Euler angles
  4371. * @returns result input
  4372. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/transforms/center_origin/rotation_conventions
  4373. */
  4374. toEulerAnglesToRef(result) {
  4375. const qz = this._z;
  4376. const qx = this._x;
  4377. const qy = this._y;
  4378. const qw = this._w;
  4379. const zAxisY = qy * qz - qx * qw;
  4380. const limit = 0.4999999;
  4381. if (zAxisY < -limit) {
  4382. result._y = 2 * Math.atan2(qy, qw);
  4383. result._x = Math.PI / 2;
  4384. result._z = 0;
  4385. result._isDirty = true;
  4386. }
  4387. else if (zAxisY > limit) {
  4388. result._y = 2 * Math.atan2(qy, qw);
  4389. result._x = -Math.PI / 2;
  4390. result._z = 0;
  4391. result._isDirty = true;
  4392. }
  4393. else {
  4394. const sqw = qw * qw;
  4395. const sqz = qz * qz;
  4396. const sqx = qx * qx;
  4397. const sqy = qy * qy;
  4398. result._z = Math.atan2(2.0 * (qx * qy + qz * qw), -sqz - sqx + sqy + sqw);
  4399. result._x = Math.asin(-2.0 * zAxisY);
  4400. result._y = Math.atan2(2.0 * (qz * qx + qy * qw), sqz - sqx - sqy + sqw);
  4401. result._isDirty = true;
  4402. }
  4403. return result;
  4404. }
  4405. /**
  4406. * Updates the given rotation matrix with the current quaternion values
  4407. * Example Playground https://playground.babylonjs.com/#L49EJ7#67
  4408. * @param result defines the target matrix
  4409. * @returns the updated matrix with the rotation
  4410. */
  4411. toRotationMatrix(result) {
  4412. Matrix.FromQuaternionToRef(this, result);
  4413. return result;
  4414. }
  4415. /**
  4416. * Updates the current quaternion from the given rotation matrix values
  4417. * Example Playground https://playground.babylonjs.com/#L49EJ7#41
  4418. * @param matrix defines the source matrix
  4419. * @returns the current updated quaternion
  4420. */
  4421. fromRotationMatrix(matrix) {
  4422. Quaternion.FromRotationMatrixToRef(matrix, this);
  4423. return this;
  4424. }
  4425. /**
  4426. * Returns the dot product (float) between the current quaternions and "other"
  4427. * @param other defines the right operand
  4428. * @returns the dot product
  4429. */
  4430. dot(other) {
  4431. return this._x * other._x + this._y * other._y + this._z * other._z + this._w * other._w;
  4432. }
  4433. // Statics
  4434. /**
  4435. * Creates a new quaternion from a rotation matrix
  4436. * Example Playground https://playground.babylonjs.com/#L49EJ7#101
  4437. * @param matrix defines the source matrix
  4438. * @returns a new quaternion created from the given rotation matrix values
  4439. */
  4440. static FromRotationMatrix(matrix) {
  4441. const result = new Quaternion();
  4442. Quaternion.FromRotationMatrixToRef(matrix, result);
  4443. return result;
  4444. }
  4445. /**
  4446. * Updates the given quaternion with the given rotation matrix values
  4447. * Example Playground https://playground.babylonjs.com/#L49EJ7#102
  4448. * @param matrix defines the source matrix
  4449. * @param result defines the target quaternion
  4450. * @returns result input
  4451. */
  4452. static FromRotationMatrixToRef(matrix, result) {
  4453. const data = matrix.m;
  4454. const m11 = data[0], m12 = data[4], m13 = data[8];
  4455. const m21 = data[1], m22 = data[5], m23 = data[9];
  4456. const m31 = data[2], m32 = data[6], m33 = data[10];
  4457. const trace = m11 + m22 + m33;
  4458. let s;
  4459. if (trace > 0) {
  4460. s = 0.5 / Math.sqrt(trace + 1.0);
  4461. result._w = 0.25 / s;
  4462. result._x = (m32 - m23) * s;
  4463. result._y = (m13 - m31) * s;
  4464. result._z = (m21 - m12) * s;
  4465. result._isDirty = true;
  4466. }
  4467. else if (m11 > m22 && m11 > m33) {
  4468. s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
  4469. result._w = (m32 - m23) / s;
  4470. result._x = 0.25 * s;
  4471. result._y = (m12 + m21) / s;
  4472. result._z = (m13 + m31) / s;
  4473. result._isDirty = true;
  4474. }
  4475. else if (m22 > m33) {
  4476. s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
  4477. result._w = (m13 - m31) / s;
  4478. result._x = (m12 + m21) / s;
  4479. result._y = 0.25 * s;
  4480. result._z = (m23 + m32) / s;
  4481. result._isDirty = true;
  4482. }
  4483. else {
  4484. s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
  4485. result._w = (m21 - m12) / s;
  4486. result._x = (m13 + m31) / s;
  4487. result._y = (m23 + m32) / s;
  4488. result._z = 0.25 * s;
  4489. result._isDirty = true;
  4490. }
  4491. return result;
  4492. }
  4493. /**
  4494. * Returns the dot product (float) between the quaternions "left" and "right"
  4495. * Example Playground https://playground.babylonjs.com/#L49EJ7#61
  4496. * @param left defines the left operand
  4497. * @param right defines the right operand
  4498. * @returns the dot product
  4499. */
  4500. static Dot(left, right) {
  4501. return left._x * right._x + left._y * right._y + left._z * right._z + left._w * right._w;
  4502. }
  4503. /**
  4504. * Checks if the orientations of two rotation quaternions are close to each other
  4505. * Example Playground https://playground.babylonjs.com/#L49EJ7#60
  4506. * @param quat0 defines the first quaternion to check
  4507. * @param quat1 defines the second quaternion to check
  4508. * @param epsilon defines closeness, 0 same orientation, 1 PI apart, default 0.1
  4509. * @returns true if the two quaternions are close to each other within epsilon
  4510. */
  4511. static AreClose(quat0, quat1, epsilon = 0.1) {
  4512. const dot = Quaternion.Dot(quat0, quat1);
  4513. return 1 - dot * dot <= epsilon;
  4514. }
  4515. /**
  4516. * Smooth interpolation between two quaternions using Slerp
  4517. * Example Playground https://playground.babylonjs.com/#L49EJ7#93
  4518. * @param source source quaternion
  4519. * @param goal goal quaternion
  4520. * @param deltaTime current interpolation frame
  4521. * @param lerpTime total interpolation time
  4522. * @param result the smoothed quaternion
  4523. * @returns the smoothed quaternion
  4524. */
  4525. static SmoothToRef(source, goal, deltaTime, lerpTime, result) {
  4526. let slerp = lerpTime === 0 ? 1 : deltaTime / lerpTime;
  4527. slerp = Clamp(slerp, 0, 1);
  4528. Quaternion.SlerpToRef(source, goal, slerp, result);
  4529. return result;
  4530. }
  4531. /**
  4532. * Creates an empty quaternion
  4533. * @returns a new quaternion set to (0.0, 0.0, 0.0)
  4534. */
  4535. static Zero() {
  4536. return new Quaternion(0.0, 0.0, 0.0, 0.0);
  4537. }
  4538. /**
  4539. * Inverse a given quaternion
  4540. * Example Playground https://playground.babylonjs.com/#L49EJ7#103
  4541. * @param q defines the source quaternion
  4542. * @returns a new quaternion as the inverted current quaternion
  4543. */
  4544. static Inverse(q) {
  4545. return new q.constructor(-q._x, -q._y, -q._z, q._w);
  4546. }
  4547. /**
  4548. * Inverse a given quaternion
  4549. * Example Playground https://playground.babylonjs.com/#L49EJ7#104
  4550. * @param q defines the source quaternion
  4551. * @param result the quaternion the result will be stored in
  4552. * @returns the result quaternion
  4553. */
  4554. static InverseToRef(q, result) {
  4555. result.set(-q._x, -q._y, -q._z, q._w);
  4556. return result;
  4557. }
  4558. /**
  4559. * Creates an identity quaternion
  4560. * @returns the identity quaternion
  4561. */
  4562. static Identity() {
  4563. return new Quaternion(0.0, 0.0, 0.0, 1.0);
  4564. }
  4565. /**
  4566. * Gets a boolean indicating if the given quaternion is identity
  4567. * @param quaternion defines the quaternion to check
  4568. * @returns true if the quaternion is identity
  4569. */
  4570. static IsIdentity(quaternion) {
  4571. return quaternion && quaternion._x === 0 && quaternion._y === 0 && quaternion._z === 0 && quaternion._w === 1;
  4572. }
  4573. /**
  4574. * Creates a quaternion from a rotation around an axis
  4575. * Example Playground https://playground.babylonjs.com/#L49EJ7#72
  4576. * @param axis defines the axis to use
  4577. * @param angle defines the angle to use
  4578. * @returns a new quaternion created from the given axis (Vector3) and angle in radians (float)
  4579. */
  4580. static RotationAxis(axis, angle) {
  4581. return Quaternion.RotationAxisToRef(axis, angle, new Quaternion());
  4582. }
  4583. /**
  4584. * Creates a rotation around an axis and stores it into the given quaternion
  4585. * Example Playground https://playground.babylonjs.com/#L49EJ7#73
  4586. * @param axis defines the axis to use
  4587. * @param angle defines the angle to use
  4588. * @param result defines the target quaternion
  4589. * @returns the target quaternion
  4590. */
  4591. static RotationAxisToRef(axis, angle, result) {
  4592. const sin = Math.sin(angle / 2);
  4593. axis.normalize();
  4594. result._w = Math.cos(angle / 2);
  4595. result._x = axis._x * sin;
  4596. result._y = axis._y * sin;
  4597. result._z = axis._z * sin;
  4598. result._isDirty = true;
  4599. return result;
  4600. }
  4601. /**
  4602. * Creates a new quaternion from data stored into an array
  4603. * Example Playground https://playground.babylonjs.com/#L49EJ7#63
  4604. * @param array defines the data source
  4605. * @param offset defines the offset in the source array where the data starts
  4606. * @returns a new quaternion
  4607. */
  4608. static FromArray(array, offset) {
  4609. if (!offset) {
  4610. offset = 0;
  4611. }
  4612. return new Quaternion(array[offset], array[offset + 1], array[offset + 2], array[offset + 3]);
  4613. }
  4614. /**
  4615. * Updates the given quaternion "result" from the starting index of the given array.
  4616. * Example Playground https://playground.babylonjs.com/#L49EJ7#64
  4617. * @param array the array to pull values from
  4618. * @param offset the offset into the array to start at
  4619. * @param result the quaternion to store the result in
  4620. * @returns result input
  4621. */
  4622. static FromArrayToRef(array, offset, result) {
  4623. result._x = array[offset];
  4624. result._y = array[offset + 1];
  4625. result._z = array[offset + 2];
  4626. result._w = array[offset + 3];
  4627. result._isDirty = true;
  4628. return result;
  4629. }
  4630. /**
  4631. * Sets the given quaternion "result" with the given floats.
  4632. * @param x defines the x coordinate of the source
  4633. * @param y defines the y coordinate of the source
  4634. * @param z defines the z coordinate of the source
  4635. * @param w defines the w coordinate of the source
  4636. * @param result defines the quaternion where to store the result
  4637. * @returns the result quaternion
  4638. */
  4639. static FromFloatsToRef(x, y, z, w, result) {
  4640. result.copyFromFloats(x, y, z, w);
  4641. return result;
  4642. }
  4643. /**
  4644. * Create a quaternion from Euler rotation angles
  4645. * Example Playground https://playground.babylonjs.com/#L49EJ7#33
  4646. * @param x Pitch
  4647. * @param y Yaw
  4648. * @param z Roll
  4649. * @returns the new Quaternion
  4650. */
  4651. static FromEulerAngles(x, y, z) {
  4652. const q = new Quaternion();
  4653. Quaternion.RotationYawPitchRollToRef(y, x, z, q);
  4654. return q;
  4655. }
  4656. /**
  4657. * Updates a quaternion from Euler rotation angles
  4658. * Example Playground https://playground.babylonjs.com/#L49EJ7#34
  4659. * @param x Pitch
  4660. * @param y Yaw
  4661. * @param z Roll
  4662. * @param result the quaternion to store the result
  4663. * @returns the updated quaternion
  4664. */
  4665. static FromEulerAnglesToRef(x, y, z, result) {
  4666. Quaternion.RotationYawPitchRollToRef(y, x, z, result);
  4667. return result;
  4668. }
  4669. /**
  4670. * Create a quaternion from Euler rotation vector
  4671. * Example Playground https://playground.babylonjs.com/#L49EJ7#35
  4672. * @param vec the Euler vector (x Pitch, y Yaw, z Roll)
  4673. * @returns the new Quaternion
  4674. */
  4675. static FromEulerVector(vec) {
  4676. const q = new Quaternion();
  4677. Quaternion.RotationYawPitchRollToRef(vec._y, vec._x, vec._z, q);
  4678. return q;
  4679. }
  4680. /**
  4681. * Updates a quaternion from Euler rotation vector
  4682. * Example Playground https://playground.babylonjs.com/#L49EJ7#36
  4683. * @param vec the Euler vector (x Pitch, y Yaw, z Roll)
  4684. * @param result the quaternion to store the result
  4685. * @returns the updated quaternion
  4686. */
  4687. static FromEulerVectorToRef(vec, result) {
  4688. Quaternion.RotationYawPitchRollToRef(vec._y, vec._x, vec._z, result);
  4689. return result;
  4690. }
  4691. /**
  4692. * Updates a quaternion so that it rotates vector vecFrom to vector vecTo
  4693. * Example Playground - https://playground.babylonjs.com/#L49EJ7#70
  4694. * @param vecFrom defines the direction vector from which to rotate
  4695. * @param vecTo defines the direction vector to which to rotate
  4696. * @param result the quaternion to store the result
  4697. * @param epsilon defines the minimal dot value to define vecs as opposite. Default: `BABYLON.Epsilon`
  4698. * @returns the updated quaternion
  4699. */
  4700. static FromUnitVectorsToRef(vecFrom, vecTo, result, epsilon = Epsilon) {
  4701. const r = Vector3.Dot(vecFrom, vecTo) + 1;
  4702. if (r < epsilon) {
  4703. if (Math.abs(vecFrom.x) > Math.abs(vecFrom.z)) {
  4704. result.set(-vecFrom.y, vecFrom.x, 0, 0);
  4705. }
  4706. else {
  4707. result.set(0, -vecFrom.z, vecFrom.y, 0);
  4708. }
  4709. }
  4710. else {
  4711. Vector3.CrossToRef(vecFrom, vecTo, TmpVectors.Vector3[0]);
  4712. result.set(TmpVectors.Vector3[0].x, TmpVectors.Vector3[0].y, TmpVectors.Vector3[0].z, r);
  4713. }
  4714. return result.normalize();
  4715. }
  4716. /**
  4717. * Creates a new quaternion from the given Euler float angles (y, x, z)
  4718. * Example Playground https://playground.babylonjs.com/#L49EJ7#77
  4719. * @param yaw defines the rotation around Y axis
  4720. * @param pitch defines the rotation around X axis
  4721. * @param roll defines the rotation around Z axis
  4722. * @returns the new quaternion
  4723. */
  4724. static RotationYawPitchRoll(yaw, pitch, roll) {
  4725. const q = new Quaternion();
  4726. Quaternion.RotationYawPitchRollToRef(yaw, pitch, roll, q);
  4727. return q;
  4728. }
  4729. /**
  4730. * Creates a new rotation from the given Euler float angles (y, x, z) and stores it in the target quaternion
  4731. * Example Playground https://playground.babylonjs.com/#L49EJ7#78
  4732. * @param yaw defines the rotation around Y axis
  4733. * @param pitch defines the rotation around X axis
  4734. * @param roll defines the rotation around Z axis
  4735. * @param result defines the target quaternion
  4736. * @returns result input
  4737. */
  4738. static RotationYawPitchRollToRef(yaw, pitch, roll, result) {
  4739. // Produces a quaternion from Euler angles in the z-y-x orientation (Tait-Bryan angles)
  4740. const halfRoll = roll * 0.5;
  4741. const halfPitch = pitch * 0.5;
  4742. const halfYaw = yaw * 0.5;
  4743. const sinRoll = Math.sin(halfRoll);
  4744. const cosRoll = Math.cos(halfRoll);
  4745. const sinPitch = Math.sin(halfPitch);
  4746. const cosPitch = Math.cos(halfPitch);
  4747. const sinYaw = Math.sin(halfYaw);
  4748. const cosYaw = Math.cos(halfYaw);
  4749. result._x = cosYaw * sinPitch * cosRoll + sinYaw * cosPitch * sinRoll;
  4750. result._y = sinYaw * cosPitch * cosRoll - cosYaw * sinPitch * sinRoll;
  4751. result._z = cosYaw * cosPitch * sinRoll - sinYaw * sinPitch * cosRoll;
  4752. result._w = cosYaw * cosPitch * cosRoll + sinYaw * sinPitch * sinRoll;
  4753. result._isDirty = true;
  4754. return result;
  4755. }
  4756. /**
  4757. * Creates a new quaternion from the given Euler float angles expressed in z-x-z orientation
  4758. * Example Playground https://playground.babylonjs.com/#L49EJ7#68
  4759. * @param alpha defines the rotation around first axis
  4760. * @param beta defines the rotation around second axis
  4761. * @param gamma defines the rotation around third axis
  4762. * @returns the new quaternion
  4763. */
  4764. static RotationAlphaBetaGamma(alpha, beta, gamma) {
  4765. const result = new Quaternion();
  4766. Quaternion.RotationAlphaBetaGammaToRef(alpha, beta, gamma, result);
  4767. return result;
  4768. }
  4769. /**
  4770. * Creates a new quaternion from the given Euler float angles expressed in z-x-z orientation and stores it in the target quaternion
  4771. * Example Playground https://playground.babylonjs.com/#L49EJ7#69
  4772. * @param alpha defines the rotation around first axis
  4773. * @param beta defines the rotation around second axis
  4774. * @param gamma defines the rotation around third axis
  4775. * @param result defines the target quaternion
  4776. * @returns result input
  4777. */
  4778. static RotationAlphaBetaGammaToRef(alpha, beta, gamma, result) {
  4779. // Produces a quaternion from Euler angles in the z-x-z orientation
  4780. const halfGammaPlusAlpha = (gamma + alpha) * 0.5;
  4781. const halfGammaMinusAlpha = (gamma - alpha) * 0.5;
  4782. const halfBeta = beta * 0.5;
  4783. result._x = Math.cos(halfGammaMinusAlpha) * Math.sin(halfBeta);
  4784. result._y = Math.sin(halfGammaMinusAlpha) * Math.sin(halfBeta);
  4785. result._z = Math.sin(halfGammaPlusAlpha) * Math.cos(halfBeta);
  4786. result._w = Math.cos(halfGammaPlusAlpha) * Math.cos(halfBeta);
  4787. result._isDirty = true;
  4788. return result;
  4789. }
  4790. /**
  4791. * Creates a new quaternion containing the rotation value to reach the target (axis1, axis2, axis3) orientation as a rotated XYZ system (axis1, axis2 and axis3 are normalized during this operation)
  4792. * Example Playground https://playground.babylonjs.com/#L49EJ7#75
  4793. * @param axis1 defines the first axis
  4794. * @param axis2 defines the second axis
  4795. * @param axis3 defines the third axis
  4796. * @returns the new quaternion
  4797. */
  4798. static RotationQuaternionFromAxis(axis1, axis2, axis3) {
  4799. const quat = new Quaternion(0.0, 0.0, 0.0, 0.0);
  4800. Quaternion.RotationQuaternionFromAxisToRef(axis1, axis2, axis3, quat);
  4801. return quat;
  4802. }
  4803. /**
  4804. * Creates a rotation value to reach the target (axis1, axis2, axis3) orientation as a rotated XYZ system (axis1, axis2 and axis3 are normalized during this operation) and stores it in the target quaternion
  4805. * Example Playground https://playground.babylonjs.com/#L49EJ7#76
  4806. * @param axis1 defines the first axis
  4807. * @param axis2 defines the second axis
  4808. * @param axis3 defines the third axis
  4809. * @param ref defines the target quaternion
  4810. * @returns result input
  4811. */
  4812. static RotationQuaternionFromAxisToRef(axis1, axis2, axis3, ref) {
  4813. const rotMat = MathTmp.Matrix[0];
  4814. Matrix.FromXYZAxesToRef(axis1.normalize(), axis2.normalize(), axis3.normalize(), rotMat);
  4815. Quaternion.FromRotationMatrixToRef(rotMat, ref);
  4816. return ref;
  4817. }
  4818. /**
  4819. * Creates a new rotation value to orient an object to look towards the given forward direction, the up direction being oriented like "up".
  4820. * This function works in left handed mode
  4821. * Example Playground https://playground.babylonjs.com/#L49EJ7#96
  4822. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  4823. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  4824. * @returns A new quaternion oriented toward the specified forward and up.
  4825. */
  4826. static FromLookDirectionLH(forward, up) {
  4827. const quat = new Quaternion();
  4828. Quaternion.FromLookDirectionLHToRef(forward, up, quat);
  4829. return quat;
  4830. }
  4831. /**
  4832. * Creates a new rotation value to orient an object to look towards the given forward direction with the up direction being oriented like "up", and stores it in the target quaternion.
  4833. * This function works in left handed mode
  4834. * Example Playground https://playground.babylonjs.com/#L49EJ7#97
  4835. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  4836. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  4837. * @param ref defines the target quaternion.
  4838. * @returns result input
  4839. */
  4840. static FromLookDirectionLHToRef(forward, up, ref) {
  4841. const rotMat = MathTmp.Matrix[0];
  4842. Matrix.LookDirectionLHToRef(forward, up, rotMat);
  4843. Quaternion.FromRotationMatrixToRef(rotMat, ref);
  4844. return ref;
  4845. }
  4846. /**
  4847. * Creates a new rotation value to orient an object to look towards the given forward direction, the up direction being oriented like "up".
  4848. * This function works in right handed mode
  4849. * Example Playground https://playground.babylonjs.com/#L49EJ7#98
  4850. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  4851. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  4852. * @returns A new quaternion oriented toward the specified forward and up.
  4853. */
  4854. static FromLookDirectionRH(forward, up) {
  4855. const quat = new Quaternion();
  4856. Quaternion.FromLookDirectionRHToRef(forward, up, quat);
  4857. return quat;
  4858. }
  4859. /**
  4860. * Creates a new rotation value to orient an object to look towards the given forward direction with the up direction being oriented like "up", and stores it in the target quaternion.
  4861. * This function works in right handed mode
  4862. * Example Playground https://playground.babylonjs.com/#L49EJ7#105
  4863. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  4864. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  4865. * @param ref defines the target quaternion.
  4866. * @returns result input
  4867. */
  4868. static FromLookDirectionRHToRef(forward, up, ref) {
  4869. const rotMat = MathTmp.Matrix[0];
  4870. Matrix.LookDirectionRHToRef(forward, up, rotMat);
  4871. return Quaternion.FromRotationMatrixToRef(rotMat, ref);
  4872. }
  4873. /**
  4874. * Interpolates between two quaternions
  4875. * Example Playground https://playground.babylonjs.com/#L49EJ7#79
  4876. * @param left defines first quaternion
  4877. * @param right defines second quaternion
  4878. * @param amount defines the gradient to use
  4879. * @returns the new interpolated quaternion
  4880. */
  4881. static Slerp(left, right, amount) {
  4882. const result = Quaternion.Identity();
  4883. Quaternion.SlerpToRef(left, right, amount, result);
  4884. return result;
  4885. }
  4886. /**
  4887. * Interpolates between two quaternions and stores it into a target quaternion
  4888. * Example Playground https://playground.babylonjs.com/#L49EJ7#92
  4889. * @param left defines first quaternion
  4890. * @param right defines second quaternion
  4891. * @param amount defines the gradient to use
  4892. * @param result defines the target quaternion
  4893. * @returns result input
  4894. */
  4895. static SlerpToRef(left, right, amount, result) {
  4896. let num2;
  4897. let num3;
  4898. let num4 = left._x * right._x + left._y * right._y + left._z * right._z + left._w * right._w;
  4899. let flag = false;
  4900. if (num4 < 0) {
  4901. flag = true;
  4902. num4 = -num4;
  4903. }
  4904. if (num4 > 0.999999) {
  4905. num3 = 1 - amount;
  4906. num2 = flag ? -amount : amount;
  4907. }
  4908. else {
  4909. const num5 = Math.acos(num4);
  4910. const num6 = 1.0 / Math.sin(num5);
  4911. num3 = Math.sin((1.0 - amount) * num5) * num6;
  4912. num2 = flag ? -Math.sin(amount * num5) * num6 : Math.sin(amount * num5) * num6;
  4913. }
  4914. result._x = num3 * left._x + num2 * right._x;
  4915. result._y = num3 * left._y + num2 * right._y;
  4916. result._z = num3 * left._z + num2 * right._z;
  4917. result._w = num3 * left._w + num2 * right._w;
  4918. result._isDirty = true;
  4919. return result;
  4920. }
  4921. /**
  4922. * Interpolate between two quaternions using Hermite interpolation
  4923. * Example Playground https://playground.babylonjs.com/#L49EJ7#47
  4924. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/drawCurves#hermite-quaternion-spline
  4925. * @param value1 defines first quaternion
  4926. * @param tangent1 defines the incoming tangent
  4927. * @param value2 defines second quaternion
  4928. * @param tangent2 defines the outgoing tangent
  4929. * @param amount defines the target quaternion
  4930. * @returns the new interpolated quaternion
  4931. */
  4932. static Hermite(value1, tangent1, value2, tangent2, amount) {
  4933. const squared = amount * amount;
  4934. const cubed = amount * squared;
  4935. const part1 = 2.0 * cubed - 3.0 * squared + 1.0;
  4936. const part2 = -2.0 * cubed + 3.0 * squared;
  4937. const part3 = cubed - 2.0 * squared + amount;
  4938. const part4 = cubed - squared;
  4939. const x = value1._x * part1 + value2._x * part2 + tangent1._x * part3 + tangent2._x * part4;
  4940. const y = value1._y * part1 + value2._y * part2 + tangent1._y * part3 + tangent2._y * part4;
  4941. const z = value1._z * part1 + value2._z * part2 + tangent1._z * part3 + tangent2._z * part4;
  4942. const w = value1._w * part1 + value2._w * part2 + tangent1._w * part3 + tangent2._w * part4;
  4943. return new value1.constructor(x, y, z, w);
  4944. }
  4945. /**
  4946. * Returns a new Quaternion which is the 1st derivative of the Hermite spline defined by the quaternions "value1", "value2", "tangent1", "tangent2".
  4947. * Example Playground https://playground.babylonjs.com/#L49EJ7#48
  4948. * @param value1 defines the first control point
  4949. * @param tangent1 defines the first tangent
  4950. * @param value2 defines the second control point
  4951. * @param tangent2 defines the second tangent
  4952. * @param time define where the derivative must be done
  4953. * @returns 1st derivative
  4954. */
  4955. static Hermite1stDerivative(value1, tangent1, value2, tangent2, time) {
  4956. const result = new value1.constructor();
  4957. this.Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result);
  4958. return result;
  4959. }
  4960. /**
  4961. * Update a Quaternion with the 1st derivative of the Hermite spline defined by the quaternions "value1", "value2", "tangent1", "tangent2".
  4962. * Example Playground https://playground.babylonjs.com/#L49EJ7#49
  4963. * @param value1 defines the first control point
  4964. * @param tangent1 defines the first tangent
  4965. * @param value2 defines the second control point
  4966. * @param tangent2 defines the second tangent
  4967. * @param time define where the derivative must be done
  4968. * @param result define where to store the derivative
  4969. * @returns result input
  4970. */
  4971. static Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result) {
  4972. const t2 = time * time;
  4973. result._x = (t2 - time) * 6 * value1._x + (3 * t2 - 4 * time + 1) * tangent1._x + (-t2 + time) * 6 * value2._x + (3 * t2 - 2 * time) * tangent2._x;
  4974. result._y = (t2 - time) * 6 * value1._y + (3 * t2 - 4 * time + 1) * tangent1._y + (-t2 + time) * 6 * value2._y + (3 * t2 - 2 * time) * tangent2._y;
  4975. result._z = (t2 - time) * 6 * value1._z + (3 * t2 - 4 * time + 1) * tangent1._z + (-t2 + time) * 6 * value2._z + (3 * t2 - 2 * time) * tangent2._z;
  4976. result._w = (t2 - time) * 6 * value1._w + (3 * t2 - 4 * time + 1) * tangent1._w + (-t2 + time) * 6 * value2._w + (3 * t2 - 2 * time) * tangent2._w;
  4977. result._isDirty = true;
  4978. return result;
  4979. }
  4980. /**
  4981. * Returns a new Quaternion as the normalization of the given Quaternion
  4982. * @param quat defines the Quaternion to normalize
  4983. * @returns the new Quaternion
  4984. */
  4985. static Normalize(quat) {
  4986. const result = Quaternion.Zero();
  4987. Quaternion.NormalizeToRef(quat, result);
  4988. return result;
  4989. }
  4990. /**
  4991. * Sets the given Quaternion "result" with the normalization of the given first Quaternion
  4992. * @param quat defines the Quaternion to normalize
  4993. * @param result defines the Quaternion where to store the result
  4994. * @returns result input
  4995. */
  4996. static NormalizeToRef(quat, result) {
  4997. quat.normalizeToRef(result);
  4998. return result;
  4999. }
  5000. /**
  5001. * Returns a new Quaternion set with the coordinates of "value", if the quaternion "value" is in the cube defined by the quaternions "min" and "max"
  5002. * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
  5003. * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
  5004. * @param value defines the current value
  5005. * @param min defines the lower range value
  5006. * @param max defines the upper range value
  5007. * @returns the new Quaternion
  5008. */
  5009. static Clamp(value, min, max) {
  5010. const result = new value.constructor();
  5011. Quaternion.ClampToRef(value, min, max, result);
  5012. return result;
  5013. }
  5014. /**
  5015. * Sets the given quaternion "result" with the coordinates of "value", if the quaternion "value" is in the cube defined by the quaternions "min" and "max"
  5016. * If a coordinate value of "value" is lower than one of the "min" coordinate, then this "value" coordinate is set with the "min" one
  5017. * If a coordinate value of "value" is greater than one of the "max" coordinate, then this "value" coordinate is set with the "max" one
  5018. * @param value defines the current value
  5019. * @param min defines the lower range value
  5020. * @param max defines the upper range value
  5021. * @param result defines the Quaternion where to store the result
  5022. * @returns result input
  5023. */
  5024. static ClampToRef(value, min, max, result) {
  5025. return result.copyFromFloats(Clamp(value.x, min.x, max.x), Clamp(value.y, min.y, max.y), Clamp(value.z, min.z, max.z), Clamp(value.w, min.w, max.w));
  5026. }
  5027. /**
  5028. * Returns a new Quaternion with random values between min and max
  5029. * @param min the minimum random value
  5030. * @param max the maximum random value
  5031. * @returns a Quaternion with random values between min and max
  5032. */
  5033. static Random(min = 0, max = 1) {
  5034. return new Quaternion(RandomRange(min, max), RandomRange(min, max), RandomRange(min, max), RandomRange(min, max));
  5035. }
  5036. /**
  5037. * Sets a Quaternion with random values between min and max
  5038. * @param min the minimum random value
  5039. * @param max the maximum random value
  5040. * @param ref the ref to store the values in
  5041. * @returns the ref with random values between min and max
  5042. */
  5043. static RandomToRef(min = 0, max = 1, ref) {
  5044. return ref.copyFromFloats(RandomRange(min, max), RandomRange(min, max), RandomRange(min, max), RandomRange(min, max));
  5045. }
  5046. /**
  5047. * Do not use
  5048. * @internal
  5049. */
  5050. static Minimize() {
  5051. throw new ReferenceError("Quaternion.Minimize does not make sense");
  5052. }
  5053. /**
  5054. * Do not use
  5055. * @internal
  5056. */
  5057. static Maximize() {
  5058. throw new ReferenceError("Quaternion.Maximize does not make sense");
  5059. }
  5060. /**
  5061. * Returns the distance (float) between the quaternions "value1" and "value2".
  5062. * @param value1 value to calulate the distance between
  5063. * @param value2 value to calulate the distance between
  5064. * @returns the distance between the two quaternions
  5065. */
  5066. static Distance(value1, value2) {
  5067. return Math.sqrt(Quaternion.DistanceSquared(value1, value2));
  5068. }
  5069. /**
  5070. * Returns the squared distance (float) between the quaternions "value1" and "value2".
  5071. * @param value1 value to calulate the distance between
  5072. * @param value2 value to calulate the distance between
  5073. * @returns the distance between the two quaternions squared
  5074. */
  5075. static DistanceSquared(value1, value2) {
  5076. const x = value1.x - value2.x;
  5077. const y = value1.y - value2.y;
  5078. const z = value1.z - value2.z;
  5079. const w = value1.w - value2.w;
  5080. return x * x + y * y + z * z + w * w;
  5081. }
  5082. /**
  5083. * Returns a new Quaternion located at the center between the quaternions "value1" and "value2".
  5084. * @param value1 value to calulate the center between
  5085. * @param value2 value to calulate the center between
  5086. * @returns the center between the two quaternions
  5087. */
  5088. static Center(value1, value2) {
  5089. return Quaternion.CenterToRef(value1, value2, Quaternion.Zero());
  5090. }
  5091. /**
  5092. * Gets the center of the quaternions "value1" and "value2" and stores the result in the quaternion "ref"
  5093. * @param value1 defines first quaternion
  5094. * @param value2 defines second quaternion
  5095. * @param ref defines third quaternion
  5096. * @returns ref
  5097. */
  5098. static CenterToRef(value1, value2, ref) {
  5099. return ref.copyFromFloats((value1.x + value2.x) / 2, (value1.y + value2.y) / 2, (value1.z + value2.z) / 2, (value1.w + value2.w) / 2);
  5100. }
  5101. }
  5102. Quaternion;
  5103. Object.defineProperties(Quaternion.prototype, {
  5104. dimension: { value: [4] },
  5105. rank: { value: 1 },
  5106. });
  5107. /**
  5108. * Class used to store matrix data (4x4)
  5109. * Note on matrix definitions in Babylon.js for setting values directly
  5110. * rather than using one of the methods available.
  5111. * Matrix size is given by rows x columns.
  5112. * A Vector3 is a 1 X 3 matrix [x, y, z].
  5113. *
  5114. * In Babylon.js multiplying a 1 x 3 matrix by a 4 x 4 matrix
  5115. * is done using BABYLON.Vector4.TransformCoordinates(Vector3, Matrix).
  5116. * and extending the passed Vector3 to a Vector4, V = [x, y, z, 1].
  5117. * Let M be a matrix with elements m(row, column), so that
  5118. * m(2, 3) is the element in row 2 column 3 of M.
  5119. *
  5120. * Multiplication is of the form VM and has the resulting Vector4
  5121. * VM = [xm(0, 0) + ym(1, 0) + zm(2, 0) + m(3, 0), xm(0, 1) + ym(1, 1) + zm(2, 1) + m(3, 1), xm(0, 2) + ym(1, 2) + zm(2, 2) + m(3, 2), xm(0, 3) + ym(1, 3) + zm(2, 3) + m(3, 3)].
  5122. * On the web you will find many examples that use the opposite convention of MV,
  5123. * in which case to make use of the examples you will need to transpose the matrix.
  5124. *
  5125. * Example Playground - Overview Linear Algebra - https://playground.babylonjs.com/#AV9X17
  5126. * Example Playground - Overview Transformation - https://playground.babylonjs.com/#AV9X17#1
  5127. * Example Playground - Overview Projection - https://playground.babylonjs.com/#AV9X17#2
  5128. */
  5129. export class Matrix {
  5130. /**
  5131. * Gets the precision of matrix computations
  5132. */
  5133. static get Use64Bits() {
  5134. return PerformanceConfigurator.MatrixUse64Bits;
  5135. }
  5136. /**
  5137. * Gets the internal data of the matrix
  5138. */
  5139. get m() {
  5140. return this._m;
  5141. }
  5142. /**
  5143. * Update the updateFlag to indicate that the matrix has been updated
  5144. */
  5145. markAsUpdated() {
  5146. this.updateFlag = Matrix._UpdateFlagSeed++;
  5147. this._isIdentity = false;
  5148. this._isIdentity3x2 = false;
  5149. this._isIdentityDirty = true;
  5150. this._isIdentity3x2Dirty = true;
  5151. }
  5152. _updateIdentityStatus(isIdentity, isIdentityDirty = false, isIdentity3x2 = false, isIdentity3x2Dirty = true) {
  5153. this._isIdentity = isIdentity;
  5154. this._isIdentity3x2 = isIdentity || isIdentity3x2;
  5155. this._isIdentityDirty = this._isIdentity ? false : isIdentityDirty;
  5156. this._isIdentity3x2Dirty = this._isIdentity3x2 ? false : isIdentity3x2Dirty;
  5157. }
  5158. /**
  5159. * Creates an empty matrix (filled with zeros)
  5160. */
  5161. constructor() {
  5162. this._isIdentity = false;
  5163. this._isIdentityDirty = true;
  5164. this._isIdentity3x2 = true;
  5165. this._isIdentity3x2Dirty = true;
  5166. /**
  5167. * Gets the update flag of the matrix which is an unique number for the matrix.
  5168. * It will be incremented every time the matrix data change.
  5169. * You can use it to speed the comparison between two versions of the same matrix.
  5170. */
  5171. this.updateFlag = -1;
  5172. if (PerformanceConfigurator.MatrixTrackPrecisionChange) {
  5173. PerformanceConfigurator.MatrixTrackedMatrices.push(this);
  5174. }
  5175. this._m = new PerformanceConfigurator.MatrixCurrentType(16);
  5176. this.markAsUpdated();
  5177. }
  5178. // Properties
  5179. /**
  5180. * Check if the current matrix is identity
  5181. * @returns true is the matrix is the identity matrix
  5182. */
  5183. isIdentity() {
  5184. if (this._isIdentityDirty) {
  5185. this._isIdentityDirty = false;
  5186. const m = this._m;
  5187. this._isIdentity =
  5188. m[0] === 1.0 &&
  5189. m[1] === 0.0 &&
  5190. m[2] === 0.0 &&
  5191. m[3] === 0.0 &&
  5192. m[4] === 0.0 &&
  5193. m[5] === 1.0 &&
  5194. m[6] === 0.0 &&
  5195. m[7] === 0.0 &&
  5196. m[8] === 0.0 &&
  5197. m[9] === 0.0 &&
  5198. m[10] === 1.0 &&
  5199. m[11] === 0.0 &&
  5200. m[12] === 0.0 &&
  5201. m[13] === 0.0 &&
  5202. m[14] === 0.0 &&
  5203. m[15] === 1.0;
  5204. }
  5205. return this._isIdentity;
  5206. }
  5207. /**
  5208. * Check if the current matrix is identity as a texture matrix (3x2 store in 4x4)
  5209. * @returns true is the matrix is the identity matrix
  5210. */
  5211. isIdentityAs3x2() {
  5212. if (this._isIdentity3x2Dirty) {
  5213. this._isIdentity3x2Dirty = false;
  5214. if (this._m[0] !== 1.0 || this._m[5] !== 1.0 || this._m[15] !== 1.0) {
  5215. this._isIdentity3x2 = false;
  5216. }
  5217. else if (this._m[1] !== 0.0 ||
  5218. this._m[2] !== 0.0 ||
  5219. this._m[3] !== 0.0 ||
  5220. this._m[4] !== 0.0 ||
  5221. this._m[6] !== 0.0 ||
  5222. this._m[7] !== 0.0 ||
  5223. this._m[8] !== 0.0 ||
  5224. this._m[9] !== 0.0 ||
  5225. this._m[10] !== 0.0 ||
  5226. this._m[11] !== 0.0 ||
  5227. this._m[12] !== 0.0 ||
  5228. this._m[13] !== 0.0 ||
  5229. this._m[14] !== 0.0) {
  5230. this._isIdentity3x2 = false;
  5231. }
  5232. else {
  5233. this._isIdentity3x2 = true;
  5234. }
  5235. }
  5236. return this._isIdentity3x2;
  5237. }
  5238. /**
  5239. * Gets the determinant of the matrix
  5240. * Example Playground - https://playground.babylonjs.com/#AV9X17#34
  5241. * @returns the matrix determinant
  5242. */
  5243. determinant() {
  5244. if (this._isIdentity === true) {
  5245. return 1;
  5246. }
  5247. const m = this._m;
  5248. const m00 = m[0], m01 = m[1], m02 = m[2], m03 = m[3];
  5249. const m10 = m[4], m11 = m[5], m12 = m[6], m13 = m[7];
  5250. const m20 = m[8], m21 = m[9], m22 = m[10], m23 = m[11];
  5251. const m30 = m[12], m31 = m[13], m32 = m[14], m33 = m[15];
  5252. // https://en.wikipedia.org/wiki/Laplace_expansion
  5253. // to compute the deterrminant of a 4x4 Matrix we compute the cofactors of any row or column,
  5254. // then we multiply each Cofactor by its corresponding matrix value and sum them all to get the determinant
  5255. // Cofactor(i, j) = sign(i,j) * det(Minor(i, j))
  5256. // where
  5257. // - sign(i,j) = (i+j) % 2 === 0 ? 1 : -1
  5258. // - Minor(i, j) is the 3x3 matrix we get by removing row i and column j from current Matrix
  5259. //
  5260. // Here we do that for the 1st row.
  5261. const det_22_33 = m22 * m33 - m32 * m23;
  5262. const det_21_33 = m21 * m33 - m31 * m23;
  5263. const det_21_32 = m21 * m32 - m31 * m22;
  5264. const det_20_33 = m20 * m33 - m30 * m23;
  5265. const det_20_32 = m20 * m32 - m22 * m30;
  5266. const det_20_31 = m20 * m31 - m30 * m21;
  5267. const cofact_00 = +(m11 * det_22_33 - m12 * det_21_33 + m13 * det_21_32);
  5268. const cofact_01 = -(m10 * det_22_33 - m12 * det_20_33 + m13 * det_20_32);
  5269. const cofact_02 = +(m10 * det_21_33 - m11 * det_20_33 + m13 * det_20_31);
  5270. const cofact_03 = -(m10 * det_21_32 - m11 * det_20_32 + m12 * det_20_31);
  5271. return m00 * cofact_00 + m01 * cofact_01 + m02 * cofact_02 + m03 * cofact_03;
  5272. }
  5273. // Methods
  5274. /**
  5275. * Gets a string with the Matrix values
  5276. * @returns a string with the Matrix values
  5277. */
  5278. toString() {
  5279. return `{${this.m[0]}, ${this.m[1]}, ${this.m[2]}, ${this.m[3]}\n${this.m[4]}, ${this.m[5]}, ${this.m[6]}, ${this.m[7]}\n${this.m[8]}, ${this.m[9]}, ${this.m[10]}, ${this.m[11]}\n${this.m[12]}, ${this.m[13]}, ${this.m[14]}, ${this.m[15]}}`;
  5280. }
  5281. toArray(array = null, index = 0) {
  5282. if (!array) {
  5283. return this._m;
  5284. }
  5285. const m = this._m;
  5286. for (let i = 0; i < 16; i++) {
  5287. array[index + i] = m[i];
  5288. }
  5289. return this;
  5290. }
  5291. /**
  5292. * Returns the matrix as a Float32Array or Array<number>
  5293. * Example Playground - https://playground.babylonjs.com/#AV9X17#114
  5294. * @returns the matrix underlying array.
  5295. */
  5296. asArray() {
  5297. return this._m;
  5298. }
  5299. fromArray(array, index = 0) {
  5300. return Matrix.FromArrayToRef(array, index, this);
  5301. }
  5302. copyFromFloats(...floats) {
  5303. return Matrix.FromArrayToRef(floats, 0, this);
  5304. }
  5305. set(...values) {
  5306. const m = this._m;
  5307. for (let i = 0; i < 16; i++) {
  5308. m[i] = values[i];
  5309. }
  5310. this.markAsUpdated();
  5311. return this;
  5312. }
  5313. setAll(value) {
  5314. const m = this._m;
  5315. for (let i = 0; i < 16; i++) {
  5316. m[i] = value;
  5317. }
  5318. this.markAsUpdated();
  5319. return this;
  5320. }
  5321. /**
  5322. * Inverts the current matrix in place
  5323. * Example Playground - https://playground.babylonjs.com/#AV9X17#118
  5324. * @returns the current inverted matrix
  5325. */
  5326. invert() {
  5327. this.invertToRef(this);
  5328. return this;
  5329. }
  5330. /**
  5331. * Sets all the matrix elements to zero
  5332. * @returns the current matrix
  5333. */
  5334. reset() {
  5335. Matrix.FromValuesToRef(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, this);
  5336. this._updateIdentityStatus(false);
  5337. return this;
  5338. }
  5339. /**
  5340. * Adds the current matrix with a second one
  5341. * Example Playground - https://playground.babylonjs.com/#AV9X17#44
  5342. * @param other defines the matrix to add
  5343. * @returns a new matrix as the addition of the current matrix and the given one
  5344. */
  5345. add(other) {
  5346. const result = new this.constructor();
  5347. this.addToRef(other, result);
  5348. return result;
  5349. }
  5350. /**
  5351. * Sets the given matrix "result" to the addition of the current matrix and the given one
  5352. * Example Playground - https://playground.babylonjs.com/#AV9X17#45
  5353. * @param other defines the matrix to add
  5354. * @param result defines the target matrix
  5355. * @returns result input
  5356. */
  5357. addToRef(other, result) {
  5358. const m = this._m;
  5359. const resultM = result._m;
  5360. const otherM = other.m;
  5361. for (let index = 0; index < 16; index++) {
  5362. resultM[index] = m[index] + otherM[index];
  5363. }
  5364. result.markAsUpdated();
  5365. return result;
  5366. }
  5367. /**
  5368. * Adds in place the given matrix to the current matrix
  5369. * Example Playground - https://playground.babylonjs.com/#AV9X17#46
  5370. * @param other defines the second operand
  5371. * @returns the current updated matrix
  5372. */
  5373. addToSelf(other) {
  5374. const m = this._m;
  5375. const otherM = other.m;
  5376. for (let index = 0; index < 16; index++) {
  5377. m[index] += otherM[index];
  5378. }
  5379. this.markAsUpdated();
  5380. return this;
  5381. }
  5382. addInPlace(other) {
  5383. const m = this._m, otherM = other.m;
  5384. for (let i = 0; i < 16; i++) {
  5385. m[i] += otherM[i];
  5386. }
  5387. this.markAsUpdated();
  5388. return this;
  5389. }
  5390. addInPlaceFromFloats(...floats) {
  5391. const m = this._m;
  5392. for (let i = 0; i < 16; i++) {
  5393. m[i] += floats[i];
  5394. }
  5395. this.markAsUpdated();
  5396. return this;
  5397. }
  5398. subtract(other) {
  5399. const m = this._m, otherM = other.m;
  5400. for (let i = 0; i < 16; i++) {
  5401. m[i] -= otherM[i];
  5402. }
  5403. this.markAsUpdated();
  5404. return this;
  5405. }
  5406. subtractToRef(other, result) {
  5407. const m = this._m, otherM = other.m, resultM = result._m;
  5408. for (let i = 0; i < 16; i++) {
  5409. resultM[i] = m[i] - otherM[i];
  5410. }
  5411. result.markAsUpdated();
  5412. return result;
  5413. }
  5414. subtractInPlace(other) {
  5415. const m = this._m, otherM = other.m;
  5416. for (let i = 0; i < 16; i++) {
  5417. m[i] -= otherM[i];
  5418. }
  5419. this.markAsUpdated();
  5420. return this;
  5421. }
  5422. subtractFromFloats(...floats) {
  5423. return this.subtractFromFloatsToRef(...floats, new this.constructor());
  5424. }
  5425. subtractFromFloatsToRef(...args) {
  5426. const result = args.pop(), m = this._m, resultM = result._m, values = args;
  5427. for (let i = 0; i < 16; i++) {
  5428. resultM[i] = m[i] - values[i];
  5429. }
  5430. result.markAsUpdated();
  5431. return result;
  5432. }
  5433. /**
  5434. * Sets the given matrix to the current inverted Matrix
  5435. * Example Playground - https://playground.babylonjs.com/#AV9X17#119
  5436. * @param other defines the target matrix
  5437. * @returns result input
  5438. */
  5439. invertToRef(other) {
  5440. if (this._isIdentity === true) {
  5441. Matrix.IdentityToRef(other);
  5442. return other;
  5443. }
  5444. // the inverse of a Matrix is the transpose of cofactor matrix divided by the determinant
  5445. const m = this._m;
  5446. const m00 = m[0], m01 = m[1], m02 = m[2], m03 = m[3];
  5447. const m10 = m[4], m11 = m[5], m12 = m[6], m13 = m[7];
  5448. const m20 = m[8], m21 = m[9], m22 = m[10], m23 = m[11];
  5449. const m30 = m[12], m31 = m[13], m32 = m[14], m33 = m[15];
  5450. const det_22_33 = m22 * m33 - m32 * m23;
  5451. const det_21_33 = m21 * m33 - m31 * m23;
  5452. const det_21_32 = m21 * m32 - m31 * m22;
  5453. const det_20_33 = m20 * m33 - m30 * m23;
  5454. const det_20_32 = m20 * m32 - m22 * m30;
  5455. const det_20_31 = m20 * m31 - m30 * m21;
  5456. const cofact_00 = +(m11 * det_22_33 - m12 * det_21_33 + m13 * det_21_32);
  5457. const cofact_01 = -(m10 * det_22_33 - m12 * det_20_33 + m13 * det_20_32);
  5458. const cofact_02 = +(m10 * det_21_33 - m11 * det_20_33 + m13 * det_20_31);
  5459. const cofact_03 = -(m10 * det_21_32 - m11 * det_20_32 + m12 * det_20_31);
  5460. const det = m00 * cofact_00 + m01 * cofact_01 + m02 * cofact_02 + m03 * cofact_03;
  5461. if (det === 0) {
  5462. // not invertible
  5463. other.copyFrom(this);
  5464. return other;
  5465. }
  5466. const detInv = 1 / det;
  5467. const det_12_33 = m12 * m33 - m32 * m13;
  5468. const det_11_33 = m11 * m33 - m31 * m13;
  5469. const det_11_32 = m11 * m32 - m31 * m12;
  5470. const det_10_33 = m10 * m33 - m30 * m13;
  5471. const det_10_32 = m10 * m32 - m30 * m12;
  5472. const det_10_31 = m10 * m31 - m30 * m11;
  5473. const det_12_23 = m12 * m23 - m22 * m13;
  5474. const det_11_23 = m11 * m23 - m21 * m13;
  5475. const det_11_22 = m11 * m22 - m21 * m12;
  5476. const det_10_23 = m10 * m23 - m20 * m13;
  5477. const det_10_22 = m10 * m22 - m20 * m12;
  5478. const det_10_21 = m10 * m21 - m20 * m11;
  5479. const cofact_10 = -(m01 * det_22_33 - m02 * det_21_33 + m03 * det_21_32);
  5480. const cofact_11 = +(m00 * det_22_33 - m02 * det_20_33 + m03 * det_20_32);
  5481. const cofact_12 = -(m00 * det_21_33 - m01 * det_20_33 + m03 * det_20_31);
  5482. const cofact_13 = +(m00 * det_21_32 - m01 * det_20_32 + m02 * det_20_31);
  5483. const cofact_20 = +(m01 * det_12_33 - m02 * det_11_33 + m03 * det_11_32);
  5484. const cofact_21 = -(m00 * det_12_33 - m02 * det_10_33 + m03 * det_10_32);
  5485. const cofact_22 = +(m00 * det_11_33 - m01 * det_10_33 + m03 * det_10_31);
  5486. const cofact_23 = -(m00 * det_11_32 - m01 * det_10_32 + m02 * det_10_31);
  5487. const cofact_30 = -(m01 * det_12_23 - m02 * det_11_23 + m03 * det_11_22);
  5488. const cofact_31 = +(m00 * det_12_23 - m02 * det_10_23 + m03 * det_10_22);
  5489. const cofact_32 = -(m00 * det_11_23 - m01 * det_10_23 + m03 * det_10_21);
  5490. const cofact_33 = +(m00 * det_11_22 - m01 * det_10_22 + m02 * det_10_21);
  5491. Matrix.FromValuesToRef(cofact_00 * detInv, cofact_10 * detInv, cofact_20 * detInv, cofact_30 * detInv, cofact_01 * detInv, cofact_11 * detInv, cofact_21 * detInv, cofact_31 * detInv, cofact_02 * detInv, cofact_12 * detInv, cofact_22 * detInv, cofact_32 * detInv, cofact_03 * detInv, cofact_13 * detInv, cofact_23 * detInv, cofact_33 * detInv, other);
  5492. return other;
  5493. }
  5494. /**
  5495. * add a value at the specified position in the current Matrix
  5496. * Example Playground - https://playground.babylonjs.com/#AV9X17#47
  5497. * @param index the index of the value within the matrix. between 0 and 15.
  5498. * @param value the value to be added
  5499. * @returns the current updated matrix
  5500. */
  5501. addAtIndex(index, value) {
  5502. this._m[index] += value;
  5503. this.markAsUpdated();
  5504. return this;
  5505. }
  5506. /**
  5507. * mutiply the specified position in the current Matrix by a value
  5508. * @param index the index of the value within the matrix. between 0 and 15.
  5509. * @param value the value to be added
  5510. * @returns the current updated matrix
  5511. */
  5512. multiplyAtIndex(index, value) {
  5513. this._m[index] *= value;
  5514. this.markAsUpdated();
  5515. return this;
  5516. }
  5517. /**
  5518. * Inserts the translation vector (using 3 floats) in the current matrix
  5519. * Example Playground - https://playground.babylonjs.com/#AV9X17#120
  5520. * @param x defines the 1st component of the translation
  5521. * @param y defines the 2nd component of the translation
  5522. * @param z defines the 3rd component of the translation
  5523. * @returns the current updated matrix
  5524. */
  5525. setTranslationFromFloats(x, y, z) {
  5526. this._m[12] = x;
  5527. this._m[13] = y;
  5528. this._m[14] = z;
  5529. this.markAsUpdated();
  5530. return this;
  5531. }
  5532. /**
  5533. * Adds the translation vector (using 3 floats) in the current matrix
  5534. * Example Playground - https://playground.babylonjs.com/#AV9X17#20
  5535. * Example Playground - https://playground.babylonjs.com/#AV9X17#48
  5536. * @param x defines the 1st component of the translation
  5537. * @param y defines the 2nd component of the translation
  5538. * @param z defines the 3rd component of the translation
  5539. * @returns the current updated matrix
  5540. */
  5541. addTranslationFromFloats(x, y, z) {
  5542. this._m[12] += x;
  5543. this._m[13] += y;
  5544. this._m[14] += z;
  5545. this.markAsUpdated();
  5546. return this;
  5547. }
  5548. /**
  5549. * Inserts the translation vector in the current matrix
  5550. * Example Playground - https://playground.babylonjs.com/#AV9X17#121
  5551. * @param vector3 defines the translation to insert
  5552. * @returns the current updated matrix
  5553. */
  5554. setTranslation(vector3) {
  5555. return this.setTranslationFromFloats(vector3._x, vector3._y, vector3._z);
  5556. }
  5557. /**
  5558. * Gets the translation value of the current matrix
  5559. * Example Playground - https://playground.babylonjs.com/#AV9X17#122
  5560. * @returns a new Vector3 as the extracted translation from the matrix
  5561. */
  5562. getTranslation() {
  5563. return new Vector3(this._m[12], this._m[13], this._m[14]);
  5564. }
  5565. /**
  5566. * Fill a Vector3 with the extracted translation from the matrix
  5567. * Example Playground - https://playground.babylonjs.com/#AV9X17#123
  5568. * @param result defines the Vector3 where to store the translation
  5569. * @returns the current matrix
  5570. */
  5571. getTranslationToRef(result) {
  5572. result.x = this._m[12];
  5573. result.y = this._m[13];
  5574. result.z = this._m[14];
  5575. return result;
  5576. }
  5577. /**
  5578. * Remove rotation and scaling part from the matrix
  5579. * @returns the updated matrix
  5580. */
  5581. removeRotationAndScaling() {
  5582. const m = this.m;
  5583. Matrix.FromValuesToRef(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, m[12], m[13], m[14], m[15], this);
  5584. this._updateIdentityStatus(m[12] === 0 && m[13] === 0 && m[14] === 0 && m[15] === 1);
  5585. return this;
  5586. }
  5587. /**
  5588. * Copy the current matrix from the given one
  5589. * Example Playground - https://playground.babylonjs.com/#AV9X17#21
  5590. * @param other defines the source matrix
  5591. * @returns the current updated matrix
  5592. */
  5593. copyFrom(other) {
  5594. other.copyToArray(this._m);
  5595. const o = other;
  5596. this.updateFlag = o.updateFlag;
  5597. this._updateIdentityStatus(o._isIdentity, o._isIdentityDirty, o._isIdentity3x2, o._isIdentity3x2Dirty);
  5598. return this;
  5599. }
  5600. /**
  5601. * Populates the given array from the starting index with the current matrix values
  5602. * @param array defines the target array
  5603. * @param offset defines the offset in the target array where to start storing values
  5604. * @returns the current matrix
  5605. */
  5606. copyToArray(array, offset = 0) {
  5607. const source = this._m;
  5608. array[offset] = source[0];
  5609. array[offset + 1] = source[1];
  5610. array[offset + 2] = source[2];
  5611. array[offset + 3] = source[3];
  5612. array[offset + 4] = source[4];
  5613. array[offset + 5] = source[5];
  5614. array[offset + 6] = source[6];
  5615. array[offset + 7] = source[7];
  5616. array[offset + 8] = source[8];
  5617. array[offset + 9] = source[9];
  5618. array[offset + 10] = source[10];
  5619. array[offset + 11] = source[11];
  5620. array[offset + 12] = source[12];
  5621. array[offset + 13] = source[13];
  5622. array[offset + 14] = source[14];
  5623. array[offset + 15] = source[15];
  5624. return this;
  5625. }
  5626. /**
  5627. * Multiply two matrices
  5628. * Example Playground - https://playground.babylonjs.com/#AV9X17#15
  5629. * A.multiply(B) means apply B to A so result is B x A
  5630. * @param other defines the second operand
  5631. * @returns a new matrix set with the multiplication result of the current Matrix and the given one
  5632. */
  5633. multiply(other) {
  5634. const result = new this.constructor();
  5635. this.multiplyToRef(other, result);
  5636. return result;
  5637. }
  5638. /**
  5639. * This method performs component-by-component in-place multiplication, rather than true matrix multiplication.
  5640. * Use multiply or multiplyToRef for matrix multiplication.
  5641. * @param other defines the second operand
  5642. * @returns the current updated matrix
  5643. */
  5644. multiplyInPlace(other) {
  5645. const m = this._m, otherM = other.m;
  5646. for (let i = 0; i < 16; i++) {
  5647. m[i] *= otherM[i];
  5648. }
  5649. this.markAsUpdated();
  5650. return this;
  5651. }
  5652. /**
  5653. * This method performs a component-by-component multiplication of the current matrix with the array of transmitted numbers.
  5654. * Use multiply or multiplyToRef for matrix multiplication.
  5655. * @param floats defines the array of numbers to multiply the matrix by
  5656. * @returns the current updated matrix
  5657. */
  5658. multiplyByFloats(...floats) {
  5659. const m = this._m;
  5660. for (let i = 0; i < 16; i++) {
  5661. m[i] *= floats[i];
  5662. }
  5663. this.markAsUpdated();
  5664. return this;
  5665. }
  5666. /**
  5667. * Multiples the current matrix by the given floats and stores them in the given ref
  5668. * @param args The floats and ref
  5669. * @returns The updated ref
  5670. */
  5671. multiplyByFloatsToRef(...args) {
  5672. const result = args.pop(), m = this._m, resultM = result._m, values = args;
  5673. for (let i = 0; i < 16; i++) {
  5674. resultM[i] = m[i] * values[i];
  5675. }
  5676. result.markAsUpdated();
  5677. return result;
  5678. }
  5679. /**
  5680. * Sets the given matrix "result" with the multiplication result of the current Matrix and the given one
  5681. * A.multiplyToRef(B, R) means apply B to A and store in R and R = B x A
  5682. * Example Playground - https://playground.babylonjs.com/#AV9X17#16
  5683. * @param other defines the second operand
  5684. * @param result defines the matrix where to store the multiplication
  5685. * @returns result input
  5686. */
  5687. multiplyToRef(other, result) {
  5688. if (this._isIdentity) {
  5689. result.copyFrom(other);
  5690. return result;
  5691. }
  5692. if (other._isIdentity) {
  5693. result.copyFrom(this);
  5694. return result;
  5695. }
  5696. this.multiplyToArray(other, result._m, 0);
  5697. result.markAsUpdated();
  5698. return result;
  5699. }
  5700. /**
  5701. * Sets the Float32Array "result" from the given index "offset" with the multiplication of the current matrix and the given one
  5702. * @param other defines the second operand
  5703. * @param result defines the array where to store the multiplication
  5704. * @param offset defines the offset in the target array where to start storing values
  5705. * @returns the current matrix
  5706. */
  5707. multiplyToArray(other, result, offset) {
  5708. const m = this._m;
  5709. const otherM = other.m;
  5710. const tm0 = m[0], tm1 = m[1], tm2 = m[2], tm3 = m[3];
  5711. const tm4 = m[4], tm5 = m[5], tm6 = m[6], tm7 = m[7];
  5712. const tm8 = m[8], tm9 = m[9], tm10 = m[10], tm11 = m[11];
  5713. const tm12 = m[12], tm13 = m[13], tm14 = m[14], tm15 = m[15];
  5714. const om0 = otherM[0], om1 = otherM[1], om2 = otherM[2], om3 = otherM[3];
  5715. const om4 = otherM[4], om5 = otherM[5], om6 = otherM[6], om7 = otherM[7];
  5716. const om8 = otherM[8], om9 = otherM[9], om10 = otherM[10], om11 = otherM[11];
  5717. const om12 = otherM[12], om13 = otherM[13], om14 = otherM[14], om15 = otherM[15];
  5718. result[offset] = tm0 * om0 + tm1 * om4 + tm2 * om8 + tm3 * om12;
  5719. result[offset + 1] = tm0 * om1 + tm1 * om5 + tm2 * om9 + tm3 * om13;
  5720. result[offset + 2] = tm0 * om2 + tm1 * om6 + tm2 * om10 + tm3 * om14;
  5721. result[offset + 3] = tm0 * om3 + tm1 * om7 + tm2 * om11 + tm3 * om15;
  5722. result[offset + 4] = tm4 * om0 + tm5 * om4 + tm6 * om8 + tm7 * om12;
  5723. result[offset + 5] = tm4 * om1 + tm5 * om5 + tm6 * om9 + tm7 * om13;
  5724. result[offset + 6] = tm4 * om2 + tm5 * om6 + tm6 * om10 + tm7 * om14;
  5725. result[offset + 7] = tm4 * om3 + tm5 * om7 + tm6 * om11 + tm7 * om15;
  5726. result[offset + 8] = tm8 * om0 + tm9 * om4 + tm10 * om8 + tm11 * om12;
  5727. result[offset + 9] = tm8 * om1 + tm9 * om5 + tm10 * om9 + tm11 * om13;
  5728. result[offset + 10] = tm8 * om2 + tm9 * om6 + tm10 * om10 + tm11 * om14;
  5729. result[offset + 11] = tm8 * om3 + tm9 * om7 + tm10 * om11 + tm11 * om15;
  5730. result[offset + 12] = tm12 * om0 + tm13 * om4 + tm14 * om8 + tm15 * om12;
  5731. result[offset + 13] = tm12 * om1 + tm13 * om5 + tm14 * om9 + tm15 * om13;
  5732. result[offset + 14] = tm12 * om2 + tm13 * om6 + tm14 * om10 + tm15 * om14;
  5733. result[offset + 15] = tm12 * om3 + tm13 * om7 + tm14 * om11 + tm15 * om15;
  5734. return this;
  5735. }
  5736. divide(other) {
  5737. return this.divideToRef(other, new this.constructor());
  5738. }
  5739. divideToRef(other, result) {
  5740. const m = this._m, otherM = other.m, resultM = result._m;
  5741. for (let i = 0; i < 16; i++) {
  5742. resultM[i] = m[i] / otherM[i];
  5743. }
  5744. result.markAsUpdated();
  5745. return result;
  5746. }
  5747. divideInPlace(other) {
  5748. const m = this._m, otherM = other.m;
  5749. for (let i = 0; i < 16; i++) {
  5750. m[i] /= otherM[i];
  5751. }
  5752. this.markAsUpdated();
  5753. return this;
  5754. }
  5755. minimizeInPlace(other) {
  5756. const m = this._m, otherM = other.m;
  5757. for (let i = 0; i < 16; i++) {
  5758. m[i] = Math.min(m[i], otherM[i]);
  5759. }
  5760. this.markAsUpdated();
  5761. return this;
  5762. }
  5763. minimizeInPlaceFromFloats(...floats) {
  5764. const m = this._m;
  5765. for (let i = 0; i < 16; i++) {
  5766. m[i] = Math.min(m[i], floats[i]);
  5767. }
  5768. this.markAsUpdated();
  5769. return this;
  5770. }
  5771. maximizeInPlace(other) {
  5772. const m = this._m, otherM = other.m;
  5773. for (let i = 0; i < 16; i++) {
  5774. m[i] = Math.min(m[i], otherM[i]);
  5775. }
  5776. this.markAsUpdated();
  5777. return this;
  5778. }
  5779. maximizeInPlaceFromFloats(...floats) {
  5780. const m = this._m;
  5781. for (let i = 0; i < 16; i++) {
  5782. m[i] = Math.min(m[i], floats[i]);
  5783. }
  5784. this.markAsUpdated();
  5785. return this;
  5786. }
  5787. negate() {
  5788. return this.negateToRef(new this.constructor());
  5789. }
  5790. negateInPlace() {
  5791. const m = this._m;
  5792. for (let i = 0; i < 16; i++) {
  5793. m[i] = -m[i];
  5794. }
  5795. this.markAsUpdated();
  5796. return this;
  5797. }
  5798. negateToRef(result) {
  5799. const m = this._m, resultM = result._m;
  5800. for (let i = 0; i < 16; i++) {
  5801. resultM[i] = -m[i];
  5802. }
  5803. result.markAsUpdated();
  5804. return result;
  5805. }
  5806. /**
  5807. * Check equality between this matrix and a second one
  5808. * @param value defines the second matrix to compare
  5809. * @returns true is the current matrix and the given one values are strictly equal
  5810. */
  5811. equals(value) {
  5812. const other = value;
  5813. if (!other) {
  5814. return false;
  5815. }
  5816. if (this._isIdentity || other._isIdentity) {
  5817. if (!this._isIdentityDirty && !other._isIdentityDirty) {
  5818. return this._isIdentity && other._isIdentity;
  5819. }
  5820. }
  5821. const m = this.m;
  5822. const om = other.m;
  5823. return (m[0] === om[0] &&
  5824. m[1] === om[1] &&
  5825. m[2] === om[2] &&
  5826. m[3] === om[3] &&
  5827. m[4] === om[4] &&
  5828. m[5] === om[5] &&
  5829. m[6] === om[6] &&
  5830. m[7] === om[7] &&
  5831. m[8] === om[8] &&
  5832. m[9] === om[9] &&
  5833. m[10] === om[10] &&
  5834. m[11] === om[11] &&
  5835. m[12] === om[12] &&
  5836. m[13] === om[13] &&
  5837. m[14] === om[14] &&
  5838. m[15] === om[15]);
  5839. }
  5840. equalsWithEpsilon(other, epsilon = 0) {
  5841. const m = this._m, otherM = other.m;
  5842. for (let i = 0; i < 16; i++) {
  5843. if (!WithinEpsilon(m[i], otherM[i], epsilon)) {
  5844. return false;
  5845. }
  5846. }
  5847. return true;
  5848. }
  5849. equalsToFloats(...floats) {
  5850. const m = this._m;
  5851. for (let i = 0; i < 16; i++) {
  5852. if (m[i] != floats[i]) {
  5853. return false;
  5854. }
  5855. }
  5856. return true;
  5857. }
  5858. floor() {
  5859. return this.floorToRef(new this.constructor());
  5860. }
  5861. floorToRef(result) {
  5862. const m = this._m, resultM = result._m;
  5863. for (let i = 0; i < 16; i++) {
  5864. resultM[i] = Math.floor(m[i]);
  5865. }
  5866. result.markAsUpdated();
  5867. return result;
  5868. }
  5869. fract() {
  5870. return this.fractToRef(new this.constructor());
  5871. }
  5872. fractToRef(result) {
  5873. const m = this._m, resultM = result._m;
  5874. for (let i = 0; i < 16; i++) {
  5875. resultM[i] = m[i] - Math.floor(m[i]);
  5876. }
  5877. result.markAsUpdated();
  5878. return result;
  5879. }
  5880. /**
  5881. * Clone the current matrix
  5882. * Example Playground - https://playground.babylonjs.com/#AV9X17#18
  5883. * @returns a new matrix from the current matrix
  5884. */
  5885. clone() {
  5886. const matrix = new this.constructor();
  5887. matrix.copyFrom(this);
  5888. return matrix;
  5889. }
  5890. /**
  5891. * Returns the name of the current matrix class
  5892. * @returns the string "Matrix"
  5893. */
  5894. getClassName() {
  5895. return "Matrix";
  5896. }
  5897. /**
  5898. * Gets the hash code of the current matrix
  5899. * @returns the hash code
  5900. */
  5901. getHashCode() {
  5902. let hash = _ExtractAsInt(this._m[0]);
  5903. for (let i = 1; i < 16; i++) {
  5904. hash = (hash * 397) ^ _ExtractAsInt(this._m[i]);
  5905. }
  5906. return hash;
  5907. }
  5908. /**
  5909. * Decomposes the current Matrix into a translation, rotation and scaling components of the provided node
  5910. * Example Playground - https://playground.babylonjs.com/#AV9X17#13
  5911. * @param node the node to decompose the matrix to
  5912. * @returns true if operation was successful
  5913. */
  5914. decomposeToTransformNode(node) {
  5915. node.rotationQuaternion = node.rotationQuaternion || new Quaternion();
  5916. return this.decompose(node.scaling, node.rotationQuaternion, node.position);
  5917. }
  5918. /**
  5919. * Decomposes the current Matrix into a translation, rotation and scaling components
  5920. * Example Playground - https://playground.babylonjs.com/#AV9X17#12
  5921. * @param scale defines the scale vector3 given as a reference to update
  5922. * @param rotation defines the rotation quaternion given as a reference to update
  5923. * @param translation defines the translation vector3 given as a reference to update
  5924. * @param preserveScalingNode Use scaling sign coming from this node. Otherwise scaling sign might change.
  5925. * @param useAbsoluteScaling Use scaling sign coming from this absoluteScaling when true or scaling otherwise.
  5926. * @returns true if operation was successful
  5927. */
  5928. decompose(scale, rotation, translation, preserveScalingNode, useAbsoluteScaling = true) {
  5929. if (this._isIdentity) {
  5930. if (translation) {
  5931. translation.setAll(0);
  5932. }
  5933. if (scale) {
  5934. scale.setAll(1);
  5935. }
  5936. if (rotation) {
  5937. rotation.copyFromFloats(0, 0, 0, 1);
  5938. }
  5939. return true;
  5940. }
  5941. const m = this._m;
  5942. if (translation) {
  5943. translation.copyFromFloats(m[12], m[13], m[14]);
  5944. }
  5945. scale = scale || MathTmp.Vector3[0];
  5946. scale.x = Math.sqrt(m[0] * m[0] + m[1] * m[1] + m[2] * m[2]);
  5947. scale.y = Math.sqrt(m[4] * m[4] + m[5] * m[5] + m[6] * m[6]);
  5948. scale.z = Math.sqrt(m[8] * m[8] + m[9] * m[9] + m[10] * m[10]);
  5949. if (preserveScalingNode) {
  5950. const signX = (useAbsoluteScaling ? preserveScalingNode.absoluteScaling.x : preserveScalingNode.scaling.x) < 0 ? -1 : 1;
  5951. const signY = (useAbsoluteScaling ? preserveScalingNode.absoluteScaling.y : preserveScalingNode.scaling.y) < 0 ? -1 : 1;
  5952. const signZ = (useAbsoluteScaling ? preserveScalingNode.absoluteScaling.z : preserveScalingNode.scaling.z) < 0 ? -1 : 1;
  5953. scale.x *= signX;
  5954. scale.y *= signY;
  5955. scale.z *= signZ;
  5956. }
  5957. else {
  5958. if (this.determinant() <= 0) {
  5959. scale.y *= -1;
  5960. }
  5961. }
  5962. if (scale._x === 0 || scale._y === 0 || scale._z === 0) {
  5963. if (rotation) {
  5964. rotation.copyFromFloats(0.0, 0.0, 0.0, 1.0);
  5965. }
  5966. return false;
  5967. }
  5968. if (rotation) {
  5969. const sx = 1 / scale._x, sy = 1 / scale._y, sz = 1 / scale._z;
  5970. Matrix.FromValuesToRef(m[0] * sx, m[1] * sx, m[2] * sx, 0.0, m[4] * sy, m[5] * sy, m[6] * sy, 0.0, m[8] * sz, m[9] * sz, m[10] * sz, 0.0, 0.0, 0.0, 0.0, 1.0, MathTmp.Matrix[0]);
  5971. Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
  5972. }
  5973. return true;
  5974. }
  5975. /**
  5976. * Gets specific row of the matrix
  5977. * Example Playground - https://playground.babylonjs.com/#AV9X17#36
  5978. * @param index defines the number of the row to get
  5979. * @returns the index-th row of the current matrix as a new Vector4
  5980. */
  5981. getRow(index) {
  5982. if (index < 0 || index > 3) {
  5983. return null;
  5984. }
  5985. const i = index * 4;
  5986. return new Vector4(this._m[i + 0], this._m[i + 1], this._m[i + 2], this._m[i + 3]);
  5987. }
  5988. /**
  5989. * Gets specific row of the matrix to ref
  5990. * Example Playground - https://playground.babylonjs.com/#AV9X17#36
  5991. * @param index defines the number of the row to get
  5992. * @param rowVector vector to store the index-th row of the current matrix
  5993. * @returns result input
  5994. */
  5995. getRowToRef(index, rowVector) {
  5996. if (index >= 0 && index <= 3) {
  5997. const i = index * 4;
  5998. rowVector.x = this._m[i + 0];
  5999. rowVector.y = this._m[i + 1];
  6000. rowVector.z = this._m[i + 2];
  6001. rowVector.w = this._m[i + 3];
  6002. }
  6003. return rowVector;
  6004. }
  6005. /**
  6006. * Sets the index-th row of the current matrix to the vector4 values
  6007. * Example Playground - https://playground.babylonjs.com/#AV9X17#36
  6008. * @param index defines the number of the row to set
  6009. * @param row defines the target vector4
  6010. * @returns the updated current matrix
  6011. */
  6012. setRow(index, row) {
  6013. return this.setRowFromFloats(index, row.x, row.y, row.z, row.w);
  6014. }
  6015. /**
  6016. * Compute the transpose of the matrix
  6017. * Example Playground - https://playground.babylonjs.com/#AV9X17#40
  6018. * @returns the new transposed matrix
  6019. */
  6020. transpose() {
  6021. const result = new this.constructor();
  6022. Matrix.TransposeToRef(this, result);
  6023. return result;
  6024. }
  6025. /**
  6026. * Compute the transpose of the matrix and store it in a given matrix
  6027. * Example Playground - https://playground.babylonjs.com/#AV9X17#41
  6028. * @param result defines the target matrix
  6029. * @returns result input
  6030. */
  6031. transposeToRef(result) {
  6032. Matrix.TransposeToRef(this, result);
  6033. return result;
  6034. }
  6035. /**
  6036. * Sets the index-th row of the current matrix with the given 4 x float values
  6037. * Example Playground - https://playground.babylonjs.com/#AV9X17#36
  6038. * @param index defines the row index
  6039. * @param x defines the x component to set
  6040. * @param y defines the y component to set
  6041. * @param z defines the z component to set
  6042. * @param w defines the w component to set
  6043. * @returns the updated current matrix
  6044. */
  6045. setRowFromFloats(index, x, y, z, w) {
  6046. if (index < 0 || index > 3) {
  6047. return this;
  6048. }
  6049. const i = index * 4;
  6050. this._m[i + 0] = x;
  6051. this._m[i + 1] = y;
  6052. this._m[i + 2] = z;
  6053. this._m[i + 3] = w;
  6054. this.markAsUpdated();
  6055. return this;
  6056. }
  6057. /**
  6058. * Compute a new matrix set with the current matrix values multiplied by scale (float)
  6059. * @param scale defines the scale factor
  6060. * @returns a new matrix
  6061. */
  6062. scale(scale) {
  6063. const result = new this.constructor();
  6064. this.scaleToRef(scale, result);
  6065. return result;
  6066. }
  6067. /**
  6068. * Scale the current matrix values by a factor to a given result matrix
  6069. * @param scale defines the scale factor
  6070. * @param result defines the matrix to store the result
  6071. * @returns result input
  6072. */
  6073. scaleToRef(scale, result) {
  6074. for (let index = 0; index < 16; index++) {
  6075. result._m[index] = this._m[index] * scale;
  6076. }
  6077. result.markAsUpdated();
  6078. return result;
  6079. }
  6080. /**
  6081. * Scale the current matrix values by a factor and add the result to a given matrix
  6082. * @param scale defines the scale factor
  6083. * @param result defines the Matrix to store the result
  6084. * @returns result input
  6085. */
  6086. scaleAndAddToRef(scale, result) {
  6087. for (let index = 0; index < 16; index++) {
  6088. result._m[index] += this._m[index] * scale;
  6089. }
  6090. result.markAsUpdated();
  6091. return result;
  6092. }
  6093. scaleInPlace(scale) {
  6094. const m = this._m;
  6095. for (let i = 0; i < 16; i++) {
  6096. m[i] *= scale;
  6097. }
  6098. this.markAsUpdated();
  6099. return this;
  6100. }
  6101. /**
  6102. * Writes to the given matrix a normal matrix, computed from this one (using values from identity matrix for fourth row and column).
  6103. * Example Playground - https://playground.babylonjs.com/#AV9X17#17
  6104. * @param ref matrix to store the result
  6105. * @returns the reference matrix
  6106. */
  6107. toNormalMatrix(ref) {
  6108. const tmp = MathTmp.Matrix[0];
  6109. this.invertToRef(tmp);
  6110. tmp.transposeToRef(ref);
  6111. const m = ref._m;
  6112. Matrix.FromValuesToRef(m[0], m[1], m[2], 0.0, m[4], m[5], m[6], 0.0, m[8], m[9], m[10], 0.0, 0.0, 0.0, 0.0, 1.0, ref);
  6113. return ref;
  6114. }
  6115. /**
  6116. * Gets only rotation part of the current matrix
  6117. * @returns a new matrix sets to the extracted rotation matrix from the current one
  6118. */
  6119. getRotationMatrix() {
  6120. const result = new this.constructor();
  6121. this.getRotationMatrixToRef(result);
  6122. return result;
  6123. }
  6124. /**
  6125. * Extracts the rotation matrix from the current one and sets it as the given "result"
  6126. * @param result defines the target matrix to store data to
  6127. * @returns result input
  6128. */
  6129. getRotationMatrixToRef(result) {
  6130. const scale = MathTmp.Vector3[0];
  6131. if (!this.decompose(scale)) {
  6132. Matrix.IdentityToRef(result);
  6133. return result;
  6134. }
  6135. const m = this._m;
  6136. const sx = 1 / scale._x, sy = 1 / scale._y, sz = 1 / scale._z;
  6137. Matrix.FromValuesToRef(m[0] * sx, m[1] * sx, m[2] * sx, 0.0, m[4] * sy, m[5] * sy, m[6] * sy, 0.0, m[8] * sz, m[9] * sz, m[10] * sz, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  6138. return result;
  6139. }
  6140. /**
  6141. * Toggles model matrix from being right handed to left handed in place and vice versa
  6142. * @returns the current updated matrix
  6143. */
  6144. toggleModelMatrixHandInPlace() {
  6145. const m = this._m;
  6146. m[2] *= -1;
  6147. m[6] *= -1;
  6148. m[8] *= -1;
  6149. m[9] *= -1;
  6150. m[14] *= -1;
  6151. this.markAsUpdated();
  6152. return this;
  6153. }
  6154. /**
  6155. * Toggles projection matrix from being right handed to left handed in place and vice versa
  6156. * @returns the current updated matrix
  6157. */
  6158. toggleProjectionMatrixHandInPlace() {
  6159. const m = this._m;
  6160. m[8] *= -1;
  6161. m[9] *= -1;
  6162. m[10] *= -1;
  6163. m[11] *= -1;
  6164. this.markAsUpdated();
  6165. return this;
  6166. }
  6167. // Statics
  6168. /**
  6169. * Creates a matrix from an array
  6170. * Example Playground - https://playground.babylonjs.com/#AV9X17#42
  6171. * @param array defines the source array
  6172. * @param offset defines an offset in the source array
  6173. * @returns a new Matrix set from the starting index of the given array
  6174. */
  6175. static FromArray(array, offset = 0) {
  6176. const result = new Matrix();
  6177. Matrix.FromArrayToRef(array, offset, result);
  6178. return result;
  6179. }
  6180. /**
  6181. * Copy the content of an array into a given matrix
  6182. * Example Playground - https://playground.babylonjs.com/#AV9X17#43
  6183. * @param array defines the source array
  6184. * @param offset defines an offset in the source array
  6185. * @param result defines the target matrix
  6186. * @returns result input
  6187. */
  6188. static FromArrayToRef(array, offset, result) {
  6189. for (let index = 0; index < 16; index++) {
  6190. result._m[index] = array[index + offset];
  6191. }
  6192. result.markAsUpdated();
  6193. return result;
  6194. }
  6195. /**
  6196. * Stores an array into a matrix after having multiplied each component by a given factor
  6197. * Example Playground - https://playground.babylonjs.com/#AV9X17#50
  6198. * @param array defines the source array
  6199. * @param offset defines the offset in the source array
  6200. * @param scale defines the scaling factor
  6201. * @param result defines the target matrix
  6202. * @returns result input
  6203. */
  6204. static FromFloat32ArrayToRefScaled(array, offset, scale, result) {
  6205. for (let index = 0; index < 16; index++) {
  6206. result._m[index] = array[index + offset] * scale;
  6207. }
  6208. result.markAsUpdated();
  6209. return result;
  6210. }
  6211. /**
  6212. * Gets an identity matrix that must not be updated
  6213. */
  6214. static get IdentityReadOnly() {
  6215. return Matrix._IdentityReadOnly;
  6216. }
  6217. /**
  6218. * Stores a list of values (16) inside a given matrix
  6219. * @param initialM11 defines 1st value of 1st row
  6220. * @param initialM12 defines 2nd value of 1st row
  6221. * @param initialM13 defines 3rd value of 1st row
  6222. * @param initialM14 defines 4th value of 1st row
  6223. * @param initialM21 defines 1st value of 2nd row
  6224. * @param initialM22 defines 2nd value of 2nd row
  6225. * @param initialM23 defines 3rd value of 2nd row
  6226. * @param initialM24 defines 4th value of 2nd row
  6227. * @param initialM31 defines 1st value of 3rd row
  6228. * @param initialM32 defines 2nd value of 3rd row
  6229. * @param initialM33 defines 3rd value of 3rd row
  6230. * @param initialM34 defines 4th value of 3rd row
  6231. * @param initialM41 defines 1st value of 4th row
  6232. * @param initialM42 defines 2nd value of 4th row
  6233. * @param initialM43 defines 3rd value of 4th row
  6234. * @param initialM44 defines 4th value of 4th row
  6235. * @param result defines the target matrix
  6236. */
  6237. static FromValuesToRef(initialM11, initialM12, initialM13, initialM14, initialM21, initialM22, initialM23, initialM24, initialM31, initialM32, initialM33, initialM34, initialM41, initialM42, initialM43, initialM44, result) {
  6238. const m = result._m;
  6239. m[0] = initialM11;
  6240. m[1] = initialM12;
  6241. m[2] = initialM13;
  6242. m[3] = initialM14;
  6243. m[4] = initialM21;
  6244. m[5] = initialM22;
  6245. m[6] = initialM23;
  6246. m[7] = initialM24;
  6247. m[8] = initialM31;
  6248. m[9] = initialM32;
  6249. m[10] = initialM33;
  6250. m[11] = initialM34;
  6251. m[12] = initialM41;
  6252. m[13] = initialM42;
  6253. m[14] = initialM43;
  6254. m[15] = initialM44;
  6255. result.markAsUpdated();
  6256. }
  6257. /**
  6258. * Creates new matrix from a list of values (16)
  6259. * @param initialM11 defines 1st value of 1st row
  6260. * @param initialM12 defines 2nd value of 1st row
  6261. * @param initialM13 defines 3rd value of 1st row
  6262. * @param initialM14 defines 4th value of 1st row
  6263. * @param initialM21 defines 1st value of 2nd row
  6264. * @param initialM22 defines 2nd value of 2nd row
  6265. * @param initialM23 defines 3rd value of 2nd row
  6266. * @param initialM24 defines 4th value of 2nd row
  6267. * @param initialM31 defines 1st value of 3rd row
  6268. * @param initialM32 defines 2nd value of 3rd row
  6269. * @param initialM33 defines 3rd value of 3rd row
  6270. * @param initialM34 defines 4th value of 3rd row
  6271. * @param initialM41 defines 1st value of 4th row
  6272. * @param initialM42 defines 2nd value of 4th row
  6273. * @param initialM43 defines 3rd value of 4th row
  6274. * @param initialM44 defines 4th value of 4th row
  6275. * @returns the new matrix
  6276. */
  6277. static FromValues(initialM11, initialM12, initialM13, initialM14, initialM21, initialM22, initialM23, initialM24, initialM31, initialM32, initialM33, initialM34, initialM41, initialM42, initialM43, initialM44) {
  6278. const result = new Matrix();
  6279. const m = result._m;
  6280. m[0] = initialM11;
  6281. m[1] = initialM12;
  6282. m[2] = initialM13;
  6283. m[3] = initialM14;
  6284. m[4] = initialM21;
  6285. m[5] = initialM22;
  6286. m[6] = initialM23;
  6287. m[7] = initialM24;
  6288. m[8] = initialM31;
  6289. m[9] = initialM32;
  6290. m[10] = initialM33;
  6291. m[11] = initialM34;
  6292. m[12] = initialM41;
  6293. m[13] = initialM42;
  6294. m[14] = initialM43;
  6295. m[15] = initialM44;
  6296. result.markAsUpdated();
  6297. return result;
  6298. }
  6299. /**
  6300. * Creates a new matrix composed by merging scale (vector3), rotation (quaternion) and translation (vector3)
  6301. * Example Playground - https://playground.babylonjs.com/#AV9X17#24
  6302. * @param scale defines the scale vector3
  6303. * @param rotation defines the rotation quaternion
  6304. * @param translation defines the translation vector3
  6305. * @returns a new matrix
  6306. */
  6307. static Compose(scale, rotation, translation) {
  6308. const result = new Matrix();
  6309. Matrix.ComposeToRef(scale, rotation, translation, result);
  6310. return result;
  6311. }
  6312. /**
  6313. * Sets a matrix to a value composed by merging scale (vector3), rotation (quaternion) and translation (vector3)
  6314. * Example Playground - https://playground.babylonjs.com/#AV9X17#25
  6315. * @param scale defines the scale vector3
  6316. * @param rotation defines the rotation quaternion
  6317. * @param translation defines the translation vector3
  6318. * @param result defines the target matrix
  6319. * @returns result input
  6320. */
  6321. static ComposeToRef(scale, rotation, translation, result) {
  6322. const m = result._m;
  6323. const x = rotation._x, y = rotation._y, z = rotation._z, w = rotation._w;
  6324. const x2 = x + x, y2 = y + y, z2 = z + z;
  6325. const xx = x * x2, xy = x * y2, xz = x * z2;
  6326. const yy = y * y2, yz = y * z2, zz = z * z2;
  6327. const wx = w * x2, wy = w * y2, wz = w * z2;
  6328. const sx = scale._x, sy = scale._y, sz = scale._z;
  6329. m[0] = (1 - (yy + zz)) * sx;
  6330. m[1] = (xy + wz) * sx;
  6331. m[2] = (xz - wy) * sx;
  6332. m[3] = 0;
  6333. m[4] = (xy - wz) * sy;
  6334. m[5] = (1 - (xx + zz)) * sy;
  6335. m[6] = (yz + wx) * sy;
  6336. m[7] = 0;
  6337. m[8] = (xz + wy) * sz;
  6338. m[9] = (yz - wx) * sz;
  6339. m[10] = (1 - (xx + yy)) * sz;
  6340. m[11] = 0;
  6341. m[12] = translation._x;
  6342. m[13] = translation._y;
  6343. m[14] = translation._z;
  6344. m[15] = 1;
  6345. result.markAsUpdated();
  6346. return result;
  6347. }
  6348. /**
  6349. * Creates a new identity matrix
  6350. * @returns a new identity matrix
  6351. */
  6352. static Identity() {
  6353. const identity = Matrix.FromValues(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
  6354. identity._updateIdentityStatus(true);
  6355. return identity;
  6356. }
  6357. /**
  6358. * Creates a new identity matrix and stores the result in a given matrix
  6359. * @param result defines the target matrix
  6360. * @returns result input
  6361. */
  6362. static IdentityToRef(result) {
  6363. Matrix.FromValuesToRef(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  6364. result._updateIdentityStatus(true);
  6365. return result;
  6366. }
  6367. /**
  6368. * Creates a new zero matrix
  6369. * @returns a new zero matrix
  6370. */
  6371. static Zero() {
  6372. const zero = Matrix.FromValues(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  6373. zero._updateIdentityStatus(false);
  6374. return zero;
  6375. }
  6376. /**
  6377. * Creates a new rotation matrix for "angle" radians around the X axis
  6378. * Example Playground - https://playground.babylonjs.com/#AV9X17#97
  6379. * @param angle defines the angle (in radians) to use
  6380. * @returns the new matrix
  6381. */
  6382. static RotationX(angle) {
  6383. const result = new Matrix();
  6384. Matrix.RotationXToRef(angle, result);
  6385. return result;
  6386. }
  6387. /**
  6388. * Creates a new matrix as the invert of a given matrix
  6389. * Example Playground - https://playground.babylonjs.com/#AV9X17#124
  6390. * @param source defines the source matrix
  6391. * @returns the new matrix
  6392. */
  6393. static Invert(source) {
  6394. const result = new source.constructor();
  6395. source.invertToRef(result);
  6396. return result;
  6397. }
  6398. /**
  6399. * Creates a new rotation matrix for "angle" radians around the X axis and stores it in a given matrix
  6400. * Example Playground - https://playground.babylonjs.com/#AV9X17#98
  6401. * @param angle defines the angle (in radians) to use
  6402. * @param result defines the target matrix
  6403. * @returns result input
  6404. */
  6405. static RotationXToRef(angle, result) {
  6406. const s = Math.sin(angle);
  6407. const c = Math.cos(angle);
  6408. Matrix.FromValuesToRef(1.0, 0.0, 0.0, 0.0, 0.0, c, s, 0.0, 0.0, -s, c, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  6409. result._updateIdentityStatus(c === 1 && s === 0);
  6410. return result;
  6411. }
  6412. /**
  6413. * Creates a new rotation matrix for "angle" radians around the Y axis
  6414. * Example Playground - https://playground.babylonjs.com/#AV9X17#99
  6415. * @param angle defines the angle (in radians) to use
  6416. * @returns the new matrix
  6417. */
  6418. static RotationY(angle) {
  6419. const result = new Matrix();
  6420. Matrix.RotationYToRef(angle, result);
  6421. return result;
  6422. }
  6423. /**
  6424. * Creates a new rotation matrix for "angle" radians around the Y axis and stores it in a given matrix
  6425. * Example Playground - https://playground.babylonjs.com/#AV9X17#100
  6426. * @param angle defines the angle (in radians) to use
  6427. * @param result defines the target matrix
  6428. * @returns result input
  6429. */
  6430. static RotationYToRef(angle, result) {
  6431. const s = Math.sin(angle);
  6432. const c = Math.cos(angle);
  6433. Matrix.FromValuesToRef(c, 0.0, -s, 0.0, 0.0, 1.0, 0.0, 0.0, s, 0.0, c, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  6434. result._updateIdentityStatus(c === 1 && s === 0);
  6435. return result;
  6436. }
  6437. /**
  6438. * Creates a new rotation matrix for "angle" radians around the Z axis
  6439. * Example Playground - https://playground.babylonjs.com/#AV9X17#101
  6440. * @param angle defines the angle (in radians) to use
  6441. * @returns the new matrix
  6442. */
  6443. static RotationZ(angle) {
  6444. const result = new Matrix();
  6445. Matrix.RotationZToRef(angle, result);
  6446. return result;
  6447. }
  6448. /**
  6449. * Creates a new rotation matrix for "angle" radians around the Z axis and stores it in a given matrix
  6450. * Example Playground - https://playground.babylonjs.com/#AV9X17#102
  6451. * @param angle defines the angle (in radians) to use
  6452. * @param result defines the target matrix
  6453. * @returns result input
  6454. */
  6455. static RotationZToRef(angle, result) {
  6456. const s = Math.sin(angle);
  6457. const c = Math.cos(angle);
  6458. Matrix.FromValuesToRef(c, s, 0.0, 0.0, -s, c, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  6459. result._updateIdentityStatus(c === 1 && s === 0);
  6460. return result;
  6461. }
  6462. /**
  6463. * Creates a new rotation matrix for "angle" radians around the given axis
  6464. * Example Playground - https://playground.babylonjs.com/#AV9X17#96
  6465. * @param axis defines the axis to use
  6466. * @param angle defines the angle (in radians) to use
  6467. * @returns the new matrix
  6468. */
  6469. static RotationAxis(axis, angle) {
  6470. const result = new Matrix();
  6471. Matrix.RotationAxisToRef(axis, angle, result);
  6472. return result;
  6473. }
  6474. /**
  6475. * Creates a new rotation matrix for "angle" radians around the given axis and stores it in a given matrix
  6476. * Example Playground - https://playground.babylonjs.com/#AV9X17#94
  6477. * @param axis defines the axis to use
  6478. * @param angle defines the angle (in radians) to use
  6479. * @param result defines the target matrix
  6480. * @returns result input
  6481. */
  6482. static RotationAxisToRef(axis, angle, result) {
  6483. const s = Math.sin(-angle);
  6484. const c = Math.cos(-angle);
  6485. const c1 = 1 - c;
  6486. axis.normalize();
  6487. const m = result._m;
  6488. m[0] = axis._x * axis._x * c1 + c;
  6489. m[1] = axis._x * axis._y * c1 - axis._z * s;
  6490. m[2] = axis._x * axis._z * c1 + axis._y * s;
  6491. m[3] = 0.0;
  6492. m[4] = axis._y * axis._x * c1 + axis._z * s;
  6493. m[5] = axis._y * axis._y * c1 + c;
  6494. m[6] = axis._y * axis._z * c1 - axis._x * s;
  6495. m[7] = 0.0;
  6496. m[8] = axis._z * axis._x * c1 - axis._y * s;
  6497. m[9] = axis._z * axis._y * c1 + axis._x * s;
  6498. m[10] = axis._z * axis._z * c1 + c;
  6499. m[11] = 0.0;
  6500. m[12] = 0.0;
  6501. m[13] = 0.0;
  6502. m[14] = 0.0;
  6503. m[15] = 1.0;
  6504. result.markAsUpdated();
  6505. return result;
  6506. }
  6507. /**
  6508. * Takes normalised vectors and returns a rotation matrix to align "from" with "to".
  6509. * Taken from http://www.iquilezles.org/www/articles/noacos/noacos.htm
  6510. * Example Playground - https://playground.babylonjs.com/#AV9X17#93
  6511. * @param from defines the vector to align
  6512. * @param to defines the vector to align to
  6513. * @param result defines the target matrix
  6514. * @param useYAxisForCoplanar defines a boolean indicating that we should favor Y axis for coplanar vectors (default is false)
  6515. * @returns result input
  6516. */
  6517. static RotationAlignToRef(from, to, result, useYAxisForCoplanar = false) {
  6518. const c = Vector3.Dot(to, from);
  6519. const m = result._m;
  6520. if (c < -1 + Epsilon) {
  6521. // from and to are colinear and opposite direction.
  6522. // compute a PI rotation on Y axis
  6523. m[0] = -1;
  6524. m[1] = 0;
  6525. m[2] = 0;
  6526. m[3] = 0;
  6527. m[4] = 0;
  6528. m[5] = useYAxisForCoplanar ? 1 : -1;
  6529. m[6] = 0;
  6530. m[7] = 0;
  6531. m[8] = 0;
  6532. m[9] = 0;
  6533. m[10] = useYAxisForCoplanar ? -1 : 1;
  6534. m[11] = 0;
  6535. }
  6536. else {
  6537. const v = Vector3.Cross(to, from);
  6538. const k = 1 / (1 + c);
  6539. m[0] = v._x * v._x * k + c;
  6540. m[1] = v._y * v._x * k - v._z;
  6541. m[2] = v._z * v._x * k + v._y;
  6542. m[3] = 0;
  6543. m[4] = v._x * v._y * k + v._z;
  6544. m[5] = v._y * v._y * k + c;
  6545. m[6] = v._z * v._y * k - v._x;
  6546. m[7] = 0;
  6547. m[8] = v._x * v._z * k - v._y;
  6548. m[9] = v._y * v._z * k + v._x;
  6549. m[10] = v._z * v._z * k + c;
  6550. m[11] = 0;
  6551. }
  6552. m[12] = 0;
  6553. m[13] = 0;
  6554. m[14] = 0;
  6555. m[15] = 1;
  6556. result.markAsUpdated();
  6557. return result;
  6558. }
  6559. /**
  6560. * Creates a rotation matrix
  6561. * Example Playground - https://playground.babylonjs.com/#AV9X17#103
  6562. * Example Playground - https://playground.babylonjs.com/#AV9X17#105
  6563. * @param yaw defines the yaw angle in radians (Y axis)
  6564. * @param pitch defines the pitch angle in radians (X axis)
  6565. * @param roll defines the roll angle in radians (Z axis)
  6566. * @returns the new rotation matrix
  6567. */
  6568. static RotationYawPitchRoll(yaw, pitch, roll) {
  6569. const result = new Matrix();
  6570. Matrix.RotationYawPitchRollToRef(yaw, pitch, roll, result);
  6571. return result;
  6572. }
  6573. /**
  6574. * Creates a rotation matrix and stores it in a given matrix
  6575. * Example Playground - https://playground.babylonjs.com/#AV9X17#104
  6576. * @param yaw defines the yaw angle in radians (Y axis)
  6577. * @param pitch defines the pitch angle in radians (X axis)
  6578. * @param roll defines the roll angle in radians (Z axis)
  6579. * @param result defines the target matrix
  6580. * @returns result input
  6581. */
  6582. static RotationYawPitchRollToRef(yaw, pitch, roll, result) {
  6583. Quaternion.RotationYawPitchRollToRef(yaw, pitch, roll, MathTmp.Quaternion[0]);
  6584. MathTmp.Quaternion[0].toRotationMatrix(result);
  6585. return result;
  6586. }
  6587. /**
  6588. * Creates a scaling matrix
  6589. * Example Playground - https://playground.babylonjs.com/#AV9X17#107
  6590. * @param x defines the scale factor on X axis
  6591. * @param y defines the scale factor on Y axis
  6592. * @param z defines the scale factor on Z axis
  6593. * @returns the new matrix
  6594. */
  6595. static Scaling(x, y, z) {
  6596. const result = new Matrix();
  6597. Matrix.ScalingToRef(x, y, z, result);
  6598. return result;
  6599. }
  6600. /**
  6601. * Creates a scaling matrix and stores it in a given matrix
  6602. * Example Playground - https://playground.babylonjs.com/#AV9X17#108
  6603. * @param x defines the scale factor on X axis
  6604. * @param y defines the scale factor on Y axis
  6605. * @param z defines the scale factor on Z axis
  6606. * @param result defines the target matrix
  6607. * @returns result input
  6608. */
  6609. static ScalingToRef(x, y, z, result) {
  6610. Matrix.FromValuesToRef(x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  6611. result._updateIdentityStatus(x === 1 && y === 1 && z === 1);
  6612. return result;
  6613. }
  6614. /**
  6615. * Creates a translation matrix
  6616. * Example Playground - https://playground.babylonjs.com/#AV9X17#109
  6617. * @param x defines the translation on X axis
  6618. * @param y defines the translation on Y axis
  6619. * @param z defines the translationon Z axis
  6620. * @returns the new matrix
  6621. */
  6622. static Translation(x, y, z) {
  6623. const result = new Matrix();
  6624. Matrix.TranslationToRef(x, y, z, result);
  6625. return result;
  6626. }
  6627. /**
  6628. * Creates a translation matrix and stores it in a given matrix
  6629. * Example Playground - https://playground.babylonjs.com/#AV9X17#110
  6630. * @param x defines the translation on X axis
  6631. * @param y defines the translation on Y axis
  6632. * @param z defines the translationon Z axis
  6633. * @param result defines the target matrix
  6634. * @returns result input
  6635. */
  6636. static TranslationToRef(x, y, z, result) {
  6637. Matrix.FromValuesToRef(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0, result);
  6638. result._updateIdentityStatus(x === 0 && y === 0 && z === 0);
  6639. return result;
  6640. }
  6641. /**
  6642. * Returns a new Matrix whose values are the interpolated values for "gradient" (float) between the ones of the matrices "startValue" and "endValue".
  6643. * Example Playground - https://playground.babylonjs.com/#AV9X17#55
  6644. * @param startValue defines the start value
  6645. * @param endValue defines the end value
  6646. * @param gradient defines the gradient factor
  6647. * @returns the new matrix
  6648. */
  6649. static Lerp(startValue, endValue, gradient) {
  6650. const result = new startValue.constructor();
  6651. Matrix.LerpToRef(startValue, endValue, gradient, result);
  6652. return result;
  6653. }
  6654. /**
  6655. * Set the given matrix "result" as the interpolated values for "gradient" (float) between the ones of the matrices "startValue" and "endValue".
  6656. * Example Playground - https://playground.babylonjs.com/#AV9X17#54
  6657. * @param startValue defines the start value
  6658. * @param endValue defines the end value
  6659. * @param gradient defines the gradient factor
  6660. * @param result defines the Matrix object where to store data
  6661. * @returns result input
  6662. */
  6663. static LerpToRef(startValue, endValue, gradient, result) {
  6664. const resultM = result._m;
  6665. const startM = startValue.m;
  6666. const endM = endValue.m;
  6667. for (let index = 0; index < 16; index++) {
  6668. resultM[index] = startM[index] * (1.0 - gradient) + endM[index] * gradient;
  6669. }
  6670. result.markAsUpdated();
  6671. return result;
  6672. }
  6673. /**
  6674. * Builds a new matrix whose values are computed by:
  6675. * * decomposing the "startValue" and "endValue" matrices into their respective scale, rotation and translation matrices
  6676. * * interpolating for "gradient" (float) the values between each of these decomposed matrices between the start and the end
  6677. * * recomposing a new matrix from these 3 interpolated scale, rotation and translation matrices
  6678. * Example Playground - https://playground.babylonjs.com/#AV9X17#22
  6679. * Example Playground - https://playground.babylonjs.com/#AV9X17#51
  6680. * @param startValue defines the first matrix
  6681. * @param endValue defines the second matrix
  6682. * @param gradient defines the gradient between the two matrices
  6683. * @returns the new matrix
  6684. */
  6685. static DecomposeLerp(startValue, endValue, gradient) {
  6686. const result = new startValue.constructor();
  6687. Matrix.DecomposeLerpToRef(startValue, endValue, gradient, result);
  6688. return result;
  6689. }
  6690. /**
  6691. * Update a matrix to values which are computed by:
  6692. * * decomposing the "startValue" and "endValue" matrices into their respective scale, rotation and translation matrices
  6693. * * interpolating for "gradient" (float) the values between each of these decomposed matrices between the start and the end
  6694. * * recomposing a new matrix from these 3 interpolated scale, rotation and translation matrices
  6695. * Example Playground - https://playground.babylonjs.com/#AV9X17#23
  6696. * Example Playground - https://playground.babylonjs.com/#AV9X17#53
  6697. * @param startValue defines the first matrix
  6698. * @param endValue defines the second matrix
  6699. * @param gradient defines the gradient between the two matrices
  6700. * @param result defines the target matrix
  6701. * @returns result input
  6702. */
  6703. static DecomposeLerpToRef(startValue, endValue, gradient, result) {
  6704. const startScale = MathTmp.Vector3[0];
  6705. const startRotation = MathTmp.Quaternion[0];
  6706. const startTranslation = MathTmp.Vector3[1];
  6707. startValue.decompose(startScale, startRotation, startTranslation);
  6708. const endScale = MathTmp.Vector3[2];
  6709. const endRotation = MathTmp.Quaternion[1];
  6710. const endTranslation = MathTmp.Vector3[3];
  6711. endValue.decompose(endScale, endRotation, endTranslation);
  6712. const resultScale = MathTmp.Vector3[4];
  6713. Vector3.LerpToRef(startScale, endScale, gradient, resultScale);
  6714. const resultRotation = MathTmp.Quaternion[2];
  6715. Quaternion.SlerpToRef(startRotation, endRotation, gradient, resultRotation);
  6716. const resultTranslation = MathTmp.Vector3[5];
  6717. Vector3.LerpToRef(startTranslation, endTranslation, gradient, resultTranslation);
  6718. Matrix.ComposeToRef(resultScale, resultRotation, resultTranslation, result);
  6719. return result;
  6720. }
  6721. /**
  6722. * Creates a new matrix that transforms vertices from world space to camera space. It takes three vectors as arguments that together describe the position and orientation of the camera.
  6723. * This function generates a matrix suitable for a left handed coordinate system
  6724. * Example Playground - https://playground.babylonjs.com/#AV9X17#58
  6725. * Example Playground - https://playground.babylonjs.com/#AV9X17#59
  6726. * @param eye defines the final position of the entity
  6727. * @param target defines where the entity should look at
  6728. * @param up defines the up vector for the entity
  6729. * @returns the new matrix
  6730. */
  6731. static LookAtLH(eye, target, up) {
  6732. const result = new Matrix();
  6733. Matrix.LookAtLHToRef(eye, target, up, result);
  6734. return result;
  6735. }
  6736. /**
  6737. * Sets the given "result" Matrix to a matrix that transforms vertices from world space to camera space. It takes three vectors as arguments that together describe the position and orientation of the camera.
  6738. * This function generates a matrix suitable for a left handed coordinate system
  6739. * Example Playground - https://playground.babylonjs.com/#AV9X17#60
  6740. * Example Playground - https://playground.babylonjs.com/#AV9X17#61
  6741. * @param eye defines the final position of the entity
  6742. * @param target defines where the entity should look at
  6743. * @param up defines the up vector for the entity
  6744. * @param result defines the target matrix
  6745. * @returns result input
  6746. */
  6747. static LookAtLHToRef(eye, target, up, result) {
  6748. const xAxis = MathTmp.Vector3[0];
  6749. const yAxis = MathTmp.Vector3[1];
  6750. const zAxis = MathTmp.Vector3[2];
  6751. // Z axis
  6752. target.subtractToRef(eye, zAxis);
  6753. zAxis.normalize();
  6754. // X axis
  6755. Vector3.CrossToRef(up, zAxis, xAxis);
  6756. const xSquareLength = xAxis.lengthSquared();
  6757. if (xSquareLength === 0) {
  6758. xAxis.x = 1.0;
  6759. }
  6760. else {
  6761. xAxis.normalizeFromLength(Math.sqrt(xSquareLength));
  6762. }
  6763. // Y axis
  6764. Vector3.CrossToRef(zAxis, xAxis, yAxis);
  6765. yAxis.normalize();
  6766. // Eye angles
  6767. const ex = -Vector3.Dot(xAxis, eye);
  6768. const ey = -Vector3.Dot(yAxis, eye);
  6769. const ez = -Vector3.Dot(zAxis, eye);
  6770. Matrix.FromValuesToRef(xAxis._x, yAxis._x, zAxis._x, 0.0, xAxis._y, yAxis._y, zAxis._y, 0.0, xAxis._z, yAxis._z, zAxis._z, 0.0, ex, ey, ez, 1.0, result);
  6771. return result;
  6772. }
  6773. /**
  6774. * Creates a new matrix that transforms vertices from world space to camera space. It takes three vectors as arguments that together describe the position and orientation of the camera.
  6775. * This function generates a matrix suitable for a right handed coordinate system
  6776. * Example Playground - https://playground.babylonjs.com/#AV9X17#62
  6777. * Example Playground - https://playground.babylonjs.com/#AV9X17#63
  6778. * @param eye defines the final position of the entity
  6779. * @param target defines where the entity should look at
  6780. * @param up defines the up vector for the entity
  6781. * @returns the new matrix
  6782. */
  6783. static LookAtRH(eye, target, up) {
  6784. const result = new Matrix();
  6785. Matrix.LookAtRHToRef(eye, target, up, result);
  6786. return result;
  6787. }
  6788. /**
  6789. * Sets the given "result" Matrix to a matrix that transforms vertices from world space to camera space. It takes three vectors as arguments that together describe the position and orientation of the camera.
  6790. * This function generates a matrix suitable for a right handed coordinate system
  6791. * Example Playground - https://playground.babylonjs.com/#AV9X17#64
  6792. * Example Playground - https://playground.babylonjs.com/#AV9X17#65
  6793. * @param eye defines the final position of the entity
  6794. * @param target defines where the entity should look at
  6795. * @param up defines the up vector for the entity
  6796. * @param result defines the target matrix
  6797. * @returns result input
  6798. */
  6799. static LookAtRHToRef(eye, target, up, result) {
  6800. const xAxis = MathTmp.Vector3[0];
  6801. const yAxis = MathTmp.Vector3[1];
  6802. const zAxis = MathTmp.Vector3[2];
  6803. // Z axis
  6804. eye.subtractToRef(target, zAxis);
  6805. zAxis.normalize();
  6806. // X axis
  6807. Vector3.CrossToRef(up, zAxis, xAxis);
  6808. const xSquareLength = xAxis.lengthSquared();
  6809. if (xSquareLength === 0) {
  6810. xAxis.x = 1.0;
  6811. }
  6812. else {
  6813. xAxis.normalizeFromLength(Math.sqrt(xSquareLength));
  6814. }
  6815. // Y axis
  6816. Vector3.CrossToRef(zAxis, xAxis, yAxis);
  6817. yAxis.normalize();
  6818. // Eye angles
  6819. const ex = -Vector3.Dot(xAxis, eye);
  6820. const ey = -Vector3.Dot(yAxis, eye);
  6821. const ez = -Vector3.Dot(zAxis, eye);
  6822. Matrix.FromValuesToRef(xAxis._x, yAxis._x, zAxis._x, 0.0, xAxis._y, yAxis._y, zAxis._y, 0.0, xAxis._z, yAxis._z, zAxis._z, 0.0, ex, ey, ez, 1.0, result);
  6823. return result;
  6824. }
  6825. /**
  6826. * Creates a new matrix that transforms vertices from world space to camera space. It takes two vectors as arguments that together describe the orientation of the camera. The position is assumed to be at the origin (0,0,0)
  6827. * This function generates a matrix suitable for a left handed coordinate system
  6828. * Example Playground - https://playground.babylonjs.com/#AV9X17#66
  6829. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  6830. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  6831. * @returns the new matrix
  6832. */
  6833. static LookDirectionLH(forward, up) {
  6834. const result = new Matrix();
  6835. Matrix.LookDirectionLHToRef(forward, up, result);
  6836. return result;
  6837. }
  6838. /**
  6839. * Sets the given "result" Matrix to a matrix that transforms vertices from world space to camera space. It takes two vectors as arguments that together describe the orientation of the camera. The position is assumed to be at the origin (0,0,0)
  6840. * This function generates a matrix suitable for a left handed coordinate system
  6841. * Example Playground - https://playground.babylonjs.com/#AV9X17#67
  6842. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  6843. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  6844. * @param result defines the target matrix
  6845. * @returns result input
  6846. */
  6847. static LookDirectionLHToRef(forward, up, result) {
  6848. const back = MathTmp.Vector3[0];
  6849. back.copyFrom(forward);
  6850. back.scaleInPlace(-1);
  6851. const left = MathTmp.Vector3[1];
  6852. Vector3.CrossToRef(up, back, left);
  6853. // Generate the rotation matrix.
  6854. Matrix.FromValuesToRef(left._x, left._y, left._z, 0.0, up._x, up._y, up._z, 0.0, back._x, back._y, back._z, 0.0, 0, 0, 0, 1.0, result);
  6855. return result;
  6856. }
  6857. /**
  6858. * Creates a new matrix that transforms vertices from world space to camera space. It takes two vectors as arguments that together describe the orientation of the camera. The position is assumed to be at the origin (0,0,0)
  6859. * This function generates a matrix suitable for a right handed coordinate system
  6860. * Example Playground - https://playground.babylonjs.com/#AV9X17#68
  6861. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  6862. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  6863. * @returns the new matrix
  6864. */
  6865. static LookDirectionRH(forward, up) {
  6866. const result = new Matrix();
  6867. Matrix.LookDirectionRHToRef(forward, up, result);
  6868. return result;
  6869. }
  6870. /**
  6871. * Sets the given "result" Matrix to a matrix that transforms vertices from world space to camera space. It takes two vectors as arguments that together describe the orientation of the camera. The position is assumed to be at the origin (0,0,0)
  6872. * This function generates a matrix suitable for a right handed coordinate system
  6873. * Example Playground - https://playground.babylonjs.com/#AV9X17#69
  6874. * @param forward defines the forward direction - Must be normalized and orthogonal to up.
  6875. * @param up defines the up vector for the entity - Must be normalized and orthogonal to forward.
  6876. * @param result defines the target matrix
  6877. * @returns result input
  6878. */
  6879. static LookDirectionRHToRef(forward, up, result) {
  6880. const right = MathTmp.Vector3[2];
  6881. Vector3.CrossToRef(up, forward, right);
  6882. // Generate the rotation matrix.
  6883. Matrix.FromValuesToRef(right._x, right._y, right._z, 0.0, up._x, up._y, up._z, 0.0, forward._x, forward._y, forward._z, 0.0, 0, 0, 0, 1.0, result);
  6884. return result;
  6885. }
  6886. /**
  6887. * Create a left-handed orthographic projection matrix
  6888. * Example Playground - https://playground.babylonjs.com/#AV9X17#70
  6889. * @param width defines the viewport width
  6890. * @param height defines the viewport height
  6891. * @param znear defines the near clip plane
  6892. * @param zfar defines the far clip plane
  6893. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  6894. * @returns a new matrix as a left-handed orthographic projection matrix
  6895. */
  6896. static OrthoLH(width, height, znear, zfar, halfZRange) {
  6897. const matrix = new Matrix();
  6898. Matrix.OrthoLHToRef(width, height, znear, zfar, matrix, halfZRange);
  6899. return matrix;
  6900. }
  6901. /**
  6902. * Store a left-handed orthographic projection to a given matrix
  6903. * Example Playground - https://playground.babylonjs.com/#AV9X17#71
  6904. * @param width defines the viewport width
  6905. * @param height defines the viewport height
  6906. * @param znear defines the near clip plane
  6907. * @param zfar defines the far clip plane
  6908. * @param result defines the target matrix
  6909. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  6910. * @returns result input
  6911. */
  6912. static OrthoLHToRef(width, height, znear, zfar, result, halfZRange) {
  6913. const n = znear;
  6914. const f = zfar;
  6915. const a = 2.0 / width;
  6916. const b = 2.0 / height;
  6917. const c = 2.0 / (f - n);
  6918. const d = -(f + n) / (f - n);
  6919. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, 0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0, d, 1.0, result);
  6920. if (halfZRange) {
  6921. result.multiplyToRef(mtxConvertNDCToHalfZRange, result);
  6922. }
  6923. result._updateIdentityStatus(a === 1 && b === 1 && c === 1 && d === 0);
  6924. return result;
  6925. }
  6926. /**
  6927. * Create a left-handed orthographic projection matrix
  6928. * Example Playground - https://playground.babylonjs.com/#AV9X17#72
  6929. * @param left defines the viewport left coordinate
  6930. * @param right defines the viewport right coordinate
  6931. * @param bottom defines the viewport bottom coordinate
  6932. * @param top defines the viewport top coordinate
  6933. * @param znear defines the near clip plane
  6934. * @param zfar defines the far clip plane
  6935. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  6936. * @returns a new matrix as a left-handed orthographic projection matrix
  6937. */
  6938. static OrthoOffCenterLH(left, right, bottom, top, znear, zfar, halfZRange) {
  6939. const matrix = new Matrix();
  6940. Matrix.OrthoOffCenterLHToRef(left, right, bottom, top, znear, zfar, matrix, halfZRange);
  6941. return matrix;
  6942. }
  6943. /**
  6944. * Stores a left-handed orthographic projection into a given matrix
  6945. * Example Playground - https://playground.babylonjs.com/#AV9X17#73
  6946. * @param left defines the viewport left coordinate
  6947. * @param right defines the viewport right coordinate
  6948. * @param bottom defines the viewport bottom coordinate
  6949. * @param top defines the viewport top coordinate
  6950. * @param znear defines the near clip plane
  6951. * @param zfar defines the far clip plane
  6952. * @param result defines the target matrix
  6953. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  6954. * @returns result input
  6955. */
  6956. static OrthoOffCenterLHToRef(left, right, bottom, top, znear, zfar, result, halfZRange) {
  6957. const n = znear;
  6958. const f = zfar;
  6959. const a = 2.0 / (right - left);
  6960. const b = 2.0 / (top - bottom);
  6961. const c = 2.0 / (f - n);
  6962. const d = -(f + n) / (f - n);
  6963. const i0 = (left + right) / (left - right);
  6964. const i1 = (top + bottom) / (bottom - top);
  6965. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, 0.0, 0.0, 0.0, c, 0.0, i0, i1, d, 1.0, result);
  6966. if (halfZRange) {
  6967. result.multiplyToRef(mtxConvertNDCToHalfZRange, result);
  6968. }
  6969. result.markAsUpdated();
  6970. return result;
  6971. }
  6972. /**
  6973. * Stores a left-handed oblique projection into a given matrix
  6974. * @param left defines the viewport left coordinate
  6975. * @param right defines the viewport right coordinate
  6976. * @param bottom defines the viewport bottom coordinate
  6977. * @param top defines the viewport top coordinate
  6978. * @param znear defines the near clip plane
  6979. * @param zfar defines the far clip plane
  6980. * @param length Length of the shear
  6981. * @param angle Angle (along X/Y Plane) to apply shear
  6982. * @param distance Distance from shear point
  6983. * @param result defines the target matrix
  6984. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  6985. * @returns result input
  6986. */
  6987. static ObliqueOffCenterLHToRef(left, right, bottom, top, znear, zfar, length, angle, distance, result, halfZRange) {
  6988. const a = -length * Math.cos(angle);
  6989. const b = -length * Math.sin(angle);
  6990. Matrix.TranslationToRef(0, 0, -distance, MathTmp.Matrix[1]);
  6991. Matrix.FromValuesToRef(1, 0, 0, 0, 0, 1, 0, 0, a, b, 1, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
  6992. MathTmp.Matrix[1].multiplyToRef(MathTmp.Matrix[0], MathTmp.Matrix[0]);
  6993. Matrix.TranslationToRef(0, 0, distance, MathTmp.Matrix[1]);
  6994. MathTmp.Matrix[0].multiplyToRef(MathTmp.Matrix[1], MathTmp.Matrix[0]);
  6995. Matrix.OrthoOffCenterLHToRef(left, right, bottom, top, znear, zfar, result, halfZRange);
  6996. MathTmp.Matrix[0].multiplyToRef(result, result);
  6997. return result;
  6998. }
  6999. /**
  7000. * Creates a right-handed orthographic projection matrix
  7001. * Example Playground - https://playground.babylonjs.com/#AV9X17#76
  7002. * @param left defines the viewport left coordinate
  7003. * @param right defines the viewport right coordinate
  7004. * @param bottom defines the viewport bottom coordinate
  7005. * @param top defines the viewport top coordinate
  7006. * @param znear defines the near clip plane
  7007. * @param zfar defines the far clip plane
  7008. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7009. * @returns a new matrix as a right-handed orthographic projection matrix
  7010. */
  7011. static OrthoOffCenterRH(left, right, bottom, top, znear, zfar, halfZRange) {
  7012. const matrix = new Matrix();
  7013. Matrix.OrthoOffCenterRHToRef(left, right, bottom, top, znear, zfar, matrix, halfZRange);
  7014. return matrix;
  7015. }
  7016. /**
  7017. * Stores a right-handed orthographic projection into a given matrix
  7018. * Example Playground - https://playground.babylonjs.com/#AV9X17#77
  7019. * @param left defines the viewport left coordinate
  7020. * @param right defines the viewport right coordinate
  7021. * @param bottom defines the viewport bottom coordinate
  7022. * @param top defines the viewport top coordinate
  7023. * @param znear defines the near clip plane
  7024. * @param zfar defines the far clip plane
  7025. * @param result defines the target matrix
  7026. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7027. * @returns result input
  7028. */
  7029. static OrthoOffCenterRHToRef(left, right, bottom, top, znear, zfar, result, halfZRange) {
  7030. Matrix.OrthoOffCenterLHToRef(left, right, bottom, top, znear, zfar, result, halfZRange);
  7031. result._m[10] *= -1; // No need to call markAsUpdated as previous function already called it and let _isIdentityDirty to true
  7032. return result;
  7033. }
  7034. /**
  7035. * Stores a right-handed oblique projection into a given matrix
  7036. * @param left defines the viewport left coordinate
  7037. * @param right defines the viewport right coordinate
  7038. * @param bottom defines the viewport bottom coordinate
  7039. * @param top defines the viewport top coordinate
  7040. * @param znear defines the near clip plane
  7041. * @param zfar defines the far clip plane
  7042. * @param length Length of the shear
  7043. * @param angle Angle (along X/Y Plane) to apply shear
  7044. * @param distance Distance from shear point
  7045. * @param result defines the target matrix
  7046. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7047. * @returns result input
  7048. */
  7049. static ObliqueOffCenterRHToRef(left, right, bottom, top, znear, zfar, length, angle, distance, result, halfZRange) {
  7050. const a = length * Math.cos(angle);
  7051. const b = length * Math.sin(angle);
  7052. Matrix.TranslationToRef(0, 0, distance, MathTmp.Matrix[1]);
  7053. Matrix.FromValuesToRef(1, 0, 0, 0, 0, 1, 0, 0, a, b, 1, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
  7054. MathTmp.Matrix[1].multiplyToRef(MathTmp.Matrix[0], MathTmp.Matrix[0]);
  7055. Matrix.TranslationToRef(0, 0, -distance, MathTmp.Matrix[1]);
  7056. MathTmp.Matrix[0].multiplyToRef(MathTmp.Matrix[1], MathTmp.Matrix[0]);
  7057. Matrix.OrthoOffCenterRHToRef(left, right, bottom, top, znear, zfar, result, halfZRange);
  7058. MathTmp.Matrix[0].multiplyToRef(result, result);
  7059. return result;
  7060. }
  7061. /**
  7062. * Creates a left-handed perspective projection matrix
  7063. * Example Playground - https://playground.babylonjs.com/#AV9X17#85
  7064. * @param width defines the viewport width
  7065. * @param height defines the viewport height
  7066. * @param znear defines the near clip plane
  7067. * @param zfar defines the far clip plane
  7068. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7069. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7070. * @returns a new matrix as a left-handed perspective projection matrix
  7071. */
  7072. static PerspectiveLH(width, height, znear, zfar, halfZRange, projectionPlaneTilt = 0) {
  7073. const matrix = new Matrix();
  7074. const n = znear;
  7075. const f = zfar;
  7076. const a = (2.0 * n) / width;
  7077. const b = (2.0 * n) / height;
  7078. const c = (f + n) / (f - n);
  7079. const d = (-2.0 * f * n) / (f - n);
  7080. const rot = Math.tan(projectionPlaneTilt);
  7081. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, rot, 0.0, 0.0, c, 1.0, 0.0, 0.0, d, 0.0, matrix);
  7082. if (halfZRange) {
  7083. matrix.multiplyToRef(mtxConvertNDCToHalfZRange, matrix);
  7084. }
  7085. matrix._updateIdentityStatus(false);
  7086. return matrix;
  7087. }
  7088. /**
  7089. * Creates a left-handed perspective projection matrix
  7090. * Example Playground - https://playground.babylonjs.com/#AV9X17#78
  7091. * @param fov defines the horizontal field of view
  7092. * @param aspect defines the aspect ratio
  7093. * @param znear defines the near clip plane
  7094. * @param zfar defines the far clip plane. If 0, assume we are in "infinite zfar" mode
  7095. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7096. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7097. * @param reverseDepthBufferMode true to indicate that we are in a reverse depth buffer mode (meaning znear and zfar have been inverted when calling the function)
  7098. * @returns a new matrix as a left-handed perspective projection matrix
  7099. */
  7100. static PerspectiveFovLH(fov, aspect, znear, zfar, halfZRange, projectionPlaneTilt = 0, reverseDepthBufferMode = false) {
  7101. const matrix = new Matrix();
  7102. Matrix.PerspectiveFovLHToRef(fov, aspect, znear, zfar, matrix, true, halfZRange, projectionPlaneTilt, reverseDepthBufferMode);
  7103. return matrix;
  7104. }
  7105. /**
  7106. * Stores a left-handed perspective projection into a given matrix
  7107. * Example Playground - https://playground.babylonjs.com/#AV9X17#81
  7108. * @param fov defines the horizontal field of view
  7109. * @param aspect defines the aspect ratio
  7110. * @param znear defines the near clip plane
  7111. * @param zfar defines the far clip plane. If 0, assume we are in "infinite zfar" mode
  7112. * @param result defines the target matrix
  7113. * @param isVerticalFovFixed defines it the fov is vertically fixed (default) or horizontally
  7114. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7115. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7116. * @param reverseDepthBufferMode true to indicate that we are in a reverse depth buffer mode (meaning znear and zfar have been inverted when calling the function)
  7117. * @returns result input
  7118. */
  7119. static PerspectiveFovLHToRef(fov, aspect, znear, zfar, result, isVerticalFovFixed = true, halfZRange, projectionPlaneTilt = 0, reverseDepthBufferMode = false) {
  7120. const n = znear;
  7121. const f = zfar;
  7122. const t = 1.0 / Math.tan(fov * 0.5);
  7123. const a = isVerticalFovFixed ? t / aspect : t;
  7124. const b = isVerticalFovFixed ? t : t * aspect;
  7125. const c = reverseDepthBufferMode && n === 0 ? -1 : f !== 0 ? (f + n) / (f - n) : 1;
  7126. const d = reverseDepthBufferMode && n === 0 ? 2 * f : f !== 0 ? (-2.0 * f * n) / (f - n) : -2 * n;
  7127. const rot = Math.tan(projectionPlaneTilt);
  7128. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, rot, 0.0, 0.0, c, 1.0, 0.0, 0.0, d, 0.0, result);
  7129. if (halfZRange) {
  7130. result.multiplyToRef(mtxConvertNDCToHalfZRange, result);
  7131. }
  7132. result._updateIdentityStatus(false);
  7133. return result;
  7134. }
  7135. /**
  7136. * Stores a left-handed perspective projection into a given matrix with depth reversed
  7137. * Example Playground - https://playground.babylonjs.com/#AV9X17#89
  7138. * @param fov defines the horizontal field of view
  7139. * @param aspect defines the aspect ratio
  7140. * @param znear defines the near clip plane
  7141. * @param zfar not used as infinity is used as far clip
  7142. * @param result defines the target matrix
  7143. * @param isVerticalFovFixed defines it the fov is vertically fixed (default) or horizontally
  7144. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7145. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7146. * @returns result input
  7147. */
  7148. static PerspectiveFovReverseLHToRef(fov, aspect, znear, zfar, result, isVerticalFovFixed = true, halfZRange, projectionPlaneTilt = 0) {
  7149. const t = 1.0 / Math.tan(fov * 0.5);
  7150. const a = isVerticalFovFixed ? t / aspect : t;
  7151. const b = isVerticalFovFixed ? t : t * aspect;
  7152. const rot = Math.tan(projectionPlaneTilt);
  7153. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, rot, 0.0, 0.0, -znear, 1.0, 0.0, 0.0, 1.0, 0.0, result);
  7154. if (halfZRange) {
  7155. result.multiplyToRef(mtxConvertNDCToHalfZRange, result);
  7156. }
  7157. result._updateIdentityStatus(false);
  7158. return result;
  7159. }
  7160. /**
  7161. * Creates a right-handed perspective projection matrix
  7162. * Example Playground - https://playground.babylonjs.com/#AV9X17#83
  7163. * @param fov defines the horizontal field of view
  7164. * @param aspect defines the aspect ratio
  7165. * @param znear defines the near clip plane
  7166. * @param zfar defines the far clip plane. If 0, assume we are in "infinite zfar" mode
  7167. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7168. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7169. * @param reverseDepthBufferMode true to indicate that we are in a reverse depth buffer mode (meaning znear and zfar have been inverted when calling the function)
  7170. * @returns a new matrix as a right-handed perspective projection matrix
  7171. */
  7172. static PerspectiveFovRH(fov, aspect, znear, zfar, halfZRange, projectionPlaneTilt = 0, reverseDepthBufferMode = false) {
  7173. const matrix = new Matrix();
  7174. Matrix.PerspectiveFovRHToRef(fov, aspect, znear, zfar, matrix, true, halfZRange, projectionPlaneTilt, reverseDepthBufferMode);
  7175. return matrix;
  7176. }
  7177. /**
  7178. * Stores a right-handed perspective projection into a given matrix
  7179. * Example Playground - https://playground.babylonjs.com/#AV9X17#84
  7180. * @param fov defines the horizontal field of view
  7181. * @param aspect defines the aspect ratio
  7182. * @param znear defines the near clip plane
  7183. * @param zfar defines the far clip plane. If 0, assume we are in "infinite zfar" mode
  7184. * @param result defines the target matrix
  7185. * @param isVerticalFovFixed defines it the fov is vertically fixed (default) or horizontally
  7186. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7187. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7188. * @param reverseDepthBufferMode true to indicate that we are in a reverse depth buffer mode (meaning znear and zfar have been inverted when calling the function)
  7189. * @returns result input
  7190. */
  7191. static PerspectiveFovRHToRef(fov, aspect, znear, zfar, result, isVerticalFovFixed = true, halfZRange, projectionPlaneTilt = 0, reverseDepthBufferMode = false) {
  7192. //alternatively this could be expressed as:
  7193. // m = PerspectiveFovLHToRef
  7194. // m[10] *= -1.0;
  7195. // m[11] *= -1.0;
  7196. const n = znear;
  7197. const f = zfar;
  7198. const t = 1.0 / Math.tan(fov * 0.5);
  7199. const a = isVerticalFovFixed ? t / aspect : t;
  7200. const b = isVerticalFovFixed ? t : t * aspect;
  7201. const c = reverseDepthBufferMode && n === 0 ? 1 : f !== 0 ? -(f + n) / (f - n) : -1;
  7202. const d = reverseDepthBufferMode && n === 0 ? 2 * f : f !== 0 ? (-2 * f * n) / (f - n) : -2 * n;
  7203. const rot = Math.tan(projectionPlaneTilt);
  7204. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, rot, 0.0, 0.0, c, -1.0, 0.0, 0.0, d, 0.0, result);
  7205. if (halfZRange) {
  7206. result.multiplyToRef(mtxConvertNDCToHalfZRange, result);
  7207. }
  7208. result._updateIdentityStatus(false);
  7209. return result;
  7210. }
  7211. /**
  7212. * Stores a right-handed perspective projection into a given matrix
  7213. * Example Playground - https://playground.babylonjs.com/#AV9X17#90
  7214. * @param fov defines the horizontal field of view
  7215. * @param aspect defines the aspect ratio
  7216. * @param znear defines the near clip plane
  7217. * @param zfar not used as infinity is used as far clip
  7218. * @param result defines the target matrix
  7219. * @param isVerticalFovFixed defines it the fov is vertically fixed (default) or horizontally
  7220. * @param halfZRange true to generate NDC coordinates between 0 and 1 instead of -1 and 1 (default: false)
  7221. * @param projectionPlaneTilt optional tilt angle of the projection plane around the X axis (horizontal)
  7222. * @returns result input
  7223. */
  7224. static PerspectiveFovReverseRHToRef(fov, aspect, znear, zfar, result, isVerticalFovFixed = true, halfZRange, projectionPlaneTilt = 0) {
  7225. const t = 1.0 / Math.tan(fov * 0.5);
  7226. const a = isVerticalFovFixed ? t / aspect : t;
  7227. const b = isVerticalFovFixed ? t : t * aspect;
  7228. const rot = Math.tan(projectionPlaneTilt);
  7229. Matrix.FromValuesToRef(a, 0.0, 0.0, 0.0, 0.0, b, 0.0, rot, 0.0, 0.0, -znear, -1.0, 0.0, 0.0, -1.0, 0.0, result);
  7230. if (halfZRange) {
  7231. result.multiplyToRef(mtxConvertNDCToHalfZRange, result);
  7232. }
  7233. result._updateIdentityStatus(false);
  7234. return result;
  7235. }
  7236. /**
  7237. * Computes a complete transformation matrix
  7238. * Example Playground - https://playground.babylonjs.com/#AV9X17#113
  7239. * @param viewport defines the viewport to use
  7240. * @param world defines the world matrix
  7241. * @param view defines the view matrix
  7242. * @param projection defines the projection matrix
  7243. * @param zmin defines the near clip plane
  7244. * @param zmax defines the far clip plane
  7245. * @returns the transformation matrix
  7246. */
  7247. static GetFinalMatrix(viewport, world, view, projection, zmin, zmax) {
  7248. const cw = viewport.width;
  7249. const ch = viewport.height;
  7250. const cx = viewport.x;
  7251. const cy = viewport.y;
  7252. const viewportMatrix = Matrix.FromValues(cw / 2.0, 0.0, 0.0, 0.0, 0.0, -ch / 2.0, 0.0, 0.0, 0.0, 0.0, zmax - zmin, 0.0, cx + cw / 2.0, ch / 2.0 + cy, zmin, 1.0);
  7253. const matrix = new world.constructor();
  7254. world.multiplyToRef(view, matrix);
  7255. matrix.multiplyToRef(projection, matrix);
  7256. return matrix.multiplyToRef(viewportMatrix, matrix);
  7257. }
  7258. /**
  7259. * Extracts a 2x2 matrix from a given matrix and store the result in a Float32Array
  7260. * @param matrix defines the matrix to use
  7261. * @returns a new Float32Array array with 4 elements : the 2x2 matrix extracted from the given matrix
  7262. */
  7263. static GetAsMatrix2x2(matrix) {
  7264. const m = matrix.m;
  7265. const arr = [m[0], m[1], m[4], m[5]];
  7266. return PerformanceConfigurator.MatrixUse64Bits ? arr : new Float32Array(arr);
  7267. }
  7268. /**
  7269. * Extracts a 3x3 matrix from a given matrix and store the result in a Float32Array
  7270. * @param matrix defines the matrix to use
  7271. * @returns a new Float32Array array with 9 elements : the 3x3 matrix extracted from the given matrix
  7272. */
  7273. static GetAsMatrix3x3(matrix) {
  7274. const m = matrix.m;
  7275. const arr = [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]];
  7276. return PerformanceConfigurator.MatrixUse64Bits ? arr : new Float32Array(arr);
  7277. }
  7278. /**
  7279. * Compute the transpose of a given matrix
  7280. * Example Playground - https://playground.babylonjs.com/#AV9X17#111
  7281. * @param matrix defines the matrix to transpose
  7282. * @returns the new matrix
  7283. */
  7284. static Transpose(matrix) {
  7285. const result = new matrix.constructor();
  7286. Matrix.TransposeToRef(matrix, result);
  7287. return result;
  7288. }
  7289. /**
  7290. * Compute the transpose of a matrix and store it in a target matrix
  7291. * Example Playground - https://playground.babylonjs.com/#AV9X17#112
  7292. * @param matrix defines the matrix to transpose
  7293. * @param result defines the target matrix
  7294. * @returns result input
  7295. */
  7296. static TransposeToRef(matrix, result) {
  7297. const mm = matrix.m;
  7298. const rm0 = mm[0];
  7299. const rm1 = mm[4];
  7300. const rm2 = mm[8];
  7301. const rm3 = mm[12];
  7302. const rm4 = mm[1];
  7303. const rm5 = mm[5];
  7304. const rm6 = mm[9];
  7305. const rm7 = mm[13];
  7306. const rm8 = mm[2];
  7307. const rm9 = mm[6];
  7308. const rm10 = mm[10];
  7309. const rm11 = mm[14];
  7310. const rm12 = mm[3];
  7311. const rm13 = mm[7];
  7312. const rm14 = mm[11];
  7313. const rm15 = mm[15];
  7314. const rm = result._m;
  7315. rm[0] = rm0;
  7316. rm[1] = rm1;
  7317. rm[2] = rm2;
  7318. rm[3] = rm3;
  7319. rm[4] = rm4;
  7320. rm[5] = rm5;
  7321. rm[6] = rm6;
  7322. rm[7] = rm7;
  7323. rm[8] = rm8;
  7324. rm[9] = rm9;
  7325. rm[10] = rm10;
  7326. rm[11] = rm11;
  7327. rm[12] = rm12;
  7328. rm[13] = rm13;
  7329. rm[14] = rm14;
  7330. rm[15] = rm15;
  7331. result.markAsUpdated();
  7332. // identity-ness does not change when transposing
  7333. result._updateIdentityStatus(matrix._isIdentity, matrix._isIdentityDirty);
  7334. return result;
  7335. }
  7336. /**
  7337. * Computes a reflection matrix from a plane
  7338. * Example Playground - https://playground.babylonjs.com/#AV9X17#87
  7339. * @param plane defines the reflection plane
  7340. * @returns a new matrix
  7341. */
  7342. static Reflection(plane) {
  7343. const matrix = new Matrix();
  7344. Matrix.ReflectionToRef(plane, matrix);
  7345. return matrix;
  7346. }
  7347. /**
  7348. * Computes a reflection matrix from a plane
  7349. * Example Playground - https://playground.babylonjs.com/#AV9X17#88
  7350. * @param plane defines the reflection plane
  7351. * @param result defines the target matrix
  7352. * @returns result input
  7353. */
  7354. static ReflectionToRef(plane, result) {
  7355. plane.normalize();
  7356. const x = plane.normal.x;
  7357. const y = plane.normal.y;
  7358. const z = plane.normal.z;
  7359. const temp = -2 * x;
  7360. const temp2 = -2 * y;
  7361. const temp3 = -2 * z;
  7362. Matrix.FromValuesToRef(temp * x + 1, temp2 * x, temp3 * x, 0.0, temp * y, temp2 * y + 1, temp3 * y, 0.0, temp * z, temp2 * z, temp3 * z + 1, 0.0, temp * plane.d, temp2 * plane.d, temp3 * plane.d, 1.0, result);
  7363. return result;
  7364. }
  7365. /**
  7366. * Sets the given matrix as a rotation matrix composed from the 3 left handed axes
  7367. * @param xaxis defines the value of the 1st axis
  7368. * @param yaxis defines the value of the 2nd axis
  7369. * @param zaxis defines the value of the 3rd axis
  7370. * @param result defines the target matrix
  7371. * @returns result input
  7372. */
  7373. static FromXYZAxesToRef(xaxis, yaxis, zaxis, result) {
  7374. Matrix.FromValuesToRef(xaxis._x, xaxis._y, xaxis._z, 0.0, yaxis._x, yaxis._y, yaxis._z, 0.0, zaxis._x, zaxis._y, zaxis._z, 0.0, 0.0, 0.0, 0.0, 1.0, result);
  7375. return result;
  7376. }
  7377. /**
  7378. * Creates a rotation matrix from a quaternion and stores it in a target matrix
  7379. * @param quat defines the quaternion to use
  7380. * @param result defines the target matrix
  7381. * @returns result input
  7382. */
  7383. static FromQuaternionToRef(quat, result) {
  7384. const xx = quat._x * quat._x;
  7385. const yy = quat._y * quat._y;
  7386. const zz = quat._z * quat._z;
  7387. const xy = quat._x * quat._y;
  7388. const zw = quat._z * quat._w;
  7389. const zx = quat._z * quat._x;
  7390. const yw = quat._y * quat._w;
  7391. const yz = quat._y * quat._z;
  7392. const xw = quat._x * quat._w;
  7393. result._m[0] = 1.0 - 2.0 * (yy + zz);
  7394. result._m[1] = 2.0 * (xy + zw);
  7395. result._m[2] = 2.0 * (zx - yw);
  7396. result._m[3] = 0.0;
  7397. result._m[4] = 2.0 * (xy - zw);
  7398. result._m[5] = 1.0 - 2.0 * (zz + xx);
  7399. result._m[6] = 2.0 * (yz + xw);
  7400. result._m[7] = 0.0;
  7401. result._m[8] = 2.0 * (zx + yw);
  7402. result._m[9] = 2.0 * (yz - xw);
  7403. result._m[10] = 1.0 - 2.0 * (yy + xx);
  7404. result._m[11] = 0.0;
  7405. result._m[12] = 0.0;
  7406. result._m[13] = 0.0;
  7407. result._m[14] = 0.0;
  7408. result._m[15] = 1.0;
  7409. result.markAsUpdated();
  7410. return result;
  7411. }
  7412. }
  7413. Matrix._UpdateFlagSeed = 0;
  7414. Matrix._IdentityReadOnly = Matrix.Identity();
  7415. Object.defineProperties(Matrix.prototype, {
  7416. dimension: { value: [4, 4] },
  7417. rank: { value: 2 },
  7418. });
  7419. /**
  7420. * @internal
  7421. * Same as Tmp but not exported to keep it only for math functions to avoid conflicts
  7422. */
  7423. class MathTmp {
  7424. }
  7425. // Temporary Vector3s
  7426. MathTmp.Vector3 = ArrayTools.BuildTuple(11, Vector3.Zero);
  7427. // Temporary Matricies
  7428. MathTmp.Matrix = ArrayTools.BuildTuple(2, Matrix.Identity);
  7429. // Temporary Quaternions
  7430. MathTmp.Quaternion = ArrayTools.BuildTuple(3, Quaternion.Zero);
  7431. /**
  7432. * @internal
  7433. */
  7434. export class TmpVectors {
  7435. }
  7436. /** 3 temp Vector2 at once should be enough */
  7437. TmpVectors.Vector2 = ArrayTools.BuildTuple(3, Vector2.Zero);
  7438. /** 13 temp Vector3 at once should be enough */
  7439. TmpVectors.Vector3 = ArrayTools.BuildTuple(13, Vector3.Zero);
  7440. /** 3 temp Vector4 at once should be enough */
  7441. TmpVectors.Vector4 = ArrayTools.BuildTuple(3, Vector4.Zero);
  7442. /** 2 temp Quaternion at once should be enough */
  7443. TmpVectors.Quaternion = ArrayTools.BuildTuple(2, Quaternion.Zero);
  7444. /** 8 temp Matrices at once should be enough */
  7445. TmpVectors.Matrix = ArrayTools.BuildTuple(8, Matrix.Identity);
  7446. RegisterClass("BABYLON.Vector2", Vector2);
  7447. RegisterClass("BABYLON.Vector3", Vector3);
  7448. RegisterClass("BABYLON.Vector4", Vector4);
  7449. RegisterClass("BABYLON.Matrix", Matrix);
  7450. const mtxConvertNDCToHalfZRange = Matrix.FromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 1);
  7451. //# sourceMappingURL=math.vector.js.map